Initial Contribution
msm-2.6.38: tag AU_LINUX_ANDROID_GINGERBREAD.02.03.04.00.142
Signed-off-by: Bryan Huntsman <bryanh@codeaurora.org>
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 4c85a4b..a564a03 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -25,6 +25,8 @@
source "drivers/gpu/ion/Kconfig"
+source "drivers/gpu/msm/Kconfig"
+
config VGASTATE
tristate
default n
@@ -2323,13 +2325,6 @@
Select this option if display contents should be inherited as set by
the bootloader.
-config FB_MSM
- tristate "MSM Framebuffer support"
- depends on FB && ARCH_MSM
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
-
config FB_MX3
tristate "MX3 Framebuffer support"
depends on FB && MX3_IPU
@@ -2385,6 +2380,8 @@
Choose this option if you want to use the Unigfx device as a
framebuffer device. Without the support of PCI & AGP.
+source "drivers/video/msm/Kconfig"
+
source "drivers/video/omap/Kconfig"
source "drivers/video/omap2/Kconfig"
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 5aac00e..a024064 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1169,14 +1169,11 @@
unlock_fb_info(info);
break;
default:
- if (!lock_fb_info(info))
- return -ENODEV;
fb = info->fbops;
if (fb->fb_ioctl)
ret = fb->fb_ioctl(info, cmd, arg);
else
ret = -ENOTTY;
- unlock_fb_info(info);
}
return ret;
}
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
new file mode 100644
index 0000000..677863d
--- /dev/null
+++ b/drivers/video/msm/Kconfig
@@ -0,0 +1,661 @@
+
+source "drivers/video/msm/vidc/Kconfig"
+
+config FB_MSM
+ tristate "MSM Framebuffer support"
+ depends on FB && ARCH_MSM
+ select FB_BACKLIGHT if FB_MSM_BACKLIGHT
+ select NEW_LEDS
+ select LEDS_CLASS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Support for MSM Framebuffer.
+
+if FB_MSM
+
+config FB_MSM_BACKLIGHT
+ bool "Support for backlight control"
+ default y
+ ---help---
+ Say Y here if you want to control the backlight of your display.
+
+config FB_MSM_LOGO
+ bool "MSM Frame Buffer Logo"
+ default n
+ ---help---
+ Show /initlogo.rle during boot.
+
+config FB_MSM_LCDC_HW
+ bool
+ default n
+
+config FB_MSM_TRIPLE_BUFFER
+ bool "Support for triple frame buffer"
+ default n
+
+choice
+ prompt "MDP HW version"
+ default FB_MSM_MDP22
+
+config FB_MSM_MDP22
+ bool "MDP HW ver2.2"
+ ---help---
+ Support for MSM MDP HW revision 2.2
+ Say Y here if this is msm7201 variant platform.
+
+config FB_MSM_MDP30
+ select FB_MSM_LCDC_HW
+ bool "MDP HW ver3.0"
+ ---help---
+ Support for MSM MDP HW revision 3.0
+ Say Y here if this is msm7x25 variant platform.
+
+config FB_MSM_MDP303
+ depends on FB_MSM_MDP30
+ bool "MDP HW ver3.03"
+ default n
+ ---help---
+ Support for MSM MDP HW revision 3.03. This is a new version of
+ MDP3.0 which has the required functionality to support the features
+ required for msm7x2xA platform.
+ Say Y here if this is msm7x2xA variant platform.
+
+config FB_MSM_MDP31
+ select FB_MSM_LCDC_HW
+ bool "MDP HW ver3.1"
+ ---help---
+ Support for MSM MDP HW revision 3.1
+ Say Y here if this is msm8x50 variant platform.
+
+config FB_MSM_MDP40
+ select FB_MSM_LCDC_HW
+ bool "MDP HW ver4.0"
+ ---help---
+ Support for MSM MDP HW revision 4.0
+ Say Y here if this is msm7x30 variant platform.
+endchoice
+
+config FB_MSM_EBI2
+ bool
+ default n
+
+config FB_MSM_MDDI
+ bool
+ default n
+
+config FB_MSM_MIPI_DSI
+ bool
+ default n
+
+config FB_MSM_LCDC
+ bool
+ default n
+
+config FB_MSM_OVERLAY
+ depends on FB_MSM_MDP40 && ANDROID_PMEM
+ bool "MDP4 overlay support"
+ default n
+
+config FB_MSM_DTV
+ depends on FB_MSM_OVERLAY
+ bool
+ default n
+
+config FB_MSM_EXTMDDI
+ bool
+ default n
+
+config FB_MSM_TVOUT
+ bool
+ default n
+
+config FB_MSM_MDDI_TOSHIBA_COMMON
+ bool
+ select FB_MSM_MDDI
+ default n
+
+config FB_MSM_MDDI_TOSHIBA_COMMON_VGA
+ bool
+ select FB_MSM_MDDI_TOSHIBA_COMMON
+ default n
+
+config FB_MSM_MDDI_ORISE
+ bool
+ select FB_MSM_MDDI
+ default n
+
+config FB_MSM_MDDI_QUICKVX
+ bool
+ select FB_MSM_MDDI
+ default n
+
+config FB_MSM_MDDI_AUTO_DETECT
+ bool
+ select FB_MSM_MDDI
+ default n
+
+config FB_MSM_LCDC_AUTO_DETECT
+ bool
+ select FB_MSM_LCDC
+ default n
+
+config FB_MSM_LCDC_PANEL
+ bool
+ select FB_MSM_LCDC
+ default n
+
+config FB_MSM_MIPI_DSI_TOSHIBA
+ bool
+ select FB_MSM_MIPI_DSI
+ default n
+
+config FB_MSM_MIPI_DSI_RENESAS
+ bool
+ select FB_MSM_MIPI_DSI
+ default n
+
+config FB_MSM_MIPI_DSI_SIMULATOR
+ bool
+ select FB_MSM_MIPI_DSI
+ default n
+
+config FB_MSM_MIPI_DSI_NOVATEK
+ bool
+ select FB_MSM_MIPI_DSI
+ default n
+
+config FB_MSM_LCDC_ST15_WXGA
+ bool
+ select FB_MSM_LCDC_PANEL
+ default n
+
+config FB_MSM_LCDC_ST15_PANEL
+ depends on FB_MSM_LCDC_HW
+ bool "LCDC ST1.5 Panel"
+ select FB_MSM_LCDC_ST15_WXGA
+ ---help---
+ Support for ST1.5 WXGA (1366x768) panel
+
+config FB_MSM_LCDC_PRISM_WVGA
+ bool
+ select FB_MSM_LCDC_PANEL
+ default n
+
+config FB_MSM_LCDC_SAMSUNG_WSVGA
+ bool
+ select FB_MSM_LCDC_PANEL
+ default n
+
+config FB_MSM_LCDC_CHIMEI_WXGA
+ bool
+ select FB_MSM_LCDC_PANEL
+ default n
+
+config FB_MSM_LCDC_GORDON_VGA
+ bool
+ select FB_MSM_LCDC_PANEL
+ default n
+
+config FB_MSM_LCDC_TOSHIBA_WVGA_PT
+ bool
+ select FB_MSM_LCDC_PANEL
+ default n
+
+config FB_MSM_LCDC_TOSHIBA_FWVGA_PT
+ bool
+ select FB_MSM_LCDC_PANEL
+ default n
+
+config FB_MSM_LCDC_SHARP_WVGA_PT
+ bool
+ select FB_MSM_LCDC_PANEL
+ default n
+
+config FB_MSM_LCDC_AUO_WVGA
+ bool
+ select FB_MSM_LCDC_PANEL
+ default n
+
+config FB_MSM_LCDC_SAMSUNG_OLED_PT
+ bool
+ select FB_MSM_LCDC_PANEL
+ default n
+
+config FB_MSM_LCDC_WXGA
+ bool
+ select FB_MSM_LCDC_PANEL
+ default n
+
+config FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT
+ bool
+ select FB_MSM_MIPI_DSI_TOSHIBA
+ default n
+
+config FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT
+ bool
+ select FB_MSM_MIPI_DSI_TOSHIBA
+ default n
+
+config FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT
+ bool
+ select FB_MSM_MIPI_DSI_NOVATEK
+ default n
+
+config FB_MSM_MIPI_NOVATEK_CMD_QHD_PT
+ bool
+ select FB_MSM_MIPI_DSI_NOVATEK
+ default n
+
+config FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT
+ bool
+ select FB_MSM_MIPI_DSI_RENESAS
+ default n
+
+config FB_MSM_MIPI_RENESAS_CMD_FWVGA_PT
+ bool
+ select FB_MSM_MIPI_DSI_RENESAS
+ default n
+
+config FB_MSM_MIPI_SIMULATOR_VIDEO
+ bool
+ select FB_MSM_MIPI_DSI_SIMULATOR
+ default n
+
+
+config FB_MSM_OVERLAY_WRITEBACK
+ depends on FB_MSM_OVERLAY
+ bool "MDP overlay write back mode enable"
+ ---help---
+ Support for MDP4 OVERLAY write back mode
+
+choice
+ prompt "LCD Panel"
+ default FB_MSM_MDDI_AUTO_DETECT
+
+config FB_MSM_LCDC_PRISM_WVGA_PANEL
+ depends on FB_MSM_LCDC_HW
+ bool "LCDC Prism WVGA Panel"
+ select FB_MSM_LCDC_PRISM_WVGA
+ ---help---
+ Support for LCDC Prism WVGA (800x480) panel
+
+config FB_MSM_LCDC_SAMSUNG_WSVGA_PANEL
+ depends on FB_MSM_LCDC_HW
+ bool "LCDC Samsung WSVGA Panel"
+ select FB_MSM_LCDC_SAMSUNG_WSVGA
+ ---help---
+ Support for LCDC Samsung WSVGA (1024x600) panel
+
+config FB_MSM_LCDC_CHIMEI_WXGA_PANEL
+ depends on FB_MSM_LCDC_HW
+ bool "LCDC Chimei WXGA Panel"
+ select FB_MSM_LCDC_CHIMEI_WXGA
+ ---help---
+ Support for LCDC Chimei WXGA (1366x768) panel
+
+config FB_MSM_LCDC_GORDON_VGA_PANEL
+ depends on FB_MSM_LCDC_HW
+ bool "LCDC Gordon VGA Panel"
+ select FB_MSM_LCDC_GORDON_VGA
+ ---help---
+ Support for LCDC Gordon VGA (480x640) panel
+
+config FB_MSM_LCDC_TOSHIBA_WVGA_PT_PANEL
+ depends on FB_MSM_LCDC_HW
+ bool "LCDC Toshiba WVGA PT Panel"
+ select FB_MSM_LCDC_TOSHIBA_WVGA_PT
+ ---help---
+ Support for LCDC Toshiba WVGA PT (480x800) panel
+
+config FB_MSM_LCDC_TOSHIBA_FWVGA_PT_PANEL
+ depends on FB_MSM_LCDC_HW
+ bool "LCDC Toshiba FWVGA PT Panel"
+ select FB_MSM_LCDC_TOSHIBA_FWVGA_PT
+ ---help---
+ Support for LCDC Toshiba FWVGA PT (480x864) panel. This
+ configuration has to be selected to support the Toshiba
+ FWVGA (480x864) portrait panel.
+ .
+ .
+
+config FB_MSM_LCDC_SHARP_WVGA_PT_PANEL
+ depends on FB_MSM_LCDC_HW
+ bool "LCDC Sharp WVGA PT Panel"
+ select FB_MSM_LCDC_SHARP_WVGA_PT
+ ---help---
+ Support for LCDC Sharp WVGA PT (480x800) panel
+
+config FB_MSM_LCDC_AUO_WVGA_PANEL
+ depends on FB_MSM_LCDC_HW
+ bool "LCDC AUO WVGA Panel"
+ select FB_MSM_LCDC_AUO_WVGA
+ ---help---
+ Support for LCDC AUO WVGA(480x800) panel
+ .
+ .
+ .
+config FB_MSM_LCDC_SAMSUNG_OLED_PT_PANEL
+ depends on FB_MSM_LCDC_HW
+ bool "LCDC Samsung OLED PT Panel"
+ select FB_MSM_LCDC_SAMSUNG_OLED_PT
+ ---help---
+ Support for LCDC Samsung OLED PT (480x800) panel
+ .
+ .
+ .
+
+config FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+ depends on FB_MSM_LCDC_HW
+ bool "MDDI Panel Auto Detect + LCDC Prism WVGA"
+ select FB_MSM_MDDI_AUTO_DETECT
+ select FB_MSM_LCDC_PRISM_WVGA
+ select FB_MSM_LCDC_GORDON_VGA
+ select FB_MSM_LCDC_WXGA
+ select FB_MSM_LCDC_TOSHIBA_WVGA_PT
+ select FB_MSM_LCDC_TOSHIBA_FWVGA_PT
+ select FB_MSM_LCDC_SHARP_WVGA_PT
+ select FB_MSM_LCDC_ST15_WXGA
+ ---help---
+ Support for MDDI panel auto detect.
+ If it can't find any MDDI panel, it will load an LCDC panel.
+
+config FB_MSM_MIPI_PANEL_DETECT
+ depends on FB_MSM_LCDC_HW
+ bool "MIPI Panel Detect + LCDC Panel Auto Detect"
+ select FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT
+ select FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT
+ select FB_MSM_LCDC_AUTO_DETECT
+ select FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT
+ select FB_MSM_MIPI_SIMULATOR_VIDEO
+ select FB_MSM_LCDC_SAMSUNG_WSVGA
+ select FB_MSM_LCDC_AUO_WVGA
+ select FB_MSM_LCDC_SAMSUNG_OLED_PT
+
+config FB_MSM_MDDI_PANEL_AUTO_DETECT
+ bool "MDDI Panel Auto Detect"
+ select FB_MSM_MDDI_AUTO_DETECT
+ ---help---
+ Support for MDDI panel auto detect
+
+config FB_MSM_LCDC_PANEL_AUTO_DETECT
+ bool "LCDC Panel Auto Detect"
+ select FB_MSM_LCDC_AUTO_DETECT
+ select FB_MSM_LCDC_SAMSUNG_WSVGA
+ select FB_MSM_LCDC_AUO_WVGA
+ select FB_MSM_LCDC_SAMSUNG_OLED_PT
+ ---help---
+ Support for LCDC panel auto detect
+ .
+ .
+ .
+
+config FB_MSM_MDDI_PRISM_WVGA
+ bool "MDDI Prism WVGA Panel"
+ select FB_MSM_MDDI
+ ---help---
+ Support for MDDI Prism WVGA (800x480) panel
+
+config FB_MSM_MDDI_TOSHIBA_WVGA_PORTRAIT
+ bool "MDDI Toshiba WVGA Portrait Panel"
+ select FB_MSM_MDDI_TOSHIBA_COMMON
+ ---help---
+ Support for MDDI Toshiba WVGA (480x800) panel
+
+config FB_MSM_MDDI_TOSHIBA_VGA
+ bool "MDDI Toshiba VGA Panel"
+ select FB_MSM_MDDI_TOSHIBA_COMMON_VGA
+ ---help---
+ Support for MDDI Toshiba VGA (480x640) and QCIF (176x220) panel
+
+config FB_MSM_MDDI_TOSHIBA_WVGA
+ bool "MDDI Toshiba WVGA panel"
+ select FB_MSM_MDDI_TOSHIBA_COMMON
+ ---help---
+ Support for MDDI Toshiba (800x480) WVGA panel
+
+config FB_MSM_MDDI_SHARP_QVGA_128x128
+ bool "MDDI Sharp QVGA Dual Panel"
+ select FB_MSM_MDDI
+ ---help---
+ Support for MDDI Sharp QVGA (240x320) and 128x128 dual panel
+
+config FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT_PANEL
+ bool "MIPI Toshiba WVGA PT Panel"
+ select FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT
+
+config FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT_PANEL
+ bool "MIPI Toshiba WSVGA PT Panel"
+ select FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT
+
+config FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT_PANEL
+ bool "MIPI NOVATEK VIDEO QHD PT Panel"
+ select FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT
+
+config FB_MSM_MIPI_NOVATEK_CMD_QHD_PT_PANEL
+ bool "MIPI NOVATEK CMD QHD PT Panel"
+ select FB_MSM_MIPI_NOVATEK_CMD_QHD_PT
+
+config FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT_PANEL
+ bool "MIPI Renesas Video FWVGA PT Panel"
+ select FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT
+
+config FB_MSM_MIPI_RENESAS_CMD_FWVGA_PT_PANEL
+ bool "MIPI Renesas Command FWVGA PT Panel"
+ select FB_MSM_MIPI_RENESAS_CMD_FWVGA_PT
+
+config FB_MSM_MIPI_SIMULATOR_VIDEO_PANEL
+ bool "MIPI Simulator Video Panel"
+ select FB_MSM_MIPI_SIMULATOR_VIDEO
+
+config FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF
+ bool "EBI2 TMD QVGA Epson QCIF Dual Panel"
+ select FB_MSM_EBI2
+ ---help---
+ Support for EBI2 TMD QVGA (240x320) and Epson QCIF (176x220) panel
+
+config FB_MSM_PANEL_NONE
+ bool "NONE"
+ ---help---
+ This will disable LCD panel
+endchoice
+
+choice
+ prompt "Secondary LCD Panel"
+ depends on FB_MSM_MDP31
+ default FB_MSM_SECONDARY_PANEL_NONE
+
+config FB_MSM_LCDC_EXTERNAL_WXGA
+ depends on FB_MSM_MDP31
+ bool "External WXGA on LCDC"
+ select FB_MSM_LCDC_PANEL
+ ---help---
+ Support for external WXGA display (1280x720)
+
+config FB_MSM_HDMI_SII_EXTERNAL_720P
+ depends on FB_MSM_MDP31
+ bool "External SiI9022 HDMI 720P"
+ select FB_MSM_LCDC_PANEL
+ ---help---
+ Support for external HDMI 720p display (1280x720p)
+ Using SiI9022 chipset
+
+config FB_MSM_SECONDARY_PANEL_NONE
+ bool "NONE"
+ ---help---
+ No secondary panel
+endchoice
+
+config FB_MSM_LCDC_DSUB
+ depends on FB_MSM_LCDC_SAMSUNG_WSVGA && FB_MSM_MDP40 && FB_MSM_LCDC_HW
+ bool "External DSUB support"
+ default n
+ ---help---
+ Support for external DSUB (VGA) display up to 1440x900. The DSUB
+ display shares the same video bus as the primary LCDC attached display.
+ Typically only one of the two displays can be used at one time.
+
+config FB_MSM_EXT_INTERFACE_COMMON
+ bool
+ default n
+
+config FB_MSM_HDMI_COMMON
+ bool
+ default n
+
+config FB_MSM_HDMI_3D
+ bool
+ default n
+
+config FB_MSM_HDMI_ADV7520_PANEL
+ depends on FB_MSM_MDP40 && FB_MSM_OVERLAY
+ bool "LCDC HDMI ADV7520 720p Panel"
+ select FB_MSM_DTV
+ select FB_MSM_EXT_INTERFACE_COMMON
+ select FB_MSM_HDMI_COMMON
+ default n
+ ---help---
+ Support for LCDC 720p HDMI panel attached to ADV7520
+
+config FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
+ depends on FB_MSM_HDMI_ADV7520_PANEL
+ bool "Use HDCP mode"
+ default y
+ ---help---
+ Support for HDCP mode for ADV7520 HDMI 720p Panel
+ Choose to enable HDCP
+
+
+config FB_MSM_HDMI_MSM_PANEL
+ depends on FB_MSM_MDP40
+ bool "MSM HDMI 1080p Panel"
+ select FB_MSM_DTV
+ select FB_MSM_EXT_INTERFACE_COMMON
+ select FB_MSM_HDMI_COMMON
+ select FB_MSM_HDMI_3D
+ default n
+ ---help---
+ Support for 480p/720p/1080i/1080p output through MSM HDMI
+
+config FB_MSM_HDMI_MSM_PANEL_DVI_SUPPORT
+ depends on FB_MSM_HDMI_MSM_PANEL
+ bool "Use DVI mode"
+ default n
+ ---help---
+ Support for DVI mode for MSM HDMI 1080p Panel
+
+config FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ depends on FB_MSM_HDMI_MSM_PANEL
+ bool "Use HDCP mode"
+ default y
+ ---help---
+ Support for HDCP mode for MSM HDMI 1080p Panel
+ Choose to enable HDCP
+ .
+ .
+
+choice
+ depends on (FB_MSM_MDP22 || FB_MSM_MDP31 || FB_MSM_MDP40)
+ prompt "TVOut Region"
+ default FB_MSM_TVOUT_NONE
+
+config FB_MSM_TVOUT_NTSC_M
+ bool "NTSC M"
+ select FB_MSM_TVOUT
+ select FB_MSM_EXT_INTERFACE_COMMON
+ ---help---
+ Support for NTSC M region (North American and Korea)
+ .
+ .
+ .
+
+config FB_MSM_TVOUT_NTSC_J
+ bool "NTSC J"
+ select FB_MSM_TVOUT
+ select FB_MSM_EXT_INTERFACE_COMMON
+ ---help---
+ Support for NTSC J region (Japan)
+ .
+ .
+ .
+
+config FB_MSM_TVOUT_PAL_BDGHIN
+ bool "PAL BDGHIN"
+ select FB_MSM_TVOUT
+ select FB_MSM_EXT_INTERFACE_COMMON
+ ---help---
+ Support for PAL BDGHIN region (Non-argentina PAL-N)
+ .
+ .
+ .
+
+config FB_MSM_TVOUT_PAL_M
+ bool "PAL M"
+ select FB_MSM_TVOUT
+ select FB_MSM_EXT_INTERFACE_COMMON
+ ---help---
+ Support for PAL M region
+ .
+ .
+ .
+
+config FB_MSM_TVOUT_PAL_N
+ bool "PAL N"
+ select FB_MSM_TVOUT
+ select FB_MSM_EXT_INTERFACE_COMMON
+ ---help---
+ Support for PAL N region (Argentina PAL-N)
+ .
+ .
+ .
+
+config FB_MSM_TVOUT_NONE
+ bool "NONE"
+ ---help---
+ This will disable TV Out functionality.
+endchoice
+
+config FB_MSM_TVOUT_SVIDEO
+ bool "TVOut on S-video"
+ depends on FB_MSM_TVOUT
+ default n
+ ---help---
+ Selects whether the TVOut signal uses S-video.
+ Choose n for composite output.
+
+choice
+ depends on FB_MSM_MDP22
+ prompt "External MDDI"
+ default FB_MSM_EXTMDDI_SVGA
+
+config FB_MSM_EXTMDDI_SVGA
+ bool "External MDDI SVGA"
+ select FB_MSM_MDDI
+ select FB_MSM_EXTMDDI
+ ---help---
+ Support for MSM SVGA (800x600) external MDDI panel
+
+config FB_MSM_EXTMDDI_NONE
+ bool "NONE"
+ ---help---
+ This will disable External MDDI functionality.
+endchoice
+
+choice
+ prompt "Default framebuffer color depth"
+ depends on FB_MSM_MDP40 || FB_MSM_MDP31
+ default FB_MSM_DEFAULT_DEPTH_RGBA8888
+
+config FB_MSM_DEFAULT_DEPTH_RGB565
+ bool "16 bits per pixel (RGB565)"
+
+config FB_MSM_DEFAULT_DEPTH_ARGB8888
+ bool "32 bits per pixel (ARGB8888)"
+
+config FB_MSM_DEFAULT_DEPTH_RGBA8888
+ bool "32 bits per pixel (RGBA8888)"
+
+endchoice
+
+endif
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
index 802d6ae..280e528 100644
--- a/drivers/video/msm/Makefile
+++ b/drivers/video/msm/Makefile
@@ -1,19 +1,150 @@
-
-# core framebuffer
-#
obj-y := msm_fb.o
-# MDP DMA/PPP engine
-#
-obj-y += mdp.o mdp_scale_tables.o mdp_ppp.o
+obj-$(CONFIG_FB_MSM_LOGO) += logo.o
+obj-$(CONFIG_FB_BACKLIGHT) += msm_fb_bl.o
-# MDDI interface
-#
-obj-y += mddi.o
+# MDP
+obj-y += mdp.o
-# MDDI client/panel drivers
-#
-obj-y += mddi_client_dummy.o
-obj-y += mddi_client_toshiba.o
-obj-y += mddi_client_nt35399.o
+obj-$(CONFIG_DEBUG_FS) += mdp_debugfs.o
+ifeq ($(CONFIG_FB_MSM_MDP40),y)
+obj-y += mdp4_util.o
+else
+obj-y += mdp_hw_init.o
+obj-y += mdp_ppp.o
+ifeq ($(CONFIG_FB_MSM_MDP31),y)
+obj-y += mdp_ppp_v31.o
+else
+obj-y += mdp_ppp_v20.o
+endif
+endif
+
+ifeq ($(CONFIG_FB_MSM_OVERLAY),y)
+obj-y += mdp4_overlay.o
+obj-y += mdp4_overlay_lcdc.o
+ifeq ($(CONFIG_FB_MSM_MIPI_DSI),y)
+obj-y += mdp4_overlay_dsi_video.o
+obj-y += mdp4_overlay_dsi_cmd.o
+else
+obj-y += mdp4_overlay_mddi.o
+endif
+else
+obj-y += mdp_dma_lcdc.o
+endif
+
+obj-$(CONFIG_FB_MSM_MDP303) += mdp_dma_dsi_video.o
+
+ifeq ($(CONFIG_FB_MSM_DTV),y)
+obj-y += mdp4_dtv.o
+obj-y += mdp4_overlay_dtv.o
+endif
+
+obj-y += mdp_dma.o
+obj-y += mdp_dma_s.o
+obj-y += mdp_vsync.o
+obj-y += mdp_cursor.o
+obj-y += mdp_dma_tv.o
+obj-$(CONFIG_ARCH_MSM7X27A) += msm_dss_io_7x27a.o
+obj-$(CONFIG_ARCH_MSM8X60) += msm_dss_io_8x60.o
+obj-$(CONFIG_ARCH_MSM8960) += msm_dss_io_8960.o
+
+# EBI2
+obj-$(CONFIG_FB_MSM_EBI2) += ebi2_lcd.o
+
+# LCDC
+obj-$(CONFIG_FB_MSM_LCDC) += lcdc.o
+
+# MDDI
+msm_mddi-objs := mddi.o mddihost.o mddihosti.o
+obj-$(CONFIG_FB_MSM_MDDI) += msm_mddi.o
+
+# External MDDI
+msm_mddi_ext-objs := mddihost_e.o mddi_ext.o
+obj-$(CONFIG_FB_MSM_EXTMDDI) += msm_mddi_ext.o
+
+# MIPI gereric
+msm_mipi-objs := mipi_dsi.o mipi_dsi_host.o
+obj-$(CONFIG_FB_MSM_MIPI_DSI) += msm_mipi.o
+
+# MIPI manufacture
+obj-$(CONFIG_FB_MSM_MIPI_DSI_TOSHIBA) += mipi_toshiba.o
+obj-$(CONFIG_FB_MSM_MIPI_DSI_NOVATEK) += mipi_novatek.o
+obj-$(CONFIG_FB_MSM_MIPI_DSI_RENESAS) += mipi_renesas.o
+obj-$(CONFIG_FB_MSM_MIPI_DSI_SIMULATOR) += mipi_simulator.o
+
+# TVEnc
+obj-$(CONFIG_FB_MSM_TVOUT) += tvenc.o
+ifeq ($(CONFIG_FB_MSM_OVERLAY),y)
+obj-$(CONFIG_FB_MSM_TVOUT) += mdp4_overlay_atv.o
+endif
+
+# MSM FB Panel
+obj-y += msm_fb_panel.o
+obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_tmd20.o
+obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_l2f.o
+
+ifeq ($(CONFIG_FB_MSM_MDDI_AUTO_DETECT),y)
+obj-y += mddi_prism.o
+obj-y += mddi_toshiba.o
+obj-y += mddi_toshiba_vga.o
+obj-y += mddi_toshiba_wvga_pt.o
+obj-y += mddi_toshiba_wvga.o
+obj-y += mddi_sharp.o
+obj-y += mddi_orise.o
+obj-y += mddi_quickvx.o
+else
+obj-$(CONFIG_FB_MSM_MDDI_PRISM_WVGA) += mddi_prism.o
+obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON) += mddi_toshiba.o
+obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON_VGA) += mddi_toshiba_vga.o
+obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_WVGA_PORTRAIT) += mddi_toshiba_wvga_pt.o
+obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_WVGA) += mddi_toshiba_wvga.o
+obj-$(CONFIG_FB_MSM_MDDI_SHARP_QVGA_128x128) += mddi_sharp.o
+obj-$(CONFIG_FB_MSM_MDDI_ORISE) += mddi_orise.o
+obj-$(CONFIG_FB_MSM_MDDI_QUICKVX) += mddi_quickvx.o
+endif
+
+ifeq ($(CONFIG_FB_MSM_MIPI_PANEL_DETECT),y)
+obj-y += mipi_toshiba_video_wvga_pt.o mipi_toshiba_video_wsvga_pt.o
+obj-y += mipi_novatek_video_qhd_pt.o mipi_novatek_cmd_qhd_pt.o
+obj-y += mipi_renesas_video_fwvga_pt.o mipi_renesas_cmd_fwvga_pt.o
+else
+obj-$(CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT) += mipi_toshiba_video_wvga_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT) += mipi_toshiba_video_wsvga_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT) += mipi_novatek_video_qhd_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_NOVATEK_CMD_QHD_PT) += mipi_novatek_cmd_qhd_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT) += mipi_renesas_video_fwvga_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_RENESAS_CMD_FWVGA_PT) += mipi_renesas_cmd_fwvga_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_SIMULATOR_VIDEO) += mipi_simulator_video.o
+endif
+
+
+
+
+obj-$(CONFIG_FB_MSM_LCDC_PANEL) += lcdc_panel.o
+obj-$(CONFIG_FB_MSM_LCDC_PRISM_WVGA) += lcdc_prism.o
+obj-$(CONFIG_FB_MSM_LCDC_SAMSUNG_WSVGA) += lcdc_samsung_wsvga.o
+obj-$(CONFIG_FB_MSM_LCDC_CHIMEI_WXGA) += lcdc_chimei_wxga.o
+obj-$(CONFIG_FB_MSM_LCDC_EXTERNAL_WXGA) += lcdc_external.o
+obj-$(CONFIG_FB_MSM_HDMI_SII_EXTERNAL_720P) += hdmi_sii9022.o
+obj-$(CONFIG_FB_MSM_LCDC_GORDON_VGA) += lcdc_gordon.o
+obj-$(CONFIG_FB_MSM_LCDC_WXGA) += lcdc_wxga.o
+obj-$(CONFIG_FB_MSM_LCDC_TOSHIBA_WVGA_PT) += lcdc_toshiba_wvga_pt.o
+obj-$(CONFIG_FB_MSM_LCDC_TOSHIBA_FWVGA_PT) += lcdc_toshiba_fwvga_pt.o
+obj-$(CONFIG_FB_MSM_LCDC_SHARP_WVGA_PT) += lcdc_sharp_wvga_pt.o
+obj-$(CONFIG_FB_MSM_LCDC_AUO_WVGA) += lcdc_auo_wvga.o
+obj-$(CONFIG_FB_MSM_LCDC_SAMSUNG_OLED_PT) += lcdc_samsung_oled_pt.o
+obj-$(CONFIG_FB_MSM_HDMI_ADV7520_PANEL) += adv7520.o
+obj-$(CONFIG_FB_MSM_LCDC_ST15_WXGA) += lcdc_st15.o
+obj-$(CONFIG_FB_MSM_HDMI_MSM_PANEL) += hdmi_msm.o
+obj-$(CONFIG_FB_MSM_EXT_INTERFACE_COMMON) += external_common.o
+
+obj-$(CONFIG_FB_MSM_TVOUT) += tvout_msm.o
+
+obj-$(CONFIG_FB_MSM_EXTMDDI_SVGA) += mddi_ext_lcd.o
+
+obj-$(CONFIG_MSM_VIDC_1080P) += vidc/
+obj-$(CONFIG_MSM_VIDC_720P) += vidc/
+
+clean:
+ rm *.o .*cmd
diff --git a/drivers/video/msm/adv7520.c b/drivers/video/msm/adv7520.c
new file mode 100644
index 0000000..0900f23
--- /dev/null
+++ b/drivers/video/msm/adv7520.c
@@ -0,0 +1,1005 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/i2c.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/adv7520.h>
+#include <linux/time.h>
+#include <linux/completion.h>
+#include <linux/wakelock.h>
+#include <asm/atomic.h>
+#include "msm_fb.h"
+
+#define DEBUG
+#define DEV_DBG_PREFIX "HDMI: "
+
+#include "external_common.h"
+
+/* #define PORT_DEBUG */
+/* #define TESTING_FORCE_480p */
+
+#define HPD_DUTY_CYCLE 4 /*secs*/
+
+static struct external_common_state_type hdmi_common;
+
+static struct i2c_client *hclient;
+
+static bool chip_power_on = FALSE; /* For chip power on/off */
+static bool enable_5v_on = FALSE;
+static bool hpd_power_on = FALSE;
+static atomic_t comm_power_on; /* For dtv power on/off (I2C) */
+static int suspend_count;
+
+static u8 reg[256]; /* HDMI panel registers */
+
+struct hdmi_data {
+ struct msm_hdmi_platform_data *pd;
+ struct work_struct isr_work;
+};
+static struct hdmi_data *dd;
+static struct work_struct hpd_timer_work;
+
+#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
+static struct work_struct hdcp_handle_work;
+static int hdcp_activating;
+static DEFINE_MUTEX(hdcp_state_mutex);
+static int has_hdcp_hw_support = true;
+#endif
+
+static struct timer_list hpd_timer;
+static struct timer_list hpd_duty_timer;
+static struct work_struct hpd_duty_work;
+static unsigned int monitor_sense;
+static boolean hpd_cable_chg_detected;
+
+struct wake_lock wlock;
+
+/* Change HDMI state */
+static void change_hdmi_state(int online)
+{
+ if (!external_common_state)
+ return;
+
+ mutex_lock(&external_common_state_hpd_mutex);
+ external_common_state->hpd_state = online;
+ mutex_unlock(&external_common_state_hpd_mutex);
+
+ if (!external_common_state->uevent_kobj)
+ return;
+
+ if (online)
+ kobject_uevent(external_common_state->uevent_kobj,
+ KOBJ_ONLINE);
+ else
+ kobject_uevent(external_common_state->uevent_kobj,
+ KOBJ_OFFLINE);
+ DEV_INFO("adv7520_uevent: %d [suspend# %d]\n", online, suspend_count);
+}
+
+
+/*
+ * Read a value from a register on ADV7520 device
+ * If sucessfull returns value read , otherwise error.
+ */
+static u8 adv7520_read_reg(struct i2c_client *client, u8 reg)
+{
+ int err;
+ struct i2c_msg msg[2];
+ u8 reg_buf[] = { reg };
+ u8 data_buf[] = { 0 };
+
+ if (!client->adapter)
+ return -ENODEV;
+ if (!atomic_read(&comm_power_on)) {
+ DEV_WARN("%s: WARN: missing GPIO power\n", __func__);
+ return -ENODEV;
+ }
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = 1;
+ msg[0].buf = reg_buf;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = 1;
+ msg[1].buf = data_buf;
+
+ err = i2c_transfer(client->adapter, msg, 2);
+
+ if (err < 0) {
+ DEV_INFO("%s: I2C err: %d\n", __func__, err);
+ return err;
+ }
+
+#ifdef PORT_DEBUG
+ DEV_INFO("HDMI[%02x] [R] %02x\n", reg, data);
+#endif
+ return *data_buf;
+}
+
+/*
+ * Write a value to a register on adv7520 device.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+static int adv7520_write_reg(struct i2c_client *client, u8 reg, u8 val)
+{
+ int err;
+ struct i2c_msg msg[1];
+ unsigned char data[2];
+
+ if (!client->adapter)
+ return -ENODEV;
+ if (!atomic_read(&comm_power_on)) {
+ DEV_WARN("%s: WARN: missing GPIO power\n", __func__);
+ return -ENODEV;
+ }
+
+ msg->addr = client->addr;
+ msg->flags = 0;
+ msg->len = 2;
+ msg->buf = data;
+ data[0] = reg;
+ data[1] = val;
+
+ err = i2c_transfer(client->adapter, msg, 1);
+ if (err >= 0)
+ return 0;
+#ifdef PORT_DEBUG
+ DEV_INFO("HDMI[%02x] [W] %02x [%d]\n", reg, val, err);
+#endif
+ return err;
+}
+
+#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
+static void adv7520_close_hdcp_link(void)
+{
+ if (!external_common_state->hdcp_active && !hdcp_activating)
+ return;
+
+ DEV_INFO("HDCP: Close link\n");
+
+ reg[0xD5] = adv7520_read_reg(hclient, 0xD5);
+ reg[0xD5] &= 0xFE;
+ adv7520_write_reg(hclient, 0xD5, (u8)reg[0xD5]);
+
+ reg[0x16] = adv7520_read_reg(hclient, 0x16);
+ reg[0x16] &= 0xFE;
+ adv7520_write_reg(hclient, 0x16, (u8)reg[0x16]);
+
+ /* UnMute Audio */
+ adv7520_write_reg(hclient, 0x0C, (u8)0x84);
+
+ external_common_state->hdcp_active = FALSE;
+ mutex_lock(&hdcp_state_mutex);
+ hdcp_activating = FALSE;
+ mutex_unlock(&hdcp_state_mutex);
+}
+
+static void adv7520_comm_power(int on, int show);
+static void adv7520_hdcp_enable(struct work_struct *work)
+{
+ DEV_INFO("HDCP: Start reg[0xaf]=%02x (mute audio)\n", reg[0xaf]);
+
+ adv7520_comm_power(1, 1);
+
+ /* Mute Audio */
+ adv7520_write_reg(hclient, 0x0C, (u8)0xC3);
+
+ msleep(200);
+ /* Wait for BKSV ready interrupt */
+ /* Read BKSV's keys from HDTV */
+ reg[0xBF] = adv7520_read_reg(hclient, 0xBF);
+ reg[0xC0] = adv7520_read_reg(hclient, 0xC0);
+ reg[0xC1] = adv7520_read_reg(hclient, 0xC1);
+ reg[0xC2] = adv7520_read_reg(hclient, 0xC2);
+ reg[0xc3] = adv7520_read_reg(hclient, 0xC3);
+
+ DEV_DBG("HDCP: BKSV={%02x,%02x,%02x,%02x,%02x}\n", reg[0xbf], reg[0xc0],
+ reg[0xc1], reg[0xc2], reg[0xc3]);
+
+ /* Is SINK repeater */
+ reg[0xBE] = adv7520_read_reg(hclient, 0xBE);
+ if (~(reg[0xBE] & 0x40)) {
+ ; /* compare with revocation list */
+ /* Check 20 1's and 20 zero's */
+ } else {
+ /* Don't implement HDCP if sink as a repeater */
+ adv7520_write_reg(hclient, 0x0C, (u8)0x84);
+ mutex_lock(&hdcp_state_mutex);
+ hdcp_activating = FALSE;
+ mutex_unlock(&hdcp_state_mutex);
+ DEV_WARN("HDCP: Sink Repeater (%02x), (unmute audio)\n",
+ reg[0xbe]);
+
+ adv7520_comm_power(0, 1);
+ return;
+ }
+
+ msleep(200);
+ reg[0xB8] = adv7520_read_reg(hclient, 0xB8);
+ DEV_INFO("HDCP: Status reg[0xB8] is %02x\n", reg[0xb8]);
+ if (reg[0xb8] & 0x40) {
+ /* UnMute Audio */
+ adv7520_write_reg(hclient, 0x0C, (u8)0x84);
+ DEV_INFO("HDCP: A/V content Encrypted (unmute audio)\n");
+ external_common_state->hdcp_active = TRUE;
+ }
+ adv7520_comm_power(0, 1);
+
+ mutex_lock(&hdcp_state_mutex);
+ hdcp_activating = FALSE;
+ mutex_unlock(&hdcp_state_mutex);
+}
+#endif
+
+static int adv7520_read_edid_block(int block, uint8 *edid_buf)
+{
+ u8 r = 0;
+ int ret;
+ struct i2c_msg msg[] = {
+ { .addr = reg[0x43] >> 1,
+ .flags = 0,
+ .len = 1,
+ .buf = &r },
+ { .addr = reg[0x43] >> 1,
+ .flags = I2C_M_RD,
+ .len = 0x100,
+ .buf = edid_buf } };
+
+ if (block > 0)
+ return 0;
+ ret = i2c_transfer(hclient->adapter, msg, 2);
+ DEV_DBG("EDID block: addr=%02x, ret=%d\n", reg[0x43] >> 1, ret);
+ return (ret < 2) ? -ENODEV : 0;
+}
+
+static void adv7520_read_edid(void)
+{
+ external_common_state->read_edid_block = adv7520_read_edid_block;
+ if (hdmi_common_read_edid()) {
+ u8 timeout;
+ DEV_INFO("%s: retry\n", __func__);
+ adv7520_write_reg(hclient, 0xc9, 0x13);
+ msleep(500);
+ timeout = (adv7520_read_reg(hclient, 0x96) & (1 << 2));
+ if (timeout) {
+ hdmi_common_read_edid();
+ }
+ }
+}
+
+static void adv7520_chip_on(void)
+{
+ if (!chip_power_on) {
+ /* Get the current register holding the power bit. */
+ unsigned long reg0xaf = adv7520_read_reg(hclient, 0xaf);
+
+ dd->pd->core_power(1, 1);
+
+ /* Set the HDMI select bit. */
+ set_bit(1, ®0xaf);
+ DEV_INFO("%s: turn on chip power\n", __func__);
+ adv7520_write_reg(hclient, 0x41, 0x10);
+ adv7520_write_reg(hclient, 0xaf, (u8)reg0xaf);
+ chip_power_on = TRUE;
+ } else
+ DEV_INFO("%s: chip already has power\n", __func__);
+}
+
+static void adv7520_chip_off(void)
+{
+ if (chip_power_on) {
+#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
+ if (has_hdcp_hw_support)
+ adv7520_close_hdcp_link();
+#endif
+
+ DEV_INFO("%s: turn off chip power\n", __func__);
+ adv7520_write_reg(hclient, 0x41, 0x50);
+ dd->pd->core_power(0, 1);
+ chip_power_on = FALSE;
+ } else
+ DEV_INFO("%s: chip is already off\n", __func__);
+
+ monitor_sense = 0;
+ hpd_cable_chg_detected = FALSE;
+
+ if (enable_5v_on) {
+ dd->pd->enable_5v(0);
+ enable_5v_on = FALSE;
+ }
+}
+
+/* Power ON/OFF ADV7520 chip */
+static void adv7520_isr_w(struct work_struct *work);
+static void adv7520_comm_power(int on, int show)
+{
+ if (!on)
+ atomic_dec(&comm_power_on);
+ dd->pd->comm_power(on, 0/*show*/);
+ if (on)
+ atomic_inc(&comm_power_on);
+}
+
+#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
+static void adv7520_start_hdcp(void);
+#endif
+static int adv7520_power_on(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
+
+ external_common_state->dev = &pdev->dev;
+ if (mfd != NULL) {
+ DEV_INFO("adv7520_power: ON (%dx%d %d)\n",
+ mfd->var_xres, mfd->var_yres, mfd->var_pixclock);
+ hdmi_common_get_video_format_from_drv_data(mfd);
+ }
+
+ adv7520_comm_power(1, 1);
+ /* Check if HPD is signaled */
+ if (adv7520_read_reg(hclient, 0x42) & (1 << 6)) {
+ DEV_INFO("power_on: cable detected\n");
+ monitor_sense = adv7520_read_reg(hclient, 0xC6);
+#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
+ if (has_hdcp_hw_support) {
+ if (!hdcp_activating)
+ adv7520_start_hdcp();
+ }
+#endif
+ } else
+ DEV_INFO("power_on: cable NOT detected\n");
+ adv7520_comm_power(0, 1);
+ wake_lock(&wlock);
+
+ return 0;
+}
+
+static int adv7520_power_off(struct platform_device *pdev)
+{
+ DEV_INFO("power_off\n");
+ adv7520_comm_power(1, 1);
+ adv7520_chip_off();
+ wake_unlock(&wlock);
+ adv7520_comm_power(0, 1);
+
+ return 0;
+}
+
+
+/* AV7520 chip specific initialization */
+static void adv7520_chip_init(void)
+{
+ /* Initialize the variables used to read/write the ADV7520 chip. */
+ memset(®, 0xff, sizeof(reg));
+
+ /* Get the values from the "Fixed Registers That Must Be Set". */
+ reg[0x98] = adv7520_read_reg(hclient, 0x98);
+ reg[0x9c] = adv7520_read_reg(hclient, 0x9c);
+ reg[0x9d] = adv7520_read_reg(hclient, 0x9d);
+ reg[0xa2] = adv7520_read_reg(hclient, 0xa2);
+ reg[0xa3] = adv7520_read_reg(hclient, 0xa3);
+ reg[0xde] = adv7520_read_reg(hclient, 0xde);
+
+ /* Get the "HDMI/DVI Selection" register. */
+ reg[0xaf] = adv7520_read_reg(hclient, 0xaf);
+
+ /* Read Packet Memory I2C Address */
+ reg[0x45] = adv7520_read_reg(hclient, 0x45);
+
+ /* Hard coded values provided by ADV7520 data sheet. */
+ reg[0x98] = 0x03;
+ reg[0x9c] = 0x38;
+ reg[0x9d] = 0x61;
+ reg[0xa2] = 0x94;
+ reg[0xa3] = 0x94;
+ reg[0xde] = 0x88;
+
+ /* Set the HDMI select bit. */
+ reg[0xaf] |= 0x16;
+
+ /* Set the audio related registers. */
+ reg[0x01] = 0x00;
+ reg[0x02] = 0x2d;
+ reg[0x03] = 0x80;
+ reg[0x0a] = 0x4d;
+ reg[0x0b] = 0x0e;
+ reg[0x0c] = 0x84;
+ reg[0x0d] = 0x10;
+ reg[0x12] = 0x00;
+ reg[0x14] = 0x00;
+ reg[0x15] = 0x20;
+ reg[0x44] = 0x79;
+ reg[0x73] = 0x01;
+ reg[0x76] = 0x00;
+
+ /* Set 720p display related registers */
+ reg[0x16] = 0x00;
+
+ reg[0x18] = 0x46;
+ reg[0x55] = 0x00;
+ reg[0x3c] = 0x04;
+
+ /* Set Interrupt Mask register for HPD/HDCP */
+ reg[0x94] = 0xC0;
+#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
+ if (has_hdcp_hw_support)
+ reg[0x95] = 0xC0;
+ else
+ reg[0x95] = 0x00;
+#else
+ reg[0x95] = 0x00;
+#endif
+ adv7520_write_reg(hclient, 0x94, reg[0x94]);
+ adv7520_write_reg(hclient, 0x95, reg[0x95]);
+
+ /* Set Packet Memory I2C Address */
+ reg[0x45] = 0x74;
+
+ /* Set the values from the "Fixed Registers That Must Be Set". */
+ adv7520_write_reg(hclient, 0x98, reg[0x98]);
+ adv7520_write_reg(hclient, 0x9c, reg[0x9c]);
+ adv7520_write_reg(hclient, 0x9d, reg[0x9d]);
+ adv7520_write_reg(hclient, 0xa2, reg[0xa2]);
+ adv7520_write_reg(hclient, 0xa3, reg[0xa3]);
+ adv7520_write_reg(hclient, 0xde, reg[0xde]);
+
+ /* Set the "HDMI/DVI Selection" register. */
+ adv7520_write_reg(hclient, 0xaf, reg[0xaf]);
+
+ /* Set EDID Monitor address */
+ reg[0x43] = 0x7E;
+ adv7520_write_reg(hclient, 0x43, reg[0x43]);
+
+ /* Enable the i2s audio input. */
+ adv7520_write_reg(hclient, 0x01, reg[0x01]);
+ adv7520_write_reg(hclient, 0x02, reg[0x02]);
+ adv7520_write_reg(hclient, 0x03, reg[0x03]);
+ adv7520_write_reg(hclient, 0x0a, reg[0x0a]);
+ adv7520_write_reg(hclient, 0x0b, reg[0x0b]);
+ adv7520_write_reg(hclient, 0x0c, reg[0x0c]);
+ adv7520_write_reg(hclient, 0x0d, reg[0x0d]);
+ adv7520_write_reg(hclient, 0x12, reg[0x12]);
+ adv7520_write_reg(hclient, 0x14, reg[0x14]);
+ adv7520_write_reg(hclient, 0x15, reg[0x15]);
+ adv7520_write_reg(hclient, 0x44, reg[0x44]);
+ adv7520_write_reg(hclient, 0x73, reg[0x73]);
+ adv7520_write_reg(hclient, 0x76, reg[0x76]);
+
+ /* Enable 720p display */
+ adv7520_write_reg(hclient, 0x16, reg[0x16]);
+ adv7520_write_reg(hclient, 0x18, reg[0x18]);
+ adv7520_write_reg(hclient, 0x55, reg[0x55]);
+ adv7520_write_reg(hclient, 0x3c, reg[0x3c]);
+
+ /* Set Packet Memory address to avoid conflict
+ with Bosch Accelerometer */
+ adv7520_write_reg(hclient, 0x45, reg[0x45]);
+
+ /* Ensure chip is in low-power state */
+ adv7520_write_reg(hclient, 0x41, 0x50);
+}
+
+#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
+static void adv7520_start_hdcp(void)
+{
+ mutex_lock(&hdcp_state_mutex);
+ if (hdcp_activating) {
+ DEV_WARN("adv7520_timer: HDCP already"
+ " activating, skipping\n");
+ mutex_unlock(&hdcp_state_mutex);
+ return;
+ }
+ hdcp_activating = TRUE;
+ mutex_unlock(&hdcp_state_mutex);
+
+ del_timer(&hpd_duty_timer);
+
+ adv7520_comm_power(1, 1);
+
+ if (!enable_5v_on) {
+ dd->pd->enable_5v(1);
+ enable_5v_on = TRUE;
+ adv7520_chip_on();
+ }
+
+ /* request for HDCP */
+ reg[0xaf] = adv7520_read_reg(hclient, 0xaf);
+ reg[0xaf] |= 0x90;
+ adv7520_write_reg(hclient, 0xaf, reg[0xaf]);
+ reg[0xaf] = adv7520_read_reg(hclient, 0xaf);
+
+ reg[0xba] = adv7520_read_reg(hclient, 0xba);
+ reg[0xba] |= 0x10;
+ adv7520_write_reg(hclient, 0xba, reg[0xba]);
+ reg[0xba] = adv7520_read_reg(hclient, 0xba);
+ adv7520_comm_power(0, 1);
+
+ DEV_INFO("HDCP: reg[0xaf]=0x%02x, reg[0xba]=0x%02x, waiting for BKSV\n",
+ reg[0xaf], reg[0xba]);
+
+ /* will check for HDCP Error or BKSV ready */
+ mod_timer(&hpd_duty_timer, jiffies + HZ/2);
+}
+#endif
+
+static void adv7520_hpd_timer_w(struct work_struct *work)
+{
+ if (!external_common_state->hpd_feature_on) {
+ DEV_INFO("adv7520_timer: skipping, feature off\n");
+ return;
+ }
+
+ if ((monitor_sense & 0x4) && !external_common_state->hpd_state) {
+ int timeout;
+ DEV_DBG("adv7520_timer: Cable Detected\n");
+ adv7520_comm_power(1, 1);
+ adv7520_chip_on();
+
+ if (hpd_cable_chg_detected) {
+ hpd_cable_chg_detected = FALSE;
+ /* Ensure 5V to read EDID */
+ if (!enable_5v_on) {
+ dd->pd->enable_5v(1);
+ enable_5v_on = TRUE;
+ }
+ msleep(500);
+ timeout = (adv7520_read_reg(hclient, 0x96) & (1 << 2));
+ if (timeout) {
+ DEV_DBG("adv7520_timer: EDID-Ready..\n");
+ adv7520_read_edid();
+ } else
+ DEV_DBG("adv7520_timer: EDID TIMEOUT (C9=%02x)"
+ "\n", adv7520_read_reg(hclient, 0xC9));
+ }
+#ifdef TESTING_FORCE_480p
+ external_common_state->disp_mode_list.num_of_elements = 1;
+ external_common_state->disp_mode_list.disp_mode_list[0] =
+ HDMI_VFRMT_720x480p60_16_9;
+#endif
+ adv7520_comm_power(0, 1);
+#ifndef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
+ /* HDMI_5V_EN not needed anymore */
+ if (enable_5v_on) {
+ DEV_DBG("adv7520_timer: EDID done, no HDCP, 5V not "
+ "needed anymore\n");
+ dd->pd->enable_5v(0);
+ enable_5v_on = FALSE;
+ }
+#endif
+ change_hdmi_state(1);
+ } else if (external_common_state->hpd_state) {
+ adv7520_comm_power(1, 1);
+ adv7520_chip_off();
+ adv7520_comm_power(0, 1);
+ DEV_DBG("adv7520_timer: Cable Removed\n");
+ change_hdmi_state(0);
+ }
+}
+
+static void adv7520_hpd_timer_f(unsigned long data)
+{
+ schedule_work(&hpd_timer_work);
+}
+
+static void adv7520_isr_w(struct work_struct *work)
+{
+ static int state_count;
+ static u8 last_reg0x96;
+ u8 reg0xc8;
+ u8 reg0x96;
+#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
+ static u8 last_reg0x97;
+ u8 reg0x97 = 0;
+#endif
+ if (!external_common_state->hpd_feature_on) {
+ DEV_DBG("adv7520_irq: skipping, hpd off\n");
+ return;
+ }
+
+ adv7520_comm_power(1, 1);
+ reg0x96 = adv7520_read_reg(hclient, 0x96);
+#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
+ if (has_hdcp_hw_support) {
+ reg0x97 = adv7520_read_reg(hclient, 0x97);
+ /* Clearing the Interrupts */
+ adv7520_write_reg(hclient, 0x97, reg0x97);
+ }
+#endif
+ /* Clearing the Interrupts */
+ adv7520_write_reg(hclient, 0x96, reg0x96);
+
+ if ((reg0x96 == 0xC0) || (reg0x96 & 0x40)) {
+#ifdef DEBUG
+ unsigned int hpd_state = adv7520_read_reg(hclient, 0x42);
+#endif
+ monitor_sense = adv7520_read_reg(hclient, 0xC6);
+ DEV_DBG("adv7520_irq: reg[0x42]=%02x && reg[0xC6]=%02x\n",
+ hpd_state, monitor_sense);
+
+ if (!enable_5v_on) {
+ dd->pd->enable_5v(1);
+ enable_5v_on = TRUE;
+ }
+ if (!hpd_power_on) {
+ dd->pd->core_power(1, 1);
+ hpd_power_on = TRUE;
+ }
+
+ /* Timer for catching interrupt debouning */
+ DEV_DBG("adv7520_irq: Timer in .5sec\n");
+ hpd_cable_chg_detected = TRUE;
+ mod_timer(&hpd_timer, jiffies + HZ/2);
+ }
+#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
+ if (has_hdcp_hw_support) {
+ if (hdcp_activating) {
+ /* HDCP controller error Interrupt */
+ if (reg0x97 & 0x80) {
+ DEV_ERR("adv7520_irq: HDCP_ERROR\n");
+ state_count = 0;
+ adv7520_close_hdcp_link();
+ /* BKSV Ready interrupts */
+ } else if (reg0x97 & 0x40) {
+ DEV_INFO("adv7520_irq: BKSV keys ready, Begin"
+ " HDCP encryption\n");
+ state_count = 0;
+ schedule_work(&hdcp_handle_work);
+ } else if (++state_count > 2 && (monitor_sense & 0x4)) {
+ DEV_INFO("adv7520_irq: Still waiting for BKSV,"
+ "restart HDCP\n");
+ hdcp_activating = FALSE;
+ state_count = 0;
+ adv7520_chip_off();
+ adv7520_start_hdcp();
+ }
+ reg0xc8 = adv7520_read_reg(hclient, 0xc8);
+ DEV_INFO("adv7520_irq: DDC controller reg[0xC8]=0x%02x,"
+ "state_count=%d, monitor_sense=%x\n",
+ reg0xc8, state_count, monitor_sense);
+ } else if (!external_common_state->hdcp_active
+ && (monitor_sense & 0x4)) {
+ DEV_INFO("adv7520_irq: start HDCP with"
+ " monitor sense\n");
+ state_count = 0;
+ adv7520_start_hdcp();
+ } else
+ state_count = 0;
+ if (last_reg0x97 != reg0x97 || last_reg0x96 != reg0x96)
+ DEV_DBG("adv7520_irq: reg[0x96]=%02x "
+ "reg[0x97]=%02x: HDCP: %d\n", reg0x96, reg0x97,
+ external_common_state->hdcp_active);
+ last_reg0x97 = reg0x97;
+ } else {
+ if (last_reg0x96 != reg0x96)
+ DEV_DBG("adv7520_irq: reg[0x96]=%02x\n", reg0x96);
+ }
+#else
+ if (last_reg0x96 != reg0x96)
+ DEV_DBG("adv7520_irq: reg[0x96]=%02x\n", reg0x96);
+#endif
+ last_reg0x96 = reg0x96;
+ adv7520_comm_power(0, 1);
+}
+
+static void adv7520_hpd_duty_work(struct work_struct *work)
+{
+ if (!external_common_state->hpd_feature_on) {
+ DEV_WARN("%s: hpd feature is off, skipping\n", __func__);
+ return;
+ }
+
+ dd->pd->core_power(1, 0);
+ msleep(10);
+ adv7520_isr_w(NULL);
+ dd->pd->core_power(0, 0);
+}
+
+static void adv7520_hpd_duty_timer_f(unsigned long data)
+{
+ if (!external_common_state->hpd_feature_on) {
+ DEV_WARN("%s: hpd feature is off, skipping\n", __func__);
+ return;
+ }
+
+ mod_timer(&hpd_duty_timer, jiffies + HPD_DUTY_CYCLE*HZ);
+ schedule_work(&hpd_duty_work);
+}
+
+static const struct i2c_device_id adv7520_id[] = {
+ { ADV7520_DRV_NAME , 0},
+ {}
+};
+
+static struct msm_fb_panel_data hdmi_panel_data = {
+ .on = adv7520_power_on,
+ .off = adv7520_power_off,
+};
+
+static struct platform_device hdmi_device = {
+ .name = ADV7520_DRV_NAME ,
+ .id = 2,
+ .dev = {
+ .platform_data = &hdmi_panel_data,
+ }
+};
+
+static void adv7520_ensure_init(void)
+{
+ static boolean init_done;
+ if (!init_done) {
+ int rc = dd->pd->init_irq();
+ if (rc) {
+ DEV_ERR("adv7520_init: init_irq: %d\n", rc);
+ return;
+ }
+
+ init_done = TRUE;
+ }
+ DEV_INFO("adv7520_init: chip init\n");
+ adv7520_comm_power(1, 1);
+ adv7520_chip_init();
+ adv7520_comm_power(0, 1);
+}
+
+static int adv7520_hpd_feature(int on)
+{
+ int rc = 0;
+
+ if (!on) {
+ if (enable_5v_on) {
+ dd->pd->enable_5v(0);
+ enable_5v_on = FALSE;
+ }
+ if (hpd_power_on) {
+ dd->pd->core_power(0, 1);
+ hpd_power_on = FALSE;
+ }
+
+ DEV_DBG("adv7520_hpd: %d: stop duty timer\n", on);
+ del_timer(&hpd_timer);
+ del_timer(&hpd_duty_timer);
+ external_common_state->hpd_state = 0;
+ }
+
+ if (on) {
+ dd->pd->core_power(1, 0);
+ adv7520_ensure_init();
+
+ adv7520_comm_power(1, 1);
+ monitor_sense = adv7520_read_reg(hclient, 0xC6);
+ DEV_DBG("adv7520_irq: reg[0xC6]=%02x\n", monitor_sense);
+ adv7520_comm_power(0, 1);
+ dd->pd->core_power(0, 0);
+
+ if (monitor_sense & 0x4) {
+ if (!enable_5v_on) {
+ dd->pd->enable_5v(1);
+ enable_5v_on = TRUE;
+ }
+ if (!hpd_power_on) {
+ dd->pd->core_power(1, 1);
+ hpd_power_on = TRUE;
+ }
+
+ hpd_cable_chg_detected = TRUE;
+ mod_timer(&hpd_timer, jiffies + HZ/2);
+ }
+
+ DEV_DBG("adv7520_hpd: %d start duty timer\n", on);
+ mod_timer(&hpd_duty_timer, jiffies + HZ/100);
+ }
+
+ DEV_INFO("adv7520_hpd: %d\n", on);
+ return rc;
+}
+
+static int __devinit
+ adv7520_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ int rc;
+ struct platform_device *fb_dev;
+
+ dd = kzalloc(sizeof *dd, GFP_KERNEL);
+ if (!dd) {
+ rc = -ENOMEM;
+ goto probe_exit;
+ }
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ return -ENODEV;
+
+ external_common_state->dev = &client->dev;
+
+ /* Init real i2c_client */
+ hclient = client;
+
+ i2c_set_clientdata(client, dd);
+ dd->pd = client->dev.platform_data;
+ if (!dd->pd) {
+ rc = -ENODEV;
+ goto probe_free;
+ }
+
+ INIT_WORK(&dd->isr_work, adv7520_isr_w);
+ INIT_WORK(&hpd_timer_work, adv7520_hpd_timer_w);
+#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
+ if (dd->pd->check_hdcp_hw_support)
+ has_hdcp_hw_support = dd->pd->check_hdcp_hw_support();
+
+ if (has_hdcp_hw_support)
+ INIT_WORK(&hdcp_handle_work, adv7520_hdcp_enable);
+ else
+ DEV_INFO("%s: no hdcp hw support.\n", __func__);
+#endif
+
+ init_timer(&hpd_timer);
+ hpd_timer.function = adv7520_hpd_timer_f;
+ hpd_timer.data = (unsigned long)NULL;
+ hpd_timer.expires = 0xffffffff;
+ add_timer(&hpd_timer);
+
+ external_common_state->hpd_feature = adv7520_hpd_feature;
+ DEV_INFO("adv7520_probe: HPD detection on request\n");
+ init_timer(&hpd_duty_timer);
+ hpd_duty_timer.function = adv7520_hpd_duty_timer_f;
+ hpd_duty_timer.data = (unsigned long)NULL;
+ hpd_duty_timer.expires = 0xffffffff;
+ add_timer(&hpd_duty_timer);
+ INIT_WORK(&hpd_duty_work, adv7520_hpd_duty_work);
+ DEV_INFO("adv7520_probe: HPD detection ON (duty)\n");
+
+ fb_dev = msm_fb_add_device(&hdmi_device);
+
+ if (fb_dev) {
+ rc = external_common_state_create(fb_dev);
+ if (rc)
+ goto probe_free;
+ } else
+ DEV_ERR("adv7520_probe: failed to add fb device\n");
+
+ return 0;
+
+probe_free:
+ kfree(dd);
+ dd = NULL;
+probe_exit:
+ return rc;
+
+}
+
+static int __devexit adv7520_remove(struct i2c_client *client)
+{
+ if (!client->adapter) {
+ DEV_ERR("%s: No HDMI Device\n", __func__);
+ return -ENODEV;
+ }
+ wake_lock_destroy(&wlock);
+ kfree(dd);
+ dd = NULL;
+ return 0;
+}
+
+#ifdef CONFIG_SUSPEND
+static int adv7520_i2c_suspend(struct device *dev)
+{
+ DEV_INFO("%s\n", __func__);
+
+ ++suspend_count;
+
+ if (external_common_state->hpd_feature_on) {
+ DEV_DBG("%s: stop duty timer\n", __func__);
+ del_timer(&hpd_duty_timer);
+ del_timer(&hpd_timer);
+ }
+
+ /* Turn off LDO8 and go into low-power state */
+ if (chip_power_on) {
+ DEV_DBG("%s: turn off power\n", __func__);
+ adv7520_comm_power(1, 1);
+ adv7520_write_reg(hclient, 0x41, 0x50);
+ adv7520_comm_power(0, 1);
+ dd->pd->core_power(0, 1);
+ }
+
+ return 0;
+}
+
+static int adv7520_i2c_resume(struct device *dev)
+{
+ DEV_INFO("%s\n", __func__);
+
+ /* Turn on LDO8 and go into normal-power state */
+ if (chip_power_on) {
+ DEV_DBG("%s: turn on power\n", __func__);
+ dd->pd->core_power(1, 1);
+ adv7520_comm_power(1, 1);
+ adv7520_write_reg(hclient, 0x41, 0x10);
+ adv7520_comm_power(0, 1);
+ }
+
+ if (external_common_state->hpd_feature_on) {
+ DEV_DBG("%s: start duty timer\n", __func__);
+ mod_timer(&hpd_duty_timer, jiffies + HPD_DUTY_CYCLE*HZ);
+ }
+
+ return 0;
+}
+#else
+#define adv7520_i2c_suspend NULL
+#define adv7520_i2c_resume NULL
+#endif
+
+static const struct dev_pm_ops adv7520_device_pm_ops = {
+ .suspend = adv7520_i2c_suspend,
+ .resume = adv7520_i2c_resume,
+};
+
+static struct i2c_driver hdmi_i2c_driver = {
+ .driver = {
+ .name = ADV7520_DRV_NAME,
+ .owner = THIS_MODULE,
+ .pm = &adv7520_device_pm_ops,
+ },
+ .probe = adv7520_probe,
+ .id_table = adv7520_id,
+ .remove = __devexit_p(adv7520_remove),
+};
+
+static int __init adv7520_init(void)
+{
+ int rc;
+
+ pr_info("%s\n", __func__);
+ external_common_state = &hdmi_common;
+ external_common_state->video_resolution = HDMI_VFRMT_1280x720p60_16_9;
+ HDMI_SETUP_LUT(640x480p60_4_3); /* 25.20MHz */
+ HDMI_SETUP_LUT(720x480p60_16_9); /* 27.03MHz */
+ HDMI_SETUP_LUT(1280x720p60_16_9); /* 74.25MHz */
+
+ HDMI_SETUP_LUT(720x576p50_16_9); /* 27.00MHz */
+ HDMI_SETUP_LUT(1280x720p50_16_9); /* 74.25MHz */
+
+ hdmi_common_init_panel_info(&hdmi_panel_data.panel_info);
+
+ rc = i2c_add_driver(&hdmi_i2c_driver);
+ if (rc) {
+ pr_err("hdmi_init FAILED: i2c_add_driver rc=%d\n", rc);
+ goto init_exit;
+ }
+
+ if (machine_is_msm7x30_surf() || machine_is_msm8x55_surf()) {
+ short *hdtv_mux = (short *)ioremap(0x8e000170 , 0x100);
+ *hdtv_mux++ = 0x020b;
+ *hdtv_mux = 0x8000;
+ iounmap(hdtv_mux);
+ }
+ wake_lock_init(&wlock, WAKE_LOCK_IDLE, "hdmi_active");
+
+ return 0;
+
+init_exit:
+ return rc;
+}
+
+static void __exit adv7520_exit(void)
+{
+ i2c_del_driver(&hdmi_i2c_driver);
+}
+
+module_init(adv7520_init);
+module_exit(adv7520_exit);
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("0.1");
+MODULE_AUTHOR("Qualcomm Innovation Center, Inc.");
+MODULE_DESCRIPTION("ADV7520 HDMI driver");
diff --git a/drivers/video/msm/ebi2_l2f.c b/drivers/video/msm/ebi2_l2f.c
new file mode 100644
index 0000000..767b802
--- /dev/null
+++ b/drivers/video/msm/ebi2_l2f.c
@@ -0,0 +1,566 @@
+/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+
+#include <linux/memory.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+/* The following are for MSM5100 on Gator
+*/
+#ifdef FEATURE_PM1000
+#include "pm1000.h"
+#endif /* FEATURE_PM1000 */
+/* The following are for MSM6050 on Bambi
+*/
+#ifdef FEATURE_PMIC_LCDKBD_LED_DRIVER
+#include "pm.h"
+#endif /* FEATURE_PMIC_LCDKBD_LED_DRIVER */
+
+#ifdef DISP_DEVICE_18BPP
+#undef DISP_DEVICE_18BPP
+#define DISP_DEVICE_16BPP
+#endif
+
+#define QCIF_WIDTH 176
+#define QCIF_HEIGHT 220
+
+static void *DISP_CMD_PORT;
+static void *DISP_DATA_PORT;
+
+#define DISP_CMD_DISON 0xaf
+#define DISP_CMD_DISOFF 0xae
+#define DISP_CMD_DISNOR 0xa6
+#define DISP_CMD_DISINV 0xa7
+#define DISP_CMD_DISCTL 0xca
+#define DISP_CMD_GCP64 0xcb
+#define DISP_CMD_GCP16 0xcc
+#define DISP_CMD_GSSET 0xcd
+#define DISP_GS_2 0x02
+#define DISP_GS_16 0x01
+#define DISP_GS_64 0x00
+#define DISP_CMD_SLPIN 0x95
+#define DISP_CMD_SLPOUT 0x94
+#define DISP_CMD_SD_PSET 0x75
+#define DISP_CMD_MD_PSET 0x76
+#define DISP_CMD_SD_CSET 0x15
+#define DISP_CMD_MD_CSET 0x16
+#define DISP_CMD_DATCTL 0xbc
+#define DISP_DATCTL_666 0x08
+#define DISP_DATCTL_565 0x28
+#define DISP_DATCTL_444 0x38
+#define DISP_CMD_RAMWR 0x5c
+#define DISP_CMD_RAMRD 0x5d
+#define DISP_CMD_PTLIN 0xa8
+#define DISP_CMD_PTLOUT 0xa9
+#define DISP_CMD_ASCSET 0xaa
+#define DISP_CMD_SCSTART 0xab
+#define DISP_CMD_VOLCTL 0xc6
+#define DISP_VOLCTL_TONE 0x80
+#define DISP_CMD_NOp 0x25
+#define DISP_CMD_OSSEL 0xd0
+#define DISP_CMD_3500KSET 0xd1
+#define DISP_CMD_3500KEND 0xd2
+#define DISP_CMD_14MSET 0xd3
+#define DISP_CMD_14MEND 0xd4
+
+#define DISP_CMD_OUT(cmd) outpw(DISP_CMD_PORT, cmd);
+
+#define DISP_DATA_OUT(data) outpw(DISP_DATA_PORT, data);
+
+#define DISP_DATA_IN() inpw(DISP_DATA_PORT);
+
+/* Epson device column number starts at 2
+*/
+#define DISP_SET_RECT(ulhc_row, lrhc_row, ulhc_col, lrhc_col) \
+ DISP_CMD_OUT(DISP_CMD_SD_PSET) \
+ DISP_DATA_OUT((ulhc_row) & 0xFF) \
+ DISP_DATA_OUT((ulhc_row) >> 8) \
+ DISP_DATA_OUT((lrhc_row) & 0xFF) \
+ DISP_DATA_OUT((lrhc_row) >> 8) \
+ DISP_CMD_OUT(DISP_CMD_SD_CSET) \
+ DISP_DATA_OUT(((ulhc_col)+2) & 0xFF) \
+ DISP_DATA_OUT(((ulhc_col)+2) >> 8) \
+ DISP_DATA_OUT(((lrhc_col)+2) & 0xFF) \
+ DISP_DATA_OUT(((lrhc_col)+2) >> 8)
+
+#define DISP_MIN_CONTRAST 0
+#define DISP_MAX_CONTRAST 127
+#define DISP_DEFAULT_CONTRAST 80
+
+#define DISP_MIN_BACKLIGHT 0
+#define DISP_MAX_BACKLIGHT 15
+#define DISP_DEFAULT_BACKLIGHT 2
+
+#define WAIT_SEC(sec) mdelay((sec)/1000)
+
+static word disp_area_start_row;
+static word disp_area_end_row;
+static byte disp_contrast = DISP_DEFAULT_CONTRAST;
+static boolean disp_powered_up;
+static boolean disp_initialized = FALSE;
+/* For some reason the contrast set at init time is not good. Need to do
+ * it again
+ */
+static boolean display_on = FALSE;
+static void epsonQcif_disp_init(struct platform_device *pdev);
+static void epsonQcif_disp_set_contrast(word contrast);
+static void epsonQcif_disp_set_display_area(word start_row, word end_row);
+static int epsonQcif_disp_off(struct platform_device *pdev);
+static int epsonQcif_disp_on(struct platform_device *pdev);
+static void epsonQcif_disp_set_rect(int x, int y, int xres, int yres);
+
+volatile word databack;
+static void epsonQcif_disp_init(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+
+ int i;
+
+ if (disp_initialized)
+ return;
+
+ mfd = platform_get_drvdata(pdev);
+
+ DISP_CMD_PORT = mfd->cmd_port;
+ DISP_DATA_PORT = mfd->data_port;
+
+ /* Sleep in */
+ DISP_CMD_OUT(DISP_CMD_SLPIN);
+
+ /* Display off */
+ DISP_CMD_OUT(DISP_CMD_DISOFF);
+
+ /* Display normal */
+ DISP_CMD_OUT(DISP_CMD_DISNOR);
+
+ /* Set data mode */
+ DISP_CMD_OUT(DISP_CMD_DATCTL);
+ DISP_DATA_OUT(DISP_DATCTL_565);
+
+ /* Set display timing */
+ DISP_CMD_OUT(DISP_CMD_DISCTL);
+ DISP_DATA_OUT(0x1c); /* p1 */
+ DISP_DATA_OUT(0x02); /* p1 */
+ DISP_DATA_OUT(0x82); /* p2 */
+ DISP_DATA_OUT(0x00); /* p3 */
+ DISP_DATA_OUT(0x00); /* p4 */
+ DISP_DATA_OUT(0xe0); /* p5 */
+ DISP_DATA_OUT(0x00); /* p5 */
+ DISP_DATA_OUT(0xdc); /* p6 */
+ DISP_DATA_OUT(0x00); /* p6 */
+ DISP_DATA_OUT(0x02); /* p7 */
+ DISP_DATA_OUT(0x00); /* p8 */
+
+ /* Set 64 gray scale level */
+ DISP_CMD_OUT(DISP_CMD_GCP64);
+ DISP_DATA_OUT(0x08); /* p01 */
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x2a); /* p02 */
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x4e); /* p03 */
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x6b); /* p04 */
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x88); /* p05 */
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0xa3); /* p06 */
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0xba); /* p07 */
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0xd1); /* p08 */
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0xe5); /* p09 */
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0xf3); /* p10 */
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x03); /* p11 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x13); /* p12 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x22); /* p13 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x2f); /* p14 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x3b); /* p15 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x46); /* p16 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x51); /* p17 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x5b); /* p18 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x64); /* p19 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x6c); /* p20 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x74); /* p21 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x7c); /* p22 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x83); /* p23 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x8a); /* p24 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x91); /* p25 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x98); /* p26 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x9f); /* p27 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xa6); /* p28 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xac); /* p29 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xb2); /* p30 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xb7); /* p31 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xbc); /* p32 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xc1); /* p33 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xc6); /* p34 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xcb); /* p35 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xd0); /* p36 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xd4); /* p37 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xd8); /* p38 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xdc); /* p39 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xe0); /* p40 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xe4); /* p41 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xe8); /* p42 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xec); /* p43 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xf0); /* p44 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xf4); /* p45 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xf8); /* p46 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xfb); /* p47 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xfe); /* p48 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x01); /* p49 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x03); /* p50 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x05); /* p51 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x07); /* p52 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x09); /* p53 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x0b); /* p54 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x0d); /* p55 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x0f); /* p56 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x11); /* p57 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x13); /* p58 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x15); /* p59 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x17); /* p60 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x19); /* p61 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x1b); /* p62 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x1c); /* p63 */
+ DISP_DATA_OUT(0x02);
+
+ /* Set 16 gray scale level */
+ DISP_CMD_OUT(DISP_CMD_GCP16);
+ DISP_DATA_OUT(0x1a); /* p01 */
+ DISP_DATA_OUT(0x32); /* p02 */
+ DISP_DATA_OUT(0x42); /* p03 */
+ DISP_DATA_OUT(0x4c); /* p04 */
+ DISP_DATA_OUT(0x58); /* p05 */
+ DISP_DATA_OUT(0x5f); /* p06 */
+ DISP_DATA_OUT(0x66); /* p07 */
+ DISP_DATA_OUT(0x6b); /* p08 */
+ DISP_DATA_OUT(0x70); /* p09 */
+ DISP_DATA_OUT(0x74); /* p10 */
+ DISP_DATA_OUT(0x78); /* p11 */
+ DISP_DATA_OUT(0x7b); /* p12 */
+ DISP_DATA_OUT(0x7e); /* p13 */
+ DISP_DATA_OUT(0x80); /* p14 */
+ DISP_DATA_OUT(0x82); /* p15 */
+
+ /* Set DSP column */
+ DISP_CMD_OUT(DISP_CMD_MD_CSET);
+ DISP_DATA_OUT(0xff);
+ DISP_DATA_OUT(0x03);
+ DISP_DATA_OUT(0xff);
+ DISP_DATA_OUT(0x03);
+
+ /* Set DSP page */
+ DISP_CMD_OUT(DISP_CMD_MD_PSET);
+ DISP_DATA_OUT(0xff);
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xff);
+ DISP_DATA_OUT(0x01);
+
+ /* Set ARM column */
+ DISP_CMD_OUT(DISP_CMD_SD_CSET);
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT((QCIF_WIDTH + 1) & 0xFF);
+ DISP_DATA_OUT((QCIF_WIDTH + 1) >> 8);
+
+ /* Set ARM page */
+ DISP_CMD_OUT(DISP_CMD_SD_PSET);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT((QCIF_HEIGHT - 1) & 0xFF);
+ DISP_DATA_OUT((QCIF_HEIGHT - 1) >> 8);
+
+ /* Set 64 gray scales */
+ DISP_CMD_OUT(DISP_CMD_GSSET);
+ DISP_DATA_OUT(DISP_GS_64);
+
+ DISP_CMD_OUT(DISP_CMD_OSSEL);
+ DISP_DATA_OUT(0);
+
+ /* Sleep out */
+ DISP_CMD_OUT(DISP_CMD_SLPOUT);
+
+ WAIT_SEC(40000);
+
+ /* Initialize power IC */
+ DISP_CMD_OUT(DISP_CMD_VOLCTL);
+ DISP_DATA_OUT(DISP_VOLCTL_TONE);
+
+ WAIT_SEC(40000);
+
+ /* Set electronic volume, d'xx */
+ DISP_CMD_OUT(DISP_CMD_VOLCTL);
+ DISP_DATA_OUT(DISP_DEFAULT_CONTRAST); /* value from 0 to 127 */
+
+ /* Initialize display data */
+ DISP_SET_RECT(0, (QCIF_HEIGHT - 1), 0, (QCIF_WIDTH - 1));
+ DISP_CMD_OUT(DISP_CMD_RAMWR);
+ for (i = 0; i < QCIF_HEIGHT * QCIF_WIDTH; i++)
+ DISP_DATA_OUT(0xffff);
+
+ DISP_CMD_OUT(DISP_CMD_RAMRD);
+ databack = DISP_DATA_IN();
+ databack = DISP_DATA_IN();
+ databack = DISP_DATA_IN();
+ databack = DISP_DATA_IN();
+
+ WAIT_SEC(80000);
+
+ DISP_CMD_OUT(DISP_CMD_DISON);
+
+ disp_area_start_row = 0;
+ disp_area_end_row = QCIF_HEIGHT - 1;
+ disp_powered_up = TRUE;
+ disp_initialized = TRUE;
+ epsonQcif_disp_set_display_area(0, QCIF_HEIGHT - 1);
+ display_on = TRUE;
+}
+
+static void epsonQcif_disp_set_rect(int x, int y, int xres, int yres)
+{
+ if (!disp_initialized)
+ return;
+
+ DISP_SET_RECT(y, y + yres - 1, x, x + xres - 1);
+ DISP_CMD_OUT(DISP_CMD_RAMWR);
+}
+
+static void epsonQcif_disp_set_display_area(word start_row, word end_row)
+{
+ if (!disp_initialized)
+ return;
+
+ if ((start_row == disp_area_start_row)
+ && (end_row == disp_area_end_row))
+ return;
+ disp_area_start_row = start_row;
+ disp_area_end_row = end_row;
+
+ /* Range checking
+ */
+ if (end_row >= QCIF_HEIGHT)
+ end_row = QCIF_HEIGHT - 1;
+ if (start_row > end_row)
+ start_row = end_row;
+
+ /* When display is not the full screen, gray scale is set to
+ ** 2; otherwise it is set to 64.
+ */
+ if ((start_row == 0) && (end_row == (QCIF_HEIGHT - 1))) {
+ /* The whole screen */
+ DISP_CMD_OUT(DISP_CMD_PTLOUT);
+ WAIT_SEC(10000);
+ DISP_CMD_OUT(DISP_CMD_DISOFF);
+ WAIT_SEC(100000);
+ DISP_CMD_OUT(DISP_CMD_GSSET);
+ DISP_DATA_OUT(DISP_GS_64);
+ WAIT_SEC(100000);
+ DISP_CMD_OUT(DISP_CMD_DISON);
+ } else {
+ /* partial screen */
+ DISP_CMD_OUT(DISP_CMD_PTLIN);
+ DISP_DATA_OUT(start_row);
+ DISP_DATA_OUT(start_row >> 8);
+ DISP_DATA_OUT(end_row);
+ DISP_DATA_OUT(end_row >> 8);
+ DISP_CMD_OUT(DISP_CMD_GSSET);
+ DISP_DATA_OUT(DISP_GS_2);
+ }
+}
+
+static int epsonQcif_disp_off(struct platform_device *pdev)
+{
+ if (!disp_initialized)
+ epsonQcif_disp_init(pdev);
+
+ if (display_on) {
+ DISP_CMD_OUT(DISP_CMD_DISOFF);
+ DISP_CMD_OUT(DISP_CMD_SLPIN);
+ display_on = FALSE;
+ }
+
+ return 0;
+}
+
+static int epsonQcif_disp_on(struct platform_device *pdev)
+{
+ if (!disp_initialized)
+ epsonQcif_disp_init(pdev);
+
+ if (!display_on) {
+ DISP_CMD_OUT(DISP_CMD_SLPOUT);
+ WAIT_SEC(40000);
+ DISP_CMD_OUT(DISP_CMD_DISON);
+ epsonQcif_disp_set_contrast(disp_contrast);
+ display_on = TRUE;
+ }
+
+ return 0;
+}
+
+static void epsonQcif_disp_set_contrast(word contrast)
+{
+ if (!disp_initialized)
+ return;
+
+ /* Initialize power IC, d'24 */
+ DISP_CMD_OUT(DISP_CMD_VOLCTL);
+ DISP_DATA_OUT(DISP_VOLCTL_TONE);
+
+ WAIT_SEC(40000);
+
+ /* Set electronic volume, d'xx */
+ DISP_CMD_OUT(DISP_CMD_VOLCTL);
+ if (contrast > 127)
+ contrast = 127;
+ DISP_DATA_OUT(contrast); /* value from 0 to 127 */
+ disp_contrast = (byte) contrast;
+} /* End disp_set_contrast */
+
+static void epsonQcif_disp_clear_screen_area(
+ word start_row, word end_row, word start_column, word end_column) {
+ int32 i;
+
+ /* Clear the display screen */
+ DISP_SET_RECT(start_row, end_row, start_column, end_column);
+ DISP_CMD_OUT(DISP_CMD_RAMWR);
+ i = (end_row - start_row + 1) * (end_column - start_column + 1);
+ for (; i > 0; i--)
+ DISP_DATA_OUT(0xffff);
+}
+
+static int __init epsonQcif_probe(struct platform_device *pdev)
+{
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = epsonQcif_probe,
+ .driver = {
+ .name = "ebi2_epson_qcif",
+ },
+};
+
+static struct msm_fb_panel_data epsonQcif_panel_data = {
+ .on = epsonQcif_disp_on,
+ .off = epsonQcif_disp_off,
+ .set_rect = epsonQcif_disp_set_rect,
+};
+
+static struct platform_device this_device = {
+ .name = "ebi2_epson_qcif",
+ .id = 0,
+ .dev = {
+ .platform_data = &epsonQcif_panel_data,
+ }
+};
+
+static int __init epsonQcif_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+ ret = platform_driver_register(&this_driver);
+ if (!ret) {
+ pinfo = &epsonQcif_panel_data.panel_info;
+ pinfo->xres = QCIF_WIDTH;
+ pinfo->yres = QCIF_HEIGHT;
+ MSM_FB_SINGLE_MODE_PANEL(pinfo);
+ pinfo->type = EBI2_PANEL;
+ pinfo->pdest = DISPLAY_2;
+ pinfo->wait_cycle = 0x808000;
+ pinfo->bpp = 16;
+ pinfo->fb_num = 2;
+ pinfo->lcd.vsync_enable = FALSE;
+
+ ret = platform_device_register(&this_device);
+ if (ret)
+ platform_driver_unregister(&this_driver);
+ }
+
+ return ret;
+}
+
+module_init(epsonQcif_init);
diff --git a/drivers/video/msm/ebi2_lcd.c b/drivers/video/msm/ebi2_lcd.c
new file mode 100644
index 0000000..68590af
--- /dev/null
+++ b/drivers/video/msm/ebi2_lcd.c
@@ -0,0 +1,268 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
+#include <linux/debugfs.h>
+
+#include "msm_fb.h"
+
+static int ebi2_lcd_probe(struct platform_device *pdev);
+static int ebi2_lcd_remove(struct platform_device *pdev);
+
+static int ebi2_lcd_runtime_suspend(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: suspending...\n");
+ return 0;
+}
+
+static int ebi2_lcd_runtime_resume(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: resuming...\n");
+ return 0;
+}
+
+static struct dev_pm_ops ebi2_lcd_dev_pm_ops = {
+ .runtime_suspend = ebi2_lcd_runtime_suspend,
+ .runtime_resume = ebi2_lcd_runtime_resume,
+};
+
+static struct platform_driver ebi2_lcd_driver = {
+ .probe = ebi2_lcd_probe,
+ .remove = ebi2_lcd_remove,
+ .suspend = NULL,
+ .suspend_late = NULL,
+ .resume_early = NULL,
+ .resume = NULL,
+ .shutdown = NULL,
+ .driver = {
+ .name = "ebi2_lcd",
+ .pm = &ebi2_lcd_dev_pm_ops,
+ },
+};
+
+static void *ebi2_base;
+static void *ebi2_lcd_cfg0;
+static void *ebi2_lcd_cfg1;
+static void __iomem *lcd01_base;
+static void __iomem *lcd02_base;
+static int ebi2_lcd_resource_initialized;
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+
+static int ebi2_lcd_probe(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct platform_device *mdp_dev = NULL;
+ struct msm_fb_panel_data *pdata = NULL;
+ int rc, i;
+
+ if (pdev->id == 0) {
+ for (i = 0; i < pdev->num_resources; i++) {
+ if (!strncmp(pdev->resource[i].name, "base", 4)) {
+ ebi2_base = ioremap(pdev->resource[i].start,
+ pdev->resource[i].end -
+ pdev->resource[i].start + 1);
+ if (!ebi2_base) {
+ printk(KERN_ERR
+ "ebi2_base ioremap failed!\n");
+ return -ENOMEM;
+ }
+ ebi2_lcd_cfg0 = (void *)(ebi2_base + 0x20);
+ ebi2_lcd_cfg1 = (void *)(ebi2_base + 0x24);
+ } else if (!strncmp(pdev->resource[i].name,
+ "lcd01", 5)) {
+ lcd01_base = ioremap(pdev->resource[i].start,
+ pdev->resource[i].end -
+ pdev->resource[i].start + 1);
+ if (!lcd01_base) {
+ printk(KERN_ERR
+ "lcd01_base ioremap failed!\n");
+ return -ENOMEM;
+ }
+ } else if (!strncmp(pdev->resource[i].name,
+ "lcd02", 5)) {
+ lcd02_base = ioremap(pdev->resource[i].start,
+ pdev->resource[i].end -
+ pdev->resource[i].start + 1);
+ if (!lcd02_base) {
+ printk(KERN_ERR
+ "lcd02_base ioremap failed!\n");
+ return -ENOMEM;
+ }
+ }
+ }
+ ebi2_lcd_resource_initialized = 1;
+ return 0;
+ }
+
+ if (!ebi2_lcd_resource_initialized)
+ return -EPERM;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+ return -ENOMEM;
+
+ if (ebi2_base == NULL)
+ return -ENOMEM;
+
+ mdp_dev = platform_device_alloc("mdp", pdev->id);
+ if (!mdp_dev)
+ return -ENOMEM;
+
+ /* link to the latest pdev */
+ mfd->pdev = mdp_dev;
+ mfd->dest = DISPLAY_LCD;
+
+ /* add panel data */
+ if (platform_device_add_data
+ (mdp_dev, pdev->dev.platform_data,
+ sizeof(struct msm_fb_panel_data))) {
+ printk(KERN_ERR "ebi2_lcd_probe: platform_device_add_data failed!\n");
+ platform_device_put(mdp_dev);
+ return -ENOMEM;
+ }
+
+ /* data chain */
+ pdata = mdp_dev->dev.platform_data;
+ pdata->on = panel_next_on;
+ pdata->off = panel_next_off;
+ pdata->next = pdev;
+
+ /* get/set panel specific fb info */
+ mfd->panel_info = pdata->panel_info;
+
+ if (mfd->panel_info.bpp == 24)
+ mfd->fb_imgType = MDP_RGB_888;
+ else
+ mfd->fb_imgType = MDP_RGB_565;
+
+ /* config msm ebi2 lcd register */
+ if (mfd->panel_info.pdest == DISPLAY_1) {
+ outp32(ebi2_base,
+ (inp32(ebi2_base) & (~(EBI2_PRIM_LCD_CLR))) |
+ EBI2_PRIM_LCD_SEL);
+ /*
+ * current design has one set of cfg0/1 register to control
+ * both EBI2 channels. so, we're using the PRIM channel to
+ * configure both.
+ */
+ outp32(ebi2_lcd_cfg0, mfd->panel_info.wait_cycle);
+ if (mfd->panel_info.bpp == 18)
+ outp32(ebi2_lcd_cfg1, 0x01000000);
+ else
+ outp32(ebi2_lcd_cfg1, 0x0);
+ } else {
+#ifdef DEBUG_EBI2_LCD
+ /*
+ * confliting with QCOM SURF FPGA CS.
+ * OEM should enable below for their CS mapping
+ */
+ outp32(ebi2_base, (inp32(ebi2_base)&(~(EBI2_SECD_LCD_CLR)))
+ |EBI2_SECD_LCD_SEL);
+#endif
+ }
+
+ /*
+ * map cs (chip select) address
+ */
+ if (mfd->panel_info.pdest == DISPLAY_1) {
+ mfd->cmd_port = lcd01_base;
+ mfd->data_port =
+ (void *)((uint32) mfd->cmd_port + EBI2_PRIM_LCD_RS_PIN);
+ mfd->data_port_phys =
+ (void *)(LCD_PRIM_BASE_PHYS + EBI2_PRIM_LCD_RS_PIN);
+ } else {
+ mfd->cmd_port = lcd01_base;
+ mfd->data_port =
+ (void *)((uint32) mfd->cmd_port + EBI2_SECD_LCD_RS_PIN);
+ mfd->data_port_phys =
+ (void *)(LCD_SECD_BASE_PHYS + EBI2_SECD_LCD_RS_PIN);
+ }
+
+ /*
+ * set driver data
+ */
+ platform_set_drvdata(mdp_dev, mfd);
+
+ /*
+ * register in mdp driver
+ */
+ rc = platform_device_add(mdp_dev);
+ if (rc) {
+ goto ebi2_lcd_probe_err;
+ }
+
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+
+ pdev_list[pdev_list_cnt++] = pdev;
+ return 0;
+
+ ebi2_lcd_probe_err:
+ platform_device_put(mdp_dev);
+ return rc;
+}
+
+static int ebi2_lcd_remove(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return 0;
+
+ if (mfd->key != MFD_KEY)
+ return 0;
+
+ iounmap(mfd->cmd_port);
+ pm_runtime_disable(&pdev->dev);
+ return 0;
+}
+
+static int ebi2_lcd_register_driver(void)
+{
+ return platform_driver_register(&ebi2_lcd_driver);
+}
+
+static int __init ebi2_lcd_driver_init(void)
+{
+ return ebi2_lcd_register_driver();
+}
+
+module_init(ebi2_lcd_driver_init);
diff --git a/drivers/video/msm/ebi2_tmd20.c b/drivers/video/msm/ebi2_tmd20.c
new file mode 100644
index 0000000..280373f
--- /dev/null
+++ b/drivers/video/msm/ebi2_tmd20.c
@@ -0,0 +1,1120 @@
+/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+
+#include <linux/memory.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+/* #define TMD20QVGA_LCD_18BPP */
+#define QVGA_WIDTH 240
+#define QVGA_HEIGHT 320
+
+#ifdef TMD20QVGA_LCD_18BPP
+#define DISP_QVGA_18BPP(x) ((((x)<<2) & 0x3FC00)|(( (x)<<1)& 0x1FE))
+#define DISP_REG(name) uint32 register_##name;
+#define OUTPORT(x, y) outpdw(x, y)
+#define INPORT(x) inpdw(x)
+#else
+#define DISP_QVGA_18BPP(x) (x)
+#define DISP_REG(name) uint16 register_##name;
+#define OUTPORT(x, y) outpw(x, y)
+#define INPORT(x) intpw(x)
+#endif
+
+static void *DISP_CMD_PORT;
+static void *DISP_DATA_PORT;
+
+#define DISP_RNTI 0x10
+
+#define DISP_CMD_OUT(cmd) OUTPORT(DISP_CMD_PORT, DISP_QVGA_18BPP(cmd))
+#define DISP_DATA_OUT(data) OUTPORT(DISP_DATA_PORT, data)
+#define DISP_DATA_IN() INPORT(DISP_DATA_PORT)
+
+#if (defined(TMD20QVGA_LCD_18BPP))
+#define DISP_DATA_OUT_16TO18BPP(x) \
+ DISP_DATA_OUT((((x)&0xf800)<<2|((x)&0x80000)>>3) \
+ | (((x)&0x7e0)<<1) \
+ | (((x)&0x1F)<<1|((x)&0x10)>>4))
+#else
+#define DISP_DATA_OUT_16TO18BPP(x) \
+ DISP_DATA_OUT(x)
+#endif
+
+#define DISP_WRITE_OUT(addr, data) \
+ register_##addr = DISP_QVGA_18BPP(data); \
+ DISP_CMD_OUT(addr); \
+ DISP_DATA_OUT(register_##addr);
+
+#define DISP_UPDATE_VALUE(addr, bitmask, data) \
+ DISP_WRITE_OUT(##addr, (register_##addr & ~(bitmask)) | (data));
+
+#define DISP_VAL_IF(bitvalue, bitmask) \
+ ((bitvalue) ? (bitmask) : 0)
+
+/* QVGA = 256 x 320 */
+/* actual display is 240 x 320...offset by 0x10 */
+#define DISP_ROW_COL_TO_ADDR(row, col) ((row) * 0x100 + col)
+#define DISP_SET_RECT(ulhc_row, lrhc_row, ulhc_col, lrhc_col) \
+ { \
+ DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_1_ADDR, (ulhc_col) + tmd20qvga_panel_offset); \
+ DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_2_ADDR, (lrhc_col) + tmd20qvga_panel_offset); \
+ DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_1_ADDR, (ulhc_row)); \
+ DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_2_ADDR, (lrhc_row)); \
+ DISP_WRITE_OUT(DISP_RAM_ADDR_SET_1_ADDR, (ulhc_col) + tmd20qvga_panel_offset); \
+ DISP_WRITE_OUT(DISP_RAM_ADDR_SET_2_ADDR, (ulhc_row)); \
+ }
+
+#define WAIT_MSEC(msec) mdelay(msec)
+
+/*
+ * TMD QVGA Address
+ */
+/* Display Control */
+#define DISP_START_OSCILLATION_ADDR 0x000
+DISP_REG(DISP_START_OSCILLATION_ADDR)
+#define DISP_DRIVER_OUTPUT_CTL_ADDR 0x001
+ DISP_REG(DISP_DRIVER_OUTPUT_CTL_ADDR)
+#define DISP_LCD_DRIVING_SIG_ADDR 0x002
+ DISP_REG(DISP_LCD_DRIVING_SIG_ADDR)
+#define DISP_ENTRY_MODE_ADDR 0x003
+ DISP_REG(DISP_ENTRY_MODE_ADDR)
+#define DISP_DISPLAY_CTL_1_ADDR 0x007
+ DISP_REG(DISP_DISPLAY_CTL_1_ADDR)
+#define DISP_DISPLAY_CTL_2_ADDR 0x008
+ DISP_REG(DISP_DISPLAY_CTL_2_ADDR)
+
+/* DISPLAY MODE 0x009 partial display not supported */
+#define DISP_POWER_SUPPLY_INTF_ADDR 0x00A
+ DISP_REG(DISP_POWER_SUPPLY_INTF_ADDR)
+
+/* DISPLAY MODE 0x00B xZoom feature is not supported */
+#define DISP_EXT_DISPLAY_CTL_1_ADDR 0x00C
+ DISP_REG(DISP_EXT_DISPLAY_CTL_1_ADDR)
+
+#define DISP_FRAME_CYCLE_CTL_ADDR 0x00D
+ DISP_REG(DISP_FRAME_CYCLE_CTL_ADDR)
+
+#define DISP_EXT_DISPLAY_CTL_2_ADDR 0x00E
+ DISP_REG(DISP_EXT_DISPLAY_CTL_2_ADDR)
+
+#define DISP_EXT_DISPLAY_CTL_3_ADDR 0x00F
+ DISP_REG(DISP_EXT_DISPLAY_CTL_3_ADDR)
+
+#define DISP_LTPS_CTL_1_ADDR 0x012
+ DISP_REG(DISP_LTPS_CTL_1_ADDR)
+#define DISP_LTPS_CTL_2_ADDR 0x013
+ DISP_REG(DISP_LTPS_CTL_2_ADDR)
+#define DISP_LTPS_CTL_3_ADDR 0x014
+ DISP_REG(DISP_LTPS_CTL_3_ADDR)
+#define DISP_LTPS_CTL_4_ADDR 0x018
+ DISP_REG(DISP_LTPS_CTL_4_ADDR)
+#define DISP_LTPS_CTL_5_ADDR 0x019
+ DISP_REG(DISP_LTPS_CTL_5_ADDR)
+#define DISP_LTPS_CTL_6_ADDR 0x01A
+ DISP_REG(DISP_LTPS_CTL_6_ADDR)
+#define DISP_AMP_SETTING_ADDR 0x01C
+ DISP_REG(DISP_AMP_SETTING_ADDR)
+#define DISP_MODE_SETTING_ADDR 0x01D
+ DISP_REG(DISP_MODE_SETTING_ADDR)
+#define DISP_POFF_LN_SETTING_ADDR 0x01E
+ DISP_REG(DISP_POFF_LN_SETTING_ADDR)
+/* Power Contol */
+#define DISP_POWER_CTL_1_ADDR 0x100
+ DISP_REG(DISP_POWER_CTL_1_ADDR)
+#define DISP_POWER_CTL_2_ADDR 0x101
+ DISP_REG(DISP_POWER_CTL_2_ADDR)
+#define DISP_POWER_CTL_3_ADDR 0x102
+ DISP_REG(DISP_POWER_CTL_3_ADDR)
+#define DISP_POWER_CTL_4_ADDR 0x103
+ DISP_REG(DISP_POWER_CTL_4_ADDR)
+#define DISP_POWER_CTL_5_ADDR 0x104
+ DISP_REG(DISP_POWER_CTL_5_ADDR)
+#define DISP_POWER_CTL_6_ADDR 0x105
+ DISP_REG(DISP_POWER_CTL_6_ADDR)
+#define DISP_POWER_CTL_7_ADDR 0x106
+ DISP_REG(DISP_POWER_CTL_7_ADDR)
+/* RAM Access */
+#define DISP_RAM_ADDR_SET_1_ADDR 0x200
+ DISP_REG(DISP_RAM_ADDR_SET_1_ADDR)
+#define DISP_RAM_ADDR_SET_2_ADDR 0x201
+ DISP_REG(DISP_RAM_ADDR_SET_2_ADDR)
+#define DISP_CMD_RAMRD DISP_CMD_RAMWR
+#define DISP_CMD_RAMWR 0x202
+ DISP_REG(DISP_CMD_RAMWR)
+#define DISP_RAM_DATA_MASK_1_ADDR 0x203
+ DISP_REG(DISP_RAM_DATA_MASK_1_ADDR)
+#define DISP_RAM_DATA_MASK_2_ADDR 0x204
+ DISP_REG(DISP_RAM_DATA_MASK_2_ADDR)
+/* Gamma Control, Contrast, Gray Scale Setting */
+#define DISP_GAMMA_CONTROL_1_ADDR 0x300
+ DISP_REG(DISP_GAMMA_CONTROL_1_ADDR)
+#define DISP_GAMMA_CONTROL_2_ADDR 0x301
+ DISP_REG(DISP_GAMMA_CONTROL_2_ADDR)
+#define DISP_GAMMA_CONTROL_3_ADDR 0x302
+ DISP_REG(DISP_GAMMA_CONTROL_3_ADDR)
+#define DISP_GAMMA_CONTROL_4_ADDR 0x303
+ DISP_REG(DISP_GAMMA_CONTROL_4_ADDR)
+#define DISP_GAMMA_CONTROL_5_ADDR 0x304
+ DISP_REG(DISP_GAMMA_CONTROL_5_ADDR)
+/* Coordinate Control */
+#define DISP_VERT_SCROLL_CTL_1_ADDR 0x400
+ DISP_REG(DISP_VERT_SCROLL_CTL_1_ADDR)
+#define DISP_VERT_SCROLL_CTL_2_ADDR 0x401
+ DISP_REG(DISP_VERT_SCROLL_CTL_2_ADDR)
+#define DISP_SCREEN_1_DRV_POS_1_ADDR 0x402
+ DISP_REG(DISP_SCREEN_1_DRV_POS_1_ADDR)
+#define DISP_SCREEN_1_DRV_POS_2_ADDR 0x403
+ DISP_REG(DISP_SCREEN_1_DRV_POS_2_ADDR)
+#define DISP_SCREEN_2_DRV_POS_1_ADDR 0x404
+ DISP_REG(DISP_SCREEN_2_DRV_POS_1_ADDR)
+#define DISP_SCREEN_2_DRV_POS_2_ADDR 0x405
+ DISP_REG(DISP_SCREEN_2_DRV_POS_2_ADDR)
+#define DISP_HORZ_RAM_ADDR_POS_1_ADDR 0x406
+ DISP_REG(DISP_HORZ_RAM_ADDR_POS_1_ADDR)
+#define DISP_HORZ_RAM_ADDR_POS_2_ADDR 0x407
+ DISP_REG(DISP_HORZ_RAM_ADDR_POS_2_ADDR)
+#define DISP_VERT_RAM_ADDR_POS_1_ADDR 0x408
+ DISP_REG(DISP_VERT_RAM_ADDR_POS_1_ADDR)
+#define DISP_VERT_RAM_ADDR_POS_2_ADDR 0x409
+ DISP_REG(DISP_VERT_RAM_ADDR_POS_2_ADDR)
+#define DISP_TMD_700_ADDR 0x700 /* 0x700 */
+ DISP_REG(DISP_TMD_700_ADDR)
+#define DISP_TMD_015_ADDR 0x015 /* 0x700 */
+ DISP_REG(DISP_TMD_015_ADDR)
+#define DISP_TMD_305_ADDR 0x305 /* 0x700 */
+ DISP_REG(DISP_TMD_305_ADDR)
+
+/*
+ * TMD QVGA Bit Definations
+ */
+
+#define DISP_BIT_IB15 0x8000
+#define DISP_BIT_IB14 0x4000
+#define DISP_BIT_IB13 0x2000
+#define DISP_BIT_IB12 0x1000
+#define DISP_BIT_IB11 0x0800
+#define DISP_BIT_IB10 0x0400
+#define DISP_BIT_IB09 0x0200
+#define DISP_BIT_IB08 0x0100
+#define DISP_BIT_IB07 0x0080
+#define DISP_BIT_IB06 0x0040
+#define DISP_BIT_IB05 0x0020
+#define DISP_BIT_IB04 0x0010
+#define DISP_BIT_IB03 0x0008
+#define DISP_BIT_IB02 0x0004
+#define DISP_BIT_IB01 0x0002
+#define DISP_BIT_IB00 0x0001
+/*
+ * Display Control
+ * DISP_START_OSCILLATION_ADDR Start Oscillation
+ * DISP_DRIVER_OUTPUT_CTL_ADDR Driver Output Control
+ */
+#define DISP_BITMASK_SS DISP_BIT_IB08
+#define DISP_BITMASK_NL5 DISP_BIT_IB05
+#define DISP_BITMASK_NL4 DISP_BIT_IB04
+#define DISP_BITMASK_NL3 DISP_BIT_IB03
+#define DISP_BITMASK_NL2 DISP_BIT_IB02
+#define DISP_BITMASK_NL1 DISP_BIT_IB01
+#define DISP_BITMASK_NL0 DISP_BIT_IB00
+/* DISP_LCD_DRIVING_SIG_ADDR LCD Driving Signal Setting */
+#define DISP_BITMASK_BC DISP_BIT_IB09
+/* DISP_ENTRY_MODE_ADDR Entry Mode */
+#define DISP_BITMASK_TRI DISP_BIT_IB15
+#define DISP_BITMASK_DFM1 DISP_BIT_IB14
+#define DISP_BITMASK_DFM0 DISP_BIT_IB13
+#define DISP_BITMASK_BGR DISP_BIT_IB12
+#define DISP_BITMASK_HWM0 DISP_BIT_IB08
+#define DISP_BITMASK_ID1 DISP_BIT_IB05
+#define DISP_BITMASK_ID0 DISP_BIT_IB04
+#define DISP_BITMASK_AM DISP_BIT_IB03
+/* DISP_DISPLAY_CTL_1_ADDR Display Control (1) */
+#define DISP_BITMASK_COL1 DISP_BIT_IB15
+#define DISP_BITMASK_COL0 DISP_BIT_IB14
+#define DISP_BITMASK_VLE2 DISP_BIT_IB10
+#define DISP_BITMASK_VLE1 DISP_BIT_IB09
+#define DISP_BITMASK_SPT DISP_BIT_IB08
+#define DISP_BITMASK_PT1 DISP_BIT_IB07
+#define DISP_BITMASK_PT0 DISP_BIT_IB06
+#define DISP_BITMASK_REV DISP_BIT_IB02
+/* DISP_DISPLAY_CTL_2_ADDR Display Control (2) */
+#define DISP_BITMASK_FP3 DISP_BIT_IB11
+#define DISP_BITMASK_FP2 DISP_BIT_IB10
+#define DISP_BITMASK_FP1 DISP_BIT_IB09
+#define DISP_BITMASK_FP0 DISP_BIT_IB08
+#define DISP_BITMASK_BP3 DISP_BIT_IB03
+#define DISP_BITMASK_BP2 DISP_BIT_IB02
+#define DISP_BITMASK_BP1 DISP_BIT_IB01
+#define DISP_BITMASK_BP0 DISP_BIT_IB00
+/* DISP_POWER_SUPPLY_INTF_ADDR Power Supply IC Interface Control */
+#define DISP_BITMASK_CSE DISP_BIT_IB12
+#define DISP_BITMASK_TE DISP_BIT_IB08
+#define DISP_BITMASK_IX3 DISP_BIT_IB03
+#define DISP_BITMASK_IX2 DISP_BIT_IB02
+#define DISP_BITMASK_IX1 DISP_BIT_IB01
+#define DISP_BITMASK_IX0 DISP_BIT_IB00
+/* DISP_EXT_DISPLAY_CTL_1_ADDR External Display Interface Control (1) */
+#define DISP_BITMASK_RM DISP_BIT_IB08
+#define DISP_BITMASK_DM1 DISP_BIT_IB05
+#define DISP_BITMASK_DM0 DISP_BIT_IB04
+#define DISP_BITMASK_RIM1 DISP_BIT_IB01
+#define DISP_BITMASK_RIM0 DISP_BIT_IB00
+/* DISP_FRAME_CYCLE_CTL_ADDR Frame Frequency Adjustment Control */
+#define DISP_BITMASK_DIVI1 DISP_BIT_IB09
+#define DISP_BITMASK_DIVI0 DISP_BIT_IB08
+#define DISP_BITMASK_RTNI4 DISP_BIT_IB04
+#define DISP_BITMASK_RTNI3 DISP_BIT_IB03
+#define DISP_BITMASK_RTNI2 DISP_BIT_IB02
+#define DISP_BITMASK_RTNI1 DISP_BIT_IB01
+#define DISP_BITMASK_RTNI0 DISP_BIT_IB00
+/* DISP_EXT_DISPLAY_CTL_2_ADDR External Display Interface Control (2) */
+#define DISP_BITMASK_DIVE1 DISP_BIT_IB09
+#define DISP_BITMASK_DIVE0 DISP_BIT_IB08
+#define DISP_BITMASK_RTNE7 DISP_BIT_IB07
+#define DISP_BITMASK_RTNE6 DISP_BIT_IB06
+#define DISP_BITMASK_RTNE5 DISP_BIT_IB05
+#define DISP_BITMASK_RTNE4 DISP_BIT_IB04
+#define DISP_BITMASK_RTNE3 DISP_BIT_IB03
+#define DISP_BITMASK_RTNE2 DISP_BIT_IB02
+#define DISP_BITMASK_RTNE1 DISP_BIT_IB01
+#define DISP_BITMASK_RTNE0 DISP_BIT_IB00
+/* DISP_EXT_DISPLAY_CTL_3_ADDR External Display Interface Control (3) */
+#define DISP_BITMASK_VSPL DISP_BIT_IB04
+#define DISP_BITMASK_HSPL DISP_BIT_IB03
+#define DISP_BITMASK_VPL DISP_BIT_IB02
+#define DISP_BITMASK_EPL DISP_BIT_IB01
+#define DISP_BITMASK_DPL DISP_BIT_IB00
+/* DISP_LTPS_CTL_1_ADDR LTPS Interface Control (1) */
+#define DISP_BITMASK_CLWI3 DISP_BIT_IB11
+#define DISP_BITMASK_CLWI2 DISP_BIT_IB10
+#define DISP_BITMASK_CLWI1 DISP_BIT_IB09
+#define DISP_BITMASK_CLWI0 DISP_BIT_IB08
+#define DISP_BITMASK_CLTI1 DISP_BIT_IB01
+#define DISP_BITMASK_CLTI0 DISP_BIT_IB00
+/* DISP_LTPS_CTL_2_ADDR LTPS Interface Control (2) */
+#define DISP_BITMASK_OEVBI1 DISP_BIT_IB09
+#define DISP_BITMASK_OEVBI0 DISP_BIT_IB08
+#define DISP_BITMASK_OEVFI1 DISP_BIT_IB01
+#define DISP_BITMASK_OEVFI0 DISP_BIT_IB00
+/* DISP_LTPS_CTL_3_ADDR LTPS Interface Control (3) */
+#define DISP_BITMASK_SHI1 DISP_BIT_IB01
+#define DISP_BITMASK_SHI0 DISP_BIT_IB00
+/* DISP_LTPS_CTL_4_ADDR LTPS Interface Control (4) */
+#define DISP_BITMASK_CLWE5 DISP_BIT_IB13
+#define DISP_BITMASK_CLWE4 DISP_BIT_IB12
+#define DISP_BITMASK_CLWE3 DISP_BIT_IB11
+#define DISP_BITMASK_CLWE2 DISP_BIT_IB10
+#define DISP_BITMASK_CLWE1 DISP_BIT_IB09
+#define DISP_BITMASK_CLWE0 DISP_BIT_IB08
+#define DISP_BITMASK_CLTE3 DISP_BIT_IB03
+#define DISP_BITMASK_CLTE2 DISP_BIT_IB02
+#define DISP_BITMASK_CLTE1 DISP_BIT_IB01
+#define DISP_BITMASK_CLTE0 DISP_BIT_IB00
+/* DISP_LTPS_CTL_5_ADDR LTPS Interface Control (5) */
+#define DISP_BITMASK_OEVBE3 DISP_BIT_IB11
+#define DISP_BITMASK_OEVBE2 DISP_BIT_IB10
+#define DISP_BITMASK_OEVBE1 DISP_BIT_IB09
+#define DISP_BITMASK_OEVBE0 DISP_BIT_IB08
+#define DISP_BITMASK_OEVFE3 DISP_BIT_IB03
+#define DISP_BITMASK_OEVFE2 DISP_BIT_IB02
+#define DISP_BITMASK_OEVFE1 DISP_BIT_IB01
+#define DISP_BITMASK_OEVFE0 DISP_BIT_IB00
+/* DISP_LTPS_CTL_6_ADDR LTPS Interface Control (6) */
+#define DISP_BITMASK_SHE3 DISP_BIT_IB03
+#define DISP_BITMASK_SHE2 DISP_BIT_IB02
+#define DISP_BITMASK_SHE1 DISP_BIT_IB01
+#define DISP_BITMASK_SHE0 DISP_BIT_IB00
+/* DISP_AMP_SETTING_ADDR Amplify Setting */
+#define DISP_BITMASK_ABSW1 DISP_BIT_IB01
+#define DISP_BITMASK_ABSW0 DISP_BIT_IB00
+/* DISP_MODE_SETTING_ADDR Mode Setting */
+#define DISP_BITMASK_DSTB DISP_BIT_IB02
+#define DISP_BITMASK_STB DISP_BIT_IB00
+/* DISP_POFF_LN_SETTING_ADDR Power Off Line Setting */
+#define DISP_BITMASK_POFH3 DISP_BIT_IB03
+#define DISP_BITMASK_POFH2 DISP_BIT_IB02
+#define DISP_BITMASK_POFH1 DISP_BIT_IB01
+#define DISP_BITMASK_POFH0 DISP_BIT_IB00
+
+/* Power Contol */
+/* DISP_POWER_CTL_1_ADDR Power Control (1) */
+#define DISP_BITMASK_PO DISP_BIT_IB11
+#define DISP_BITMASK_VCD DISP_BIT_IB09
+#define DISP_BITMASK_VSC DISP_BIT_IB08
+#define DISP_BITMASK_CON DISP_BIT_IB07
+#define DISP_BITMASK_ASW1 DISP_BIT_IB06
+#define DISP_BITMASK_ASW0 DISP_BIT_IB05
+#define DISP_BITMASK_OEV DISP_BIT_IB04
+#define DISP_BITMASK_OEVE DISP_BIT_IB03
+#define DISP_BITMASK_FR DISP_BIT_IB02
+#define DISP_BITMASK_D1 DISP_BIT_IB01
+#define DISP_BITMASK_D0 DISP_BIT_IB00
+/* DISP_POWER_CTL_2_ADDR Power Control (2) */
+#define DISP_BITMASK_DC4 DISP_BIT_IB15
+#define DISP_BITMASK_DC3 DISP_BIT_IB14
+#define DISP_BITMASK_SAP2 DISP_BIT_IB13
+#define DISP_BITMASK_SAP1 DISP_BIT_IB12
+#define DISP_BITMASK_SAP0 DISP_BIT_IB11
+#define DISP_BITMASK_BT2 DISP_BIT_IB10
+#define DISP_BITMASK_BT1 DISP_BIT_IB09
+#define DISP_BITMASK_BT0 DISP_BIT_IB08
+#define DISP_BITMASK_DC2 DISP_BIT_IB07
+#define DISP_BITMASK_DC1 DISP_BIT_IB06
+#define DISP_BITMASK_DC0 DISP_BIT_IB05
+#define DISP_BITMASK_AP2 DISP_BIT_IB04
+#define DISP_BITMASK_AP1 DISP_BIT_IB03
+#define DISP_BITMASK_AP0 DISP_BIT_IB02
+/* DISP_POWER_CTL_3_ADDR Power Control (3) */
+#define DISP_BITMASK_VGL4 DISP_BIT_IB10
+#define DISP_BITMASK_VGL3 DISP_BIT_IB09
+#define DISP_BITMASK_VGL2 DISP_BIT_IB08
+#define DISP_BITMASK_VGL1 DISP_BIT_IB07
+#define DISP_BITMASK_VGL0 DISP_BIT_IB06
+#define DISP_BITMASK_VGH4 DISP_BIT_IB04
+#define DISP_BITMASK_VGH3 DISP_BIT_IB03
+#define DISP_BITMASK_VGH2 DISP_BIT_IB02
+#define DISP_BITMASK_VGH1 DISP_BIT_IB01
+#define DISP_BITMASK_VGH0 DISP_BIT_IB00
+/* DISP_POWER_CTL_4_ADDR Power Control (4) */
+#define DISP_BITMASK_VC2 DISP_BIT_IB02
+#define DISP_BITMASK_VC1 DISP_BIT_IB01
+#define DISP_BITMASK_VC0 DISP_BIT_IB00
+/* DISP_POWER_CTL_5_ADDR Power Control (5) */
+#define DISP_BITMASK_VRL3 DISP_BIT_IB11
+#define DISP_BITMASK_VRL2 DISP_BIT_IB10
+#define DISP_BITMASK_VRL1 DISP_BIT_IB09
+#define DISP_BITMASK_VRL0 DISP_BIT_IB08
+#define DISP_BITMASK_PON DISP_BIT_IB04
+#define DISP_BITMASK_VRH3 DISP_BIT_IB03
+#define DISP_BITMASK_VRH2 DISP_BIT_IB02
+#define DISP_BITMASK_VRH1 DISP_BIT_IB01
+#define DISP_BITMASK_VRH0 DISP_BIT_IB00
+/* DISP_POWER_CTL_6_ADDR Power Control (6) */
+#define DISP_BITMASK_VCOMG DISP_BIT_IB13
+#define DISP_BITMASK_VDV4 DISP_BIT_IB12
+#define DISP_BITMASK_VDV3 DISP_BIT_IB11
+#define DISP_BITMASK_VDV2 DISP_BIT_IB10
+#define DISP_BITMASK_VDV1 DISP_BIT_IB09
+#define DISP_BITMASK_VDV0 DISP_BIT_IB08
+#define DISP_BITMASK_VCM4 DISP_BIT_IB04
+#define DISP_BITMASK_VCM3 DISP_BIT_IB03
+#define DISP_BITMASK_VCM2 DISP_BIT_IB02
+#define DISP_BITMASK_VCM1 DISP_BIT_IB01
+#define DISP_BITMASK_VCM0 DISP_BIT_IB00
+/* RAM Access */
+/* DISP_RAM_ADDR_SET_1_ADDR RAM Address Set (1) */
+#define DISP_BITMASK_AD7 DISP_BIT_IB07
+#define DISP_BITMASK_AD6 DISP_BIT_IB06
+#define DISP_BITMASK_AD5 DISP_BIT_IB05
+#define DISP_BITMASK_AD4 DISP_BIT_IB04
+#define DISP_BITMASK_AD3 DISP_BIT_IB03
+#define DISP_BITMASK_AD2 DISP_BIT_IB02
+#define DISP_BITMASK_AD1 DISP_BIT_IB01
+#define DISP_BITMASK_AD0 DISP_BIT_IB00
+/* DISP_RAM_ADDR_SET_2_ADDR RAM Address Set (2) */
+#define DISP_BITMASK_AD16 DISP_BIT_IB08
+#define DISP_BITMASK_AD15 DISP_BIT_IB07
+#define DISP_BITMASK_AD14 DISP_BIT_IB06
+#define DISP_BITMASK_AD13 DISP_BIT_IB05
+#define DISP_BITMASK_AD12 DISP_BIT_IB04
+#define DISP_BITMASK_AD11 DISP_BIT_IB03
+#define DISP_BITMASK_AD10 DISP_BIT_IB02
+#define DISP_BITMASK_AD9 DISP_BIT_IB01
+#define DISP_BITMASK_AD8 DISP_BIT_IB00
+/*
+ * DISP_CMD_RAMWR RAM Data Read/Write
+ * Use Data Bit Configuration
+ */
+/* DISP_RAM_DATA_MASK_1_ADDR RAM Write Data Mask (1) */
+#define DISP_BITMASK_WM11 DISP_BIT_IB13
+#define DISP_BITMASK_WM10 DISP_BIT_IB12
+#define DISP_BITMASK_WM9 DISP_BIT_IB11
+#define DISP_BITMASK_WM8 DISP_BIT_IB10
+#define DISP_BITMASK_WM7 DISP_BIT_IB09
+#define DISP_BITMASK_WM6 DISP_BIT_IB08
+#define DISP_BITMASK_WM5 DISP_BIT_IB05
+#define DISP_BITMASK_WM4 DISP_BIT_IB04
+#define DISP_BITMASK_WM3 DISP_BIT_IB03
+#define DISP_BITMASK_WM2 DISP_BIT_IB02
+#define DISP_BITMASK_WM1 DISP_BIT_IB01
+#define DISP_BITMASK_WM0 DISP_BIT_IB00
+/* DISP_RAM_DATA_MASK_2_ADDR RAM Write Data Mask (2) */
+#define DISP_BITMASK_WM17 DISP_BIT_IB05
+#define DISP_BITMASK_WM16 DISP_BIT_IB04
+#define DISP_BITMASK_WM15 DISP_BIT_IB03
+#define DISP_BITMASK_WM14 DISP_BIT_IB02
+#define DISP_BITMASK_WM13 DISP_BIT_IB01
+#define DISP_BITMASK_WM12 DISP_BIT_IB00
+/*Gamma Control */
+/* DISP_GAMMA_CONTROL_1_ADDR Gamma Control (1) */
+#define DISP_BITMASK_PKP12 DISP_BIT_IB10
+#define DISP_BITMASK_PKP11 DISP_BIT_IB08
+#define DISP_BITMASK_PKP10 DISP_BIT_IB09
+#define DISP_BITMASK_PKP02 DISP_BIT_IB02
+#define DISP_BITMASK_PKP01 DISP_BIT_IB01
+#define DISP_BITMASK_PKP00 DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_2_ADDR Gamma Control (2) */
+#define DISP_BITMASK_PKP32 DISP_BIT_IB10
+#define DISP_BITMASK_PKP31 DISP_BIT_IB09
+#define DISP_BITMASK_PKP30 DISP_BIT_IB08
+#define DISP_BITMASK_PKP22 DISP_BIT_IB02
+#define DISP_BITMASK_PKP21 DISP_BIT_IB01
+#define DISP_BITMASK_PKP20 DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_3_ADDR Gamma Control (3) */
+#define DISP_BITMASK_PKP52 DISP_BIT_IB10
+#define DISP_BITMASK_PKP51 DISP_BIT_IB09
+#define DISP_BITMASK_PKP50 DISP_BIT_IB08
+#define DISP_BITMASK_PKP42 DISP_BIT_IB02
+#define DISP_BITMASK_PKP41 DISP_BIT_IB01
+#define DISP_BITMASK_PKP40 DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_4_ADDR Gamma Control (4) */
+#define DISP_BITMASK_PRP12 DISP_BIT_IB10
+#define DISP_BITMASK_PRP11 DISP_BIT_IB08
+#define DISP_BITMASK_PRP10 DISP_BIT_IB09
+#define DISP_BITMASK_PRP02 DISP_BIT_IB02
+#define DISP_BITMASK_PRP01 DISP_BIT_IB01
+#define DISP_BITMASK_PRP00 DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_5_ADDR Gamma Control (5) */
+#define DISP_BITMASK_VRP14 DISP_BIT_IB12
+#define DISP_BITMASK_VRP13 DISP_BIT_IB11
+#define DISP_BITMASK_VRP12 DISP_BIT_IB10
+#define DISP_BITMASK_VRP11 DISP_BIT_IB08
+#define DISP_BITMASK_VRP10 DISP_BIT_IB09
+#define DISP_BITMASK_VRP03 DISP_BIT_IB03
+#define DISP_BITMASK_VRP02 DISP_BIT_IB02
+#define DISP_BITMASK_VRP01 DISP_BIT_IB01
+#define DISP_BITMASK_VRP00 DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_6_ADDR Gamma Control (6) */
+#define DISP_BITMASK_PKN12 DISP_BIT_IB10
+#define DISP_BITMASK_PKN11 DISP_BIT_IB08
+#define DISP_BITMASK_PKN10 DISP_BIT_IB09
+#define DISP_BITMASK_PKN02 DISP_BIT_IB02
+#define DISP_BITMASK_PKN01 DISP_BIT_IB01
+#define DISP_BITMASK_PKN00 DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_7_ADDR Gamma Control (7) */
+#define DISP_BITMASK_PKN32 DISP_BIT_IB10
+#define DISP_BITMASK_PKN31 DISP_BIT_IB08
+#define DISP_BITMASK_PKN30 DISP_BIT_IB09
+#define DISP_BITMASK_PKN22 DISP_BIT_IB02
+#define DISP_BITMASK_PKN21 DISP_BIT_IB01
+#define DISP_BITMASK_PKN20 DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_8_ADDR Gamma Control (8) */
+#define DISP_BITMASK_PKN52 DISP_BIT_IB10
+#define DISP_BITMASK_PKN51 DISP_BIT_IB08
+#define DISP_BITMASK_PKN50 DISP_BIT_IB09
+#define DISP_BITMASK_PKN42 DISP_BIT_IB02
+#define DISP_BITMASK_PKN41 DISP_BIT_IB01
+#define DISP_BITMASK_PKN40 DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_9_ADDR Gamma Control (9) */
+#define DISP_BITMASK_PRN12 DISP_BIT_IB10
+#define DISP_BITMASK_PRN11 DISP_BIT_IB08
+#define DISP_BITMASK_PRN10 DISP_BIT_IB09
+#define DISP_BITMASK_PRN02 DISP_BIT_IB02
+#define DISP_BITMASK_PRN01 DISP_BIT_IB01
+#define DISP_BITMASK_PRN00 DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_10_ADDR Gamma Control (10) */
+#define DISP_BITMASK_VRN14 DISP_BIT_IB12
+#define DISP_BITMASK_VRN13 DISP_BIT_IB11
+#define DISP_BITMASK_VRN12 DISP_BIT_IB10
+#define DISP_BITMASK_VRN11 DISP_BIT_IB08
+#define DISP_BITMASK_VRN10 DISP_BIT_IB09
+#define DISP_BITMASK_VRN03 DISP_BIT_IB03
+#define DISP_BITMASK_VRN02 DISP_BIT_IB02
+#define DISP_BITMASK_VRN01 DISP_BIT_IB01
+#define DISP_BITMASK_VRN00 DISP_BIT_IB00
+/* Coordinate Control */
+/* DISP_VERT_SCROLL_CTL_1_ADDR Vertical Scroll Control (1) */
+#define DISP_BITMASK_VL18 DISP_BIT_IB08
+#define DISP_BITMASK_VL17 DISP_BIT_IB07
+#define DISP_BITMASK_VL16 DISP_BIT_IB06
+#define DISP_BITMASK_VL15 DISP_BIT_IB05
+#define DISP_BITMASK_VL14 DISP_BIT_IB04
+#define DISP_BITMASK_VL13 DISP_BIT_IB03
+#define DISP_BITMASK_VL12 DISP_BIT_IB02
+#define DISP_BITMASK_VL11 DISP_BIT_IB01
+#define DISP_BITMASK_VL10 DISP_BIT_IB00
+/* DISP_VERT_SCROLL_CTL_2_ADDR Vertical Scroll Control (2) */
+#define DISP_BITMASK_VL28 DISP_BIT_IB08
+#define DISP_BITMASK_VL27 DISP_BIT_IB07
+#define DISP_BITMASK_VL26 DISP_BIT_IB06
+#define DISP_BITMASK_VL25 DISP_BIT_IB05
+#define DISP_BITMASK_VL24 DISP_BIT_IB04
+#define DISP_BITMASK_VL23 DISP_BIT_IB03
+#define DISP_BITMASK_VL22 DISP_BIT_IB02
+#define DISP_BITMASK_VL21 DISP_BIT_IB01
+#define DISP_BITMASK_VL20 DISP_BIT_IB00
+/* DISP_SCREEN_1_DRV_POS_1_ADDR First Screen Driving Position (1) */
+#define DISP_BITMASK_SS18 DISP_BIT_IB08
+#define DISP_BITMASK_SS17 DISP_BIT_IB07
+#define DISP_BITMASK_SS16 DISP_BIT_IB06
+#define DISP_BITMASK_SS15 DISP_BIT_IB05
+#define DISP_BITMASK_SS14 DISP_BIT_IB04
+#define DISP_BITMASK_SS13 DISP_BIT_IB03
+#define DISP_BITMASK_SS12 DISP_BIT_IB02
+#define DISP_BITMASK_SS11 DISP_BIT_IB01
+#define DISP_BITMASK_SS10 DISP_BIT_IB00
+/* DISP_SCREEN_1_DRV_POS_2_ADDR First Screen Driving Position (2) */
+#define DISP_BITMASK_SE18 DISP_BIT_IB08
+#define DISP_BITMASK_SE17 DISP_BIT_IB07
+#define DISP_BITMASK_SE16 DISP_BIT_IB06
+#define DISP_BITMASK_SE15 DISP_BIT_IB05
+#define DISP_BITMASK_SE14 DISP_BIT_IB04
+#define DISP_BITMASK_SE13 DISP_BIT_IB03
+#define DISP_BITMASK_SE12 DISP_BIT_IB02
+#define DISP_BITMASK_SE11 DISP_BIT_IB01
+#define DISP_BITMASK_SE10 DISP_BIT_IB00
+/* DISP_SCREEN_2_DRV_POS_1_ADDR Second Screen Driving Position (1) */
+#define DISP_BITMASK_SS28 DISP_BIT_IB08
+#define DISP_BITMASK_SS27 DISP_BIT_IB07
+#define DISP_BITMASK_SS26 DISP_BIT_IB06
+#define DISP_BITMASK_SS25 DISP_BIT_IB05
+#define DISP_BITMASK_SS24 DISP_BIT_IB04
+#define DISP_BITMASK_SS23 DISP_BIT_IB03
+#define DISP_BITMASK_SS22 DISP_BIT_IB02
+#define DISP_BITMASK_SS21 DISP_BIT_IB01
+#define DISP_BITMASK_SS20 DISP_BIT_IB00
+/* DISP_SCREEN_3_DRV_POS_2_ADDR Second Screen Driving Position (2) */
+#define DISP_BITMASK_SE28 DISP_BIT_IB08
+#define DISP_BITMASK_SE27 DISP_BIT_IB07
+#define DISP_BITMASK_SE26 DISP_BIT_IB06
+#define DISP_BITMASK_SE25 DISP_BIT_IB05
+#define DISP_BITMASK_SE24 DISP_BIT_IB04
+#define DISP_BITMASK_SE23 DISP_BIT_IB03
+#define DISP_BITMASK_SE22 DISP_BIT_IB02
+#define DISP_BITMASK_SE21 DISP_BIT_IB01
+#define DISP_BITMASK_SE20 DISP_BIT_IB00
+/* DISP_HORZ_RAM_ADDR_POS_1_ADDR Horizontal RAM Address Position (1) */
+#define DISP_BITMASK_HSA7 DISP_BIT_IB07
+#define DISP_BITMASK_HSA6 DISP_BIT_IB06
+#define DISP_BITMASK_HSA5 DISP_BIT_IB05
+#define DISP_BITMASK_HSA4 DISP_BIT_IB04
+#define DISP_BITMASK_HSA3 DISP_BIT_IB03
+#define DISP_BITMASK_HSA2 DISP_BIT_IB02
+#define DISP_BITMASK_HSA1 DISP_BIT_IB01
+#define DISP_BITMASK_HSA0 DISP_BIT_IB00
+/* DISP_HORZ_RAM_ADDR_POS_2_ADDR Horizontal RAM Address Position (2) */
+#define DISP_BITMASK_HEA7 DISP_BIT_IB07
+#define DISP_BITMASK_HEA6 DISP_BIT_IB06
+#define DISP_BITMASK_HEA5 DISP_BIT_IB05
+#define DISP_BITMASK_HEA4 DISP_BIT_IB04
+#define DISP_BITMASK_HEA3 DISP_BIT_IB03
+#define DISP_BITMASK_HEA2 DISP_BIT_IB02
+#define DISP_BITMASK_HEA1 DISP_BIT_IB01
+#define DISP_BITMASK_HEA0 DISP_BIT_IB00
+/* DISP_VERT_RAM_ADDR_POS_1_ADDR Vertical RAM Address Position (1) */
+#define DISP_BITMASK_VSA8 DISP_BIT_IB08
+#define DISP_BITMASK_VSA7 DISP_BIT_IB07
+#define DISP_BITMASK_VSA6 DISP_BIT_IB06
+#define DISP_BITMASK_VSA5 DISP_BIT_IB05
+#define DISP_BITMASK_VSA4 DISP_BIT_IB04
+#define DISP_BITMASK_VSA3 DISP_BIT_IB03
+#define DISP_BITMASK_VSA2 DISP_BIT_IB02
+#define DISP_BITMASK_VSA1 DISP_BIT_IB01
+#define DISP_BITMASK_VSA0 DISP_BIT_IB00
+/* DISP_VERT_RAM_ADDR_POS_2_ADDR Vertical RAM Address Position (2) */
+#define DISP_BITMASK_VEA8 DISP_BIT_IB08
+#define DISP_BITMASK_VEA7 DISP_BIT_IB07
+#define DISP_BITMASK_VEA6 DISP_BIT_IB06
+#define DISP_BITMASK_VEA5 DISP_BIT_IB05
+#define DISP_BITMASK_VEA4 DISP_BIT_IB04
+#define DISP_BITMASK_VEA3 DISP_BIT_IB03
+#define DISP_BITMASK_VEA2 DISP_BIT_IB02
+#define DISP_BITMASK_VEA1 DISP_BIT_IB01
+#define DISP_BITMASK_VEA0 DISP_BIT_IB00
+static word disp_area_start_row;
+static word disp_area_end_row;
+static boolean disp_initialized = FALSE;
+/* For some reason the contrast set at init time is not good. Need to do
+* it again
+*/
+static boolean display_on = FALSE;
+
+static uint32 tmd20qvga_lcd_rev;
+uint16 tmd20qvga_panel_offset;
+
+#ifdef DISP_DEVICE_8BPP
+static word convert_8_to_16_tbl[256] = {
+ 0x0000, 0x2000, 0x4000, 0x6000, 0x8000, 0xA000, 0xC000, 0xE000,
+ 0x0100, 0x2100, 0x4100, 0x6100, 0x8100, 0xA100, 0xC100, 0xE100,
+ 0x0200, 0x2200, 0x4200, 0x6200, 0x8200, 0xA200, 0xC200, 0xE200,
+ 0x0300, 0x2300, 0x4300, 0x6300, 0x8300, 0xA300, 0xC300, 0xE300,
+ 0x0400, 0x2400, 0x4400, 0x6400, 0x8400, 0xA400, 0xC400, 0xE400,
+ 0x0500, 0x2500, 0x4500, 0x6500, 0x8500, 0xA500, 0xC500, 0xE500,
+ 0x0600, 0x2600, 0x4600, 0x6600, 0x8600, 0xA600, 0xC600, 0xE600,
+ 0x0700, 0x2700, 0x4700, 0x6700, 0x8700, 0xA700, 0xC700, 0xE700,
+ 0x0008, 0x2008, 0x4008, 0x6008, 0x8008, 0xA008, 0xC008, 0xE008,
+ 0x0108, 0x2108, 0x4108, 0x6108, 0x8108, 0xA108, 0xC108, 0xE108,
+ 0x0208, 0x2208, 0x4208, 0x6208, 0x8208, 0xA208, 0xC208, 0xE208,
+ 0x0308, 0x2308, 0x4308, 0x6308, 0x8308, 0xA308, 0xC308, 0xE308,
+ 0x0408, 0x2408, 0x4408, 0x6408, 0x8408, 0xA408, 0xC408, 0xE408,
+ 0x0508, 0x2508, 0x4508, 0x6508, 0x8508, 0xA508, 0xC508, 0xE508,
+ 0x0608, 0x2608, 0x4608, 0x6608, 0x8608, 0xA608, 0xC608, 0xE608,
+ 0x0708, 0x2708, 0x4708, 0x6708, 0x8708, 0xA708, 0xC708, 0xE708,
+ 0x0010, 0x2010, 0x4010, 0x6010, 0x8010, 0xA010, 0xC010, 0xE010,
+ 0x0110, 0x2110, 0x4110, 0x6110, 0x8110, 0xA110, 0xC110, 0xE110,
+ 0x0210, 0x2210, 0x4210, 0x6210, 0x8210, 0xA210, 0xC210, 0xE210,
+ 0x0310, 0x2310, 0x4310, 0x6310, 0x8310, 0xA310, 0xC310, 0xE310,
+ 0x0410, 0x2410, 0x4410, 0x6410, 0x8410, 0xA410, 0xC410, 0xE410,
+ 0x0510, 0x2510, 0x4510, 0x6510, 0x8510, 0xA510, 0xC510, 0xE510,
+ 0x0610, 0x2610, 0x4610, 0x6610, 0x8610, 0xA610, 0xC610, 0xE610,
+ 0x0710, 0x2710, 0x4710, 0x6710, 0x8710, 0xA710, 0xC710, 0xE710,
+ 0x0018, 0x2018, 0x4018, 0x6018, 0x8018, 0xA018, 0xC018, 0xE018,
+ 0x0118, 0x2118, 0x4118, 0x6118, 0x8118, 0xA118, 0xC118, 0xE118,
+ 0x0218, 0x2218, 0x4218, 0x6218, 0x8218, 0xA218, 0xC218, 0xE218,
+ 0x0318, 0x2318, 0x4318, 0x6318, 0x8318, 0xA318, 0xC318, 0xE318,
+ 0x0418, 0x2418, 0x4418, 0x6418, 0x8418, 0xA418, 0xC418, 0xE418,
+ 0x0518, 0x2518, 0x4518, 0x6518, 0x8518, 0xA518, 0xC518, 0xE518,
+ 0x0618, 0x2618, 0x4618, 0x6618, 0x8618, 0xA618, 0xC618, 0xE618,
+ 0x0718, 0x2718, 0x4718, 0x6718, 0x8718, 0xA718, 0xC718, 0xE718
+};
+#endif /* DISP_DEVICE_8BPP */
+
+static void tmd20qvga_disp_set_rect(int x, int y, int xres, int yres);
+static void tmd20qvga_disp_init(struct platform_device *pdev);
+static void tmd20qvga_disp_set_contrast(void);
+static void tmd20qvga_disp_set_display_area(word start_row, word end_row);
+static int tmd20qvga_disp_off(struct platform_device *pdev);
+static int tmd20qvga_disp_on(struct platform_device *pdev);
+static void tmd20qvga_set_revId(int);
+
+/* future use */
+void tmd20qvga_disp_clear_screen_area(word start_row, word end_row,
+ word start_column, word end_column);
+
+static void tmd20qvga_set_revId(int id)
+{
+
+ tmd20qvga_lcd_rev = id;
+
+ if (tmd20qvga_lcd_rev == 1)
+ tmd20qvga_panel_offset = 0x10;
+ else
+ tmd20qvga_panel_offset = 0;
+}
+
+static void tmd20qvga_disp_init(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+
+ if (disp_initialized)
+ return;
+
+ mfd = platform_get_drvdata(pdev);
+
+ DISP_CMD_PORT = mfd->cmd_port;
+ DISP_DATA_PORT = mfd->data_port;
+
+#ifdef TMD20QVGA_LCD_18BPP
+ tmd20qvga_set_revId(2);
+#else
+ tmd20qvga_set_revId(1);
+#endif
+
+ disp_initialized = TRUE;
+ tmd20qvga_disp_set_contrast();
+ tmd20qvga_disp_set_display_area(0, QVGA_HEIGHT - 1);
+}
+
+static void tmd20qvga_disp_set_rect(int x, int y, int xres, int yres)
+{
+ if (!disp_initialized)
+ return;
+
+ DISP_SET_RECT(y, y + yres - 1, x, x + xres - 1);
+
+ DISP_CMD_OUT(DISP_CMD_RAMWR);
+}
+
+static void tmd20qvga_disp_set_display_area(word start_row, word end_row)
+{
+ word start_driving = start_row;
+ word end_driving = end_row;
+
+ if (!disp_initialized)
+ return;
+
+ /* Range checking
+ */
+ if (end_driving >= QVGA_HEIGHT)
+ end_driving = QVGA_HEIGHT - 1;
+ if (start_driving > end_driving) {
+ /* Probably Backwards Switch */
+ start_driving = end_driving;
+ end_driving = start_row; /* Has not changed */
+ if (end_driving >= QVGA_HEIGHT)
+ end_driving = QVGA_HEIGHT - 1;
+ }
+
+ if ((start_driving == disp_area_start_row)
+ && (end_driving == disp_area_end_row))
+ return;
+
+ disp_area_start_row = start_driving;
+ disp_area_end_row = end_driving;
+
+ DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR,
+ DISP_VAL_IF(start_driving & 0x100,
+ DISP_BITMASK_SS18) |
+ DISP_VAL_IF(start_driving & 0x080,
+ DISP_BITMASK_SS17) |
+ DISP_VAL_IF(start_driving & 0x040,
+ DISP_BITMASK_SS16) |
+ DISP_VAL_IF(start_driving & 0x020,
+ DISP_BITMASK_SS15) |
+ DISP_VAL_IF(start_driving & 0x010,
+ DISP_BITMASK_SS14) |
+ DISP_VAL_IF(start_driving & 0x008,
+ DISP_BITMASK_SS13) |
+ DISP_VAL_IF(start_driving & 0x004,
+ DISP_BITMASK_SS12) |
+ DISP_VAL_IF(start_driving & 0x002,
+ DISP_BITMASK_SS11) |
+ DISP_VAL_IF(start_driving & 0x001, DISP_BITMASK_SS10));
+
+ DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR,
+ DISP_VAL_IF(end_driving & 0x100, DISP_BITMASK_SE18) |
+ DISP_VAL_IF(end_driving & 0x080, DISP_BITMASK_SE17) |
+ DISP_VAL_IF(end_driving & 0x040, DISP_BITMASK_SE16) |
+ DISP_VAL_IF(end_driving & 0x020, DISP_BITMASK_SE15) |
+ DISP_VAL_IF(end_driving & 0x010, DISP_BITMASK_SE14) |
+ DISP_VAL_IF(end_driving & 0x008, DISP_BITMASK_SE13) |
+ DISP_VAL_IF(end_driving & 0x004, DISP_BITMASK_SE12) |
+ DISP_VAL_IF(end_driving & 0x002, DISP_BITMASK_SE11) |
+ DISP_VAL_IF(end_driving & 0x001, DISP_BITMASK_SE10));
+}
+
+static int tmd20qvga_disp_off(struct platform_device *pdev)
+{
+ if (!disp_initialized)
+ tmd20qvga_disp_init(pdev);
+
+ if (display_on) {
+ if (tmd20qvga_lcd_rev == 2) {
+ DISP_WRITE_OUT(DISP_POFF_LN_SETTING_ADDR, 0x000A);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xFFEE);
+ WAIT_MSEC(40);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xF812);
+ WAIT_MSEC(40);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xE811);
+ WAIT_MSEC(40);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xC011);
+ WAIT_MSEC(40);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x4011);
+ WAIT_MSEC(20);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0010);
+
+ } else {
+ DISP_WRITE_OUT(DISP_POFF_LN_SETTING_ADDR, 0x000F);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BFE);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+ WAIT_MSEC(40);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BED);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+ WAIT_MSEC(40);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x00CD);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+ WAIT_MSEC(20);
+ DISP_WRITE_OUT(DISP_START_OSCILLATION_ADDR, 0x0);
+ }
+
+ DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0004);
+ DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0000);
+
+ display_on = FALSE;
+ }
+
+ return 0;
+}
+
+static int tmd20qvga_disp_on(struct platform_device *pdev)
+{
+ if (!disp_initialized)
+ tmd20qvga_disp_init(pdev);
+
+ if (!display_on) {
+ /* Deep Stand-by -> Stand-by */
+ DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR);
+ WAIT_MSEC(1);
+ DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR);
+ WAIT_MSEC(1);
+ DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR);
+ WAIT_MSEC(1);
+
+ /* OFF -> Deep Stan-By -> Stand-by */
+ /* let's change the state from "Stand-by" to "Sleep" */
+ DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0005);
+ WAIT_MSEC(1);
+
+ /* Sleep -> Displaying */
+ DISP_WRITE_OUT(DISP_START_OSCILLATION_ADDR, 0x0001);
+ DISP_WRITE_OUT(DISP_DRIVER_OUTPUT_CTL_ADDR, 0x0127);
+ DISP_WRITE_OUT(DISP_LCD_DRIVING_SIG_ADDR, 0x200);
+ /* fast write mode */
+ DISP_WRITE_OUT(DISP_ENTRY_MODE_ADDR, 0x0130);
+ if (tmd20qvga_lcd_rev == 2)
+ DISP_WRITE_OUT(DISP_TMD_700_ADDR, 0x0003);
+ /* back porch = 14 + front porch = 2 --> 16 lines */
+ if (tmd20qvga_lcd_rev == 2) {
+#ifdef TMD20QVGA_LCD_18BPP
+ /* 256k color */
+ DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x0000);
+#else
+ /* 65k color */
+ DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x4000);
+#endif
+ DISP_WRITE_OUT(DISP_DISPLAY_CTL_2_ADDR, 0x0302);
+ } else {
+#ifdef TMD20QVGA_LCD_18BPP
+ /* 256k color */
+ DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x0004);
+#else
+ /* 65k color */
+ DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x4004);
+#endif
+ DISP_WRITE_OUT(DISP_DISPLAY_CTL_2_ADDR, 0x020E);
+ }
+ /* 16 bit one transfer */
+ if (tmd20qvga_lcd_rev == 2) {
+ DISP_WRITE_OUT(DISP_EXT_DISPLAY_CTL_1_ADDR, 0x0000);
+ DISP_WRITE_OUT(DISP_FRAME_CYCLE_CTL_ADDR, 0x0010);
+ DISP_WRITE_OUT(DISP_LTPS_CTL_1_ADDR, 0x0302);
+ DISP_WRITE_OUT(DISP_LTPS_CTL_2_ADDR, 0x0102);
+ DISP_WRITE_OUT(DISP_LTPS_CTL_3_ADDR, 0x0000);
+ DISP_WRITE_OUT(DISP_TMD_015_ADDR, 0x2000);
+
+ DISP_WRITE_OUT(DISP_AMP_SETTING_ADDR, 0x0000);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0304);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0403);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0101);
+ DISP_WRITE_OUT(DISP_TMD_305_ADDR, 0);
+
+ DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR, 0x0000);
+ DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR, 0x013F);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_3_ADDR, 0x077D);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_4_ADDR, 0x0005);
+ DISP_WRITE_OUT(DISP_POWER_CTL_5_ADDR, 0x0000);
+ DISP_WRITE_OUT(DISP_POWER_CTL_6_ADDR, 0x0015);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xC010);
+ WAIT_MSEC(1);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x0001);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xFFFE);
+ WAIT_MSEC(60);
+ } else {
+ DISP_WRITE_OUT(DISP_EXT_DISPLAY_CTL_1_ADDR, 0x0001);
+ DISP_WRITE_OUT(DISP_FRAME_CYCLE_CTL_ADDR, 0x0010);
+ DISP_WRITE_OUT(DISP_LTPS_CTL_1_ADDR, 0x0301);
+ DISP_WRITE_OUT(DISP_LTPS_CTL_2_ADDR, 0x0001);
+ DISP_WRITE_OUT(DISP_LTPS_CTL_3_ADDR, 0x0000);
+ DISP_WRITE_OUT(DISP_AMP_SETTING_ADDR, 0x0000);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0507);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0405);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0607);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0502);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0301);
+ DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR, 0x0000);
+ DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR, 0x013F);
+ DISP_WRITE_OUT(DISP_POWER_CTL_3_ADDR, 0x0795);
+
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0102);
+ WAIT_MSEC(1);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_4_ADDR, 0x0450);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0103);
+ WAIT_MSEC(1);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_5_ADDR, 0x0008);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0104);
+ WAIT_MSEC(1);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_6_ADDR, 0x0C00);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0105);
+ WAIT_MSEC(1);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_7_ADDR, 0x0000);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0106);
+ WAIT_MSEC(1);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0801);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+ WAIT_MSEC(1);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x001F);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0101);
+ WAIT_MSEC(60);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x009F);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0101);
+ WAIT_MSEC(10);
+
+ DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_1_ADDR, 0x0010);
+ DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_2_ADDR, 0x00FF);
+ DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_1_ADDR, 0x0000);
+ DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_2_ADDR, 0x013F);
+ /* RAM starts at address 0x10 */
+ DISP_WRITE_OUT(DISP_RAM_ADDR_SET_1_ADDR, 0x0010);
+ DISP_WRITE_OUT(DISP_RAM_ADDR_SET_2_ADDR, 0x0000);
+
+ /* lcd controller uses internal clock, not ext. vsync */
+ DISP_CMD_OUT(DISP_CMD_RAMWR);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0881);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+ WAIT_MSEC(40);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BE1);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+ WAIT_MSEC(40);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BFF);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+ }
+ display_on = TRUE;
+ }
+
+ return 0;
+}
+
+static void tmd20qvga_disp_set_contrast(void)
+{
+#if (defined(TMD20QVGA_LCD_18BPP))
+
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0302);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0403);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0F07);
+
+#else
+ int newcontrast = 0x46;
+
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403);
+
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR,
+ DISP_VAL_IF(newcontrast & 0x0001, DISP_BITMASK_PKP20) |
+ DISP_VAL_IF(newcontrast & 0x0002, DISP_BITMASK_PKP21) |
+ DISP_VAL_IF(newcontrast & 0x0004, DISP_BITMASK_PKP22) |
+ DISP_VAL_IF(newcontrast & 0x0010, DISP_BITMASK_PKP30) |
+ DISP_VAL_IF(newcontrast & 0x0020, DISP_BITMASK_PKP31) |
+ DISP_VAL_IF(newcontrast & 0x0040, DISP_BITMASK_PKP32));
+
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR,
+ DISP_VAL_IF(newcontrast & 0x0010, DISP_BITMASK_PKP40) |
+ DISP_VAL_IF(newcontrast & 0x0020, DISP_BITMASK_PKP41) |
+ DISP_VAL_IF(newcontrast & 0x0040, DISP_BITMASK_PKP42) |
+ DISP_VAL_IF(newcontrast & 0x0001, DISP_BITMASK_PKP50) |
+ DISP_VAL_IF(newcontrast & 0x0002, DISP_BITMASK_PKP51) |
+ DISP_VAL_IF(newcontrast & 0x0004, DISP_BITMASK_PKP52));
+
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0F07);
+
+#endif /* defined(TMD20QVGA_LCD_18BPP) */
+
+} /* End disp_set_contrast */
+
+void tmd20qvga_disp_clear_screen_area
+ (word start_row, word end_row, word start_column, word end_column) {
+ int32 i;
+
+ /* Clear the display screen */
+ DISP_SET_RECT(start_row, end_row, start_column, end_column);
+ DISP_CMD_OUT(DISP_CMD_RAMWR);
+ i = (end_row - start_row + 1) * (end_column - start_column + 1);
+ for (; i > 0; i--)
+ DISP_DATA_OUT_16TO18BPP(0x0);
+}
+
+static int __init tmd20qvga_probe(struct platform_device *pdev)
+{
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = tmd20qvga_probe,
+ .driver = {
+ .name = "ebi2_tmd_qvga",
+ },
+};
+
+static struct msm_fb_panel_data tmd20qvga_panel_data = {
+ .on = tmd20qvga_disp_on,
+ .off = tmd20qvga_disp_off,
+ .set_rect = tmd20qvga_disp_set_rect,
+};
+
+static struct platform_device this_device = {
+ .name = "ebi2_tmd_qvga",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmd20qvga_panel_data,
+ }
+};
+
+static int __init tmd20qvga_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+ ret = platform_driver_register(&this_driver);
+ if (!ret) {
+ pinfo = &tmd20qvga_panel_data.panel_info;
+ pinfo->xres = 240;
+ pinfo->yres = 320;
+ MSM_FB_SINGLE_MODE_PANEL(pinfo);
+ pinfo->type = EBI2_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->wait_cycle = 0x808000;
+#ifdef TMD20QVGA_LCD_18BPP
+ pinfo->bpp = 18;
+#else
+ pinfo->bpp = 16;
+#endif
+ pinfo->fb_num = 2;
+ pinfo->lcd.vsync_enable = TRUE;
+ pinfo->lcd.refx100 = 6000;
+ pinfo->lcd.v_back_porch = 16;
+ pinfo->lcd.v_front_porch = 4;
+ pinfo->lcd.v_pulse_width = 0;
+ pinfo->lcd.hw_vsync_mode = FALSE;
+ pinfo->lcd.vsync_notifier_period = 0;
+
+ ret = platform_device_register(&this_device);
+ if (ret)
+ platform_driver_unregister(&this_driver);
+ }
+
+ return ret;
+}
+
+module_init(tmd20qvga_init);
+
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c
new file mode 100644
index 0000000..694450a
--- /dev/null
+++ b/drivers/video/msm/external_common.c
@@ -0,0 +1,1229 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/mutex.h>
+
+#define DEBUG
+#define DEV_DBG_PREFIX "EXT_COMMON: "
+
+#include "msm_fb.h"
+#include "external_common.h"
+
+struct external_common_state_type *external_common_state;
+EXPORT_SYMBOL(external_common_state);
+DEFINE_MUTEX(external_common_state_hpd_mutex);
+EXPORT_SYMBOL(external_common_state_hpd_mutex);
+
+static int atoi(const char *name)
+{
+ int val = 0;
+
+ for (;; name++) {
+ switch (*name) {
+ case '0' ... '9':
+ val = 10*val+(*name-'0');
+ break;
+ default:
+ return val;
+ }
+ }
+}
+
+const char *video_format_2string(uint32 format)
+{
+ switch (format) {
+ default:
+#ifdef CONFIG_FB_MSM_HDMI_COMMON
+ case HDMI_VFRMT_640x480p60_4_3: return " 640x 480 p60 4/3";
+ case HDMI_VFRMT_720x480p60_4_3: return " 720x 480 p60 4/3";
+ case HDMI_VFRMT_720x480p60_16_9: return " 720x 480 p60 16/9";
+ case HDMI_VFRMT_1280x720p60_16_9: return "1280x 720 p60 16/9";
+ case HDMI_VFRMT_1920x1080i60_16_9: return "1920x1080 i60 16/9";
+ case HDMI_VFRMT_1440x480i60_4_3: return "1440x 480 i60 4/3";
+ case HDMI_VFRMT_1440x480i60_16_9: return "1440x 480 i60 16/9";
+ case HDMI_VFRMT_1440x240p60_4_3: return "1440x 240 p60 4/3";
+ case HDMI_VFRMT_1440x240p60_16_9: return "1440x 240 p60 16/9";
+ case HDMI_VFRMT_2880x480i60_4_3: return "2880x 480 i60 4/3";
+ case HDMI_VFRMT_2880x480i60_16_9: return "2880x 480 i60 16/9";
+ case HDMI_VFRMT_2880x240p60_4_3: return "2880x 240 p60 4/3";
+ case HDMI_VFRMT_2880x240p60_16_9: return "2880x 240 p60 16/9";
+ case HDMI_VFRMT_1440x480p60_4_3: return "1440x 480 p60 4/3";
+ case HDMI_VFRMT_1440x480p60_16_9: return "1440x 480 p60 16/9";
+ case HDMI_VFRMT_1920x1080p60_16_9: return "1920x1080 p60 16/9";
+ case HDMI_VFRMT_720x576p50_4_3: return " 720x 576 p50 4/3";
+ case HDMI_VFRMT_720x576p50_16_9: return " 720x 576 p50 16/9";
+ case HDMI_VFRMT_1280x720p50_16_9: return "1280x 720 p50 16/9";
+ case HDMI_VFRMT_1920x1080i50_16_9: return "1920x1080 i50 16/9";
+ case HDMI_VFRMT_1440x576i50_4_3: return "1440x 576 i50 4/3";
+ case HDMI_VFRMT_1440x576i50_16_9: return "1440x 576 i50 16/9";
+ case HDMI_VFRMT_1440x288p50_4_3: return "1440x 288 p50 4/3";
+ case HDMI_VFRMT_1440x288p50_16_9: return "1440x 288 p50 16/9";
+ case HDMI_VFRMT_2880x576i50_4_3: return "2880x 576 i50 4/3";
+ case HDMI_VFRMT_2880x576i50_16_9: return "2880x 576 i50 16/9";
+ case HDMI_VFRMT_2880x288p50_4_3: return "2880x 288 p50 4/3";
+ case HDMI_VFRMT_2880x288p50_16_9: return "2880x 288 p50 16/9";
+ case HDMI_VFRMT_1440x576p50_4_3: return "1440x 576 p50 4/3";
+ case HDMI_VFRMT_1440x576p50_16_9: return "1440x 576 p50 16/9";
+ case HDMI_VFRMT_1920x1080p50_16_9: return "1920x1080 p50 16/9";
+ case HDMI_VFRMT_1920x1080p24_16_9: return "1920x1080 p24 16/9";
+ case HDMI_VFRMT_1920x1080p25_16_9: return "1920x1080 p25 16/9";
+ case HDMI_VFRMT_1920x1080p30_16_9: return "1920x1080 p30 16/9";
+ case HDMI_VFRMT_2880x480p60_4_3: return "2880x 480 p60 4/3";
+ case HDMI_VFRMT_2880x480p60_16_9: return "2880x 480 p60 16/9";
+ case HDMI_VFRMT_2880x576p50_4_3: return "2880x 576 p50 4/3";
+ case HDMI_VFRMT_2880x576p50_16_9: return "2880x 576 p50 16/9";
+ case HDMI_VFRMT_1920x1250i50_16_9: return "1920x1250 i50 16/9";
+ case HDMI_VFRMT_1920x1080i100_16_9:return "1920x1080 i100 16/9";
+ case HDMI_VFRMT_1280x720p100_16_9: return "1280x 720 p100 16/9";
+ case HDMI_VFRMT_720x576p100_4_3: return " 720x 576 p100 4/3";
+ case HDMI_VFRMT_720x576p100_16_9: return " 720x 576 p100 16/9";
+ case HDMI_VFRMT_1440x576i100_4_3: return "1440x 576 i100 4/3";
+ case HDMI_VFRMT_1440x576i100_16_9: return "1440x 576 i100 16/9";
+ case HDMI_VFRMT_1920x1080i120_16_9:return "1920x1080 i120 16/9";
+ case HDMI_VFRMT_1280x720p120_16_9: return "1280x 720 p120 16/9";
+ case HDMI_VFRMT_720x480p120_4_3: return " 720x 480 p120 4/3";
+ case HDMI_VFRMT_720x480p120_16_9: return " 720x 480 p120 16/9";
+ case HDMI_VFRMT_1440x480i120_4_3: return "1440x 480 i120 4/3";
+ case HDMI_VFRMT_1440x480i120_16_9: return "1440x 480 i120 16/9";
+ case HDMI_VFRMT_720x576p200_4_3: return " 720x 576 p200 4/3";
+ case HDMI_VFRMT_720x576p200_16_9: return " 720x 576 p200 16/9";
+ case HDMI_VFRMT_1440x576i200_4_3: return "1440x 576 i200 4/3";
+ case HDMI_VFRMT_1440x576i200_16_9: return "1440x 576 i200 16/9";
+ case HDMI_VFRMT_720x480p240_4_3: return " 720x 480 p240 4/3";
+ case HDMI_VFRMT_720x480p240_16_9: return " 720x 480 p240 16/9";
+ case HDMI_VFRMT_1440x480i240_4_3: return "1440x 480 i240 4/3";
+ case HDMI_VFRMT_1440x480i240_16_9: return "1440x 480 i240 16/9";
+#elif defined(CONFIG_FB_MSM_TVOUT)
+ case TVOUT_VFRMT_NTSC_M_720x480i: return "NTSC_M_720x480i";
+ case TVOUT_VFRMT_NTSC_J_720x480i: return "NTSC_J_720x480i";
+ case TVOUT_VFRMT_PAL_BDGHIN_720x576i: return "PAL_BDGHIN_720x576i";
+ case TVOUT_VFRMT_PAL_M_720x480i: return "PAL_M_720x480i";
+ case TVOUT_VFRMT_PAL_N_720x480i: return "PAL_N_720x480i";
+#endif
+
+ }
+}
+EXPORT_SYMBOL(video_format_2string);
+
+static ssize_t external_common_rda_video_mode_str(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = snprintf(buf, PAGE_SIZE, "%s\n",
+ video_format_2string(external_common_state->video_resolution));
+ DEV_DBG("%s: '%s'\n", __func__,
+ video_format_2string(external_common_state->video_resolution));
+ return ret;
+}
+
+#ifdef CONFIG_FB_MSM_HDMI_COMMON
+struct hdmi_disp_mode_timing_type
+ hdmi_common_supported_video_mode_lut[HDMI_VFRMT_MAX] = {
+ HDMI_SETTINGS_640x480p60_4_3,
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x480p60_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x480p60_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1280x720p60_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1920x1080i60_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x480i60_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x480i60_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x240p60_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x240p60_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x480i60_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x480i60_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x240p60_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x240p60_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x480p60_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x480p60_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1920x1080p60_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x576p50_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x576p50_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1280x720p50_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1920x1080i50_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x576i50_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x576i50_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x288p50_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x288p50_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x576i50_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x576i50_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x288p50_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x288p50_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x576p50_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x576p50_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1920x1080p50_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1920x1080p24_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1920x1080p25_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1920x1080p30_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x480p60_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x480p60_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x576p50_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x576p50_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1920x1250i50_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1920x1080i100_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1280x720p100_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x576p100_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x576p100_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x576i100_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x576i100_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1920x1080i120_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1280x720p120_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x480p120_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x480p120_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x480i120_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x480i120_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x576p200_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x576p200_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x576i200_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x576i200_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x480p240_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x480p240_16_9),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x480i240_4_3),
+ VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x480i240_16_9),
+};
+EXPORT_SYMBOL(hdmi_common_supported_video_mode_lut);
+
+static ssize_t hdmi_common_rda_edid_modes(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+ int i;
+
+ buf[0] = 0;
+ if (external_common_state->disp_mode_list.num_of_elements) {
+ uint32 *video_mode = external_common_state->disp_mode_list
+ .disp_mode_list;
+ for (i = 0; i < external_common_state->disp_mode_list
+ .num_of_elements; ++i) {
+ if (ret > 0)
+ ret += snprintf(buf+ret, PAGE_SIZE-ret, ",%d",
+ *video_mode++ + 1);
+ else
+ ret += snprintf(buf+ret, PAGE_SIZE-ret, "%d",
+ *video_mode++ + 1);
+ }
+ } else
+ ret += snprintf(buf+ret, PAGE_SIZE-ret, "%d",
+ external_common_state->video_resolution+1);
+
+ DEV_DBG("%s: '%s'\n", __func__, buf);
+ ret += snprintf(buf+ret, PAGE_SIZE-ret, "\n");
+ return ret;
+}
+
+static ssize_t hdmi_common_rda_hdcp(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = snprintf(buf, PAGE_SIZE, "%d\n",
+ external_common_state->hdcp_active);
+ DEV_DBG("%s: '%d'\n", __func__,
+ external_common_state->hdcp_active);
+ return ret;
+}
+
+static ssize_t hdmi_common_rda_hpd(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret;
+ if (external_common_state->hpd_feature) {
+ ret = snprintf(buf, PAGE_SIZE, "%d\n",
+ external_common_state->hpd_feature_on);
+ DEV_DBG("%s: '%d'\n", __func__,
+ external_common_state->hpd_feature_on);
+ } else {
+ ret = snprintf(buf, PAGE_SIZE, "-1\n");
+ DEV_DBG("%s: 'not supported'\n", __func__);
+ }
+ return ret;
+}
+
+static ssize_t hdmi_common_wta_hpd(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ ssize_t ret = strnlen(buf, PAGE_SIZE);
+ int hpd = atoi(buf);
+
+ if (external_common_state->hpd_feature) {
+ if (hpd == 0 && external_common_state->hpd_feature_on) {
+ external_common_state->hpd_feature(0);
+ external_common_state->hpd_feature_on = 0;
+ DEV_DBG("%s: '%d'\n", __func__,
+ external_common_state->hpd_feature_on);
+ } else if (hpd == 1 && !external_common_state->hpd_feature_on) {
+ external_common_state->hpd_feature(1);
+ external_common_state->hpd_feature_on = 1;
+ DEV_DBG("%s: '%d'\n", __func__,
+ external_common_state->hpd_feature_on);
+ } else {
+ DEV_DBG("%s: '%d' (unchanged)\n", __func__,
+ external_common_state->hpd_feature_on);
+ }
+ } else {
+ DEV_DBG("%s: 'not supported'\n", __func__);
+ }
+
+ return ret;
+}
+
+static ssize_t hdmi_common_rda_3d_present(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = snprintf(buf, PAGE_SIZE, "%d\n",
+ external_common_state->present_3d);
+ DEV_DBG("%s: '%d'\n", __func__,
+ external_common_state->present_3d);
+ return ret;
+}
+
+static ssize_t hdmi_common_rda_hdcp_present(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = snprintf(buf, PAGE_SIZE, "%d\n",
+ external_common_state->present_hdcp);
+ DEV_DBG("%s: '%d'\n", __func__,
+ external_common_state->present_hdcp);
+ return ret;
+}
+#endif
+
+#ifdef CONFIG_FB_MSM_HDMI_3D
+static ssize_t hdmi_3d_rda_format_3d(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = snprintf(buf, PAGE_SIZE, "%d\n",
+ external_common_state->format_3d);
+ DEV_DBG("%s: '%d'\n", __func__,
+ external_common_state->format_3d);
+ return ret;
+}
+
+static ssize_t hdmi_3d_wta_format_3d(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ ssize_t ret = strnlen(buf, PAGE_SIZE);
+ int format_3d = atoi(buf);
+
+ if (format_3d >= 0 && format_3d <= 2) {
+ if (format_3d != external_common_state->format_3d) {
+ external_common_state->format_3d = format_3d;
+ if (external_common_state->switch_3d)
+ external_common_state->switch_3d(format_3d);
+ DEV_DBG("%s: '%d'\n", __func__,
+ external_common_state->format_3d);
+ } else {
+ DEV_DBG("%s: '%d' (unchanged)\n", __func__,
+ external_common_state->format_3d);
+ }
+ } else {
+ DEV_DBG("%s: '%d' (unknown)\n", __func__, format_3d);
+ }
+
+ return ret;
+}
+#endif
+
+static ssize_t external_common_rda_video_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = snprintf(buf, PAGE_SIZE, "%d\n",
+ external_common_state->video_resolution+1);
+ DEV_DBG("%s: '%d'\n", __func__,
+ external_common_state->video_resolution+1);
+ return ret;
+}
+
+static ssize_t external_common_wta_video_mode(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ ssize_t ret = strnlen(buf, PAGE_SIZE);
+ uint32 video_mode;
+#ifdef CONFIG_FB_MSM_HDMI_COMMON
+ const struct hdmi_disp_mode_timing_type *disp_mode;
+#endif
+ mutex_lock(&external_common_state_hpd_mutex);
+ if (!external_common_state->hpd_state) {
+ mutex_unlock(&external_common_state_hpd_mutex);
+ DEV_INFO("%s: FAILED: display off or cable disconnected\n",
+ __func__);
+ return ret;
+ }
+ mutex_unlock(&external_common_state_hpd_mutex);
+
+ video_mode = atoi(buf)-1;
+ kobject_uevent(external_common_state->uevent_kobj, KOBJ_OFFLINE);
+#ifdef CONFIG_FB_MSM_HDMI_COMMON
+ disp_mode = hdmi_common_get_supported_mode(video_mode);
+ if (!disp_mode) {
+ DEV_INFO("%s: FAILED: mode not supported (%d)\n",
+ __func__, video_mode);
+ return ret;
+ }
+ external_common_state->disp_mode_list.num_of_elements = 1;
+ external_common_state->disp_mode_list.disp_mode_list[0] = video_mode;
+#elif defined(CONFIG_FB_MSM_TVOUT)
+ external_common_state->video_resolution = video_mode;
+#endif
+ DEV_DBG("%s: 'mode=%d %s' successful (sending OFF/ONLINE)\n", __func__,
+ video_mode, video_format_2string(video_mode));
+ kobject_uevent(external_common_state->uevent_kobj, KOBJ_ONLINE);
+ return ret;
+}
+
+static ssize_t external_common_rda_connected(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret;
+ mutex_lock(&external_common_state_hpd_mutex);
+ ret = snprintf(buf, PAGE_SIZE, "%d\n",
+ external_common_state->hpd_state);
+ DEV_DBG("%s: '%d'\n", __func__,
+ external_common_state->hpd_state);
+ mutex_unlock(&external_common_state_hpd_mutex);
+ return ret;
+}
+
+static DEVICE_ATTR(video_mode, S_IRUGO | S_IWUGO,
+ external_common_rda_video_mode, external_common_wta_video_mode);
+static DEVICE_ATTR(video_mode_str, S_IRUGO, external_common_rda_video_mode_str,
+ NULL);
+static DEVICE_ATTR(connected, S_IRUGO, external_common_rda_connected, NULL);
+#ifdef CONFIG_FB_MSM_HDMI_COMMON
+static DEVICE_ATTR(edid_modes, S_IRUGO, hdmi_common_rda_edid_modes, NULL);
+static DEVICE_ATTR(hpd, S_IRUGO | S_IWUGO, hdmi_common_rda_hpd,
+ hdmi_common_wta_hpd);
+static DEVICE_ATTR(hdcp, S_IRUGO, hdmi_common_rda_hdcp, NULL);
+static DEVICE_ATTR(3d_present, S_IRUGO, hdmi_common_rda_3d_present, NULL);
+static DEVICE_ATTR(hdcp_present, S_IRUGO, hdmi_common_rda_hdcp_present, NULL);
+#endif
+#ifdef CONFIG_FB_MSM_HDMI_3D
+static DEVICE_ATTR(format_3d, S_IRUGO | S_IWUGO, hdmi_3d_rda_format_3d,
+ hdmi_3d_wta_format_3d);
+#endif
+
+static struct attribute *external_common_fs_attrs[] = {
+ &dev_attr_video_mode.attr,
+ &dev_attr_video_mode_str.attr,
+ &dev_attr_connected.attr,
+#ifdef CONFIG_FB_MSM_HDMI_COMMON
+ &dev_attr_edid_modes.attr,
+ &dev_attr_hdcp.attr,
+ &dev_attr_hpd.attr,
+ &dev_attr_3d_present.attr,
+ &dev_attr_hdcp_present.attr,
+#endif
+#ifdef CONFIG_FB_MSM_HDMI_3D
+ &dev_attr_format_3d.attr,
+#endif
+ NULL,
+};
+static struct attribute_group external_common_fs_attr_group = {
+ .attrs = external_common_fs_attrs,
+};
+
+/* create external interface kobject and initialize */
+int external_common_state_create(struct platform_device *pdev)
+{
+ int rc;
+ struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
+ if (!mfd) {
+ DEV_ERR("%s: mfd not found\n", __func__);
+ return -ENODEV;
+ }
+ if (!mfd->fbi) {
+ DEV_ERR("%s: mfd->fbi not found\n", __func__);
+ return -ENODEV;
+ }
+ if (!mfd->fbi->dev) {
+ DEV_ERR("%s: mfd->fbi->dev not found\n", __func__);
+ return -ENODEV;
+ }
+ rc = sysfs_create_group(&mfd->fbi->dev->kobj,
+ &external_common_fs_attr_group);
+ if (rc) {
+ DEV_ERR("%s: sysfs group creation failed, rc=%d\n", __func__,
+ rc);
+ return rc;
+ }
+ external_common_state->uevent_kobj = &mfd->fbi->dev->kobj;
+ DEV_ERR("%s: sysfs group %p\n", __func__,
+ external_common_state->uevent_kobj);
+
+ kobject_uevent(external_common_state->uevent_kobj, KOBJ_ADD);
+ DEV_DBG("%s: kobject_uevent(KOBJ_ADD)\n", __func__);
+ return 0;
+}
+EXPORT_SYMBOL(external_common_state_create);
+
+void external_common_state_remove(void)
+{
+ if (external_common_state->uevent_kobj)
+ sysfs_remove_group(external_common_state->uevent_kobj,
+ &external_common_fs_attr_group);
+ external_common_state->uevent_kobj = NULL;
+}
+EXPORT_SYMBOL(external_common_state_remove);
+
+#ifdef CONFIG_FB_MSM_HDMI_COMMON
+/* The Logic ID for HDMI TX Core. Currently only support 1 HDMI TX Core. */
+struct hdmi_edid_video_mode_property_type {
+ uint32 video_code;
+ uint32 active_h;
+ uint32 active_v;
+ boolean interlaced;
+ uint32 total_h;
+ uint32 total_blank_h;
+ uint32 total_v;
+ uint32 total_blank_v;
+ /* Must divide by 1000 to get the frequency */
+ uint32 freq_h;
+ /* Must divide by 1000 to get the frequency */
+ uint32 freq_v;
+ /* Must divide by 1000 to get the frequency */
+ uint32 pixel_freq;
+ /* Must divide by 1000 to get the frequency */
+ uint32 refresh_rate;
+ boolean aspect_ratio_4_3;
+};
+
+/* LUT is sorted from lowest Active H to highest Active H - ease searching */
+static struct hdmi_edid_video_mode_property_type
+ hdmi_edid_disp_mode_lut[] = {
+
+ /* All 640 H Active */
+ {HDMI_VFRMT_640x480p60_4_3, 640, 480, FALSE, 800, 160, 525, 45,
+ 31465, 59940, 25175, 59940, TRUE},
+ {HDMI_VFRMT_640x480p60_4_3, 640, 480, FALSE, 800, 160, 525, 45,
+ 31500, 60000, 25200, 60000, TRUE},
+
+ /* All 720 H Active */
+ {HDMI_VFRMT_720x576p50_4_3, 720, 576, FALSE, 864, 144, 625, 49,
+ 31250, 50000, 27000, 50000, TRUE},
+ {HDMI_VFRMT_720x480p60_4_3, 720, 480, FALSE, 858, 138, 525, 45,
+ 31465, 59940, 27000, 59940, TRUE},
+ {HDMI_VFRMT_720x480p60_4_3, 720, 480, FALSE, 858, 138, 525, 45,
+ 31500, 60000, 27030, 60000, TRUE},
+ {HDMI_VFRMT_720x576p100_4_3, 720, 576, FALSE, 864, 144, 625, 49,
+ 62500, 100000, 54000, 100000, TRUE},
+ {HDMI_VFRMT_720x480p120_4_3, 720, 480, FALSE, 858, 138, 525, 45,
+ 62937, 119880, 54000, 119880, TRUE},
+ {HDMI_VFRMT_720x480p120_4_3, 720, 480, FALSE, 858, 138, 525, 45,
+ 63000, 120000, 54054, 120000, TRUE},
+ {HDMI_VFRMT_720x576p200_4_3, 720, 576, FALSE, 864, 144, 625, 49,
+ 125000, 200000, 108000, 200000, TRUE},
+ {HDMI_VFRMT_720x480p240_4_3, 720, 480, FALSE, 858, 138, 525, 45,
+ 125874, 239760, 108000, 239000, TRUE},
+ {HDMI_VFRMT_720x480p240_4_3, 720, 480, FALSE, 858, 138, 525, 45,
+ 126000, 240000, 108108, 240000, TRUE},
+
+ /* All 1280 H Active */
+ {HDMI_VFRMT_1280x720p50_16_9, 1280, 720, FALSE, 1980, 700, 750, 30,
+ 37500, 50000, 74250, 50000, FALSE},
+ {HDMI_VFRMT_1280x720p60_16_9, 1280, 720, FALSE, 1650, 370, 750, 30,
+ 44955, 59940, 74176, 59940, FALSE},
+ {HDMI_VFRMT_1280x720p60_16_9, 1280, 720, FALSE, 1650, 370, 750, 30,
+ 45000, 60000, 74250, 60000, FALSE},
+ {HDMI_VFRMT_1280x720p100_16_9, 1280, 720, FALSE, 1980, 700, 750, 30,
+ 75000, 100000, 148500, 100000, FALSE},
+ {HDMI_VFRMT_1280x720p120_16_9, 1280, 720, FALSE, 1650, 370, 750, 30,
+ 89909, 119880, 148352, 119880, FALSE},
+ {HDMI_VFRMT_1280x720p120_16_9, 1280, 720, FALSE, 1650, 370, 750, 30,
+ 90000, 120000, 148500, 120000, FALSE},
+
+ /* All 1440 H Active */
+ {HDMI_VFRMT_1440x576i50_4_3, 1440, 576, TRUE, 1728, 288, 625, 24,
+ 15625, 50000, 27000, 50000, TRUE},
+ {HDMI_VFRMT_720x288p50_4_3, 1440, 288, FALSE, 1728, 288, 312, 24,
+ 15625, 50080, 27000, 50000, TRUE},
+ {HDMI_VFRMT_720x288p50_4_3, 1440, 288, FALSE, 1728, 288, 313, 25,
+ 15625, 49920, 27000, 50000, TRUE},
+ {HDMI_VFRMT_720x288p50_4_3, 1440, 288, FALSE, 1728, 288, 314, 26,
+ 15625, 49761, 27000, 50000, TRUE},
+ {HDMI_VFRMT_1440x576p50_4_3, 1440, 576, FALSE, 1728, 288, 625, 49,
+ 31250, 50000, 54000, 50000, TRUE},
+ {HDMI_VFRMT_1440x480i60_4_3, 1440, 480, TRUE, 1716, 276, 525, 22,
+ 15734, 59940, 27000, 59940, TRUE},
+ {HDMI_VFRMT_1440x240p60_4_3, 1440, 240, FALSE, 1716, 276, 262, 22,
+ 15734, 60054, 27000, 59940, TRUE},
+ {HDMI_VFRMT_1440x240p60_4_3, 1440, 240, FALSE, 1716, 276, 263, 23,
+ 15734, 59826, 27000, 59940, TRUE},
+ {HDMI_VFRMT_1440x480p60_4_3, 1440, 480, FALSE, 1716, 276, 525, 45,
+ 31469, 59940, 54000, 59940, TRUE},
+ {HDMI_VFRMT_1440x480i60_4_3, 1440, 480, TRUE, 1716, 276, 525, 22,
+ 15750, 60000, 27027, 60000, TRUE},
+ {HDMI_VFRMT_1440x240p60_4_3, 1440, 240, FALSE, 1716, 276, 262, 22,
+ 15750, 60115, 27027, 60000, TRUE},
+ {HDMI_VFRMT_1440x240p60_4_3, 1440, 240, FALSE, 1716, 276, 263, 23,
+ 15750, 59886, 27027, 60000, TRUE},
+ {HDMI_VFRMT_1440x480p60_4_3, 1440, 480, FALSE, 1716, 276, 525, 45,
+ 31500, 60000, 54054, 60000, TRUE},
+ {HDMI_VFRMT_1440x576i100_4_3, 1440, 576, TRUE, 1728, 288, 625, 24,
+ 31250, 100000, 54000, 100000, TRUE},
+ {HDMI_VFRMT_1440x480i120_4_3, 1440, 480, TRUE, 1716, 276, 525, 22,
+ 31469, 119880, 54000, 119880, TRUE},
+ {HDMI_VFRMT_1440x480i120_4_3, 1440, 480, TRUE, 1716, 276, 525, 22,
+ 31500, 120000, 54054, 120000, TRUE},
+ {HDMI_VFRMT_1440x576i200_4_3, 1440, 576, TRUE, 1728, 288, 625, 24,
+ 62500, 200000, 108000, 200000, TRUE},
+ {HDMI_VFRMT_1440x480i240_4_3, 1440, 480, TRUE, 1716, 276, 525, 22,
+ 62937, 239760, 108000, 239000, TRUE},
+ {HDMI_VFRMT_1440x480i240_4_3, 1440, 480, TRUE, 1716, 276, 525, 22,
+ 63000, 240000, 108108, 240000, TRUE},
+
+ /* All 1920 H Active */
+ {HDMI_VFRMT_1920x1080p60_16_9, 1920, 1080, FALSE, 2200, 280, 1125,
+ 45, 67433, 59940, 148352, 59940, FALSE},
+ {HDMI_VFRMT_1920x1080p60_16_9, 1920, 1080, TRUE, 2200, 280, 1125,
+ 45, 67500, 60000, 148500, 60000, FALSE},
+ {HDMI_VFRMT_1920x1080p50_16_9, 1920, 1080, FALSE, 2640, 720, 1125,
+ 45, 56250, 50000, 148500, 50000, FALSE},
+ {HDMI_VFRMT_1920x1080p24_16_9, 1920, 1080, FALSE, 2750, 830, 1125,
+ 45, 26973, 23976, 74176, 24000, FALSE},
+ {HDMI_VFRMT_1920x1080p24_16_9, 1920, 1080, FALSE, 2750, 830, 1125,
+ 45, 27000, 24000, 74250, 24000, FALSE},
+ {HDMI_VFRMT_1920x1080p25_16_9, 1920, 1080, FALSE, 2640, 720, 1125,
+ 45, 28125, 25000, 74250, 25000, FALSE},
+ {HDMI_VFRMT_1920x1080p30_16_9, 1920, 1080, FALSE, 2200, 280, 1125,
+ 45, 33716, 29970, 74176, 30000, FALSE},
+ {HDMI_VFRMT_1920x1080p30_16_9, 1920, 1080, FALSE, 2200, 280, 1125,
+ 45, 33750, 30000, 74250, 30000, FALSE},
+ {HDMI_VFRMT_1920x1080i50_16_9, 1920, 1080, TRUE, 2304, 384, 1250,
+ 85, 31250, 50000, 72000, 50000, FALSE},
+ {HDMI_VFRMT_1920x1080i60_16_9, 1920, 1080, TRUE, 2200, 280, 1125,
+ 22, 33716, 59940, 74176, 59940, FALSE},
+ {HDMI_VFRMT_1920x1080i60_16_9, 1920, 1080, TRUE, 2200, 280, 1125,
+ 22, 33750, 60000, 74250, 60000, FALSE},
+ {HDMI_VFRMT_1920x1080i100_16_9, 1920, 1080, TRUE, 2640, 720, 1125,
+ 22, 56250, 100000, 148500, 100000, FALSE},
+ {HDMI_VFRMT_1920x1080i120_16_9, 1920, 1080, TRUE, 2200, 280, 1125,
+ 22, 67432, 119880, 148352, 119980, FALSE},
+ {HDMI_VFRMT_1920x1080i120_16_9, 1920, 1080, TRUE, 2200, 280, 1125,
+ 22, 67500, 120000, 148500, 120000, FALSE},
+
+ /* All 2880 H Active */
+ {HDMI_VFRMT_2880x576i50_4_3, 2880, 576, TRUE, 3456, 576, 625, 24,
+ 15625, 50000, 54000, 50000, TRUE},
+ {HDMI_VFRMT_2880x288p50_4_3, 2880, 576, FALSE, 3456, 576, 312, 24,
+ 15625, 50080, 54000, 50000, TRUE},
+ {HDMI_VFRMT_2880x288p50_4_3, 2880, 576, FALSE, 3456, 576, 313, 25,
+ 15625, 49920, 54000, 50000, TRUE},
+ {HDMI_VFRMT_2880x288p50_4_3, 2880, 576, FALSE, 3456, 576, 314, 26,
+ 15625, 49761, 54000, 50000, TRUE},
+ {HDMI_VFRMT_2880x576p50_4_3, 2880, 576, FALSE, 3456, 576, 625, 49,
+ 31250, 50000, 108000, 50000, TRUE},
+ {HDMI_VFRMT_2880x480i60_4_3, 2880, 480, TRUE, 3432, 552, 525, 22,
+ 15734, 59940, 54000, 59940, TRUE},
+ {HDMI_VFRMT_2880x240p60_4_3, 2880, 480, FALSE, 3432, 552, 262, 22,
+ 15734, 60054, 54000, 59940, TRUE},
+ {HDMI_VFRMT_2880x240p60_4_3, 2880, 480, FALSE, 3432, 552, 263, 23,
+ 15734, 59940, 54000, 59940, TRUE},
+ {HDMI_VFRMT_2880x480p60_4_3, 2880, 480, FALSE, 3432, 552, 525, 45,
+ 31469, 59940, 108000, 59940, TRUE},
+ {HDMI_VFRMT_2880x480i60_4_3, 2880, 480, TRUE, 3432, 552, 525, 22,
+ 15750, 60000, 54054, 60000, TRUE},
+ {HDMI_VFRMT_2880x240p60_4_3, 2880, 240, FALSE, 3432, 552, 262, 22,
+ 15750, 60115, 54054, 60000, TRUE},
+ {HDMI_VFRMT_2880x240p60_4_3, 2880, 240, FALSE, 3432, 552, 262, 23,
+ 15750, 59886, 54054, 60000, TRUE},
+ {HDMI_VFRMT_2880x480p60_4_3, 2880, 480, FALSE, 3432, 552, 525, 45,
+ 31500, 60000, 108108, 60000, TRUE},
+};
+
+static const uint8 *hdmi_edid_find_block(const uint8 *in_buf, uint8 type,
+ uint8 *len)
+{
+ /* the start of data block collection, start of Video Data Block */
+ uint32 offset = 4;
+
+ *len = 0;
+ if (in_buf[2] == 4) { /* no non-DTD data present */
+ DEV_WARN("EDID: no non-DTD data present\n");
+ return NULL;
+ }
+ while (offset < 0x80) {
+ uint8 block_len = in_buf[offset] & 0x1F;
+ if ((in_buf[offset] >> 5) == type) {
+ *len = block_len;
+ DEV_DBG("EDID: block=%d found @ %d with length=%d\n",
+ type, offset, block_len);
+ return in_buf+offset;
+ }
+ offset += 1 + block_len;
+ }
+ DEV_WARN("EDID: block=%d not found in EDID block\n", type);
+ return NULL;
+}
+
+static void hdmi_edid_extract_vendor_id(const uint8 *in_buf,
+ char *vendor_id)
+{
+ uint32 id_codes = ((uint32)in_buf[8] << 8) + in_buf[9];
+
+ vendor_id[0] = 'A' - 1 + ((id_codes >> 10) & 0x1F);
+ vendor_id[1] = 'A' - 1 + ((id_codes >> 5) & 0x1F);
+ vendor_id[2] = 'A' - 1 + (id_codes & 0x1F);
+ vendor_id[3] = 0;
+}
+
+static uint32 hdmi_edid_extract_ieee_reg_id(const uint8 *in_buf)
+{
+ uint8 len;
+ const uint8 *vsd = hdmi_edid_find_block(in_buf, 3, &len);
+
+ if (vsd == NULL)
+ return 0;
+
+ DEV_DBG("EDID: VSD PhyAddr=%04x, MaxTMDS=%dMHz\n",
+ ((uint32)vsd[6] << 8) + (uint32)vsd[5], (uint32)vsd[7] * 5);
+ return ((uint32)vsd[3] << 16) + ((uint32)vsd[2] << 8) + (uint32)vsd[1];
+}
+
+static void hdmi_edid_extract_3d_present(const uint8 *in_buf)
+{
+ uint8 len, offset;
+ const uint8 *vsd = hdmi_edid_find_block(in_buf, 3, &len);
+
+ external_common_state->present_3d = 0;
+ if (vsd == NULL || len < 9) {
+ DEV_DBG("EDID[3D]: block-id 3 not found or not long enough\n");
+ return;
+ }
+
+ offset = !(vsd[8] & BIT(7)) ? 9 : 13;
+ DEV_DBG("EDID: 3D present @ %d = %02x\n", offset, vsd[offset]);
+ if (vsd[offset] >> 7) { /* 3D format indication present */
+ DEV_INFO("EDID: 3D present, 3D-len=%d\n", vsd[offset+1] & 0x1F);
+ external_common_state->present_3d = 1;
+ }
+}
+
+
+static void hdmi_edid_extract_latency_fields(const uint8 *in_buf)
+{
+ uint8 len;
+ const uint8 *vsd = hdmi_edid_find_block(in_buf, 3, &len);
+
+ if (vsd == NULL || len < 12 || !(vsd[8] & BIT(7))) {
+ external_common_state->video_latency = (uint16)-1;
+ external_common_state->audio_latency = (uint16)-1;
+ DEV_DBG("EDID: No audio/video latency present\n");
+ } else {
+ external_common_state->video_latency = vsd[9];
+ external_common_state->audio_latency = vsd[10];
+ DEV_DBG("EDID: video-latency=%04x, audio-latency=%04x\n",
+ external_common_state->video_latency,
+ external_common_state->audio_latency);
+ }
+}
+
+static void hdmi_edid_extract_speaker_allocation_data(const uint8 *in_buf)
+{
+ uint8 len;
+ const uint8 *sad = hdmi_edid_find_block(in_buf, 4, &len);
+
+ if (sad == NULL)
+ return;
+
+ external_common_state->speaker_allocation_block = sad[1];
+ DEV_DBG("EDID: speaker allocation data=%s%s%s%s%s%s%s\n",
+ (sad[1] & BIT(0)) ? "FL/FR," : "",
+ (sad[1] & BIT(1)) ? "LFE," : "",
+ (sad[1] & BIT(2)) ? "FC," : "",
+ (sad[1] & BIT(3)) ? "RL/RR," : "",
+ (sad[1] & BIT(4)) ? "RC," : "",
+ (sad[1] & BIT(5)) ? "FLC/FRC," : "",
+ (sad[1] & BIT(6)) ? "LFE," : "");
+}
+
+static void hdmi_edid_extract_audio_data_blocks(const uint8 *in_buf)
+{
+ uint8 len;
+ const uint8 *sad = hdmi_edid_find_block(in_buf, 1, &len);
+ uint32 *adb = external_common_state->audio_data_blocks;
+
+ if (sad == NULL)
+ return;
+
+ external_common_state->audio_data_block_cnt = 0;
+ while (len >= 3 && external_common_state->audio_data_block_cnt < 16) {
+ DEV_DBG("EDID: Audio Data Block=<ch=%d, format=%d "
+ "sampling=0x%02x bit-depth=0x%02x>\n",
+ (sad[1] & 0x7)+1, sad[1] >> 3, sad[2], sad[3]);
+ *adb++ = (uint32)sad[1] + ((uint32)sad[2] << 8)
+ + ((uint32)sad[2] << 16);
+ ++external_common_state->audio_data_block_cnt;
+ len -= 3;
+ sad += 3;
+ }
+}
+
+
+static void hdmi_edid_detail_desc(const uint8 *data_buf, uint32 *disp_mode)
+{
+ boolean aspect_ratio_4_3 = FALSE;
+ boolean interlaced = FALSE;
+ uint32 active_h = 0;
+ uint32 active_v = 0;
+ uint32 blank_h = 0;
+ uint32 blank_v = 0;
+ uint32 ndx = 0;
+ uint32 max_num_of_elements = 0;
+ uint32 img_size_h = 0;
+ uint32 img_size_v = 0;
+
+ /* See VESA Spec */
+ /* EDID_TIMING_DESC_UPPER_H_NIBBLE[0x4]: Relative Offset to the EDID
+ * detailed timing descriptors - Upper 4 bit for each H active/blank
+ * field */
+ /* EDID_TIMING_DESC_H_ACTIVE[0x2]: Relative Offset to the EDID detailed
+ * timing descriptors - H active */
+ active_h = ((((uint32)data_buf[0x4] >> 0x4) & 0xF) << 8)
+ | data_buf[0x2];
+
+ /* EDID_TIMING_DESC_H_BLANK[0x3]: Relative Offset to the EDID detailed
+ * timing descriptors - H blank */
+ blank_h = (((uint32)data_buf[0x4] & 0xF) << 8)
+ | data_buf[0x3];
+
+ /* EDID_TIMING_DESC_UPPER_V_NIBBLE[0x7]: Relative Offset to the EDID
+ * detailed timing descriptors - Upper 4 bit for each V active/blank
+ * field */
+ /* EDID_TIMING_DESC_V_ACTIVE[0x5]: Relative Offset to the EDID detailed
+ * timing descriptors - V active */
+ active_v = ((((uint32)data_buf[0x7] >> 0x4) & 0xF) << 8)
+ | data_buf[0x5];
+
+ /* EDID_TIMING_DESC_V_BLANK[0x6]: Relative Offset to the EDID detailed
+ * timing descriptors - V blank */
+ blank_v = (((uint32)data_buf[0x7] & 0xF) << 8)
+ | data_buf[0x6];
+
+ /* EDID_TIMING_DESC_IMAGE_SIZE_UPPER_NIBBLE[0xE]: Relative Offset to the
+ * EDID detailed timing descriptors - Image Size upper nibble
+ * V and H */
+ /* EDID_TIMING_DESC_H_IMAGE_SIZE[0xC]: Relative Offset to the EDID
+ * detailed timing descriptors - H image size */
+ /* EDID_TIMING_DESC_V_IMAGE_SIZE[0xD]: Relative Offset to the EDID
+ * detailed timing descriptors - V image size */
+ img_size_h = ((((uint32)data_buf[0xE] >> 0x4) & 0xF) << 8)
+ | data_buf[0xC];
+ img_size_v = (((uint32)data_buf[0xE] & 0xF) << 8)
+ | data_buf[0xD];
+
+ aspect_ratio_4_3 = (img_size_h * 3 == img_size_v * 4);
+
+ max_num_of_elements = sizeof(hdmi_edid_disp_mode_lut)
+ / sizeof(*hdmi_edid_disp_mode_lut);
+
+ /* Break table in half and search using H Active */
+ ndx = active_h < hdmi_edid_disp_mode_lut[max_num_of_elements / 2]
+ .active_h ? 0 : max_num_of_elements / 2;
+
+ /* EDID_TIMING_DESC_INTERLACE[0xD:8]: Relative Offset to the EDID
+ * detailed timing descriptors - Interlace flag */
+ interlaced = (data_buf[0xD] & 0x80) >> 7;
+
+ DEV_DBG("%s: A[%ux%u] B[%ux%u] V[%ux%u] %s\n", __func__,
+ active_h, active_v, blank_h, blank_v, img_size_h, img_size_v,
+ interlaced ? "i" : "p");
+
+ *disp_mode = HDMI_VFRMT_FORCE_32BIT;
+ while (ndx < max_num_of_elements) {
+ const struct hdmi_edid_video_mode_property_type *edid =
+ hdmi_edid_disp_mode_lut+ndx;
+
+ if ((interlaced == edid->interlaced) &&
+ (active_h == edid->active_h) &&
+ (blank_h == edid->total_blank_h) &&
+ (blank_v == edid->total_blank_v) &&
+ ((active_v == edid->active_v) ||
+ (active_v == (edid->active_v + 1)))
+ ) {
+ if (edid->aspect_ratio_4_3 && !aspect_ratio_4_3)
+ /* Aspect ratio 16:9 */
+ *disp_mode = edid->video_code + 1;
+ else
+ /* Aspect ratio 4:3 */
+ *disp_mode = edid->video_code;
+
+ DEV_DBG("%s: mode found:%d\n", __func__, *disp_mode);
+ break;
+ }
+ ++ndx;
+ }
+ if (ndx == max_num_of_elements)
+ DEV_INFO("%s: *no mode* found\n", __func__);
+}
+
+static void add_supported_video_format(
+ struct hdmi_disp_mode_list_type *disp_mode_list,
+ uint32 video_format)
+{
+ const struct hdmi_disp_mode_timing_type *timing =
+ hdmi_common_get_supported_mode(video_format);
+ boolean supported = timing != NULL;
+
+ if (video_format >= HDMI_VFRMT_MAX)
+ return;
+
+ DEV_DBG("EDID: format: %d [%s], %s\n",
+ video_format, video_format_2string(video_format),
+ supported ? "Supported" : "Not-Supported");
+ if (supported)
+ disp_mode_list->disp_mode_list[
+ disp_mode_list->num_of_elements++] = video_format;
+}
+
+static void hdmi_edid_get_display_mode(const uint8 *data_buf,
+ struct hdmi_disp_mode_list_type *disp_mode_list,
+ uint32 num_og_cea_blocks)
+{
+ uint8 i = 0;
+ uint32 video_format = HDMI_VFRMT_640x480p60_4_3;
+ boolean has480p = FALSE;
+ uint8 len;
+ const uint8 *svd = num_og_cea_blocks ?
+ hdmi_edid_find_block(data_buf+0x80, 2, &len) : NULL;
+
+ disp_mode_list->num_of_elements = 0;
+ if (svd != NULL) {
+ ++svd;
+ for (i = 0; i < len; ++i, ++svd) {
+ /* Subtract 1 because it is zero based in the driver,
+ * while the Video identification code is 1 based in the
+ * CEA_861D spec */
+ video_format = (*svd & 0x7F) - 1;
+ add_supported_video_format(disp_mode_list,
+ video_format);
+ if (video_format == HDMI_VFRMT_640x480p60_4_3)
+ has480p = TRUE;
+ }
+ } else if (!num_og_cea_blocks) {
+ /* Detailed timing descriptors */
+ uint32 desc_offset = 0;
+ /* Maximum 4 timing descriptor in block 0 - No CEA
+ * extension in this case */
+ /* EDID_FIRST_TIMING_DESC[0x36] - 1st detailed timing
+ * descriptor */
+ /* EDID_DETAIL_TIMING_DESC_BLCK_SZ[0x12] - Each detailed timing
+ * descriptor has block size of 18 */
+ while (4 > i && 0 != data_buf[0x36+desc_offset]) {
+ hdmi_edid_detail_desc(data_buf+0x36+desc_offset,
+ &video_format);
+ add_supported_video_format(disp_mode_list,
+ video_format);
+ if (video_format == HDMI_VFRMT_640x480p60_4_3)
+ has480p = TRUE;
+ desc_offset += 0x12;
+ ++i;
+ }
+ } else if (1 == num_og_cea_blocks) {
+ uint32 desc_offset = 0;
+ /* Parse block 1 - CEA extension byte offset of first
+ * detailed timing generation - offset is relevant to
+ * the offset of block 1 */
+
+ /* EDID_CEA_EXTENSION_FIRST_DESC[0x82]: Offset to CEA
+ * extension first timing desc - indicate the offset of
+ * the first detailed timing descriptor */
+ /* EDID_BLOCK_SIZE = 0x80 Each page size in the EDID ROM */
+ desc_offset = data_buf[0x82];
+ while (0 != data_buf[0x80 + desc_offset]) {
+ hdmi_edid_detail_desc(data_buf+0x36+desc_offset,
+ &video_format);
+ add_supported_video_format(disp_mode_list,
+ video_format);
+ if (video_format == HDMI_VFRMT_640x480p60_4_3)
+ has480p = TRUE;
+ desc_offset += 0x12;
+ ++i;
+ }
+ }
+
+ if (!has480p)
+ /* Need to add default 640 by 480 timings, in case not described
+ * in the EDID structure.
+ * All DTV sink devices should support this mode */
+ add_supported_video_format(disp_mode_list,
+ HDMI_VFRMT_640x480p60_4_3);
+}
+
+static int hdmi_common_read_edid_block(int block, uint8 *edid_buf)
+{
+ uint32 ndx, check_sum;
+ int status = external_common_state->read_edid_block(block, edid_buf);
+ if (status || block > 0)
+ goto error;
+
+ /* Calculate checksum */
+ check_sum = 0;
+ for (ndx = 0; ndx < 0x80; ++ndx)
+ check_sum += edid_buf[ndx];
+
+ if (check_sum & 0xFF) {
+#ifdef DEBUG
+ const u8 *b = edid_buf;
+#endif
+ DEV_ERR("%s: failed CHECKSUM (read:%x, expected:%x)\n",
+ __func__, (uint8)edid_buf[0x7F], (uint8)check_sum);
+
+#ifdef DEBUG
+ for (ndx = 0; ndx < 0x100; ndx += 16)
+ DEV_DBG("EDID[%02x-%02x] %02x %02x %02x %02x "
+ "%02x %02x %02x %02x %02x %02x %02x %02x "
+ "%02x %02x %02x %02x\n", ndx, ndx+15,
+ b[ndx+0], b[ndx+1], b[ndx+2], b[ndx+3],
+ b[ndx+4], b[ndx+5], b[ndx+6], b[ndx+7],
+ b[ndx+8], b[ndx+9], b[ndx+10], b[ndx+11],
+ b[ndx+12], b[ndx+13], b[ndx+14], b[ndx+15]);
+#endif
+ status = -EPROTO;
+ goto error;
+ }
+
+error:
+ return status;
+}
+
+static boolean check_edid_header(const uint8 *edid_buf)
+{
+ return (edid_buf[0] == 0x00) && (edid_buf[1] == 0xff)
+ && (edid_buf[2] == 0xff) && (edid_buf[3] == 0xff)
+ && (edid_buf[4] == 0xff) && (edid_buf[5] == 0xff)
+ && (edid_buf[6] == 0xff) && (edid_buf[7] == 0x00);
+}
+
+int hdmi_common_read_edid(void)
+{
+ int status = 0;
+ uint32 cea_extension_ver = 0;
+ uint32 num_og_cea_blocks = 0;
+ uint32 ieee_reg_id = 0;
+ uint32 i = 1;
+ char vendor_id[5];
+ /* EDID_BLOCK_SIZE[0x80] Each page size in the EDID ROM */
+ uint8 edid_buf[0x80 * 4];
+
+ external_common_state->present_3d = 0;
+ memset(&external_common_state->disp_mode_list, 0,
+ sizeof(external_common_state->disp_mode_list));
+ memset(edid_buf, 0, sizeof(edid_buf));
+
+ status = hdmi_common_read_edid_block(0, edid_buf);
+ if (status || !check_edid_header(edid_buf)) {
+ if (!status)
+ status = -EPROTO;
+ DEV_ERR("%s: edid read block(0) failed: %d "
+ "[%02x%02x%02x%02x%02x%02x%02x%02x]\n", __func__,
+ status,
+ edid_buf[0], edid_buf[1], edid_buf[2], edid_buf[3],
+ edid_buf[4], edid_buf[5], edid_buf[6], edid_buf[7]);
+ goto error;
+ }
+ hdmi_edid_extract_vendor_id(edid_buf, vendor_id);
+
+ /* EDID_CEA_EXTENSION_FLAG[0x7E] - CEC extension byte */
+ num_og_cea_blocks = edid_buf[0x7E];
+
+ DEV_DBG("[JSR] (%s): No. of CEA blocks is [%u]\n", __func__,
+ num_og_cea_blocks);
+ /* Find out any CEA extension blocks following block 0 */
+ switch (num_og_cea_blocks) {
+ case 0: /* No CEA extension */
+ external_common_state->hdmi_sink = false;
+ DEV_DBG("HDMI DVI mode: %s\n",
+ external_common_state->hdmi_sink ? "no" : "yes");
+ break;
+ case 1: /* Read block 1 */
+ status = hdmi_common_read_edid_block(1, edid_buf+0x80);
+ if (status) {
+ DEV_ERR("%s: ddc read block(1) failed: %d\n", __func__,
+ status);
+ goto error;
+ }
+ if (edid_buf[0x80] != 2)
+ num_og_cea_blocks = 0;
+ if (num_og_cea_blocks) {
+ ieee_reg_id =
+ hdmi_edid_extract_ieee_reg_id(edid_buf+0x80);
+ if (ieee_reg_id == 0x0c03)
+ external_common_state->hdmi_sink = TRUE ;
+ else
+ external_common_state->hdmi_sink = FALSE ;
+ hdmi_edid_extract_latency_fields(edid_buf+0x80);
+ hdmi_edid_extract_speaker_allocation_data(
+ edid_buf+0x80);
+ hdmi_edid_extract_audio_data_blocks(edid_buf+0x80);
+ hdmi_edid_extract_3d_present(edid_buf+0x80);
+ }
+ break;
+ case 2:
+ case 3:
+ case 4:
+ for (i = 1; i <= num_og_cea_blocks; i++) {
+ if (!(i % 2)) {
+ status = hdmi_common_read_edid_block(i,
+ edid_buf+0x00);
+ if (status) {
+ DEV_ERR("%s: ddc read block(%d)"
+ "failed: %d\n", __func__, i,
+ status);
+ goto error;
+ }
+ } else {
+ status = hdmi_common_read_edid_block(i,
+ edid_buf+0x80);
+ if (status) {
+ DEV_ERR("%s: ddc read block(%d)"
+ "failed:%d\n", __func__, i,
+ status);
+ goto error;
+ }
+ }
+ }
+ break;
+ default:
+ DEV_ERR("%s: ddc read failed, not supported multi-blocks: %d\n",
+ __func__, num_og_cea_blocks);
+ status = -EPROTO;
+ goto error;
+ }
+
+ if (num_og_cea_blocks) {
+ /* EDID_CEA_EXTENSION_VERSION[0x81]: Offset to CEA extension
+ * version number - v1,v2,v3 (v1 is seldom, v2 is obsolete,
+ * v3 most common) */
+ cea_extension_ver = edid_buf[0x81];
+ }
+
+ /* EDID_VERSION[0x12] - EDID Version */
+ /* EDID_REVISION[0x13] - EDID Revision */
+ DEV_INFO("EDID (V=%d.%d, #CEABlocks=%d[V%d], ID=%s, IEEE=%04x, "
+ "EDID-Ext=0x%02x)\n", edid_buf[0x12], edid_buf[0x13],
+ num_og_cea_blocks, cea_extension_ver, vendor_id, ieee_reg_id,
+ edid_buf[0x80]);
+
+ hdmi_edid_get_display_mode(edid_buf,
+ &external_common_state->disp_mode_list, num_og_cea_blocks);
+
+ return 0;
+
+error:
+ external_common_state->disp_mode_list.num_of_elements = 1;
+ external_common_state->disp_mode_list.disp_mode_list[0] =
+ external_common_state->video_resolution;
+ return status;
+}
+EXPORT_SYMBOL(hdmi_common_read_edid);
+
+bool hdmi_common_get_video_format_from_drv_data(struct msm_fb_data_type *mfd)
+{
+ uint32 format;
+ struct fb_var_screeninfo *var = &mfd->fbi->var;
+ bool changed = TRUE;
+
+ if (var->reserved[3]) {
+ format = var->reserved[3]-1;
+ } else {
+ DEV_DBG("detecting resolution from %dx%d use var->reserved[3]"
+ " to specify mode", mfd->var_xres, mfd->var_yres);
+ switch (mfd->var_xres) {
+ default:
+ case 640:
+ format = HDMI_VFRMT_640x480p60_4_3;
+ break;
+ case 720:
+ format = (mfd->var_yres == 480)
+ ? HDMI_VFRMT_720x480p60_16_9
+ : HDMI_VFRMT_720x576p50_16_9;
+ break;
+ case 1280:
+ format = HDMI_VFRMT_1280x720p60_16_9;
+ break;
+ case 1440:
+ format = (mfd->var_yres == 480)
+ ? HDMI_VFRMT_1440x480i60_16_9
+ : HDMI_VFRMT_1440x576i50_16_9;
+ break;
+ case 1920:
+ format = HDMI_VFRMT_1920x1080p60_16_9;
+ break;
+ }
+ }
+
+ changed = external_common_state->video_resolution != format;
+ if (external_common_state->video_resolution != format)
+ DEV_DBG("switching %s => %s", video_format_2string(
+ external_common_state->video_resolution),
+ video_format_2string(format));
+ else
+ DEV_DBG("resolution %s", video_format_2string(
+ external_common_state->video_resolution));
+ external_common_state->video_resolution = format;
+ return changed;
+}
+EXPORT_SYMBOL(hdmi_common_get_video_format_from_drv_data);
+
+const struct hdmi_disp_mode_timing_type *hdmi_common_get_mode(uint32 mode)
+{
+ if (mode >= HDMI_VFRMT_MAX)
+ return NULL;
+
+ return &hdmi_common_supported_video_mode_lut[mode];
+}
+EXPORT_SYMBOL(hdmi_common_get_mode);
+
+const struct hdmi_disp_mode_timing_type *hdmi_common_get_supported_mode(
+ uint32 mode)
+{
+ const struct hdmi_disp_mode_timing_type *ret
+ = hdmi_common_get_mode(mode);
+
+ if (ret == NULL || !ret->supported)
+ return NULL;
+ return ret;
+}
+EXPORT_SYMBOL(hdmi_common_get_supported_mode);
+
+void hdmi_common_init_panel_info(struct msm_panel_info *pinfo)
+{
+ const struct hdmi_disp_mode_timing_type *timing =
+ hdmi_common_get_supported_mode(
+ external_common_state->video_resolution);
+
+ if (timing == NULL)
+ return;
+
+ pinfo->xres = timing->active_h;
+ pinfo->yres = timing->active_v;
+ pinfo->clk_rate = timing->pixel_freq*1000;
+
+ pinfo->lcdc.h_back_porch = timing->back_porch_h;
+ pinfo->lcdc.h_front_porch = timing->front_porch_h;
+ pinfo->lcdc.h_pulse_width = timing->pulse_width_h;
+ pinfo->lcdc.v_back_porch = timing->back_porch_v;
+ pinfo->lcdc.v_front_porch = timing->front_porch_v;
+ pinfo->lcdc.v_pulse_width = timing->pulse_width_v;
+
+ pinfo->type = DTV_PANEL;
+ pinfo->pdest = DISPLAY_2;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 24;
+ pinfo->fb_num = 1;
+
+ /* blk */
+ pinfo->lcdc.border_clr = 0;
+ /* blue */
+ pinfo->lcdc.underflow_clr = 0xff;
+ pinfo->lcdc.hsync_skew = 0;
+}
+EXPORT_SYMBOL(hdmi_common_init_panel_info);
+#endif
diff --git a/drivers/video/msm/external_common.h b/drivers/video/msm/external_common.h
new file mode 100644
index 0000000..30a8f48
--- /dev/null
+++ b/drivers/video/msm/external_common.h
@@ -0,0 +1,251 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef __EXTERNAL_COMMON_H__
+#define __EXTERNAL_COMMON_H__
+
+#ifdef DEBUG
+#ifndef DEV_DBG_PREFIX
+#define DEV_DBG_PREFIX "EXT_INTERFACE: "
+#endif
+#define DEV_DBG(args...) pr_debug(DEV_DBG_PREFIX args)
+#else
+#define DEV_DBG(args...) (void)0
+#endif /* DEBUG */
+#define DEV_INFO(args...) dev_info(external_common_state->dev, args)
+#define DEV_WARN(args...) dev_warn(external_common_state->dev, args)
+#define DEV_ERR(args...) dev_err(external_common_state->dev, args)
+
+#ifdef CONFIG_FB_MSM_TVOUT
+#define TVOUT_VFRMT_NTSC_M_720x480i 0
+#define TVOUT_VFRMT_NTSC_J_720x480i 1
+#define TVOUT_VFRMT_PAL_BDGHIN_720x576i 2
+#define TVOUT_VFRMT_PAL_M_720x480i 3
+#define TVOUT_VFRMT_PAL_N_720x480i 4
+#elif defined(CONFIG_FB_MSM_HDMI_COMMON)
+/* all video formats defined by EIA CEA 861D */
+#define HDMI_VFRMT_640x480p60_4_3 0
+#define HDMI_VFRMT_720x480p60_4_3 1
+#define HDMI_VFRMT_720x480p60_16_9 2
+#define HDMI_VFRMT_1280x720p60_16_9 3
+#define HDMI_VFRMT_1920x1080i60_16_9 4
+#define HDMI_VFRMT_720x480i60_4_3 5
+#define HDMI_VFRMT_1440x480i60_4_3 HDMI_VFRMT_720x480i60_4_3
+#define HDMI_VFRMT_720x480i60_16_9 6
+#define HDMI_VFRMT_1440x480i60_16_9 HDMI_VFRMT_720x480i60_16_9
+#define HDMI_VFRMT_720x240p60_4_3 7
+#define HDMI_VFRMT_1440x240p60_4_3 HDMI_VFRMT_720x240p60_4_3
+#define HDMI_VFRMT_720x240p60_16_9 8
+#define HDMI_VFRMT_1440x240p60_16_9 HDMI_VFRMT_720x240p60_16_9
+#define HDMI_VFRMT_2880x480i60_4_3 9
+#define HDMI_VFRMT_2880x480i60_16_9 10
+#define HDMI_VFRMT_2880x240p60_4_3 11
+#define HDMI_VFRMT_2880x240p60_16_9 12
+#define HDMI_VFRMT_1440x480p60_4_3 13
+#define HDMI_VFRMT_1440x480p60_16_9 14
+#define HDMI_VFRMT_1920x1080p60_16_9 15
+#define HDMI_VFRMT_720x576p50_4_3 16
+#define HDMI_VFRMT_720x576p50_16_9 17
+#define HDMI_VFRMT_1280x720p50_16_9 18
+#define HDMI_VFRMT_1920x1080i50_16_9 19
+#define HDMI_VFRMT_720x576i50_4_3 20
+#define HDMI_VFRMT_1440x576i50_4_3 HDMI_VFRMT_720x576i50_4_3
+#define HDMI_VFRMT_720x576i50_16_9 21
+#define HDMI_VFRMT_1440x576i50_16_9 HDMI_VFRMT_720x576i50_16_9
+#define HDMI_VFRMT_720x288p50_4_3 22
+#define HDMI_VFRMT_1440x288p50_4_3 HDMI_VFRMT_720x288p50_4_3
+#define HDMI_VFRMT_720x288p50_16_9 23
+#define HDMI_VFRMT_1440x288p50_16_9 HDMI_VFRMT_720x288p50_16_9
+#define HDMI_VFRMT_2880x576i50_4_3 24
+#define HDMI_VFRMT_2880x576i50_16_9 25
+#define HDMI_VFRMT_2880x288p50_4_3 26
+#define HDMI_VFRMT_2880x288p50_16_9 27
+#define HDMI_VFRMT_1440x576p50_4_3 28
+#define HDMI_VFRMT_1440x576p50_16_9 29
+#define HDMI_VFRMT_1920x1080p50_16_9 30
+#define HDMI_VFRMT_1920x1080p24_16_9 31
+#define HDMI_VFRMT_1920x1080p25_16_9 32
+#define HDMI_VFRMT_1920x1080p30_16_9 33
+#define HDMI_VFRMT_2880x480p60_4_3 34
+#define HDMI_VFRMT_2880x480p60_16_9 35
+#define HDMI_VFRMT_2880x576p50_4_3 36
+#define HDMI_VFRMT_2880x576p50_16_9 37
+#define HDMI_VFRMT_1920x1250i50_16_9 38
+#define HDMI_VFRMT_1920x1080i100_16_9 39
+#define HDMI_VFRMT_1280x720p100_16_9 40
+#define HDMI_VFRMT_720x576p100_4_3 41
+#define HDMI_VFRMT_720x576p100_16_9 42
+#define HDMI_VFRMT_720x576i100_4_3 43
+#define HDMI_VFRMT_1440x576i100_4_3 HDMI_VFRMT_720x576i100_4_3
+#define HDMI_VFRMT_720x576i100_16_9 44
+#define HDMI_VFRMT_1440x576i100_16_9 HDMI_VFRMT_720x576i100_16_9
+#define HDMI_VFRMT_1920x1080i120_16_9 45
+#define HDMI_VFRMT_1280x720p120_16_9 46
+#define HDMI_VFRMT_720x480p120_4_3 47
+#define HDMI_VFRMT_720x480p120_16_9 48
+#define HDMI_VFRMT_720x480i120_4_3 49
+#define HDMI_VFRMT_1440x480i120_4_3 HDMI_VFRMT_720x480i120_4_3
+#define HDMI_VFRMT_720x480i120_16_9 50
+#define HDMI_VFRMT_1440x480i120_16_9 HDMI_VFRMT_720x480i120_16_9
+#define HDMI_VFRMT_720x576p200_4_3 51
+#define HDMI_VFRMT_720x576p200_16_9 52
+#define HDMI_VFRMT_720x576i200_4_3 53
+#define HDMI_VFRMT_1440x576i200_4_3 HDMI_VFRMT_720x576i200_4_3
+#define HDMI_VFRMT_720x576i200_16_9 54
+#define HDMI_VFRMT_1440x576i200_16_9 HDMI_VFRMT_720x576i200_16_9
+#define HDMI_VFRMT_720x480p240_4_3 55
+#define HDMI_VFRMT_720x480p240_16_9 56
+#define HDMI_VFRMT_720x480i240_4_3 57
+#define HDMI_VFRMT_1440x480i240_4_3 HDMI_VFRMT_720x480i240_4_3
+#define HDMI_VFRMT_720x480i240_16_9 58
+#define HDMI_VFRMT_1440x480i240_16_9 HDMI_VFRMT_720x480i240_16_9
+#define HDMI_VFRMT_MAX 59
+#define HDMI_VFRMT_FORCE_32BIT 0x7FFFFFFF
+
+struct hdmi_disp_mode_timing_type {
+ uint32 video_format;
+ uint32 active_h;
+ uint32 front_porch_h;
+ uint32 pulse_width_h;
+ uint32 back_porch_h;
+ boolean active_low_h;
+ uint32 active_v;
+ uint32 front_porch_v;
+ uint32 pulse_width_v;
+ uint32 back_porch_v;
+ boolean active_low_v;
+ /* Must divide by 1000 to get the actual frequency in MHZ */
+ uint32 pixel_freq;
+ /* Must divide by 1000 to get the actual frequency in HZ */
+ uint32 refresh_rate;
+ boolean interlaced;
+ boolean supported;
+};
+
+#define HDMI_SETTINGS_640x480p60_4_3 \
+ {HDMI_VFRMT_640x480p60_4_3, 640, 16, 96, 48, TRUE, \
+ 480, 10, 2, 33, TRUE, 25200, 60000, FALSE, TRUE}
+#define HDMI_SETTINGS_720x480p60_4_3 \
+ {HDMI_VFRMT_720x480p60_4_3, 720, 16, 62, 60, TRUE, \
+ 480, 9, 6, 30, TRUE, 27030, 60000, FALSE, TRUE}
+#define HDMI_SETTINGS_720x480p60_16_9 \
+ {HDMI_VFRMT_720x480p60_16_9, 720, 16, 62, 60, TRUE, \
+ 480, 9, 6, 30, TRUE, 27030, 60000, FALSE, TRUE}
+#define HDMI_SETTINGS_1280x720p60_16_9 \
+ {HDMI_VFRMT_1280x720p60_16_9, 1280, 110, 40, 220, FALSE, \
+ 720, 5, 5, 20, FALSE, 74250, 60000, FALSE, TRUE}
+#define HDMI_SETTINGS_1920x1080i60_16_9 \
+ {HDMI_VFRMT_1920x1080i60_16_9, 1920, 88, 44, 148, FALSE, \
+ 540, 2, 5, 5, FALSE, 74250, 60000, FALSE, TRUE}
+#define HDMI_SETTINGS_1440x480i60_4_3 \
+ {HDMI_VFRMT_1440x480i60_4_3, 1440, 38, 124, 114, TRUE, \
+ 240, 4, 3, 15, TRUE, 27000, 60000, TRUE, TRUE}
+#define HDMI_SETTINGS_1440x480i60_16_9 \
+ {HDMI_VFRMT_1440x480i60_16_9, 1440, 38, 124, 114, TRUE, \
+ 240, 4, 3, 15, TRUE, 27000, 60000, TRUE, TRUE}
+#define HDMI_SETTINGS_1920x1080p60_16_9 \
+ {HDMI_VFRMT_1920x1080p60_16_9, 1920, 88, 44, 148, FALSE, \
+ 1080, 4, 5, 36, FALSE, 148500, 60000, FALSE, TRUE}
+#define HDMI_SETTINGS_720x576p50_4_3 \
+ {HDMI_VFRMT_720x576p50_4_3, 720, 12, 64, 68, TRUE, \
+ 576, 5, 5, 39, TRUE, 27000, 50000, FALSE, TRUE}
+#define HDMI_SETTINGS_720x576p50_16_9 \
+ {HDMI_VFRMT_720x576p50_16_9, 720, 12, 64, 68, TRUE, \
+ 576, 5, 5, 39, TRUE, 27000, 50000, FALSE, TRUE}
+#define HDMI_SETTINGS_1280x720p50_16_9 \
+ {HDMI_VFRMT_1280x720p50_16_9, 1280, 440, 40, 220, FALSE, \
+ 720, 5, 5, 20, FALSE, 74250, 50000, FALSE, TRUE}
+#define HDMI_SETTINGS_1440x576i50_4_3 \
+ {HDMI_VFRMT_1440x576i50_4_3, 1440, 24, 126, 138, TRUE, \
+ 288, 2, 3, 19, TRUE, 27000, 50000, TRUE, TRUE}
+#define HDMI_SETTINGS_1440x576i50_16_9 \
+ {HDMI_VFRMT_1440x576i50_16_9, 1440, 24, 126, 138, TRUE, \
+ 288, 2, 3, 19, TRUE, 27000, 50000, TRUE, TRUE}
+#define HDMI_SETTINGS_1920x1080p50_16_9 \
+ {HDMI_VFRMT_1920x1080p50_16_9, 1920, 528, 44, 148, FALSE, \
+ 1080, 4, 5, 36, FALSE, 148500, 50000, FALSE, TRUE}
+#define HDMI_SETTINGS_1920x1080p24_16_9 \
+ {HDMI_VFRMT_1920x1080p24_16_9, 1920, 638, 44, 148, FALSE, \
+ 1080, 4, 5, 36, FALSE, 74250, 24000, FALSE, TRUE}
+#define HDMI_SETTINGS_1920x1080p25_16_9 \
+ {HDMI_VFRMT_1920x1080p25_16_9, 1920, 528, 44, 148, FALSE, \
+ 1080, 4, 5, 36, FALSE, 74250, 25000, FALSE, TRUE}
+#define HDMI_SETTINGS_1920x1080p30_16_9 \
+ {HDMI_VFRMT_1920x1080p30_16_9, 1920, 88, 44, 148, FALSE, \
+ 1080, 4, 5, 36, FALSE, 74250, 30000, FALSE, TRUE}
+
+/* A lookup table for all the supported display modes by the HDMI
+ * hardware and driver. Use HDMI_SETUP_LUT in the module init to
+ * setup the LUT with the supported modes. */
+extern struct hdmi_disp_mode_timing_type
+ hdmi_common_supported_video_mode_lut[HDMI_VFRMT_MAX];
+
+/* Structure that encapsulates all the supported display modes by the HDMI sink
+ * device */
+struct hdmi_disp_mode_list_type {
+ uint32 disp_mode_list[HDMI_VFRMT_MAX];
+ uint32 num_of_elements;
+};
+#endif
+
+struct external_common_state_type {
+ boolean hpd_state;
+ struct kobject *uevent_kobj;
+ uint32 video_resolution;
+ struct device *dev;
+#ifdef CONFIG_FB_MSM_HDMI_3D
+ boolean format_3d;
+ void (*switch_3d)(boolean on);
+#endif
+#ifdef CONFIG_FB_MSM_HDMI_COMMON
+ boolean hdcp_active;
+ boolean hpd_feature_on;
+ boolean hdmi_sink;
+ struct hdmi_disp_mode_list_type disp_mode_list;
+ uint8 speaker_allocation_block;
+ uint16 video_latency, audio_latency;
+ uint8 audio_data_block_cnt;
+ boolean present_3d;
+ boolean present_hdcp;
+ uint32 audio_data_blocks[16];
+ int (*read_edid_block)(int block, uint8 *edid_buf);
+ int (*hpd_feature)(int on);
+#endif
+};
+
+/* The external interface driver needs to initialize the common state. */
+extern struct external_common_state_type *external_common_state;
+extern struct mutex external_common_state_hpd_mutex;
+
+#ifdef CONFIG_FB_MSM_HDMI_COMMON
+#define VFRMT_NOT_SUPPORTED(VFRMT) \
+ {VFRMT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FALSE}
+#define HDMI_SETUP_LUT(MODE) do { \
+ struct hdmi_disp_mode_timing_type mode \
+ = HDMI_SETTINGS_ ## MODE; \
+ hdmi_common_supported_video_mode_lut[mode.video_format] \
+ = mode; \
+ } while (0)
+
+int hdmi_common_read_edid(void);
+const char *video_format_2string(uint32 format);
+bool hdmi_common_get_video_format_from_drv_data(struct msm_fb_data_type *mfd);
+const struct hdmi_disp_mode_timing_type *hdmi_common_get_mode(uint32 mode);
+const struct hdmi_disp_mode_timing_type *hdmi_common_get_supported_mode(
+ uint32 mode);
+void hdmi_common_init_panel_info(struct msm_panel_info *pinfo);
+#endif
+
+int external_common_state_create(struct platform_device *pdev);
+void external_common_state_remove(void);
+
+#endif /* __EXTERNAL_COMMON_H__ */
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
new file mode 100644
index 0000000..53dc911
--- /dev/null
+++ b/drivers/video/msm/hdmi_msm.c
@@ -0,0 +1,3731 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/* #define DEBUG */
+#define DEV_DBG_PREFIX "HDMI: "
+/* #define REG_DUMP */
+
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <mach/msm_hdmi_audio.h>
+#include <mach/clk.h>
+#include <mach/msm_iomap.h>
+
+#include "msm_fb.h"
+#include "hdmi_msm.h"
+
+/* Supported HDMI Audio channels */
+#define MSM_HDMI_AUDIO_CHANNEL_2 0
+#define MSM_HDMI_AUDIO_CHANNEL_4 1
+#define MSM_HDMI_AUDIO_CHANNEL_6 2
+#define MSM_HDMI_AUDIO_CHANNEL_8 3
+#define MSM_HDMI_AUDIO_CHANNEL_MAX 4
+#define MSM_HDMI_AUDIO_CHANNEL_FORCE_32BIT 0x7FFFFFFF
+
+/* Supported HDMI Audio sample rates */
+#define MSM_HDMI_SAMPLE_RATE_32KHZ 0
+#define MSM_HDMI_SAMPLE_RATE_44_1KHZ 1
+#define MSM_HDMI_SAMPLE_RATE_48KHZ 2
+#define MSM_HDMI_SAMPLE_RATE_88_2KHZ 3
+#define MSM_HDMI_SAMPLE_RATE_96KHZ 4
+#define MSM_HDMI_SAMPLE_RATE_176_4KHZ 5
+#define MSM_HDMI_SAMPLE_RATE_192KHZ 6
+#define MSM_HDMI_SAMPLE_RATE_MAX 7
+#define MSM_HDMI_SAMPLE_RATE_FORCE_32BIT 0x7FFFFFFF
+
+struct workqueue_struct *hdmi_work_queue;
+struct hdmi_msm_state_type *hdmi_msm_state;
+
+static DEFINE_MUTEX(hdmi_msm_state_mutex);
+static DEFINE_MUTEX(hdcp_auth_state_mutex);
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+static void hdmi_msm_hdcp_enable(void);
+#else
+static inline void hdmi_msm_hdcp_enable(void) {}
+#endif
+
+uint32 hdmi_msm_get_io_base(void)
+{
+ return (uint32)MSM_HDMI_BASE;
+}
+EXPORT_SYMBOL(hdmi_msm_get_io_base);
+
+/* Table indicating the video format supported by the HDMI TX Core v1.0 */
+/* Valid Pixel-Clock rates: 25.2MHz, 27MHz, 27.03MHz, 74.25MHz, 148.5MHz */
+static void hdmi_msm_setup_video_mode_lut(void)
+{
+ HDMI_SETUP_LUT(640x480p60_4_3);
+ HDMI_SETUP_LUT(720x480p60_4_3);
+ HDMI_SETUP_LUT(720x480p60_16_9);
+ HDMI_SETUP_LUT(1280x720p60_16_9);
+ HDMI_SETUP_LUT(1920x1080i60_16_9);
+ HDMI_SETUP_LUT(1440x480i60_4_3);
+ HDMI_SETUP_LUT(1440x480i60_16_9);
+ HDMI_SETUP_LUT(1920x1080p60_16_9);
+ HDMI_SETUP_LUT(720x576p50_4_3);
+ HDMI_SETUP_LUT(720x576p50_16_9);
+ HDMI_SETUP_LUT(1280x720p50_16_9);
+ HDMI_SETUP_LUT(1440x576i50_4_3);
+ HDMI_SETUP_LUT(1440x576i50_16_9);
+ HDMI_SETUP_LUT(1920x1080p50_16_9);
+ HDMI_SETUP_LUT(1920x1080p24_16_9);
+ HDMI_SETUP_LUT(1920x1080p25_16_9);
+ HDMI_SETUP_LUT(1920x1080p30_16_9);
+}
+
+#ifdef PORT_DEBUG
+const char *hdmi_msm_name(uint32 offset)
+{
+ switch (offset) {
+ case 0x0000: return "CTRL";
+ case 0x0020: return "AUDIO_PKT_CTRL1";
+ case 0x0024: return "ACR_PKT_CTRL";
+ case 0x0028: return "VBI_PKT_CTRL";
+ case 0x002C: return "INFOFRAME_CTRL0";
+#ifdef CONFIG_FB_MSM_HDMI_3D
+ case 0x0034: return "GEN_PKT_CTRL";
+#endif
+ case 0x003C: return "ACP";
+ case 0x0040: return "GC";
+ case 0x0044: return "AUDIO_PKT_CTRL2";
+ case 0x0048: return "ISRC1_0";
+ case 0x004C: return "ISRC1_1";
+ case 0x0050: return "ISRC1_2";
+ case 0x0054: return "ISRC1_3";
+ case 0x0058: return "ISRC1_4";
+ case 0x005C: return "ISRC2_0";
+ case 0x0060: return "ISRC2_1";
+ case 0x0064: return "ISRC2_2";
+ case 0x0068: return "ISRC2_3";
+ case 0x006C: return "AVI_INFO0";
+ case 0x0070: return "AVI_INFO1";
+ case 0x0074: return "AVI_INFO2";
+ case 0x0078: return "AVI_INFO3";
+#ifdef CONFIG_FB_MSM_HDMI_3D
+ case 0x0084: return "GENERIC0_HDR";
+ case 0x0088: return "GENERIC0_0";
+ case 0x008C: return "GENERIC0_1";
+#endif
+ case 0x00C4: return "ACR_32_0";
+ case 0x00C8: return "ACR_32_1";
+ case 0x00CC: return "ACR_44_0";
+ case 0x00D0: return "ACR_44_1";
+ case 0x00D4: return "ACR_48_0";
+ case 0x00D8: return "ACR_48_1";
+ case 0x00E4: return "AUDIO_INFO0";
+ case 0x00E8: return "AUDIO_INFO1";
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ case 0x0110: return "HDCP_CTRL";
+ case 0x0114: return "HDCP_DEBUG_CTRL";
+ case 0x0118: return "HDCP_INT_CTRL";
+ case 0x011C: return "HDCP_LINK0_STATUS";
+ case 0x012C: return "HDCP_ENTROPY_CTRL0";
+ case 0x0130: return "HDCP_RESET";
+ case 0x0134: return "HDCP_RCVPORT_DATA0";
+ case 0x0138: return "HDCP_RCVPORT_DATA1";
+ case 0x013C: return "HDCP_RCVPORT_DATA2";
+ case 0x0144: return "HDCP_RCVPORT_DATA3";
+ case 0x0148: return "HDCP_RCVPORT_DATA4";
+ case 0x014C: return "HDCP_RCVPORT_DATA5";
+ case 0x0150: return "HDCP_RCVPORT_DATA6";
+ case 0x0168: return "HDCP_RCVPORT_DATA12";
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
+ case 0x01D0: return "AUDIO_CFG";
+ case 0x0208: return "USEC_REFTIMER";
+ case 0x020C: return "DDC_CTRL";
+ case 0x0214: return "DDC_INT_CTRL";
+ case 0x0218: return "DDC_SW_STATUS";
+ case 0x021C: return "DDC_HW_STATUS";
+ case 0x0220: return "DDC_SPEED";
+ case 0x0224: return "DDC_SETUP";
+ case 0x0228: return "DDC_TRANS0";
+ case 0x022C: return "DDC_TRANS1";
+ case 0x0238: return "DDC_DATA";
+ case 0x0250: return "HPD_INT_STATUS";
+ case 0x0254: return "HPD_INT_CTRL";
+ case 0x0258: return "HPD_CTRL";
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ case 0x025C: return "HDCP_ENTROPY_CTRL1";
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
+ case 0x027C: return "DDC_REF";
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ case 0x0284: return "HDCP_SW_UPPER_AKSV";
+ case 0x0288: return "HDCP_SW_LOWER_AKSV";
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
+ case 0x02B4: return "ACTIVE_H";
+ case 0x02B8: return "ACTIVE_V";
+ case 0x02BC: return "ACTIVE_V_F2";
+ case 0x02C0: return "TOTAL";
+ case 0x02C4: return "V_TOTAL_F2";
+ case 0x02C8: return "FRAME_CTRL";
+ case 0x02CC: return "AUD_INT";
+ case 0x0300: return "PHY_REG0";
+ case 0x0304: return "PHY_REG1";
+ case 0x0308: return "PHY_REG2";
+ case 0x030C: return "PHY_REG3";
+ case 0x0310: return "PHY_REG4";
+ case 0x0314: return "PHY_REG5";
+ case 0x0318: return "PHY_REG6";
+ case 0x031C: return "PHY_REG7";
+ case 0x0320: return "PHY_REG8";
+ case 0x0324: return "PHY_REG9";
+ case 0x0328: return "PHY_REG10";
+ case 0x032C: return "PHY_REG11";
+ case 0x0330: return "PHY_REG12";
+ default: return "???";
+ }
+}
+
+void hdmi_outp(uint32 offset, uint32 value)
+{
+ uint32 in_val;
+
+ outpdw(MSM_HDMI_BASE+offset, value);
+ in_val = inpdw(MSM_HDMI_BASE+offset);
+ DEV_DBG("HDMI[%04x] => %08x [%08x] %s\n",
+ offset, value, in_val, hdmi_msm_name(offset));
+}
+
+uint32 hdmi_inp(uint32 offset)
+{
+ uint32 value = inpdw(MSM_HDMI_BASE+offset);
+ DEV_DBG("HDMI[%04x] <= %08x %s\n",
+ offset, value, hdmi_msm_name(offset));
+ return value;
+}
+#endif /* DEBUG */
+
+static void hdmi_msm_turn_on(void);
+static int hdmi_msm_audio_off(void);
+static int hdmi_msm_read_edid(void);
+static void hdmi_msm_hpd_off(void);
+
+static void hdmi_msm_hpd_state_work(struct work_struct *work)
+{
+ boolean hpd_state;
+ char *envp[2];
+
+ if (!hdmi_msm_state || !hdmi_msm_state->hpd_initialized ||
+ !MSM_HDMI_BASE) {
+ DEV_DBG("%s: ignored, probe failed\n", __func__);
+ return;
+ }
+#ifdef CONFIG_SUSPEND
+ mutex_lock(&hdmi_msm_state_mutex);
+ if (hdmi_msm_state->pm_suspended) {
+ mutex_unlock(&hdmi_msm_state_mutex);
+ DEV_WARN("%s: ignored, pm_suspended\n", __func__);
+ return;
+ }
+ mutex_unlock(&hdmi_msm_state_mutex);
+#endif
+
+ /* HPD_INT_STATUS[0x0250] */
+ hpd_state = (HDMI_INP(0x0250) & 0x2) >> 1;
+ mutex_lock(&external_common_state_hpd_mutex);
+ mutex_lock(&hdmi_msm_state_mutex);
+ if ((external_common_state->hpd_state != hpd_state) || (hdmi_msm_state->
+ hpd_prev_state != external_common_state->hpd_state)) {
+ external_common_state->hpd_state = hpd_state;
+ hdmi_msm_state->hpd_prev_state =
+ external_common_state->hpd_state;
+ DEV_DBG("%s: state not stable yet, wait again (%d|%d|%d)\n",
+ __func__, hdmi_msm_state->hpd_prev_state,
+ external_common_state->hpd_state, hpd_state);
+ mutex_unlock(&external_common_state_hpd_mutex);
+ hdmi_msm_state->hpd_stable = 0;
+ mutex_unlock(&hdmi_msm_state_mutex);
+ mod_timer(&hdmi_msm_state->hpd_state_timer, jiffies + HZ/2);
+ return;
+ }
+ mutex_unlock(&external_common_state_hpd_mutex);
+
+ if (hdmi_msm_state->hpd_stable++) {
+ mutex_unlock(&hdmi_msm_state_mutex);
+ DEV_DBG("%s: no more timer, depending for IRQ now\n",
+ __func__);
+ return;
+ }
+
+ hdmi_msm_state->hpd_stable = 1;
+ DEV_INFO("HDMI HPD: event detected\n");
+
+ if (!hdmi_msm_state->hpd_cable_chg_detected) {
+ mutex_unlock(&hdmi_msm_state_mutex);
+ if (hpd_state) {
+ if (!external_common_state->
+ disp_mode_list.num_of_elements)
+ hdmi_msm_read_edid();
+ hdmi_msm_turn_on();
+ }
+ } else {
+ hdmi_msm_state->hpd_cable_chg_detected = FALSE;
+ mutex_unlock(&hdmi_msm_state_mutex);
+ if (hpd_state) {
+ hdmi_msm_read_edid();
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ hdmi_msm_state->reauth = FALSE ;
+#endif
+ /* Build EDID table */
+ envp[0] = "HDCP_STATE=FAIL";
+ envp[1] = NULL;
+ DEV_INFO("HDMI HPD: QDSP OFF\n");
+ kobject_uevent_env(external_common_state->uevent_kobj,
+ KOBJ_CHANGE, envp);
+ hdmi_msm_turn_on();
+ DEV_INFO("HDMI HPD: sense CONNECTED: send ONLINE\n");
+ kobject_uevent(external_common_state->uevent_kobj,
+ KOBJ_ONLINE);
+ hdmi_msm_hdcp_enable();
+ } else {
+ DEV_INFO("HDMI HPD: sense DISCONNECTED: send OFFLINE\n"
+ );
+ kobject_uevent(external_common_state->uevent_kobj,
+ KOBJ_OFFLINE);
+ }
+ }
+
+ /* HPD_INT_CTRL[0x0254]
+ * 31:10 Reserved
+ * 9 RCV_PLUGIN_DET_MASK receiver plug in interrupt mask.
+ * When programmed to 1,
+ * RCV_PLUGIN_DET_INT will toggle
+ * the interrupt line
+ * 8:6 Reserved
+ * 5 RX_INT_EN Panel RX interrupt enable
+ * 0: Disable
+ * 1: Enable
+ * 4 RX_INT_ACK WRITE ONLY. Panel RX interrupt
+ * ack
+ * 3 Reserved
+ * 2 INT_EN Panel interrupt control
+ * 0: Disable
+ * 1: Enable
+ * 1 INT_POLARITY Panel interrupt polarity
+ * 0: generate interrupt on disconnect
+ * 1: generate interrupt on connect
+ * 0 INT_ACK WRITE ONLY. Panel interrupt ack */
+ /* Set IRQ for HPD */
+ HDMI_OUTP(0x0254, 4 | (hpd_state ? 0 : 2));
+}
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+static void hdcp_deauthenticate(void);
+static void hdmi_msm_hdcp_reauth_work(struct work_struct *work)
+{
+#ifdef CONFIG_SUSPEND
+ mutex_lock(&hdmi_msm_state_mutex);
+ if (hdmi_msm_state->pm_suspended) {
+ mutex_unlock(&hdmi_msm_state_mutex);
+ DEV_WARN("HDCP: deauthenticating skipped, pm_suspended\n");
+ return;
+ }
+ mutex_unlock(&hdmi_msm_state_mutex);
+#endif
+
+ /* Don't process recursive actions */
+ mutex_lock(&hdmi_msm_state_mutex);
+ if (hdmi_msm_state->hdcp_activating) {
+ mutex_unlock(&hdmi_msm_state_mutex);
+ return;
+ }
+ mutex_unlock(&hdmi_msm_state_mutex);
+
+ /*
+ * Reauth=>deauth, hdcp_auth
+ * hdcp_auth=>turn_on() which calls
+ * HDMI Core reset without informing the Audio QDSP
+ * this can do bad things to video playback on the HDTV
+ * Therefore, as surprising as it may sound do reauth
+ * only if the device is HDCP-capable
+ */
+ if (external_common_state->present_hdcp) {
+ hdcp_deauthenticate();
+ mod_timer(&hdmi_msm_state->hdcp_timer, jiffies + HZ/2);
+ }
+}
+
+static void hdmi_msm_hdcp_work(struct work_struct *work)
+{
+#ifdef CONFIG_SUSPEND
+ mutex_lock(&hdmi_msm_state_mutex);
+ if (hdmi_msm_state->pm_suspended) {
+ mutex_unlock(&hdmi_msm_state_mutex);
+ DEV_WARN("HDCP: Re-enable skipped, pm_suspended\n");
+ return;
+ }
+ mutex_unlock(&hdmi_msm_state_mutex);
+#endif
+
+ /* Only re-enable if cable still connected */
+ mutex_lock(&external_common_state_hpd_mutex);
+ if (external_common_state->hpd_state &&
+ !(hdmi_msm_state->full_auth_done)) {
+ mutex_unlock(&external_common_state_hpd_mutex);
+ hdmi_msm_state->reauth = TRUE;
+ hdmi_msm_turn_on();
+ } else
+ mutex_unlock(&external_common_state_hpd_mutex);
+}
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
+
+static irqreturn_t hdmi_msm_isr(int irq, void *dev_id)
+{
+ uint32 hpd_int_status;
+ uint32 hpd_int_ctrl;
+ uint32 ddc_int_ctrl;
+ uint32 audio_int_val;
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ uint32 hdcp_int_val;
+ char *envp[2];
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
+ static uint32 fifo_urun_int_occurred;
+ static uint32 sample_drop_int_occurred;
+ const uint32 occurrence_limit = 5;
+
+ if (!hdmi_msm_state || !hdmi_msm_state->hpd_initialized ||
+ !MSM_HDMI_BASE) {
+ DEV_DBG("ISR ignored, probe failed\n");
+ return IRQ_HANDLED;
+ }
+#ifdef CONFIG_SUSPEND
+ mutex_lock(&hdmi_msm_state_mutex);
+ if (hdmi_msm_state->pm_suspended) {
+ mutex_unlock(&hdmi_msm_state_mutex);
+ DEV_WARN("ISR ignored, pm_suspended\n");
+ return IRQ_HANDLED;
+ }
+ mutex_unlock(&hdmi_msm_state_mutex);
+#endif
+
+ /* Process HPD Interrupt */
+ /* HDMI_HPD_INT_STATUS[0x0250] */
+ hpd_int_status = HDMI_INP_ND(0x0250);
+ /* HDMI_HPD_INT_CTRL[0x0254] */
+ hpd_int_ctrl = HDMI_INP_ND(0x0254);
+ if ((hpd_int_ctrl & (1 << 2)) && (hpd_int_status & (1 << 0))) {
+ boolean cable_detected = (hpd_int_status & 2) >> 1;
+
+ /* HDMI_HPD_INT_CTRL[0x0254] */
+ /* Clear all interrupts, timer will turn IRQ back on */
+ HDMI_OUTP(0x0254, 1 << 0);
+
+ DEV_DBG("%s: HPD IRQ, Ctrl=%04x, State=%04x\n", __func__,
+ hpd_int_ctrl, hpd_int_status);
+ mutex_lock(&hdmi_msm_state_mutex);
+ hdmi_msm_state->hpd_cable_chg_detected = TRUE;
+
+ /* ensure 2 readouts */
+ hdmi_msm_state->hpd_prev_state = cable_detected ? 0 : 1;
+ external_common_state->hpd_state = cable_detected ? 1 : 0;
+ hdmi_msm_state->hpd_stable = 0;
+ mod_timer(&hdmi_msm_state->hpd_state_timer, jiffies + HZ/2);
+ mutex_unlock(&hdmi_msm_state_mutex);
+ /*
+ * HDCP Compliance 1A-01:
+ * The Quantum Data Box 882 triggers two consecutive
+ * HPD events very close to each other as a part of this
+ * test which can trigger two parallel HDCP auth threads
+ * if HDCP authentication is going on and we get ISR
+ * then stop the authentication , rather than
+ * reauthenticating it again
+ */
+ if (!(hdmi_msm_state->full_auth_done)) {
+ DEV_DBG("%s getting hpd while authenticating\n",\
+ __func__);
+ mutex_lock(&hdcp_auth_state_mutex);
+ hdmi_msm_state->hpd_during_auth = TRUE;
+ mutex_unlock(&hdcp_auth_state_mutex);
+ }
+ return IRQ_HANDLED;
+ }
+
+ /* Process DDC Interrupts */
+ /* HDMI_DDC_INT_CTRL[0x0214] */
+ ddc_int_ctrl = HDMI_INP_ND(0x0214);
+ if ((ddc_int_ctrl & (1 << 2)) && (ddc_int_ctrl & (1 << 0))) {
+ /* SW_DONE INT occured, clr it */
+ HDMI_OUTP_ND(0x0214, ddc_int_ctrl | (1 << 1));
+ complete(&hdmi_msm_state->ddc_sw_done);
+ return IRQ_HANDLED;
+ }
+
+ /* FIFO Underrun Int is enabled */
+ /* HDMI_AUD_INT[0x02CC]
+ * [3] AUD_SAM_DROP_MASK [R/W]
+ * [2] AUD_SAM_DROP_ACK [W], AUD_SAM_DROP_INT [R]
+ * [1] AUD_FIFO_URUN_MASK [R/W]
+ * [0] AUD_FIFO_URUN_ACK [W], AUD_FIFO_URUN_INT [R] */
+ audio_int_val = HDMI_INP_ND(0x02CC);
+ if ((audio_int_val & (1 << 1)) && (audio_int_val & (1 << 0))) {
+ /* FIFO Underrun occured, clr it */
+ HDMI_OUTP(0x02CC, audio_int_val | (1 << 0));
+
+ ++fifo_urun_int_occurred;
+ DEV_INFO("HDMI AUD_FIFO_URUN: %d\n", fifo_urun_int_occurred);
+
+ if (fifo_urun_int_occurred >= occurrence_limit) {
+ HDMI_OUTP(0x02CC, HDMI_INP(0x02CC) & ~(1 << 1));
+ DEV_INFO("HDMI AUD_FIFO_URUN: INT has been disabled "
+ "by the ISR after %d occurences...\n",
+ fifo_urun_int_occurred);
+ }
+ return IRQ_HANDLED;
+ }
+
+ /* Audio Sample Drop int is enabled */
+ if ((audio_int_val & (1 << 3)) && (audio_int_val & (1 << 2))) {
+ /* Audio Sample Drop occured, clr it */
+ HDMI_OUTP(0x02CC, audio_int_val | (1 << 2));
+ DEV_DBG("%s: AUD_SAM_DROP", __func__);
+
+ ++sample_drop_int_occurred;
+ if (sample_drop_int_occurred >= occurrence_limit) {
+ HDMI_OUTP(0x02CC, HDMI_INP(0x02CC) & ~(1 << 3));
+ DEV_INFO("HDMI AUD_SAM_DROP: INT has been disabled "
+ "by the ISR after %d occurences...\n",
+ sample_drop_int_occurred);
+ }
+ return IRQ_HANDLED;
+ }
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ /* HDCP_INT_CTRL[0x0118]
+ * [0] AUTH_SUCCESS_INT [R] HDCP Authentication Success
+ * interrupt status
+ * [1] AUTH_SUCCESS_ACK [W] Acknowledge bit for HDCP
+ * Authentication Success bit - write 1 to clear
+ * [2] AUTH_SUCCESS_MASK [R/W] Mask bit for HDCP Authentication
+ * Success interrupt - set to 1 to enable interrupt */
+ hdcp_int_val = HDMI_INP_ND(0x0118);
+ if ((hdcp_int_val & (1 << 2)) && (hdcp_int_val & (1 << 0))) {
+ /* AUTH_SUCCESS_INT */
+ HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 1)) & ~(1 << 0));
+ DEV_INFO("HDCP: AUTH_SUCCESS_INT received\n");
+ complete_all(&hdmi_msm_state->hdcp_success_done);
+ return IRQ_HANDLED;
+ }
+ /* [4] AUTH_FAIL_INT [R] HDCP Authentication Lost
+ * interrupt Status
+ * [5] AUTH_FAIL_ACK [W] Acknowledge bit for HDCP
+ * Authentication Lost bit - write 1 to clear
+ * [6] AUTH_FAIL_MASK [R/W] Mask bit fo HDCP Authentication
+ * Lost interrupt set to 1 to enable interrupt
+ * [7] AUTH_FAIL_INFO_ACK [W] Acknowledge bit for HDCP
+ * Authentication Failure Info field - write 1 to clear */
+ if ((hdcp_int_val & (1 << 6)) && (hdcp_int_val & (1 << 4))) {
+ /* AUTH_FAIL_INT */
+ /* Clear and Disable */
+ HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 5))
+ & ~((1 << 6) | (1 << 4)));
+ DEV_INFO("HDCP: AUTH_FAIL_INT received, LINK0_STATUS=0x%08x\n",
+ HDMI_INP_ND(0x011C));
+ if (hdmi_msm_state->full_auth_done) {
+ envp[0] = "HDCP_STATE=FAIL";
+ envp[1] = NULL;
+ DEV_INFO("HDMI HPD:QDSP OFF\n");
+ kobject_uevent_env(external_common_state->uevent_kobj,
+ KOBJ_CHANGE, envp);
+ mutex_lock(&hdcp_auth_state_mutex);
+ hdmi_msm_state->full_auth_done = FALSE;
+ mutex_unlock(&hdcp_auth_state_mutex);
+ /* Calling reauth only when authentication
+ * is sucessful or else we always go into
+ * the reauth loop
+ */
+ queue_work(hdmi_work_queue,
+ &hdmi_msm_state->hdcp_reauth_work);
+ }
+ mutex_lock(&hdcp_auth_state_mutex);
+ /* This flag prevents other threads from re-authenticating
+ * after we've just authenticated (i.e., finished part3)
+ */
+ hdmi_msm_state->full_auth_done = FALSE;
+
+ mutex_unlock(&hdcp_auth_state_mutex);
+ DEV_DBG("calling reauthenticate from %s HDCP FAIL INT ",
+ __func__);
+
+ return IRQ_HANDLED;
+ }
+ /* [8] DDC_XFER_REQ_INT [R] HDCP DDC Transfer Request
+ * interrupt status
+ * [9] DDC_XFER_REQ_ACK [W] Acknowledge bit for HDCP DDC
+ * Transfer Request bit - write 1 to clear
+ * [10] DDC_XFER_REQ_MASK [R/W] Mask bit for HDCP DDC Transfer
+ * Request interrupt - set to 1 to enable interrupt */
+ if ((hdcp_int_val & (1 << 10)) && (hdcp_int_val & (1 << 8))) {
+ /* DDC_XFER_REQ_INT */
+ HDMI_OUTP_ND(0x0118, (hdcp_int_val | (1 << 9)) & ~(1 << 8));
+ if (!(hdcp_int_val & (1 << 12)))
+ return IRQ_HANDLED;
+ }
+ /* [12] DDC_XFER_DONE_INT [R] HDCP DDC Transfer done interrupt
+ * status
+ * [13] DDC_XFER_DONE_ACK [W] Acknowledge bit for HDCP DDC
+ * Transfer done bit - write 1 to clear
+ * [14] DDC_XFER_DONE_MASK [R/W] Mask bit for HDCP DDC Transfer
+ * done interrupt - set to 1 to enable interrupt */
+ if ((hdcp_int_val & (1 << 14)) && (hdcp_int_val & (1 << 12))) {
+ /* DDC_XFER_DONE_INT */
+ HDMI_OUTP_ND(0x0118, (hdcp_int_val | (1 << 13)) & ~(1 << 12));
+ DEV_INFO("HDCP: DDC_XFER_DONE received\n");
+ return IRQ_HANDLED;
+ }
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
+
+ DEV_DBG("%s: HPD<Ctrl=%04x, State=%04x>, ddc_int_ctrl=%04x, "
+ "aud_int=%04x, cec_int=%04x\n", __func__, hpd_int_ctrl,
+ hpd_int_status, ddc_int_ctrl, audio_int_val,
+ HDMI_INP_ND(0x029C));
+
+ return IRQ_HANDLED;
+}
+
+static int check_hdmi_features(void)
+{
+ /* RAW_FEAT_CONFIG_ROW0_LSB */
+ uint32 val = inpdw(QFPROM_BASE + 0x0238);
+ /* HDMI_DISABLE */
+ boolean hdmi_disabled = (val & 0x00200000) >> 21;
+ /* HDCP_DISABLE */
+ boolean hdcp_disabled = (val & 0x00400000) >> 22;
+
+ DEV_DBG("Features <val:0x%08x, HDMI:%s, HDCP:%s>\n", val,
+ hdmi_disabled ? "OFF" : "ON", hdcp_disabled ? "OFF" : "ON");
+ if (hdmi_disabled) {
+ DEV_ERR("ERROR: HDMI disabled\n");
+ return -ENODEV;
+ }
+
+ if (hdcp_disabled)
+ DEV_WARN("WARNING: HDCP disabled\n");
+
+ return 0;
+}
+
+static boolean hdmi_msm_has_hdcp(void)
+{
+ /* RAW_FEAT_CONFIG_ROW0_LSB, HDCP_DISABLE */
+ return (inpdw(QFPROM_BASE + 0x0238) & 0x00400000) ? FALSE : TRUE;
+}
+
+static boolean hdmi_msm_is_power_on(void)
+{
+ /* HDMI_CTRL, ENABLE */
+ return (HDMI_INP_ND(0x0000) & 0x00000001) ? TRUE : FALSE;
+}
+
+/* 1.2.1.2.1 DVI Operation
+ * HDMI compliance requires the HDMI core to support DVI as well. The
+ * HDMI core also supports DVI. In DVI operation there are no preambles
+ * and guardbands transmitted. THe TMDS encoding of video data remains
+ * the same as HDMI. There are no VBI or audio packets transmitted. In
+ * order to enable DVI mode in HDMI core, HDMI_DVI_SEL field of
+ * HDMI_CTRL register needs to be programmed to 0. */
+static boolean hdmi_msm_is_dvi_mode(void)
+{
+ /* HDMI_CTRL, HDMI_DVI_SEL */
+ return (HDMI_INP_ND(0x0000) & 0x00000002) ? FALSE : TRUE;
+}
+
+static void hdmi_msm_set_mode(boolean power_on)
+{
+ uint32 reg_val = 0;
+ if (power_on) {
+ /* ENABLE */
+ reg_val |= 0x00000001; /* Enable the block */
+ if (external_common_state->hdmi_sink == 0) {
+ /* HDMI_DVI_SEL */
+ reg_val |= 0x00000002;
+ /* HDMI_CTRL */
+ HDMI_OUTP(0x0000, reg_val);
+ /* HDMI_DVI_SEL */
+ reg_val &= ~0x00000002;
+ } else
+ reg_val |= 0x00000002;
+ } else
+ reg_val = 0x00000002;
+
+ /* HDMI_CTRL */
+ HDMI_OUTP(0x0000, reg_val);
+ DEV_DBG("HDMI Core: %s\n", power_on ? "Enable" : "Disable");
+}
+
+static void msm_hdmi_init_ddc(void)
+{
+ /* 0x0220 HDMI_DDC_SPEED
+ [31:16] PRESCALE prescale = (m * xtal_frequency) /
+ (desired_i2c_speed), where m is multiply
+ factor, default: m = 1
+ [1:0] THRESHOLD Select threshold to use to determine whether value
+ sampled on SDA is a 1 or 0. Specified in terms of the ratio
+ between the number of sampled ones and the total number of times
+ SDA is sampled.
+ * 0x0: >0
+ * 0x1: 1/4 of total samples
+ * 0x2: 1/2 of total samples
+ * 0x3: 3/4 of total samples */
+ /* Configure the Pre-Scale multiplier
+ * Configure the Threshold */
+ HDMI_OUTP_ND(0x0220, (10 << 16) | (2 << 0));
+
+ /* 0x0224 HDMI_DDC_SETUP */
+ HDMI_OUTP_ND(0x0224, 0);
+
+ /* 0x027C HDMI_DDC_REF
+ [6] REFTIMER_ENABLE Enable the timer
+ * 0: Disable
+ * 1: Enable
+ [15:0] REFTIMER Value to set the register in order to generate
+ DDC strobe. This register counts on HDCP application clock */
+ /* Enable reference timer
+ * 27 micro-seconds */
+ HDMI_OUTP_ND(0x027C, (1 << 16) | (27 << 0));
+}
+
+static int hdmi_msm_ddc_clear_irq(const char *what)
+{
+ const uint32 time_out = 0xFFFF;
+ uint32 time_out_count, reg_val;
+
+ /* clear pending and enable interrupt */
+ time_out_count = time_out;
+ do {
+ --time_out_count;
+ /* HDMI_DDC_INT_CTRL[0x0214]
+ [2] SW_DONE_MK Mask bit for SW_DONE_INT. Set to 1 to enable
+ interrupt.
+ [1] SW_DONE_ACK WRITE ONLY. Acknowledge bit for SW_DONE_INT.
+ Write 1 to clear interrupt.
+ [0] SW_DONE_INT READ ONLY. SW_DONE interrupt status */
+ /* Clear and Enable DDC interrupt */
+ /* Write */
+ HDMI_OUTP_ND(0x0214, (1 << 2) | (1 << 1));
+ /* Read back */
+ reg_val = HDMI_INP_ND(0x0214);
+ } while ((reg_val & 0x1) && time_out_count);
+ if (!time_out_count) {
+ DEV_ERR("%s[%s]: timedout\n", __func__, what);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+static int hdmi_msm_ddc_write(uint32 dev_addr, uint32 offset,
+ const uint8 *data_buf, uint32 data_len, const char *what)
+{
+ uint32 reg_val, ndx;
+ int status = 0, retry = 10;
+ uint32 time_out_count;
+
+ if (NULL == data_buf) {
+ status = -EINVAL;
+ DEV_ERR("%s[%s]: invalid input paramter\n", __func__, what);
+ goto error;
+ }
+
+again:
+ status = hdmi_msm_ddc_clear_irq(what);
+ if (status)
+ goto error;
+
+ /* Ensure Device Address has LSB set to 0 to indicate Slave addr read */
+ dev_addr &= 0xFE;
+
+ /* 0x0238 HDMI_DDC_DATA
+ [31] INDEX_WRITE WRITE ONLY. To write index field, set this bit to
+ 1 while writing HDMI_DDC_DATA.
+ [23:16] INDEX Use to set index into DDC buffer for next read or
+ current write, or to read index of current read or next write.
+ Writable only when INDEX_WRITE=1.
+ [15:8] DATA Use to fill or read the DDC buffer
+ [0] DATA_RW Select whether buffer access will be a read or write.
+ For writes, address auto-increments on write to HDMI_DDC_DATA.
+ For reads, address autoincrements on reads to HDMI_DDC_DATA.
+ * 0: Write
+ * 1: Read */
+
+ /* 1. Write to HDMI_I2C_DATA with the following fields set in order to
+ * handle portion #1
+ * DATA_RW = 0x1 (write)
+ * DATA = linkAddress (primary link address and writing)
+ * INDEX = 0x0 (initial offset into buffer)
+ * INDEX_WRITE = 0x1 (setting initial offset) */
+ HDMI_OUTP_ND(0x0238, (0x1UL << 31) | (dev_addr << 8));
+
+ /* 2. Write to HDMI_I2C_DATA with the following fields set in order to
+ * handle portion #2
+ * DATA_RW = 0x0 (write)
+ * DATA = offsetAddress
+ * INDEX = 0x0
+ * INDEX_WRITE = 0x0 (auto-increment by hardware) */
+ HDMI_OUTP_ND(0x0238, offset << 8);
+
+ /* 3. Write to HDMI_I2C_DATA with the following fields set in order to
+ * handle portion #3
+ * DATA_RW = 0x0 (write)
+ * DATA = data_buf[ndx]
+ * INDEX = 0x0
+ * INDEX_WRITE = 0x0 (auto-increment by hardware) */
+ for (ndx = 0; ndx < data_len; ++ndx)
+ HDMI_OUTP_ND(0x0238, ((uint32)data_buf[ndx]) << 8);
+
+ /* Data setup is complete, now setup the transaction characteristics */
+
+ /* 0x0228 HDMI_DDC_TRANS0
+ [23:16] CNT0 Byte count for first transaction (excluding the first
+ byte, which is usually the address).
+ [13] STOP0 Determines whether a stop bit will be sent after the first
+ transaction
+ * 0: NO STOP
+ * 1: STOP
+ [12] START0 Determines whether a start bit will be sent before the
+ first transaction
+ * 0: NO START
+ * 1: START
+ [8] STOP_ON_NACK0 Determines whether the current transfer will stop
+ if a NACK is received during the first transaction (current
+ transaction always stops).
+ * 0: STOP CURRENT TRANSACTION, GO TO NEXT TRANSACTION
+ * 1: STOP ALL TRANSACTIONS, SEND STOP BIT
+ [0] RW0 Read/write indicator for first transaction - set to 0 for
+ write, 1 for read. This bit only controls HDMI_DDC behaviour -
+ the R/W bit in the transaction is programmed into the DDC buffer
+ as the LSB of the address byte.
+ * 0: WRITE
+ * 1: READ */
+
+ /* 4. Write to HDMI_I2C_TRANSACTION0 with the following fields set in
+ order to handle characteristics of portion #1 and portion #2
+ * RW0 = 0x0 (write)
+ * START0 = 0x1 (insert START bit)
+ * STOP0 = 0x0 (do NOT insert STOP bit)
+ * CNT0 = 0x1 (single byte transaction excluding address) */
+ HDMI_OUTP_ND(0x0228, (1 << 12) | (1 << 16));
+
+ /* 0x022C HDMI_DDC_TRANS1
+ [23:16] CNT1 Byte count for second transaction (excluding the first
+ byte, which is usually the address).
+ [13] STOP1 Determines whether a stop bit will be sent after the second
+ transaction
+ * 0: NO STOP
+ * 1: STOP
+ [12] START1 Determines whether a start bit will be sent before the
+ second transaction
+ * 0: NO START
+ * 1: START
+ [8] STOP_ON_NACK1 Determines whether the current transfer will stop if
+ a NACK is received during the second transaction (current
+ transaction always stops).
+ * 0: STOP CURRENT TRANSACTION, GO TO NEXT TRANSACTION
+ * 1: STOP ALL TRANSACTIONS, SEND STOP BIT
+ [0] RW1 Read/write indicator for second transaction - set to 0 for
+ write, 1 for read. This bit only controls HDMI_DDC behaviour -
+ the R/W bit in the transaction is programmed into the DDC buffer
+ as the LSB of the address byte.
+ * 0: WRITE
+ * 1: READ */
+
+ /* 5. Write to HDMI_I2C_TRANSACTION1 with the following fields set in
+ order to handle characteristics of portion #3
+ * RW1 = 0x1 (read)
+ * START1 = 0x1 (insert START bit)
+ * STOP1 = 0x1 (insert STOP bit)
+ * CNT1 = data_len (0xN (write N bytes of data))
+ * Byte count for second transition (excluding the first
+ * Byte which is usually the address) */
+ HDMI_OUTP_ND(0x022C, (1 << 13) | ((data_len-1) << 16));
+
+ /* Trigger the I2C transfer */
+ /* 0x020C HDMI_DDC_CTRL
+ [21:20] TRANSACTION_CNT
+ Number of transactions to be done in current transfer.
+ * 0x0: transaction0 only
+ * 0x1: transaction0, transaction1
+ * 0x2: transaction0, transaction1, transaction2
+ * 0x3: transaction0, transaction1, transaction2, transaction3
+ [3] SW_STATUS_RESET
+ Write 1 to reset HDMI_DDC_SW_STATUS flags, will reset SW_DONE,
+ ABORTED, TIMEOUT, SW_INTERRUPTED, BUFFER_OVERFLOW,
+ STOPPED_ON_NACK, NACK0, NACK1, NACK2, NACK3
+ [2] SEND_RESET Set to 1 to send reset sequence (9 clocks with no
+ data) at start of transfer. This sequence is sent after GO is
+ written to 1, before the first transaction only.
+ [1] SOFT_RESET Write 1 to reset DDC controller
+ [0] GO WRITE ONLY. Write 1 to start DDC transfer. */
+
+ /* 6. Write to HDMI_I2C_CONTROL to kick off the hardware.
+ * Note that NOTHING has been transmitted on the DDC lines up to this
+ * point.
+ * TRANSACTION_CNT = 0x1 (execute transaction0 followed by
+ * transaction1)
+ * GO = 0x1 (kicks off hardware) */
+ INIT_COMPLETION(hdmi_msm_state->ddc_sw_done);
+ HDMI_OUTP_ND(0x020C, (1 << 0) | (1 << 20));
+
+ time_out_count = wait_for_completion_interruptible_timeout(
+ &hdmi_msm_state->ddc_sw_done, HZ/2);
+ HDMI_OUTP_ND(0x0214, 0x2);
+ if (!time_out_count) {
+ if (retry-- > 0) {
+ DEV_INFO("%s[%s]: failed timout, retry=%d\n", __func__,
+ what, retry);
+ goto again;
+ }
+ status = -ETIMEDOUT;
+ DEV_ERR("%s[%s]: timedout, DDC SW Status=%08x, HW "
+ "Status=%08x, Int Ctrl=%08x\n", __func__, what,
+ HDMI_INP_ND(0x0218), HDMI_INP_ND(0x021C),
+ HDMI_INP_ND(0x0214));
+ goto error;
+ }
+
+ /* Read DDC status */
+ reg_val = HDMI_INP_ND(0x0218);
+ reg_val &= 0x00001000 | 0x00002000 | 0x00004000 | 0x00008000;
+
+ /* Check if any NACK occurred */
+ if (reg_val) {
+ if (retry > 1)
+ HDMI_OUTP_ND(0x020C, BIT(3)); /* SW_STATUS_RESET */
+ else
+ HDMI_OUTP_ND(0x020C, BIT(1)); /* SOFT_RESET */
+ if (retry-- > 0) {
+ DEV_DBG("%s[%s]: failed NACK=%08x, retry=%d\n",
+ __func__, what, reg_val, retry);
+ msleep(100);
+ goto again;
+ }
+ status = -EIO;
+ DEV_ERR("%s[%s]: failed NACK: %08x\n", __func__, what, reg_val);
+ goto error;
+ }
+
+ DEV_DBG("%s[%s] success\n", __func__, what);
+
+error:
+ return status;
+}
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
+
+static int hdmi_msm_ddc_read_retry(uint32 dev_addr, uint32 offset,
+ uint8 *data_buf, uint32 data_len, uint32 request_len, int retry,
+ const char *what)
+{
+ uint32 reg_val, ndx;
+ int status = 0;
+ uint32 time_out_count;
+ int log_retry_fail = retry != 1;
+
+ if (NULL == data_buf) {
+ status = -EINVAL;
+ DEV_ERR("%s: invalid input paramter\n", __func__);
+ goto error;
+ }
+
+again:
+ status = hdmi_msm_ddc_clear_irq(what);
+ if (status)
+ goto error;
+
+ /* Ensure Device Address has LSB set to 0 to indicate Slave addr read */
+ dev_addr &= 0xFE;
+
+ /* 0x0238 HDMI_DDC_DATA
+ [31] INDEX_WRITE WRITE ONLY. To write index field, set this bit to
+ 1 while writing HDMI_DDC_DATA.
+ [23:16] INDEX Use to set index into DDC buffer for next read or
+ current write, or to read index of current read or next write.
+ Writable only when INDEX_WRITE=1.
+ [15:8] DATA Use to fill or read the DDC buffer
+ [0] DATA_RW Select whether buffer access will be a read or write.
+ For writes, address auto-increments on write to HDMI_DDC_DATA.
+ For reads, address autoincrements on reads to HDMI_DDC_DATA.
+ * 0: Write
+ * 1: Read */
+
+ /* 1. Write to HDMI_I2C_DATA with the following fields set in order to
+ * handle portion #1
+ * DATA_RW = 0x0 (write)
+ * DATA = linkAddress (primary link address and writing)
+ * INDEX = 0x0 (initial offset into buffer)
+ * INDEX_WRITE = 0x1 (setting initial offset) */
+ HDMI_OUTP_ND(0x0238, (0x1UL << 31) | (dev_addr << 8));
+
+ /* 2. Write to HDMI_I2C_DATA with the following fields set in order to
+ * handle portion #2
+ * DATA_RW = 0x0 (write)
+ * DATA = offsetAddress
+ * INDEX = 0x0
+ * INDEX_WRITE = 0x0 (auto-increment by hardware) */
+ HDMI_OUTP_ND(0x0238, offset << 8);
+
+ /* 3. Write to HDMI_I2C_DATA with the following fields set in order to
+ * handle portion #3
+ * DATA_RW = 0x0 (write)
+ * DATA = linkAddress + 1 (primary link address 0x74 and reading)
+ * INDEX = 0x0
+ * INDEX_WRITE = 0x0 (auto-increment by hardware) */
+ HDMI_OUTP_ND(0x0238, (dev_addr | 1) << 8);
+
+ /* Data setup is complete, now setup the transaction characteristics */
+
+ /* 0x0228 HDMI_DDC_TRANS0
+ [23:16] CNT0 Byte count for first transaction (excluding the first
+ byte, which is usually the address).
+ [13] STOP0 Determines whether a stop bit will be sent after the first
+ transaction
+ * 0: NO STOP
+ * 1: STOP
+ [12] START0 Determines whether a start bit will be sent before the
+ first transaction
+ * 0: NO START
+ * 1: START
+ [8] STOP_ON_NACK0 Determines whether the current transfer will stop
+ if a NACK is received during the first transaction (current
+ transaction always stops).
+ * 0: STOP CURRENT TRANSACTION, GO TO NEXT TRANSACTION
+ * 1: STOP ALL TRANSACTIONS, SEND STOP BIT
+ [0] RW0 Read/write indicator for first transaction - set to 0 for
+ write, 1 for read. This bit only controls HDMI_DDC behaviour -
+ the R/W bit in the transaction is programmed into the DDC buffer
+ as the LSB of the address byte.
+ * 0: WRITE
+ * 1: READ */
+
+ /* 4. Write to HDMI_I2C_TRANSACTION0 with the following fields set in
+ order to handle characteristics of portion #1 and portion #2
+ * RW0 = 0x0 (write)
+ * START0 = 0x1 (insert START bit)
+ * STOP0 = 0x0 (do NOT insert STOP bit)
+ * CNT0 = 0x1 (single byte transaction excluding address) */
+ HDMI_OUTP_ND(0x0228, (1 << 12) | (1 << 16));
+
+ /* 0x022C HDMI_DDC_TRANS1
+ [23:16] CNT1 Byte count for second transaction (excluding the first
+ byte, which is usually the address).
+ [13] STOP1 Determines whether a stop bit will be sent after the second
+ transaction
+ * 0: NO STOP
+ * 1: STOP
+ [12] START1 Determines whether a start bit will be sent before the
+ second transaction
+ * 0: NO START
+ * 1: START
+ [8] STOP_ON_NACK1 Determines whether the current transfer will stop if
+ a NACK is received during the second transaction (current
+ transaction always stops).
+ * 0: STOP CURRENT TRANSACTION, GO TO NEXT TRANSACTION
+ * 1: STOP ALL TRANSACTIONS, SEND STOP BIT
+ [0] RW1 Read/write indicator for second transaction - set to 0 for
+ write, 1 for read. This bit only controls HDMI_DDC behaviour -
+ the R/W bit in the transaction is programmed into the DDC buffer
+ as the LSB of the address byte.
+ * 0: WRITE
+ * 1: READ */
+
+ /* 5. Write to HDMI_I2C_TRANSACTION1 with the following fields set in
+ order to handle characteristics of portion #3
+ * RW1 = 0x1 (read)
+ * START1 = 0x1 (insert START bit)
+ * STOP1 = 0x1 (insert STOP bit)
+ * CNT1 = data_len (it's 128 (0x80) for a blk read) */
+ HDMI_OUTP_ND(0x022C, 1 | (1 << 12) | (1 << 13) | (request_len << 16));
+
+ /* Trigger the I2C transfer */
+ /* 0x020C HDMI_DDC_CTRL
+ [21:20] TRANSACTION_CNT
+ Number of transactions to be done in current transfer.
+ * 0x0: transaction0 only
+ * 0x1: transaction0, transaction1
+ * 0x2: transaction0, transaction1, transaction2
+ * 0x3: transaction0, transaction1, transaction2, transaction3
+ [3] SW_STATUS_RESET
+ Write 1 to reset HDMI_DDC_SW_STATUS flags, will reset SW_DONE,
+ ABORTED, TIMEOUT, SW_INTERRUPTED, BUFFER_OVERFLOW,
+ STOPPED_ON_NACK, NACK0, NACK1, NACK2, NACK3
+ [2] SEND_RESET Set to 1 to send reset sequence (9 clocks with no
+ data) at start of transfer. This sequence is sent after GO is
+ written to 1, before the first transaction only.
+ [1] SOFT_RESET Write 1 to reset DDC controller
+ [0] GO WRITE ONLY. Write 1 to start DDC transfer. */
+
+ /* 6. Write to HDMI_I2C_CONTROL to kick off the hardware.
+ * Note that NOTHING has been transmitted on the DDC lines up to this
+ * point.
+ * TRANSACTION_CNT = 0x1 (execute transaction0 followed by
+ * transaction1)
+ * SEND_RESET = Set to 1 to send reset sequence
+ * GO = 0x1 (kicks off hardware) */
+ INIT_COMPLETION(hdmi_msm_state->ddc_sw_done);
+ HDMI_OUTP_ND(0x020C, (1 << 0) | (1 << 20));
+
+ time_out_count = wait_for_completion_interruptible_timeout(
+ &hdmi_msm_state->ddc_sw_done, HZ/2);
+ HDMI_OUTP_ND(0x0214, 0x2);
+ if (!time_out_count) {
+ if (retry-- > 0) {
+ DEV_INFO("%s: failed timout, retry=%d\n", __func__,
+ retry);
+ goto again;
+ }
+ status = -ETIMEDOUT;
+ DEV_ERR("%s: timedout(7), DDC SW Status=%08x, HW "
+ "Status=%08x, Int Ctrl=%08x\n", __func__,
+ HDMI_INP(0x0218), HDMI_INP(0x021C), HDMI_INP(0x0214));
+ goto error;
+ }
+
+ /* Read DDC status */
+ reg_val = HDMI_INP_ND(0x0218);
+ reg_val &= 0x00001000 | 0x00002000 | 0x00004000 | 0x00008000;
+
+ /* Check if any NACK occurred */
+ if (reg_val) {
+ HDMI_OUTP_ND(0x020C, BIT(3)); /* SW_STATUS_RESET */
+ if (retry == 1)
+ HDMI_OUTP_ND(0x020C, BIT(1)); /* SOFT_RESET */
+ if (retry-- > 0) {
+ DEV_DBG("%s(%s): failed NACK=0x%08x, retry=%d, "
+ "dev-addr=0x%02x, offset=0x%02x, "
+ "length=%d\n", __func__, what,
+ reg_val, retry, dev_addr,
+ offset, data_len);
+ goto again;
+ }
+ status = -EIO;
+ if (log_retry_fail)
+ DEV_ERR("%s(%s): failed NACK=0x%08x, dev-addr=0x%02x, "
+ "offset=0x%02x, length=%d\n", __func__, what,
+ reg_val, dev_addr, offset, data_len);
+ goto error;
+ }
+
+ /* 0x0238 HDMI_DDC_DATA
+ [31] INDEX_WRITE WRITE ONLY. To write index field, set this bit to 1
+ while writing HDMI_DDC_DATA.
+ [23:16] INDEX Use to set index into DDC buffer for next read or
+ current write, or to read index of current read or next write.
+ Writable only when INDEX_WRITE=1.
+ [15:8] DATA Use to fill or read the DDC buffer
+ [0] DATA_RW Select whether buffer access will be a read or write.
+ For writes, address auto-increments on write to HDMI_DDC_DATA.
+ For reads, address autoincrements on reads to HDMI_DDC_DATA.
+ * 0: Write
+ * 1: Read */
+
+ /* 8. ALL data is now available and waiting in the DDC buffer.
+ * Read HDMI_I2C_DATA with the following fields set
+ * RW = 0x1 (read)
+ * DATA = BCAPS (this is field where data is pulled from)
+ * INDEX = 0x3 (where the data has been placed in buffer by hardware)
+ * INDEX_WRITE = 0x1 (explicitly define offset) */
+ /* Write this data to DDC buffer */
+ HDMI_OUTP_ND(0x0238, 0x1 | (3 << 16) | (1 << 31));
+
+ /* Discard first byte */
+ HDMI_INP_ND(0x0238);
+ for (ndx = 0; ndx < data_len; ++ndx) {
+ reg_val = HDMI_INP_ND(0x0238);
+ data_buf[ndx] = (uint8) ((reg_val & 0x0000FF00) >> 8);
+ }
+
+ DEV_DBG("%s[%s] success\n", __func__, what);
+
+error:
+ return status;
+}
+
+static int hdmi_msm_ddc_read_edid_seg(uint32 dev_addr, uint32 offset,
+ uint8 *data_buf, uint32 data_len, uint32 request_len, int retry,
+ const char *what)
+{
+ uint32 reg_val, ndx;
+ int status = 0;
+ uint32 time_out_count;
+ int log_retry_fail = retry != 1;
+ int seg_addr = 0x60, seg_num = 0x01;
+
+ if (NULL == data_buf) {
+ status = -EINVAL;
+ DEV_ERR("%s: invalid input paramter\n", __func__);
+ goto error;
+ }
+
+again:
+ status = hdmi_msm_ddc_clear_irq(what);
+ if (status)
+ goto error;
+
+ /* Ensure Device Address has LSB set to 0 to indicate Slave addr read */
+ dev_addr &= 0xFE;
+
+ /* 0x0238 HDMI_DDC_DATA
+ [31] INDEX_WRITE WRITE ONLY. To write index field, set this bit to
+ 1 while writing HDMI_DDC_DATA.
+ [23:16] INDEX Use to set index into DDC buffer for next read or
+ current write, or to read index of current read or next write.
+ Writable only when INDEX_WRITE=1.
+ [15:8] DATA Use to fill or read the DDC buffer
+ [0] DATA_RW Select whether buffer access will be a read or write.
+ For writes, address auto-increments on write to HDMI_DDC_DATA.
+ For reads, address autoincrements on reads to HDMI_DDC_DATA.
+ * 0: Write
+ * 1: Read */
+
+ /* 1. Write to HDMI_I2C_DATA with the following fields set in order to
+ * handle portion #1
+ * DATA_RW = 0x0 (write)
+ * DATA = linkAddress (primary link address and writing)
+ * INDEX = 0x0 (initial offset into buffer)
+ * INDEX_WRITE = 0x1 (setting initial offset) */
+ HDMI_OUTP_ND(0x0238, (0x1UL << 31) | (seg_addr << 8));
+
+ /* 2. Write to HDMI_I2C_DATA with the following fields set in order to
+ * handle portion #2
+ * DATA_RW = 0x0 (write)
+ * DATA = offsetAddress
+ * INDEX = 0x0
+ * INDEX_WRITE = 0x0 (auto-increment by hardware) */
+ HDMI_OUTP_ND(0x0238, seg_num << 8);
+
+ /* 3. Write to HDMI_I2C_DATA with the following fields set in order to
+ * handle portion #3
+ * DATA_RW = 0x0 (write)
+ * DATA = linkAddress + 1 (primary link address 0x74 and reading)
+ * INDEX = 0x0
+ * INDEX_WRITE = 0x0 (auto-increment by hardware) */
+ HDMI_OUTP_ND(0x0238, dev_addr << 8);
+ HDMI_OUTP_ND(0x0238, offset << 8);
+ HDMI_OUTP_ND(0x0238, (dev_addr | 1) << 8);
+
+ /* Data setup is complete, now setup the transaction characteristics */
+
+ /* 0x0228 HDMI_DDC_TRANS0
+ [23:16] CNT0 Byte count for first transaction (excluding the first
+ byte, which is usually the address).
+ [13] STOP0 Determines whether a stop bit will be sent after the first
+ transaction
+ * 0: NO STOP
+ * 1: STOP
+ [12] START0 Determines whether a start bit will be sent before the
+ first transaction
+ * 0: NO START
+ * 1: START
+ [8] STOP_ON_NACK0 Determines whether the current transfer will stop
+ if a NACK is received during the first transaction (current
+ transaction always stops).
+ * 0: STOP CURRENT TRANSACTION, GO TO NEXT TRANSACTION
+ * 1: STOP ALL TRANSACTIONS, SEND STOP BIT
+ [0] RW0 Read/write indicator for first transaction - set to 0 for
+ write, 1 for read. This bit only controls HDMI_DDC behaviour -
+ the R/W bit in the transaction is programmed into the DDC buffer
+ as the LSB of the address byte.
+ * 0: WRITE
+ * 1: READ */
+
+ /* 4. Write to HDMI_I2C_TRANSACTION0 with the following fields set in
+ order to handle characteristics of portion #1 and portion #2
+ * RW0 = 0x0 (write)
+ * START0 = 0x1 (insert START bit)
+ * STOP0 = 0x0 (do NOT insert STOP bit)
+ * CNT0 = 0x1 (single byte transaction excluding address) */
+ HDMI_OUTP_ND(0x0228, (1 << 12) | (1 << 16));
+
+ /* 0x022C HDMI_DDC_TRANS1
+ [23:16] CNT1 Byte count for second transaction (excluding the first
+ byte, which is usually the address).
+ [13] STOP1 Determines whether a stop bit will be sent after the second
+ transaction
+ * 0: NO STOP
+ * 1: STOP
+ [12] START1 Determines whether a start bit will be sent before the
+ second transaction
+ * 0: NO START
+ * 1: START
+ [8] STOP_ON_NACK1 Determines whether the current transfer will stop if
+ a NACK is received during the second transaction (current
+ transaction always stops).
+ * 0: STOP CURRENT TRANSACTION, GO TO NEXT TRANSACTION
+ * 1: STOP ALL TRANSACTIONS, SEND STOP BIT
+ [0] RW1 Read/write indicator for second transaction - set to 0 for
+ write, 1 for read. This bit only controls HDMI_DDC behaviour -
+ the R/W bit in the transaction is programmed into the DDC buffer
+ as the LSB of the address byte.
+ * 0: WRITE
+ * 1: READ */
+
+ /* 5. Write to HDMI_I2C_TRANSACTION1 with the following fields set in
+ order to handle characteristics of portion #3
+ * RW1 = 0x1 (read)
+ * START1 = 0x1 (insert START bit)
+ * STOP1 = 0x1 (insert STOP bit)
+ * CNT1 = data_len (it's 128 (0x80) for a blk read) */
+ HDMI_OUTP_ND(0x022C, (1 << 12) | (1 << 16));
+
+ /* 0x022C HDMI_DDC_TRANS2
+ [23:16] CNT1 Byte count for second transaction (excluding the first
+ byte, which is usually the address).
+ [13] STOP1 Determines whether a stop bit will be sent after the second
+ transaction
+ * 0: NO STOP
+ * 1: STOP
+ [12] START1 Determines whether a start bit will be sent before the
+ second transaction
+ * 0: NO START
+ * 1: START
+ [8] STOP_ON_NACK1 Determines whether the current transfer will stop if
+ a NACK is received during the second transaction (current
+ transaction always stops).
+ * 0: STOP CURRENT TRANSACTION, GO TO NEXT TRANSACTION
+ * 1: STOP ALL TRANSACTIONS, SEND STOP BIT
+ [0] RW1 Read/write indicator for second transaction - set to 0 for
+ write, 1 for read. This bit only controls HDMI_DDC behaviour -
+ the R/W bit in the transaction is programmed into the DDC buffer
+ as the LSB of the address byte.
+ * 0: WRITE
+ * 1: READ */
+
+ /* 5. Write to HDMI_I2C_TRANSACTION1 with the following fields set in
+ order to handle characteristics of portion #3
+ * RW1 = 0x1 (read)
+ * START1 = 0x1 (insert START bit)
+ * STOP1 = 0x1 (insert STOP bit)
+ * CNT1 = data_len (it's 128 (0x80) for a blk read) */
+ HDMI_OUTP_ND(0x0230, 1 | (1 << 12) | (1 << 13) | (request_len << 16));
+
+ /* Trigger the I2C transfer */
+ /* 0x020C HDMI_DDC_CTRL
+ [21:20] TRANSACTION_CNT
+ Number of transactions to be done in current transfer.
+ * 0x0: transaction0 only
+ * 0x1: transaction0, transaction1
+ * 0x2: transaction0, transaction1, transaction2
+ * 0x3: transaction0, transaction1, transaction2, transaction3
+ [3] SW_STATUS_RESET
+ Write 1 to reset HDMI_DDC_SW_STATUS flags, will reset SW_DONE,
+ ABORTED, TIMEOUT, SW_INTERRUPTED, BUFFER_OVERFLOW,
+ STOPPED_ON_NACK, NACK0, NACK1, NACK2, NACK3
+ [2] SEND_RESET Set to 1 to send reset sequence (9 clocks with no
+ data) at start of transfer. This sequence is sent after GO is
+ written to 1, before the first transaction only.
+ [1] SOFT_RESET Write 1 to reset DDC controller
+ [0] GO WRITE ONLY. Write 1 to start DDC transfer. */
+
+ /* 6. Write to HDMI_I2C_CONTROL to kick off the hardware.
+ * Note that NOTHING has been transmitted on the DDC lines up to this
+ * point.
+ * TRANSACTION_CNT = 0x2 (execute transaction0 followed by
+ * transaction1)
+ * GO = 0x1 (kicks off hardware) */
+ INIT_COMPLETION(hdmi_msm_state->ddc_sw_done);
+ HDMI_OUTP_ND(0x020C, (1 << 0) | (2 << 20));
+
+ time_out_count = wait_for_completion_interruptible_timeout(
+ &hdmi_msm_state->ddc_sw_done, HZ/2);
+ HDMI_OUTP_ND(0x0214, 0x2);
+ if (!time_out_count) {
+ if (retry-- > 0) {
+ DEV_INFO("%s: failed timout, retry=%d\n", __func__,
+ retry);
+ goto again;
+ }
+ status = -ETIMEDOUT;
+ DEV_ERR("%s: timedout(7), DDC SW Status=%08x, HW "
+ "Status=%08x, Int Ctrl=%08x\n", __func__,
+ HDMI_INP(0x0218), HDMI_INP(0x021C), HDMI_INP(0x0214));
+ goto error;
+ }
+
+ /* Read DDC status */
+ reg_val = HDMI_INP_ND(0x0218);
+ reg_val &= 0x00001000 | 0x00002000 | 0x00004000 | 0x00008000;
+
+ /* Check if any NACK occurred */
+ if (reg_val) {
+ HDMI_OUTP_ND(0x020C, BIT(3)); /* SW_STATUS_RESET */
+ if (retry == 1)
+ HDMI_OUTP_ND(0x020C, BIT(1)); /* SOFT_RESET */
+ if (retry-- > 0) {
+ DEV_DBG("%s(%s): failed NACK=0x%08x, retry=%d, "
+ "dev-addr=0x%02x, offset=0x%02x, "
+ "length=%d\n", __func__, what,
+ reg_val, retry, dev_addr,
+ offset, data_len);
+ goto again;
+ }
+ status = -EIO;
+ if (log_retry_fail)
+ DEV_ERR("%s(%s): failed NACK=0x%08x, dev-addr=0x%02x, "
+ "offset=0x%02x, length=%d\n", __func__, what,
+ reg_val, dev_addr, offset, data_len);
+ goto error;
+ }
+
+ /* 0x0238 HDMI_DDC_DATA
+ [31] INDEX_WRITE WRITE ONLY. To write index field, set this bit to 1
+ while writing HDMI_DDC_DATA.
+ [23:16] INDEX Use to set index into DDC buffer for next read or
+ current write, or to read index of current read or next write.
+ Writable only when INDEX_WRITE=1.
+ [15:8] DATA Use to fill or read the DDC buffer
+ [0] DATA_RW Select whether buffer access will be a read or write.
+ For writes, address auto-increments on write to HDMI_DDC_DATA.
+ For reads, address autoincrements on reads to HDMI_DDC_DATA.
+ * 0: Write
+ * 1: Read */
+
+ /* 8. ALL data is now available and waiting in the DDC buffer.
+ * Read HDMI_I2C_DATA with the following fields set
+ * RW = 0x1 (read)
+ * DATA = BCAPS (this is field where data is pulled from)
+ * INDEX = 0x3 (where the data has been placed in buffer by hardware)
+ * INDEX_WRITE = 0x1 (explicitly define offset) */
+ /* Write this data to DDC buffer */
+ HDMI_OUTP_ND(0x0238, 0x1 | (3 << 16) | (1 << 31));
+
+ /* Discard first byte */
+ HDMI_INP_ND(0x0238);
+ for (ndx = 0; ndx < data_len; ++ndx) {
+ reg_val = HDMI_INP_ND(0x0238);
+ data_buf[ndx] = (uint8) ((reg_val & 0x0000FF00) >> 8);
+ }
+
+ DEV_DBG("%s[%s] success\n", __func__, what);
+
+error:
+ return status;
+}
+
+
+static int hdmi_msm_ddc_read(uint32 dev_addr, uint32 offset, uint8 *data_buf,
+ uint32 data_len, int retry, const char *what, boolean no_align)
+{
+ int ret = hdmi_msm_ddc_read_retry(dev_addr, offset, data_buf, data_len,
+ data_len, retry, what);
+ if (!ret)
+ return 0;
+ if (no_align) {
+ return hdmi_msm_ddc_read_retry(dev_addr, offset, data_buf,
+ data_len, data_len, retry, what);
+ } else {
+ return hdmi_msm_ddc_read_retry(dev_addr, offset, data_buf,
+ data_len, 32 * ((data_len + 31) / 32), retry, what);
+ }
+}
+
+
+static int hdmi_msm_read_edid_block(int block, uint8 *edid_buf)
+{
+ int i, rc = 0;
+ int block_size = 0x80;
+
+ do {
+ DEV_DBG("EDID: reading block(%d) with block-size=%d\n",
+ block, block_size);
+ for (i = 0; i < 0x80; i += block_size) {
+ /*Read EDID twice with 32bit alighnment too */
+ if (block < 2) {
+ rc = hdmi_msm_ddc_read(0xA0, block*0x80 + i,
+ edid_buf+i, block_size, 1,
+ "EDID", FALSE);
+ } else {
+ rc = hdmi_msm_ddc_read_edid_seg(0xA0,
+ block*0x80 + i, edid_buf+i, block_size,
+ block_size, 1, "EDID");
+ }
+ if (rc)
+ break;
+ }
+
+ block_size /= 2;
+ } while (rc && (block_size >= 16));
+
+ return rc;
+}
+
+static int hdmi_msm_read_edid(void)
+{
+ int status;
+
+ msm_hdmi_init_ddc();
+ /* Looks like we need to turn on HDMI engine before any
+ * DDC transaction */
+ if (!hdmi_msm_is_power_on()) {
+ DEV_ERR("%s: failed: HDMI power is off", __func__);
+ status = -ENXIO;
+ goto error;
+ }
+
+ external_common_state->read_edid_block = hdmi_msm_read_edid_block;
+ status = hdmi_common_read_edid();
+ if (!status)
+ DEV_DBG("EDID: successfully read\n");
+
+error:
+ return status;
+}
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+static void hdcp_auth_info(uint32 auth_info)
+{
+ switch (auth_info) {
+ case 0:
+ DEV_INFO("%s: None", __func__);
+ break;
+ case 1:
+ DEV_INFO("%s: Software Disabled Authentication", __func__);
+ break;
+ case 2:
+ DEV_INFO("%s: An Written", __func__);
+ break;
+ case 3:
+ DEV_INFO("%s: Invalid Aksv", __func__);
+ break;
+ case 4:
+ DEV_INFO("%s: Invalid Bksv", __func__);
+ break;
+ case 5:
+ DEV_INFO("%s: RI Mismatch (including RO)", __func__);
+ break;
+ case 6:
+ DEV_INFO("%s: consecutive Pj Mismatches", __func__);
+ break;
+ case 7:
+ DEV_INFO("%s: HPD Disconnect", __func__);
+ break;
+ case 8:
+ default:
+ DEV_INFO("%s: Reserved", __func__);
+ break;
+ }
+}
+
+static void hdcp_key_state(uint32 key_state)
+{
+ switch (key_state) {
+ case 0:
+ DEV_WARN("%s: No HDCP Keys", __func__);
+ break;
+ case 1:
+ DEV_WARN("%s: Not Checked", __func__);
+ break;
+ case 2:
+ DEV_DBG("%s: Checking", __func__);
+ break;
+ case 3:
+ DEV_DBG("%s: HDCP Keys Valid", __func__);
+ break;
+ case 4:
+ DEV_WARN("%s: AKSV not valid", __func__);
+ break;
+ case 5:
+ DEV_WARN("%s: Checksum Mismatch", __func__);
+ break;
+ case 6:
+ DEV_DBG("%s: Production AKSV"
+ "with ENABLE_USER_DEFINED_AN=1", __func__);
+ break;
+ case 7:
+ default:
+ DEV_INFO("%s: Reserved", __func__);
+ break;
+ }
+}
+
+static int hdmi_msm_count_one(uint8 *array, uint8 len)
+{
+ int i, j, count = 0;
+ for (i = 0; i < len; i++)
+ for (j = 0; j < 8; j++)
+ count += (((array[i] >> j) & 0x1) ? 1 : 0);
+ return count;
+}
+
+static void hdcp_deauthenticate(void)
+{
+ int hdcp_link_status = HDMI_INP(0x011C);
+
+ external_common_state->hdcp_active = FALSE;
+ /* 0x0130 HDCP_RESET
+ [0] LINK0_DEAUTHENTICATE */
+ HDMI_OUTP(0x0130, 0x1);
+
+ /* 0x0110 HDCP_CTRL
+ [8] ENCRYPTION_ENABLE
+ [0] ENABLE */
+ /* encryption_enable = 0 | hdcp block enable = 1 */
+ HDMI_OUTP(0x0110, 0x0);
+
+ if (hdcp_link_status & 0x00000004)
+ hdcp_auth_info((hdcp_link_status & 0x000000F0) >> 4);
+}
+
+static int hdcp_authentication_part1(void)
+{
+ int ret = 0;
+ boolean is_match;
+ boolean is_part1_done = FALSE;
+ uint32 timeout_count;
+ uint8 bcaps;
+ uint8 aksv[5];
+ uint32 qfprom_aksv_0, qfprom_aksv_1, link0_aksv_0, link0_aksv_1;
+ uint8 bksv[5];
+ uint32 link0_bksv_0, link0_bksv_1;
+ uint8 an[8];
+ uint32 link0_an_0, link0_an_1;
+ uint32 hpd_int_status, hpd_int_ctrl;
+
+
+ static uint8 buf[0xFF];
+ memset(buf, 0, sizeof(buf));
+
+ if (!is_part1_done) {
+ is_part1_done = TRUE;
+
+ /* Fetch aksv from QFprom, this info should be public. */
+ qfprom_aksv_0 = inpdw(QFPROM_BASE + 0x000060D8);
+ qfprom_aksv_1 = inpdw(QFPROM_BASE + 0x000060DC);
+
+ /* copy an and aksv to byte arrays for transmission */
+ aksv[0] = qfprom_aksv_0 & 0xFF;
+ aksv[1] = (qfprom_aksv_0 >> 8) & 0xFF;
+ aksv[2] = (qfprom_aksv_0 >> 16) & 0xFF;
+ aksv[3] = (qfprom_aksv_0 >> 24) & 0xFF;
+ aksv[4] = qfprom_aksv_1 & 0xFF;
+ /* check there are 20 ones in AKSV */
+ if (hdmi_msm_count_one(aksv, 5) != 20) {
+ DEV_ERR("HDCP: AKSV read from QFPROM doesn't have\
+ 20 1's and 20 0's, FAIL (AKSV=%02x%08x)\n",
+ qfprom_aksv_1, qfprom_aksv_0);
+ ret = -EINVAL;
+ goto error;
+ }
+ DEV_DBG("HDCP: AKSV=%02x%08x\n", qfprom_aksv_1, qfprom_aksv_0);
+
+ /* 0x0288 HDCP_SW_LOWER_AKSV
+ [31:0] LOWER_AKSV */
+ /* 0x0284 HDCP_SW_UPPER_AKSV
+ [7:0] UPPER_AKSV */
+
+ /* This is the lower 32 bits of the SW
+ * injected AKSV value(AKSV[31:0]) read
+ * from the EFUSE. It is needed for HDCP
+ * authentication and must be written
+ * before enabling HDCP. */
+ HDMI_OUTP(0x0288, qfprom_aksv_0);
+ HDMI_OUTP(0x0284, qfprom_aksv_1);
+
+ msm_hdmi_init_ddc();
+
+ /* Read Bksv 5 bytes at 0x00 in HDCP port */
+ ret = hdmi_msm_ddc_read(0x74, 0x00, bksv, 5, 5, "Bksv", TRUE);
+ if (ret) {
+ DEV_ERR("%s(%d): Read BKSV failed", __func__, __LINE__);
+ goto error;
+ }
+ /* check there are 20 ones in BKSV */
+ if (hdmi_msm_count_one(bksv, 5) != 20) {
+ DEV_ERR("HDCP: BKSV read from Sink doesn't have\
+ 20 1's and 20 0's, FAIL (BKSV=\
+ %02x%02x%02x%02x%02x)\n",
+ bksv[4], bksv[3], bksv[2], bksv[1], bksv[0]);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ link0_bksv_0 = bksv[3];
+ link0_bksv_0 = (link0_bksv_0 << 8) | bksv[2];
+ link0_bksv_0 = (link0_bksv_0 << 8) | bksv[1];
+ link0_bksv_0 = (link0_bksv_0 << 8) | bksv[0];
+ link0_bksv_1 = bksv[4];
+ DEV_DBG("HDCP: BKSV=%02x%08x\n", link0_bksv_1, link0_bksv_0);
+
+ /* read Bcaps at 0x40 in HDCP Port */
+ ret = hdmi_msm_ddc_read(0x74, 0x40, &bcaps, 1, 5, "Bcaps",
+ TRUE);
+ if (ret) {
+ DEV_ERR("%s(%d): Read Bcaps failed", __func__,
+ __LINE__);
+ goto error;
+ }
+ DEV_DBG("HDCP: Bcaps=%02x\n", bcaps);
+
+ /* HDCP setup prior to HDCP enabled */
+
+ /* 0x0148 HDCP_RCVPORT_DATA4
+ [15:8] LINK0_AINFO
+ [7:0] LINK0_AKSV_1 */
+ /* LINK0_AINFO = 0x2 FEATURE 1.1 on.
+ * = 0x0 FEATURE 1.1 off*/
+ HDMI_OUTP(0x0148, 0x2 << 8);
+
+ /* 0x012C HDCP_ENTROPY_CTRL0
+ [31:0] BITS_OF_INFLUENCE_0 */
+ /* 0x025C HDCP_ENTROPY_CTRL1
+ [31:0] BITS_OF_INFLUENCE_1 */
+ HDMI_OUTP(0x012C, 0xB1FFB0FF);
+ HDMI_OUTP(0x025C, 0xF00DFACE);
+
+ /* 0x0114 HDCP_DEBUG_CTRL
+ [2] DEBUG_RNG_CIPHER
+ else default 0 */
+ HDMI_OUTP(0x0114, HDMI_INP(0x0114) & 0xFFFFFFFB);
+
+ /* 0x0110 HDCP_CTRL
+ [8] ENCRYPTION_ENABLE
+ [0] ENABLE */
+ /* encryption_enable | enable */
+ HDMI_OUTP(0x0110, (1 << 8) | (1 << 0));
+
+ /* 0x0118 HDCP_INT_CTRL
+ * [2] AUTH_SUCCESS_MASK [R/W] Mask bit for\
+ * HDCP Authentication
+ * Success interrupt - set to 1 to enable interrupt
+ *
+ * [6] AUTH_FAIL_MASK [R/W] Mask bit for HDCP
+ * Authentication
+ * Lost interrupt set to 1 to enable interrupt
+ *
+ * [7] AUTH_FAIL_INFO_ACK [W] Acknwledge bit for HDCP
+ * Auth Failure Info field - write 1 to clear
+ *
+ * [10] DDC_XFER_REQ_MASK [R/W] Mask bit for HDCP\
+ * DDC Transfer
+ * Request interrupt - set to 1 to enable interrupt
+ *
+ * [14] DDC_XFER_DONE_MASK [R/W] Mask bit for HDCP\
+ * DDC Transfer
+ * done interrupt - set to 1 to enable interrupt */
+ /* enable all HDCP ints */
+ HDMI_OUTP(0x0118, (1 << 2) | (1 << 6) | (1 << 7));
+
+ /* 0x011C HDCP_LINK0_STATUS
+ [8] AN_0_READY
+ [9] AN_1_READY */
+ /* wait for an0 and an1 ready bits to be set in LINK0_STATUS */
+ timeout_count = 100;
+ while (((HDMI_INP_ND(0x011C) & (0x3 << 8)) != (0x3 << 8))
+ && timeout_count--)
+ msleep(20);
+ if (!timeout_count) {
+ ret = -ETIMEDOUT;
+ DEV_ERR("%s(%d): timedout, An0=%d, An1=%d\n",
+ __func__, __LINE__,
+ (HDMI_INP_ND(0x011C) & BIT(8)) >> 8,
+ (HDMI_INP_ND(0x011C) & BIT(9)) >> 9);
+ goto error;
+ }
+
+ /* 0x0168 HDCP_RCVPORT_DATA12
+ [23:8] BSTATUS
+ [7:0] BCAPS */
+ HDMI_OUTP(0x0168, bcaps);
+
+ /* 0x014C HDCP_RCVPORT_DATA5
+ [31:0] LINK0_AN_0 */
+ /* read an0 calculation */
+ link0_an_0 = HDMI_INP(0x014C);
+
+ /* 0x0150 HDCP_RCVPORT_DATA6
+ [31:0] LINK0_AN_1 */
+ /* read an1 calculation */
+ link0_an_1 = HDMI_INP(0x0150);
+
+ /* three bits 28..30 */
+ hdcp_key_state((HDMI_INP(0x011C) >> 28) & 0x7);
+
+ /* 0x0144 HDCP_RCVPORT_DATA3
+ [31:0] LINK0_AKSV_0 public key
+ 0x0148 HDCP_RCVPORT_DATA4
+ [15:8] LINK0_AINFO
+ [7:0] LINK0_AKSV_1 public key */
+ link0_aksv_0 = HDMI_INP(0x0144);
+ link0_aksv_1 = HDMI_INP(0x0148);
+
+ /* copy an and aksv to byte arrays for transmission */
+ aksv[0] = link0_aksv_0 & 0xFF;
+ aksv[1] = (link0_aksv_0 >> 8) & 0xFF;
+ aksv[2] = (link0_aksv_0 >> 16) & 0xFF;
+ aksv[3] = (link0_aksv_0 >> 24) & 0xFF;
+ aksv[4] = link0_aksv_1 & 0xFF;
+
+ an[0] = link0_an_0 & 0xFF;
+ an[1] = (link0_an_0 >> 8) & 0xFF;
+ an[2] = (link0_an_0 >> 16) & 0xFF;
+ an[3] = (link0_an_0 >> 24) & 0xFF;
+ an[4] = link0_an_1 & 0xFF;
+ an[5] = (link0_an_1 >> 8) & 0xFF;
+ an[6] = (link0_an_1 >> 16) & 0xFF;
+ an[7] = (link0_an_1 >> 24) & 0xFF;
+
+ /* Write An 8 bytes to offset 0x18 */
+ ret = hdmi_msm_ddc_write(0x74, 0x18, an, 8, "An");
+ if (ret) {
+ DEV_ERR("%s(%d): Write An failed", __func__, __LINE__);
+ goto error;
+ }
+
+ /* Write Aksv 5 bytes to offset 0x10 */
+ ret = hdmi_msm_ddc_write(0x74, 0x10, aksv, 5, "Aksv");
+ if (ret) {
+ DEV_ERR("%s(%d): Write Aksv failed", __func__,
+ __LINE__);
+ goto error;
+ }
+ DEV_DBG("HDCP: Link0-AKSV=%02x%08x\n",
+ link0_aksv_1 & 0xFF, link0_aksv_0);
+
+ /* 0x0134 HDCP_RCVPORT_DATA0
+ [31:0] LINK0_BKSV_0 */
+ HDMI_OUTP(0x0134, link0_bksv_0);
+ /* 0x0138 HDCP_RCVPORT_DATA1
+ [31:0] LINK0_BKSV_1 */
+ HDMI_OUTP(0x0138, link0_bksv_1);
+ DEV_DBG("HDCP: Link0-BKSV=%02x%08x\n", link0_bksv_1,
+ link0_bksv_0);
+
+ /* HDMI_HPD_INT_STATUS[0x0250] */
+ hpd_int_status = HDMI_INP_ND(0x0250);
+ /* HDMI_HPD_INT_CTRL[0x0254] */
+ hpd_int_ctrl = HDMI_INP_ND(0x0254);
+ DEV_DBG("[SR-DEUG]: HPD_INTR_CTRL=[%u] HPD_INTR_STATUS=[%u]\
+ before reading R0'\n", hpd_int_ctrl, hpd_int_status);
+
+ /*
+ * HDCP Compliace Test case 1B-01:
+ * Wait here until all the ksv bytes have been
+ * read from the KSV FIFO register.
+ */
+ msleep(125);
+
+ /* Reading R0' 2 bytes at offset 0x08 */
+ ret = hdmi_msm_ddc_read(0x74, 0x08, buf, 2, 5, "RO'", TRUE);
+ if (ret) {
+ DEV_ERR("%s(%d): Read RO's failed", __func__,
+ __LINE__);
+ goto error;
+ }
+
+ /* 0x013C HDCP_RCVPORT_DATA2_0
+ [15:0] LINK0_RI */
+ HDMI_OUTP(0x013C, (((uint32)buf[1]) << 8) | buf[0]);
+ DEV_DBG("HDCP: R0'=%02x%02x\n", buf[1], buf[0]);
+
+ INIT_COMPLETION(hdmi_msm_state->hdcp_success_done);
+ timeout_count = wait_for_completion_interruptible_timeout(
+ &hdmi_msm_state->hdcp_success_done, HZ*2);
+
+ if (!timeout_count) {
+ ret = -ETIMEDOUT;
+ is_match = HDMI_INP(0x011C) & BIT(12);
+ DEV_ERR("%s(%d): timedout, Link0=<%s>\n", __func__,
+ __LINE__,
+ is_match ? "RI_MATCH" : "No RI Match INTR in time");
+ if (!is_match)
+ goto error;
+ }
+
+ /* 0x011C HDCP_LINK0_STATUS
+ [12] RI_MATCHES [0] MISMATCH, [1] MATCH
+ [0] AUTH_SUCCESS */
+ /* Checking for RI, R0 Match */
+ /* RI_MATCHES */
+ if ((HDMI_INP(0x011C) & BIT(12)) != BIT(12)) {
+ ret = -EINVAL;
+ DEV_ERR("%s: HDCP_LINK0_STATUS[RI_MATCHES]: MISMATCH\n",
+ __func__);
+ goto error;
+ }
+
+ DEV_INFO("HDCP: authentication part I, successful\n");
+ is_part1_done = FALSE;
+ return 0;
+error:
+ DEV_ERR("[%s]: HDCP Reauthentication\n", __func__);
+ is_part1_done = FALSE;
+ return ret;
+ } else {
+ return 1;
+ }
+}
+
+static int hdmi_msm_transfer_v_h(void)
+{
+ /* Read V'.HO 4 Byte at offset 0x20 */
+ char what[20];
+ int ret;
+ uint8 buf[4];
+
+ snprintf(what, sizeof(what), "V' H0");
+ ret = hdmi_msm_ddc_read(0x74, 0x20, buf, 4, 5, what, TRUE);
+ if (ret) {
+ DEV_ERR("%s: Read %s failed", __func__, what);
+ return ret;
+ }
+ DEV_DBG("buf[0]= %x , buf[1] = %x , buf[2] = %x , buf[3] = %x\n ",
+ buf[0] , buf[1] , buf[2] , buf[3]);
+
+ /* 0x0154 HDCP_RCVPORT_DATA7
+ [31:0] V_HO */
+ HDMI_OUTP(0x0154 ,
+ (buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]));
+
+ snprintf(what, sizeof(what), "V' H1");
+ ret = hdmi_msm_ddc_read(0x74, 0x24, buf, 4, 5, what, TRUE);
+ if (ret) {
+ DEV_ERR("%s: Read %s failed", __func__, what);
+ return ret;
+ }
+ DEV_DBG("buf[0]= %x , buf[1] = %x , buf[2] = %x , buf[3] = %x\n ",
+ buf[0] , buf[1] , buf[2] , buf[3]);
+
+ /* 0x0158 HDCP_RCVPORT_ DATA8
+ [31:0] V_H1 */
+ HDMI_OUTP(0x0158,
+ (buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]));
+
+
+ snprintf(what, sizeof(what), "V' H2");
+ ret = hdmi_msm_ddc_read(0x74, 0x28, buf, 4, 5, what, TRUE);
+ if (ret) {
+ DEV_ERR("%s: Read %s failed", __func__, what);
+ return ret;
+ }
+ DEV_DBG("buf[0]= %x , buf[1] = %x , buf[2] = %x , buf[3] = %x\n ",
+ buf[0] , buf[1] , buf[2] , buf[3]);
+
+ /* 0x015c HDCP_RCVPORT_DATA9
+ [31:0] V_H2 */
+ HDMI_OUTP(0x015c ,
+ (buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]));
+
+ snprintf(what, sizeof(what), "V' H3");
+ ret = hdmi_msm_ddc_read(0x74, 0x2c, buf, 4, 5, what, TRUE);
+ if (ret) {
+ DEV_ERR("%s: Read %s failed", __func__, what);
+ return ret;
+ }
+ DEV_DBG("buf[0]= %x , buf[1] = %x , buf[2] = %x , buf[3] = %x\n ",
+ buf[0] , buf[1] , buf[2] , buf[3]);
+
+ /* 0x0160 HDCP_RCVPORT_DATA10
+ [31:0] V_H3 */
+ HDMI_OUTP(0x0160,
+ (buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]));
+
+ snprintf(what, sizeof(what), "V' H4");
+ ret = hdmi_msm_ddc_read(0x74, 0x30, buf, 4, 5, what, TRUE);
+ if (ret) {
+ DEV_ERR("%s: Read %s failed", __func__, what);
+ return ret;
+ }
+ DEV_DBG("buf[0]= %x , buf[1] = %x , buf[2] = %x , buf[3] = %x\n ",
+ buf[0] , buf[1] , buf[2] , buf[3]);
+ /* 0x0164 HDCP_RCVPORT_DATA11
+ [31:0] V_H4 */
+ HDMI_OUTP(0x0164,
+ (buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]));
+
+ return 0;
+}
+
+static int hdcp_authentication_part2(void)
+{
+ int ret = 0;
+ uint32 timeout_count;
+ int i = 0;
+ int cnt = 0;
+ uint bstatus;
+ uint8 bcaps;
+ uint32 down_stream_devices;
+ uint32 ksv_bytes;
+
+ static uint8 buf[0xFF];
+ static uint8 kvs_fifo[5 * 127];
+
+ boolean max_devs_exceeded = 0;
+ boolean max_cascade_exceeded = 0;
+
+ boolean ksv_done = FALSE;
+
+ memset(buf, 0, sizeof(buf));
+ memset(kvs_fifo, 0, sizeof(kvs_fifo));
+
+ /* wait until READY bit is set in bcaps */
+ timeout_count = 50;
+ do {
+ timeout_count--;
+ /* read bcaps 1 Byte at offset 0x40 */
+ ret = hdmi_msm_ddc_read(0x74, 0x40, &bcaps, 1, 1,
+ "Bcaps", FALSE);
+ if (ret) {
+ DEV_ERR("%s(%d): Read Bcaps failed", __func__,
+ __LINE__);
+ goto error;
+ }
+ msleep(100);
+ } while ((0 == (bcaps & 0x20)) && timeout_count); /* READY (Bit 5) */
+ if (!timeout_count) {
+ ret = -ETIMEDOUT;
+ DEV_ERR("%s:timedout(1)", __func__);
+ goto error;
+ }
+
+ /* read bstatus 2 bytes at offset 0x41 */
+
+ ret = hdmi_msm_ddc_read(0x74, 0x41, buf, 2, 5, "Bstatus", FALSE);
+ if (ret) {
+ DEV_ERR("%s(%d): Read Bstatus failed", __func__, __LINE__);
+ goto error;
+ }
+ bstatus = buf[1];
+ bstatus = (bstatus << 8) | buf[0];
+ /* 0x0168 DCP_RCVPORT_DATA12
+ [7:0] BCAPS
+ [23:8 BSTATUS */
+ HDMI_OUTP(0x0168, bcaps | (bstatus << 8));
+ /* BSTATUS [6:0] DEVICE_COUNT Number of HDMI device attached to repeater
+ * - see HDCP spec */
+ down_stream_devices = bstatus & 0x7F;
+
+ if (down_stream_devices == 0x0) {
+ /* There isn't any devices attaced to the Repeater */
+ DEV_ERR("%s: there isn't any devices attached to the "
+ "Repeater\n", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ /*
+ * HDCP Compliance 1B-05:
+ * Check if no. of devices connected to repeater
+ * exceed max_devices_connected from bit 7 of Bstatus.
+ */
+ max_devs_exceeded = (bstatus & 0x80) >> 7;
+ if (max_devs_exceeded == 0x01) {
+ DEV_ERR("%s: Number of devs connected to repeater "
+ "exceeds max_devs\n", __func__);
+ ret = -EINVAL;
+ goto hdcp_error;
+ }
+
+ /*
+ * HDCP Compliance 1B-06:
+ * Check if no. of cascade connected to repeater
+ * exceed max_cascade_connected from bit 11 of Bstatus.
+ */
+ max_cascade_exceeded = (bstatus & 0x800) >> 11;
+ if (max_cascade_exceeded == 0x01) {
+ DEV_ERR("%s: Number of cascade connected to repeater "
+ "exceeds max_cascade\n", __func__);
+ ret = -EINVAL;
+ goto hdcp_error;
+ }
+
+ /* Read KSV FIFO over DDC
+ * Key Slection vector FIFO
+ * Used to pull downstream KSVs from HDCP Repeaters.
+ * All bytes (DEVICE_COUNT * 5) must be read in a single,
+ * auto incrementing access.
+ * All bytes read as 0x00 for HDCP Receivers that are not
+ * HDCP Repeaters (REPEATER == 0). */
+ ksv_bytes = 5 * down_stream_devices;
+ /* Reading KSV FIFO / KSV FIFO */
+ ksv_done = FALSE;
+
+ ret = hdmi_msm_ddc_read(0x74, 0x43, kvs_fifo, ksv_bytes, 5,
+ "KSV FIFO", TRUE);
+ do {
+ if (ret) {
+ DEV_ERR("%s(%d): Read KSV FIFO failed",
+ __func__, __LINE__);
+ /*
+ * HDCP Compliace Test case 1B-01:
+ * Wait here until all the ksv bytes have been
+ * read from the KSV FIFO register.
+ */
+ msleep(25);
+ } else {
+ ksv_done = TRUE;
+ }
+ cnt++;
+ } while (!ksv_done && cnt != 20);
+
+ if (ksv_done == FALSE)
+ goto error;
+
+ ret = hdmi_msm_transfer_v_h();
+ if (ret)
+ goto error;
+
+ /* Next: Write KSV FIFO to HDCP_SHA_DATA.
+ * This is done 1 byte at time starting with the LSB.
+ * On the very last byte write,
+ * the HDCP_SHA_DATA_DONE bit[0]
+ */
+
+ /* 0x023C HDCP_SHA_CTRL
+ [0] RESET [0] Enable, [1] Reset
+ [4] SELECT [0] DIGA_HDCP, [1] DIGB_HDCP */
+ /* reset SHA engine */
+ HDMI_OUTP(0x023C, 1);
+ /* enable SHA engine, SEL=DIGA_HDCP */
+ HDMI_OUTP(0x023C, 0);
+
+ for (i = 0; i < ksv_bytes - 1; i++) {
+ /* Write KSV byte and do not set DONE bit[0] */
+ HDMI_OUTP_ND(0x0244, kvs_fifo[i] << 16);
+ }
+ /* Write l to DONE bit[0] */
+ HDMI_OUTP_ND(0x0244, (kvs_fifo[ksv_bytes - 1] << 16) | 0x1);
+
+ /* 0x0240 HDCP_SHA_STATUS
+ [4] COMP_DONE */
+ /* Now wait for HDCP_SHA_COMP_DONE */
+ timeout_count = 100;
+ while ((0x10 != (HDMI_INP_ND(0x0240) & 0x10)) && timeout_count--)
+ msleep(20);
+ if (!timeout_count) {
+ ret = -ETIMEDOUT;
+ DEV_ERR("%s(%d): timedout", __func__, __LINE__);
+ goto error;
+ }
+
+ /* 0x011C HDCP_LINK0_STATUS
+ [20] V_MATCHES */
+ timeout_count = 100;
+ while (((HDMI_INP_ND(0x011C) & (1 << 20)) != (1 << 20))
+ && timeout_count--)
+ msleep(20);
+ if (!timeout_count) {
+ ret = -ETIMEDOUT;
+ DEV_ERR("%s(%d): timedout", __func__, __LINE__);
+ goto error;
+ }
+
+ DEV_INFO("HDCP: authentication part II, successful\n");
+
+hdcp_error:
+error:
+ return ret;
+}
+
+static int hdcp_authentication_part3(uint32 found_repeater)
+{
+ int ret = 0;
+ int poll = 3000;
+ while (poll) {
+ /* 0x011C HDCP_LINK0_STATUS
+ [30:28] KEYS_STATE = 3 = "Valid"
+ [24] RO_COMPUTATION_DONE [0] Not Done, [1] Done
+ [20] V_MATCHES [0] Mismtach, [1] Match
+ [12] RI_MATCHES [0] Mismatch, [1] Match
+ [0] AUTH_SUCCESS */
+ if (HDMI_INP_ND(0x011C) != (0x31001001 |
+ (found_repeater << 20))) {
+ DEV_ERR("HDCP: autentication part III, FAILED, "
+ "Link Status=%08x\n", HDMI_INP(0x011C));
+ ret = -EINVAL;
+ goto error;
+ }
+ poll--;
+ }
+
+ DEV_INFO("HDCP: authentication part III, successful\n");
+
+error:
+ return ret;
+}
+
+static void hdmi_msm_hdcp_enable(void)
+{
+ int ret = 0;
+ uint8 bcaps;
+ uint32 found_repeater = 0x0;
+ char *envp[2];
+
+ if (!hdmi_msm_has_hdcp())
+ return;
+
+ mutex_lock(&hdmi_msm_state_mutex);
+ hdmi_msm_state->hdcp_activating = TRUE;
+ mutex_unlock(&hdmi_msm_state_mutex);
+
+ fill_black_screen();
+
+ mutex_lock(&hdcp_auth_state_mutex);
+ /*
+ * Initialize this to zero here to make
+ * sure HPD has not happened yet
+ */
+ hdmi_msm_state->hpd_during_auth = FALSE;
+ /* This flag prevents other threads from re-authenticating
+ * after we've just authenticated (i.e., finished part3)
+ * We probably need to protect this in a mutex lock */
+ hdmi_msm_state->full_auth_done = FALSE;
+ mutex_unlock(&hdcp_auth_state_mutex);
+
+ /* PART I Authentication*/
+ ret = hdcp_authentication_part1();
+ if (ret)
+ goto error;
+
+ /* PART II Authentication*/
+ /* read Bcaps at 0x40 in HDCP Port */
+ ret = hdmi_msm_ddc_read(0x74, 0x40, &bcaps, 1, 5, "Bcaps", FALSE);
+ if (ret) {
+ DEV_ERR("%s(%d): Read Bcaps failed\n", __func__, __LINE__);
+ goto error;
+ }
+ DEV_DBG("HDCP: Bcaps=0x%02x (%s)\n", bcaps,
+ (bcaps & BIT(6)) ? "repeater" : "no repeater");
+
+ /* if REPEATER (Bit 6), perform Part2 Authentication */
+ if (bcaps & BIT(6)) {
+ found_repeater = 0x1;
+ ret = hdcp_authentication_part2();
+ if (ret)
+ goto error;
+ } else
+ DEV_INFO("HDCP: authentication part II skipped, no repeater\n");
+
+ /* PART III Authentication*/
+ ret = hdcp_authentication_part3(found_repeater);
+ if (ret)
+ goto error;
+
+ unfill_black_screen();
+
+ external_common_state->hdcp_active = TRUE;
+ mutex_lock(&hdmi_msm_state_mutex);
+ hdmi_msm_state->hdcp_activating = FALSE;
+ mutex_unlock(&hdmi_msm_state_mutex);
+
+ mutex_lock(&hdcp_auth_state_mutex);
+ /*
+ * This flag prevents other threads from re-authenticating
+ * after we've just authenticated (i.e., finished part3)
+ */
+ hdmi_msm_state->full_auth_done = TRUE;
+ mutex_unlock(&hdcp_auth_state_mutex);
+
+ if (!hdmi_msm_is_dvi_mode()) {
+ DEV_INFO("HDMI HPD: sense : send HDCP_PASS\n");
+ envp[0] = "HDCP_STATE=PASS";
+ envp[1] = NULL;
+ kobject_uevent_env(external_common_state->uevent_kobj,
+ KOBJ_CHANGE, envp);
+ }
+ return;
+
+error:
+ mutex_lock(&hdmi_msm_state_mutex);
+ hdmi_msm_state->hdcp_activating = FALSE;
+ mutex_unlock(&hdmi_msm_state_mutex);
+ if (hdmi_msm_state->hpd_during_auth) {
+ DEV_WARN("Calling Deauthentication: HPD occured during\
+ authentication from [%s]\n", __func__);
+ hdcp_deauthenticate();
+ mutex_lock(&hdcp_auth_state_mutex);
+ hdmi_msm_state->hpd_during_auth = FALSE;
+ mutex_unlock(&hdcp_auth_state_mutex);
+ } else {
+ DEV_WARN("[DEV_DBG]: Calling reauth from [%s]\n", __func__);
+ if (hdmi_msm_state->panel_power_on)
+ queue_work(hdmi_work_queue,
+ &hdmi_msm_state->hdcp_reauth_work);
+ }
+}
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
+
+static void hdmi_msm_video_setup(int video_format)
+{
+ uint32 total_v = 0;
+ uint32 total_h = 0;
+ uint32 start_h = 0;
+ uint32 end_h = 0;
+ uint32 start_v = 0;
+ uint32 end_v = 0;
+ const struct hdmi_disp_mode_timing_type *timing =
+ hdmi_common_get_supported_mode(video_format);
+
+ /* timing register setup */
+ if (timing == NULL) {
+ DEV_ERR("video format not supported: %d\n", video_format);
+ return;
+ }
+
+ /* Hsync Total and Vsync Total */
+ total_h = timing->active_h + timing->front_porch_h
+ + timing->back_porch_h + timing->pulse_width_h - 1;
+ total_v = timing->active_v + timing->front_porch_v
+ + timing->back_porch_v + timing->pulse_width_v - 1;
+ /* 0x02C0 HDMI_TOTAL
+ [27:16] V_TOTAL Vertical Total
+ [11:0] H_TOTAL Horizontal Total */
+ HDMI_OUTP(0x02C0, ((total_v << 16) & 0x0FFF0000)
+ | ((total_h << 0) & 0x00000FFF));
+
+ /* Hsync Start and Hsync End */
+ start_h = timing->back_porch_h + timing->pulse_width_h;
+ end_h = (total_h + 1) - timing->front_porch_h;
+ /* 0x02B4 HDMI_ACTIVE_H
+ [27:16] END Horizontal end
+ [11:0] START Horizontal start */
+ HDMI_OUTP(0x02B4, ((end_h << 16) & 0x0FFF0000)
+ | ((start_h << 0) & 0x00000FFF));
+
+ start_v = timing->back_porch_v + timing->pulse_width_v - 1;
+ end_v = total_v - timing->front_porch_v;
+ /* 0x02B8 HDMI_ACTIVE_V
+ [27:16] END Vertical end
+ [11:0] START Vertical start */
+ HDMI_OUTP(0x02B8, ((end_v << 16) & 0x0FFF0000)
+ | ((start_v << 0) & 0x00000FFF));
+
+ if (timing->interlaced) {
+ /* 0x02C4 HDMI_V_TOTAL_F2
+ [11:0] V_TOTAL_F2 Vertical total for field2 */
+ HDMI_OUTP(0x02C4, ((total_v + 1) << 0) & 0x00000FFF);
+
+ /* 0x02BC HDMI_ACTIVE_V_F2
+ [27:16] END_F2 Vertical end for field2
+ [11:0] START_F2 Vertical start for Field2 */
+ HDMI_OUTP(0x02BC,
+ (((start_v + 1) << 0) & 0x00000FFF)
+ | (((end_v + 1) << 16) & 0x0FFF0000));
+ } else {
+ /* HDMI_V_TOTAL_F2 */
+ HDMI_OUTP(0x02C4, 0);
+ /* HDMI_ACTIVE_V_F2 */
+ HDMI_OUTP(0x02BC, 0);
+ }
+
+ hdmi_frame_ctrl_cfg(timing);
+}
+
+struct hdmi_msm_audio_acr {
+ uint32 n; /* N parameter for clock regeneration */
+ uint32 cts; /* CTS parameter for clock regeneration */
+};
+
+struct hdmi_msm_audio_arcs {
+ uint32 pclk;
+ struct hdmi_msm_audio_acr lut[MSM_HDMI_SAMPLE_RATE_MAX];
+};
+
+#define HDMI_MSM_AUDIO_ARCS(pclk, ...) { pclk, __VA_ARGS__ }
+
+/* Audio constants lookup table for hdmi_msm_audio_acr_setup */
+/* Valid Pixel-Clock rates: 25.2MHz, 27MHz, 27.03MHz, 74.25MHz, 148.5MHz */
+static const struct hdmi_msm_audio_arcs hdmi_msm_audio_acr_lut[] = {
+ /* 25.200MHz */
+ HDMI_MSM_AUDIO_ARCS(25200, {
+ {4096, 25200}, {6272, 28000}, {6144, 25200}, {12544, 28000},
+ {12288, 25200}, {25088, 28000}, {24576, 25200} }),
+ /* 27.000MHz */
+ HDMI_MSM_AUDIO_ARCS(27000, {
+ {4096, 27000}, {6272, 30000}, {6144, 27000}, {12544, 30000},
+ {12288, 27000}, {25088, 30000}, {24576, 27000} }),
+ /* 27.030MHz */
+ HDMI_MSM_AUDIO_ARCS(27030, {
+ {4096, 27030}, {6272, 30030}, {6144, 27030}, {12544, 30030},
+ {12288, 27030}, {25088, 30030}, {24576, 27030} }),
+ /* 74.250MHz */
+ HDMI_MSM_AUDIO_ARCS(74250, {
+ {4096, 74250}, {6272, 82500}, {6144, 74250}, {12544, 82500},
+ {12288, 74250}, {25088, 82500}, {24576, 74250} }),
+ /* 148.500MHz */
+ HDMI_MSM_AUDIO_ARCS(148500, {
+ {4096, 148500}, {6272, 165000}, {6144, 148500}, {12544, 165000},
+ {12288, 148500}, {25088, 165000}, {24576, 148500} }),
+};
+
+static void hdmi_msm_audio_acr_setup(boolean enabled, int video_format,
+ int audio_sample_rate, int num_of_channels)
+{
+ /* Read first before writing */
+ /* HDMI_ACR_PKT_CTRL[0x0024] */
+ uint32 acr_pck_ctrl_reg = HDMI_INP(0x0024);
+
+ if (enabled) {
+ const struct hdmi_disp_mode_timing_type *timing =
+ hdmi_common_get_supported_mode(video_format);
+ const struct hdmi_msm_audio_arcs *audio_arc =
+ &hdmi_msm_audio_acr_lut[0];
+ const int lut_size = sizeof(hdmi_msm_audio_acr_lut)
+ /sizeof(*hdmi_msm_audio_acr_lut);
+ uint32 i, n, cts, layout, multiplier, aud_pck_ctrl_2_reg;
+
+ if (timing == NULL) {
+ DEV_WARN("%s: video format %d not supported\n",
+ __func__, video_format);
+ return;
+ }
+
+ for (i = 0; i < lut_size;
+ audio_arc = &hdmi_msm_audio_acr_lut[++i]) {
+ if (audio_arc->pclk == timing->pixel_freq)
+ break;
+ }
+ if (i >= lut_size) {
+ DEV_WARN("%s: pixel clock %d not supported\n", __func__,
+ timing->pixel_freq);
+ return;
+ }
+
+ n = audio_arc->lut[audio_sample_rate].n;
+ cts = audio_arc->lut[audio_sample_rate].cts;
+ layout = (MSM_HDMI_AUDIO_CHANNEL_2 == num_of_channels) ? 0 : 1;
+
+ if ((MSM_HDMI_SAMPLE_RATE_192KHZ == audio_sample_rate) ||
+ (MSM_HDMI_SAMPLE_RATE_176_4KHZ == audio_sample_rate)) {
+ multiplier = 4;
+ n >>= 2; /* divide N by 4 and use multiplier */
+ } else if ((MSM_HDMI_SAMPLE_RATE_96KHZ == audio_sample_rate) ||
+ (MSM_HDMI_SAMPLE_RATE_88_2KHZ == audio_sample_rate)) {
+ multiplier = 2;
+ n >>= 1; /* divide N by 2 and use multiplier */
+ } else {
+ multiplier = 1;
+ }
+ DEV_DBG("%s: n=%u, cts=%u, layout=%u\n", __func__, n, cts,
+ layout);
+
+ /* AUDIO_PRIORITY | SOURCE */
+ acr_pck_ctrl_reg |= 0x80000100;
+ /* N_MULTIPLE(multiplier) */
+ acr_pck_ctrl_reg |= (multiplier & 7) << 16;
+
+ if ((MSM_HDMI_SAMPLE_RATE_48KHZ == audio_sample_rate) ||
+ (MSM_HDMI_SAMPLE_RATE_96KHZ == audio_sample_rate) ||
+ (MSM_HDMI_SAMPLE_RATE_192KHZ == audio_sample_rate)) {
+ /* SELECT(3) */
+ acr_pck_ctrl_reg |= 3 << 4;
+ /* CTS_48 */
+ cts <<= 12;
+
+ /* CTS: need to determine how many fractional bits */
+ /* HDMI_ACR_48_0 */
+ HDMI_OUTP(0x00D4, cts);
+ /* N */
+ /* HDMI_ACR_48_1 */
+ HDMI_OUTP(0x00D8, n);
+ } else if ((MSM_HDMI_SAMPLE_RATE_44_1KHZ == audio_sample_rate)
+ || (MSM_HDMI_SAMPLE_RATE_88_2KHZ ==
+ audio_sample_rate)
+ || (MSM_HDMI_SAMPLE_RATE_176_4KHZ ==
+ audio_sample_rate)) {
+ /* SELECT(2) */
+ acr_pck_ctrl_reg |= 2 << 4;
+ /* CTS_44 */
+ cts <<= 12;
+
+ /* CTS: need to determine how many fractional bits */
+ /* HDMI_ACR_44_0 */
+ HDMI_OUTP(0x00CC, cts);
+ /* N */
+ /* HDMI_ACR_44_1 */
+ HDMI_OUTP(0x00D0, n);
+ } else { /* default to 32k */
+ /* SELECT(1) */
+ acr_pck_ctrl_reg |= 1 << 4;
+ /* CTS_32 */
+ cts <<= 12;
+
+ /* CTS: need to determine how many fractional bits */
+ /* HDMI_ACR_32_0 */
+ HDMI_OUTP(0x00C4, cts);
+ /* N */
+ /* HDMI_ACR_32_1 */
+ HDMI_OUTP(0x00C8, n);
+ }
+ /* Payload layout depends on number of audio channels */
+ /* LAYOUT_SEL(layout) */
+ aud_pck_ctrl_2_reg = 1 | (layout << 1);
+ /* override | layout */
+ /* HDMI_AUDIO_PKT_CTRL2[0x00044] */
+ HDMI_OUTP(0x00044, aud_pck_ctrl_2_reg);
+
+ /* SEND | CONT */
+ acr_pck_ctrl_reg |= 0x00000003;
+ } else {
+ /* ~(SEND | CONT) */
+ acr_pck_ctrl_reg &= ~0x00000003;
+ }
+ /* HDMI_ACR_PKT_CTRL[0x0024] */
+ HDMI_OUTP(0x0024, acr_pck_ctrl_reg);
+}
+
+static void hdmi_msm_outpdw_chk(uint32 offset, uint32 data)
+{
+ uint32 check, i = 0;
+
+#ifdef DEBUG
+ HDMI_OUTP(offset, data);
+#endif
+ do {
+ outpdw(MSM_HDMI_BASE+offset, data);
+ check = inpdw(MSM_HDMI_BASE+offset);
+ } while (check != data && i++ < 10);
+
+ if (check != data)
+ DEV_ERR("%s: failed addr=%08x, data=%x, check=%x",
+ __func__, offset, data, check);
+}
+
+static void hdmi_msm_rmw32or(uint32 offset, uint32 data)
+{
+ uint32 reg_data;
+ reg_data = inpdw(MSM_HDMI_BASE+offset);
+ reg_data = inpdw(MSM_HDMI_BASE+offset);
+ hdmi_msm_outpdw_chk(offset, reg_data | data);
+}
+
+
+#define HDMI_AUDIO_CFG 0x01D0
+#define HDMI_AUDIO_ENGINE_ENABLE 1
+#define HDMI_AUDIO_FIFO_MASK 0x000000F0
+#define HDMI_AUDIO_FIFO_WATERMARK_SHIFT 4
+#define HDMI_AUDIO_FIFO_MAX_WATER_MARK 8
+
+
+int hdmi_audio_enable(bool on , u32 fifo_water_mark)
+{
+ u32 hdmi_audio_config;
+
+ hdmi_audio_config = HDMI_INP(HDMI_AUDIO_CFG);
+
+ if (on) {
+
+ if (fifo_water_mark > HDMI_AUDIO_FIFO_MAX_WATER_MARK) {
+ pr_err("%s : HDMI audio fifo water mark can not be more"
+ " than %u\n", __func__,
+ HDMI_AUDIO_FIFO_MAX_WATER_MARK);
+ return -EINVAL;
+ }
+
+ /*
+ * Enable HDMI Audio engine.
+ * MUST be enabled after Audio DMA is enabled.
+ */
+ hdmi_audio_config &= ~(HDMI_AUDIO_FIFO_MASK);
+
+ hdmi_audio_config |= (HDMI_AUDIO_ENGINE_ENABLE |
+ (fifo_water_mark << HDMI_AUDIO_FIFO_WATERMARK_SHIFT));
+
+ } else
+ hdmi_audio_config &= ~(HDMI_AUDIO_ENGINE_ENABLE);
+
+ HDMI_OUTP(HDMI_AUDIO_CFG, hdmi_audio_config);
+
+ return 0;
+}
+EXPORT_SYMBOL(hdmi_audio_enable);
+
+static void hdmi_msm_audio_info_setup(boolean enabled, int num_of_channels,
+ int level_shift, boolean down_mix)
+{
+ uint32 channel_allocation = 0; /* Default to FR,FL */
+ uint32 channel_count = 1; /* Default to 2 channels
+ -> See Table 17 in CEA-D spec */
+ uint32 check_sum, audio_info_0_reg, audio_info_1_reg;
+ uint32 audio_info_ctrl_reg;
+
+ /* Please see table 20 Audio InfoFrame in HDMI spec
+ FL = front left
+ FC = front Center
+ FR = front right
+ FLC = front left center
+ FRC = front right center
+ RL = rear left
+ RC = rear center
+ RR = rear right
+ RLC = rear left center
+ RRC = rear right center
+ LFE = low frequency effect
+ */
+
+ /* Read first then write because it is bundled with other controls */
+ /* HDMI_INFOFRAME_CTRL0[0x002C] */
+ audio_info_ctrl_reg = HDMI_INP(0x002C);
+
+ if (enabled) {
+ switch (num_of_channels) {
+ case MSM_HDMI_AUDIO_CHANNEL_2:
+ break;
+ case MSM_HDMI_AUDIO_CHANNEL_4:
+ channel_count = 3;
+ /* FC,LFE,FR,FL */
+ channel_allocation = 0x3;
+ break;
+ case MSM_HDMI_AUDIO_CHANNEL_6:
+ channel_count = 5;
+ /* RR,RL,FC,LFE,FR,FL */
+ channel_allocation = 0xB;
+ break;
+ case MSM_HDMI_AUDIO_CHANNEL_8:
+ channel_count = 7;
+ /* FRC,FLC,RR,RL,FC,LFE,FR,FL */
+ channel_allocation = 0x1f;
+ break;
+ default:
+ break;
+ }
+
+ /* Program the Channel-Speaker allocation */
+ audio_info_1_reg = 0;
+ /* CA(channel_allocation) */
+ audio_info_1_reg |= channel_allocation & 0xff;
+ /* Program the Level shifter */
+ /* LSV(level_shift) */
+ audio_info_1_reg |= (level_shift << 11) & 0x00007800;
+ /* Program the Down-mix Inhibit Flag */
+ /* DM_INH(down_mix) */
+ audio_info_1_reg |= (down_mix << 15) & 0x00008000;
+
+ /* HDMI_AUDIO_INFO1[0x00E8] */
+ HDMI_OUTP(0x00E8, audio_info_1_reg);
+
+ /* Calculate CheckSum
+ Sum of all the bytes in the Audio Info Packet bytes
+ (See table 8.4 in HDMI spec) */
+ check_sum = 0;
+ /* HDMI_AUDIO_INFO_FRAME_PACKET_HEADER_TYPE[0x84] */
+ check_sum += 0x84;
+ /* HDMI_AUDIO_INFO_FRAME_PACKET_HEADER_VERSION[0x01] */
+ check_sum += 1;
+ /* HDMI_AUDIO_INFO_FRAME_PACKET_LENGTH[0x0A] */
+ check_sum += 0x0A;
+ check_sum += channel_count;
+ check_sum += channel_allocation;
+ /* See Table 8.5 in HDMI spec */
+ check_sum += (level_shift & 0xF) << 3 | (down_mix & 0x1) << 7;
+ check_sum &= 0xFF;
+ check_sum = (uint8) (256 - check_sum);
+
+ audio_info_0_reg = 0;
+ /* CHECKSUM(check_sum) */
+ audio_info_0_reg |= check_sum & 0xff;
+ /* CC(channel_count) */
+ audio_info_0_reg |= (channel_count << 8) & 0x00000700;
+
+ /* HDMI_AUDIO_INFO0[0x00E4] */
+ HDMI_OUTP(0x00E4, audio_info_0_reg);
+
+ /* Set these flags */
+ /* AUDIO_INFO_UPDATE | AUDIO_INFO_SOURCE | AUDIO_INFO_CONT
+ | AUDIO_INFO_SEND */
+ audio_info_ctrl_reg |= 0x000000F0;
+ } else {
+ /* Clear these flags */
+ /* ~(AUDIO_INFO_UPDATE | AUDIO_INFO_SOURCE | AUDIO_INFO_CONT
+ | AUDIO_INFO_SEND) */
+ audio_info_ctrl_reg &= ~0x000000F0;
+ }
+ /* HDMI_INFOFRAME_CTRL0[0x002C] */
+ HDMI_OUTP(0x002C, audio_info_ctrl_reg);
+}
+
+static void hdmi_msm_audio_ctrl_setup(boolean enabled, int delay)
+{
+ uint32 audio_pkt_ctrl_reg = 0;
+
+ /* Enable Packet Transmission */
+ audio_pkt_ctrl_reg |= enabled ? 0x00000001 : 0;
+ audio_pkt_ctrl_reg |= (delay << 4);
+
+ /* HDMI_AUDIO_PKT_CTRL1[0x0020] */
+ HDMI_OUTP(0x0020, audio_pkt_ctrl_reg);
+}
+
+static void hdmi_msm_en_gc_packet(boolean av_mute_is_requested)
+{
+ /* HDMI_GC[0x0040] */
+ HDMI_OUTP(0x0040, av_mute_is_requested ? 1 : 0);
+
+ /* GC packet enable (every frame) */
+ /* HDMI_VBI_PKT_CTRL[0x0028] */
+ hdmi_msm_rmw32or(0x0028, 3 << 4);
+}
+
+static void hdmi_msm_en_isrc_packet(boolean isrc_is_continued)
+{
+ static const char isrc_psuedo_data[] =
+ "ISRC1:0123456789isrc2=ABCDEFGHIJ";
+ const uint32 * isrc_data = (const uint32 *) isrc_psuedo_data;
+
+ /* ISRC_STATUS =0b010 | ISRC_CONTINUE | ISRC_VALID */
+ /* HDMI_ISRC1_0[0x00048] */
+ HDMI_OUTP(0x00048, 2 | (isrc_is_continued ? 1 : 0) << 6 | 0 << 7);
+
+ /* HDMI_ISRC1_1[0x004C] */
+ HDMI_OUTP(0x004C, *isrc_data++);
+ /* HDMI_ISRC1_2[0x0050] */
+ HDMI_OUTP(0x0050, *isrc_data++);
+ /* HDMI_ISRC1_3[0x0054] */
+ HDMI_OUTP(0x0054, *isrc_data++);
+ /* HDMI_ISRC1_4[0x0058] */
+ HDMI_OUTP(0x0058, *isrc_data++);
+
+ /* HDMI_ISRC2_0[0x005C] */
+ HDMI_OUTP(0x005C, *isrc_data++);
+ /* HDMI_ISRC2_1[0x0060] */
+ HDMI_OUTP(0x0060, *isrc_data++);
+ /* HDMI_ISRC2_2[0x0064] */
+ HDMI_OUTP(0x0064, *isrc_data++);
+ /* HDMI_ISRC2_3[0x0068] */
+ HDMI_OUTP(0x0068, *isrc_data);
+
+ /* HDMI_VBI_PKT_CTRL[0x0028] */
+ /* ISRC Send + Continuous */
+ hdmi_msm_rmw32or(0x0028, 3 << 8);
+}
+
+static void hdmi_msm_en_acp_packet(uint32 byte1)
+{
+ /* HDMI_ACP[0x003C] */
+ HDMI_OUTP(0x003C, 2 | 1 << 8 | byte1 << 16);
+
+ /* HDMI_VBI_PKT_CTRL[0x0028] */
+ /* ACP send, s/w source */
+ hdmi_msm_rmw32or(0x0028, 3 << 12);
+}
+
+static void hdmi_msm_audio_setup(void)
+{
+ const int channels = MSM_HDMI_AUDIO_CHANNEL_2;
+
+ /* (0) for clr_avmute, (1) for set_avmute */
+ hdmi_msm_en_gc_packet(0);
+ /* (0) for isrc1 only, (1) for isrc1 and isrc2 */
+ hdmi_msm_en_isrc_packet(1);
+ /* arbitrary bit pattern for byte1 */
+ hdmi_msm_en_acp_packet(0x5a);
+
+ hdmi_msm_audio_acr_setup(TRUE,
+ external_common_state->video_resolution,
+ MSM_HDMI_SAMPLE_RATE_48KHZ, channels);
+ hdmi_msm_audio_info_setup(TRUE, channels, 0, FALSE);
+ hdmi_msm_audio_ctrl_setup(TRUE, 1);
+
+ /* Turn on Audio FIFO and SAM DROP ISR */
+ HDMI_OUTP(0x02CC, HDMI_INP(0x02CC) | BIT(1) | BIT(3));
+ DEV_INFO("HDMI Audio: Enabled\n");
+}
+
+static int hdmi_msm_audio_off(void)
+{
+ uint32 audio_pkt_ctrl, audio_cfg;
+ /* Number of wait iterations */
+ int i = 10;
+ audio_pkt_ctrl = HDMI_INP_ND(0x0020);
+ audio_cfg = HDMI_INP_ND(0x01D0);
+
+ /* Checking BIT[0] of AUDIO PACKET CONTROL and */
+ /* AUDIO CONFIGURATION register */
+ while (((audio_pkt_ctrl & 0x00000001) || (audio_cfg & 0x00000001))
+ && (i--)) {
+ audio_pkt_ctrl = HDMI_INP_ND(0x0020);
+ audio_cfg = HDMI_INP_ND(0x01D0);
+ DEV_DBG("%d times :: HDMI AUDIO PACKET is %08x and "
+ "AUDIO CFG is %08x", i, audio_pkt_ctrl, audio_cfg);
+ msleep(100);
+ if (!i) {
+ DEV_ERR("%s:failed to set BIT[0] AUDIO PACKET"
+ "CONTROL or AUDIO CONFIGURATION REGISTER\n",
+ __func__);
+ return -ETIMEDOUT;
+ }
+ }
+ hdmi_msm_audio_info_setup(FALSE, 0, 0, FALSE);
+ hdmi_msm_audio_ctrl_setup(FALSE, 0);
+ hdmi_msm_audio_acr_setup(FALSE, 0, 0, 0);
+ DEV_INFO("HDMI Audio: Disabled\n");
+ return 0;
+}
+
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+static uint8 hdmi_msm_avi_iframe_lut[][14] = {
+/* 480p60 480i60 576p50 576i50 720p60 720p50 1080p60 1080i60 1080p50
+ 1080i50 1080p24 1080p30 1080p25 640x480p */
+ {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10},
+ {0x18, 0x18, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+ 0x28, 0x28, 0x28, 0x28, 0x18},
+ {0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x88},
+ {0x02, 0x06, 0x11, 0x15, 0x04, 0x13, 0x10, 0x05, 0x1F,
+ 0x14, 0x20, 0x22, 0x21, 0x01},
+ {0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0xE1, 0xE1, 0x41, 0x41, 0xD1, 0xd1, 0x39, 0x39, 0x39,
+ 0x39, 0x39, 0x39, 0x39, 0xe1},
+ {0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x01},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0xD1, 0xD1, 0xD1, 0xD1, 0x01, 0x01, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81},
+ {0x02, 0x02, 0x02, 0x02, 0x05, 0x05, 0x07, 0x07, 0x07,
+ 0x07, 0x07, 0x07, 0x07, 0x02}
+};
+
+static void hdmi_msm_avi_info_frame(void)
+{
+ /* two header + length + 13 data */
+ uint8 aviInfoFrame[16];
+ uint8 checksum;
+ uint32 sum;
+ uint32 regVal;
+ int i;
+ int mode = 0;
+
+ switch (external_common_state->video_resolution) {
+ case HDMI_VFRMT_720x480p60_16_9:
+ mode = 0;
+ break;
+ case HDMI_VFRMT_720x480i60_16_9:
+ mode = 1;
+ break;
+ case HDMI_VFRMT_720x576p50_16_9:
+ mode = 2;
+ break;
+ case HDMI_VFRMT_720x576i50_16_9:
+ mode = 3;
+ break;
+ case HDMI_VFRMT_1280x720p60_16_9:
+ mode = 4;
+ break;
+ case HDMI_VFRMT_1280x720p50_16_9:
+ mode = 5;
+ break;
+ case HDMI_VFRMT_1920x1080p60_16_9:
+ mode = 6;
+ break;
+ case HDMI_VFRMT_1920x1080i60_16_9:
+ mode = 7;
+ break;
+ case HDMI_VFRMT_1920x1080p50_16_9:
+ mode = 8;
+ break;
+ case HDMI_VFRMT_1920x1080i50_16_9:
+ mode = 9;
+ break;
+ case HDMI_VFRMT_1920x1080p24_16_9:
+ mode = 10;
+ break;
+ case HDMI_VFRMT_1920x1080p30_16_9:
+ mode = 11;
+ break;
+ case HDMI_VFRMT_1920x1080p25_16_9:
+ mode = 12;
+ break;
+ case HDMI_VFRMT_640x480p60_4_3:
+ mode = 13;
+ break;
+ default:
+ DEV_INFO("%s: mode %d not supported\n", __func__,
+ external_common_state->video_resolution);
+ return;
+ }
+
+ /* InfoFrame Type = 82 */
+ aviInfoFrame[0] = 0x82;
+ /* Version = 2 */
+ aviInfoFrame[1] = 2;
+ /* Length of AVI InfoFrame = 13 */
+ aviInfoFrame[2] = 13;
+
+ /* Data Byte 01: 0 Y1 Y0 A0 B1 B0 S1 S0 */
+ aviInfoFrame[3] = hdmi_msm_avi_iframe_lut[0][mode];
+ /* Data Byte 02: C1 C0 M1 M0 R3 R2 R1 R0 */
+ aviInfoFrame[4] = hdmi_msm_avi_iframe_lut[1][mode];
+ /* Data Byte 03: ITC EC2 EC1 EC0 Q1 Q0 SC1 SC0 */
+ aviInfoFrame[5] = hdmi_msm_avi_iframe_lut[2][mode];
+ /* Data Byte 04: 0 VIC6 VIC5 VIC4 VIC3 VIC2 VIC1 VIC0 */
+ aviInfoFrame[6] = hdmi_msm_avi_iframe_lut[3][mode];
+ /* Data Byte 05: 0 0 0 0 PR3 PR2 PR1 PR0 */
+ aviInfoFrame[7] = hdmi_msm_avi_iframe_lut[4][mode];
+ /* Data Byte 06: LSB Line No of End of Top Bar */
+ aviInfoFrame[8] = hdmi_msm_avi_iframe_lut[5][mode];
+ /* Data Byte 07: MSB Line No of End of Top Bar */
+ aviInfoFrame[9] = hdmi_msm_avi_iframe_lut[6][mode];
+ /* Data Byte 08: LSB Line No of Start of Bottom Bar */
+ aviInfoFrame[10] = hdmi_msm_avi_iframe_lut[7][mode];
+ /* Data Byte 09: MSB Line No of Start of Bottom Bar */
+ aviInfoFrame[11] = hdmi_msm_avi_iframe_lut[8][mode];
+ /* Data Byte 10: LSB Pixel Number of End of Left Bar */
+ aviInfoFrame[12] = hdmi_msm_avi_iframe_lut[9][mode];
+ /* Data Byte 11: MSB Pixel Number of End of Left Bar */
+ aviInfoFrame[13] = hdmi_msm_avi_iframe_lut[10][mode];
+ /* Data Byte 12: LSB Pixel Number of Start of Right Bar */
+ aviInfoFrame[14] = hdmi_msm_avi_iframe_lut[11][mode];
+ /* Data Byte 13: MSB Pixel Number of Start of Right Bar */
+ aviInfoFrame[15] = hdmi_msm_avi_iframe_lut[12][mode];
+
+ sum = 0;
+ for (i = 0; i < 16; i++)
+ sum += aviInfoFrame[i];
+ sum &= 0xFF;
+ sum = 256 - sum;
+ checksum = (uint8) sum;
+
+ regVal = aviInfoFrame[5];
+ regVal = regVal << 8 | aviInfoFrame[4];
+ regVal = regVal << 8 | aviInfoFrame[3];
+ regVal = regVal << 8 | checksum;
+ HDMI_OUTP(0x006C, regVal);
+
+ regVal = aviInfoFrame[9];
+ regVal = regVal << 8 | aviInfoFrame[8];
+ regVal = regVal << 8 | aviInfoFrame[7];
+ regVal = regVal << 8 | aviInfoFrame[6];
+ HDMI_OUTP(0x0070, regVal);
+
+ regVal = aviInfoFrame[13];
+ regVal = regVal << 8 | aviInfoFrame[12];
+ regVal = regVal << 8 | aviInfoFrame[11];
+ regVal = regVal << 8 | aviInfoFrame[10];
+ HDMI_OUTP(0x0074, regVal);
+
+ regVal = aviInfoFrame[1];
+ regVal = regVal << 16 | aviInfoFrame[15];
+ regVal = regVal << 8 | aviInfoFrame[14];
+ HDMI_OUTP(0x0078, regVal);
+
+ /* INFOFRAME_CTRL0[0x002C] */
+ /* 0x3 for AVI InfFrame enable (every frame) */
+ HDMI_OUTP(0x002C, HDMI_INP(0x002C) | 0x00000003L);
+}
+#endif
+
+#ifdef CONFIG_FB_MSM_HDMI_3D
+static void hdmi_msm_vendor_infoframe_packetsetup(void)
+{
+ uint32 packet_header = 0;
+ uint32 check_sum = 0;
+ uint32 packet_payload = 0;
+
+ if (!external_common_state->format_3d) {
+ HDMI_OUTP(0x0034, 0);
+ return;
+ }
+
+ /* 0x0084 GENERIC0_HDR
+ * HB0 7:0 NUM
+ * HB1 15:8 NUM
+ * HB2 23:16 NUM */
+ /* Setup Packet header and payload */
+ /* 0x81 VS_INFO_FRAME_ID
+ 0x01 VS_INFO_FRAME_VERSION
+ 0x1B VS_INFO_FRAME_PAYLOAD_LENGTH */
+ packet_header = 0x81 | (0x01 << 8) | (0x1B << 16);
+ HDMI_OUTP(0x0084, packet_header);
+
+ check_sum = packet_header & 0xff;
+ check_sum += (packet_header >> 8) & 0xff;
+ check_sum += (packet_header >> 16) & 0xff;
+
+ /* 0x008C GENERIC0_1
+ * BYTE4 7:0 NUM
+ * BYTE5 15:8 NUM
+ * BYTE6 23:16 NUM
+ * BYTE7 31:24 NUM */
+ /* 0x02 VS_INFO_FRAME_3D_PRESENT */
+ packet_payload = 0x02 << 5;
+ switch (external_common_state->format_3d) {
+ case 1:
+ /* 0b1000 VIDEO_3D_FORMAT_SIDE_BY_SIDE_HALF */
+ packet_payload |= (0x08 << 8) << 4;
+ break;
+ case 2:
+ /* 0b0110 VIDEO_3D_FORMAT_TOP_AND_BOTTOM_HALF */
+ packet_payload |= (0x06 << 8) << 4;
+ break;
+ }
+ HDMI_OUTP(0x008C, packet_payload);
+
+ check_sum += packet_payload & 0xff;
+ check_sum += (packet_payload >> 8) & 0xff;
+
+ #define IEEE_REGISTRATION_ID 0xC03
+ /* Next 3 bytes are IEEE Registration Identifcation */
+ /* 0x0088 GENERIC0_0
+ * BYTE0 7:0 NUM (checksum)
+ * BYTE1 15:8 NUM
+ * BYTE2 23:16 NUM
+ * BYTE3 31:24 NUM */
+ check_sum += IEEE_REGISTRATION_ID & 0xff;
+ check_sum += (IEEE_REGISTRATION_ID >> 8) & 0xff;
+ check_sum += (IEEE_REGISTRATION_ID >> 16) & 0xff;
+
+ HDMI_OUTP(0x0088, (0x100 - (0xff & check_sum))
+ | ((IEEE_REGISTRATION_ID & 0xff) << 8)
+ | (((IEEE_REGISTRATION_ID >> 8) & 0xff) << 16)
+ | (((IEEE_REGISTRATION_ID >> 16) & 0xff) << 24));
+
+ /* 0x0034 GEN_PKT_CTRL
+ * GENERIC0_SEND 0 0 = Disable Generic0 Packet Transmission
+ * 1 = Enable Generic0 Packet Transmission
+ * GENERIC0_CONT 1 0 = Send Generic0 Packet on next frame only
+ * 1 = Send Generic0 Packet on every frame
+ * GENERIC0_UPDATE 2 NUM
+ * GENERIC1_SEND 4 0 = Disable Generic1 Packet Transmission
+ * 1 = Enable Generic1 Packet Transmission
+ * GENERIC1_CONT 5 0 = Send Generic1 Packet on next frame only
+ * 1 = Send Generic1 Packet on every frame
+ * GENERIC0_LINE 21:16 NUM
+ * GENERIC1_LINE 29:24 NUM
+ */
+ /* GENERIC0_LINE | GENERIC0_UPDATE | GENERIC0_CONT | GENERIC0_SEND
+ * Setup HDMI TX generic packet control
+ * Enable this packet to transmit every frame
+ * Enable this packet to transmit every frame
+ * Enable HDMI TX engine to transmit Generic packet 0 */
+ HDMI_OUTP(0x0034, (1 << 16) | (1 << 2) | BIT(1) | BIT(0));
+}
+
+static void hdmi_msm_switch_3d(boolean on)
+{
+ mutex_lock(&external_common_state_hpd_mutex);
+ if (external_common_state->hpd_state)
+ hdmi_msm_vendor_infoframe_packetsetup();
+ mutex_unlock(&external_common_state_hpd_mutex);
+}
+#endif
+
+static int hdmi_msm_clk(int on)
+{
+ int rc;
+
+ DEV_DBG("HDMI Clk: %s\n", on ? "Enable" : "Disable");
+ if (on) {
+ rc = clk_enable(hdmi_msm_state->hdmi_app_clk);
+ if (rc) {
+ DEV_ERR("'hdmi_app_clk' clock enable failed, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ rc = clk_enable(hdmi_msm_state->hdmi_m_pclk);
+ if (rc) {
+ DEV_ERR("'hdmi_m_pclk' clock enable failed, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ rc = clk_enable(hdmi_msm_state->hdmi_s_pclk);
+ if (rc) {
+ DEV_ERR("'hdmi_s_pclk' clock enable failed, rc=%d\n",
+ rc);
+ return rc;
+ }
+ } else {
+ clk_disable(hdmi_msm_state->hdmi_app_clk);
+ clk_disable(hdmi_msm_state->hdmi_m_pclk);
+ clk_disable(hdmi_msm_state->hdmi_s_pclk);
+ }
+
+ return 0;
+}
+
+static void hdmi_msm_reset_core(void)
+{
+ hdmi_msm_set_mode(FALSE);
+ hdmi_msm_clk(0);
+ udelay(5);
+ hdmi_msm_clk(1);
+
+ clk_reset(hdmi_msm_state->hdmi_app_clk, CLK_RESET_ASSERT);
+ clk_reset(hdmi_msm_state->hdmi_m_pclk, CLK_RESET_ASSERT);
+ clk_reset(hdmi_msm_state->hdmi_s_pclk, CLK_RESET_ASSERT);
+ udelay(20);
+ clk_reset(hdmi_msm_state->hdmi_app_clk, CLK_RESET_DEASSERT);
+ clk_reset(hdmi_msm_state->hdmi_m_pclk, CLK_RESET_DEASSERT);
+ clk_reset(hdmi_msm_state->hdmi_s_pclk, CLK_RESET_DEASSERT);
+}
+
+static void hdmi_msm_turn_on(void)
+{
+ uint32 hpd_ctrl;
+
+ hdmi_msm_reset_core();
+ hdmi_msm_init_phy(external_common_state->video_resolution);
+ /* HDMI_USEC_REFTIMER[0x0208] */
+ HDMI_OUTP(0x0208, 0x0001001B);
+
+ hdmi_msm_video_setup(external_common_state->video_resolution);
+ if (!hdmi_msm_is_dvi_mode())
+ hdmi_msm_audio_setup();
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ hdmi_msm_avi_info_frame();
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
+#ifdef CONFIG_FB_MSM_HDMI_3D
+ hdmi_msm_vendor_infoframe_packetsetup();
+#endif
+
+ /* set timeout to 4.1ms (max) for hardware debounce */
+ hpd_ctrl = (HDMI_INP(0x0258) & ~0xFFF) | 0xFFF;
+
+ /* Toggle HPD circuit to trigger HPD sense */
+ HDMI_OUTP(0x0258, ~(1 << 28) & hpd_ctrl);
+ HDMI_OUTP(0x0258, (1 << 28) | hpd_ctrl);
+
+ hdmi_msm_set_mode(TRUE);
+
+ /* Setup HPD IRQ */
+ HDMI_OUTP(0x0254, 4 | (external_common_state->hpd_state ? 0 : 2));
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ if (hdmi_msm_state->reauth) {
+ hdmi_msm_hdcp_enable();
+ hdmi_msm_state->reauth = FALSE ;
+ }
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
+ DEV_INFO("HDMI Core: Initialized\n");
+}
+
+static void hdmi_msm_hpd_state_timer(unsigned long data)
+{
+ queue_work(hdmi_work_queue, &hdmi_msm_state->hpd_state_work);
+}
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+static void hdmi_msm_hdcp_timer(unsigned long data)
+{
+ queue_work(hdmi_work_queue, &hdmi_msm_state->hdcp_work);
+}
+#endif
+
+static void hdmi_msm_hpd_read_work(struct work_struct *work)
+{
+ uint32 hpd_ctrl;
+
+ clk_enable(hdmi_msm_state->hdmi_app_clk);
+ hdmi_msm_state->pd->core_power(1, 1);
+ hdmi_msm_state->pd->enable_5v(1);
+ hdmi_msm_set_mode(FALSE);
+ hdmi_msm_init_phy(external_common_state->video_resolution);
+ /* HDMI_USEC_REFTIMER[0x0208] */
+ HDMI_OUTP(0x0208, 0x0001001B);
+ hpd_ctrl = (HDMI_INP(0x0258) & ~0xFFF) | 0xFFF;
+
+ /* Toggle HPD circuit to trigger HPD sense */
+ HDMI_OUTP(0x0258, ~(1 << 28) & hpd_ctrl);
+ HDMI_OUTP(0x0258, (1 << 28) | hpd_ctrl);
+
+ hdmi_msm_set_mode(TRUE);
+ msleep(1000);
+ external_common_state->hpd_state = (HDMI_INP(0x0250) & 0x2) >> 1;
+ if (external_common_state->hpd_state) {
+ hdmi_msm_read_edid();
+ DEV_DBG("%s: sense CONNECTED: send ONLINE\n", __func__);
+ kobject_uevent(external_common_state->uevent_kobj,
+ KOBJ_ONLINE);
+ }
+ hdmi_msm_hpd_off();
+ hdmi_msm_set_mode(FALSE);
+ hdmi_msm_state->pd->core_power(0, 1);
+ hdmi_msm_state->pd->enable_5v(0);
+ clk_disable(hdmi_msm_state->hdmi_app_clk);
+}
+
+static void hdmi_msm_hpd_off(void)
+{
+ DEV_DBG("%s: (timer, clk, 5V, core, IRQ off)\n", __func__);
+ del_timer(&hdmi_msm_state->hpd_state_timer);
+ disable_irq(hdmi_msm_state->irq);
+
+ hdmi_msm_set_mode(FALSE);
+ HDMI_OUTP_ND(0x0308, 0x7F); /*0b01111111*/
+ hdmi_msm_state->hpd_initialized = FALSE;
+ hdmi_msm_state->pd->enable_5v(0);
+ hdmi_msm_state->pd->core_power(0, 1);
+ hdmi_msm_clk(0);
+ hdmi_msm_state->hpd_initialized = FALSE;
+}
+
+static void hdmi_msm_dump_regs(const char *prefex)
+{
+#ifdef REG_DUMP
+ print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_OFFSET, 32, 4,
+ (void *)MSM_HDMI_BASE, 0x0334, false);
+#endif
+}
+
+static int hdmi_msm_hpd_on(bool trigger_handler)
+{
+ static int phy_reset_done;
+
+ hdmi_msm_clk(1);
+ hdmi_msm_state->pd->core_power(1, 1);
+ hdmi_msm_state->pd->enable_5v(1);
+ hdmi_msm_dump_regs("HDMI-INIT: ");
+ hdmi_msm_set_mode(FALSE);
+
+ if (!phy_reset_done) {
+ hdmi_phy_reset();
+ phy_reset_done = 1;
+ }
+
+ hdmi_msm_init_phy(external_common_state->video_resolution);
+ /* HDMI_USEC_REFTIMER[0x0208] */
+ HDMI_OUTP(0x0208, 0x0001001B);
+
+ /* Check HPD State */
+ if (!hdmi_msm_state->hpd_initialized) {
+ uint32 hpd_ctrl;
+ enable_irq(hdmi_msm_state->irq);
+
+ /* set timeout to 4.1ms (max) for hardware debounce */
+ hpd_ctrl = (HDMI_INP(0x0258) & ~0xFFF) | 0xFFF;
+
+ /* Toggle HPD circuit to trigger HPD sense */
+ HDMI_OUTP(0x0258, ~(1 << 28) & hpd_ctrl);
+ HDMI_OUTP(0x0258, (1 << 28) | hpd_ctrl);
+
+ DEV_DBG("%s: (clk, 5V, core, IRQ on) <trigger:%s>\n", __func__,
+ trigger_handler ? "true" : "false");
+
+ if (trigger_handler) {
+ /* Set HPD state machine: ensure at least 2 readouts */
+ mutex_lock(&hdmi_msm_state_mutex);
+ hdmi_msm_state->hpd_stable = 0;
+ hdmi_msm_state->hpd_prev_state = TRUE;
+ mutex_lock(&external_common_state_hpd_mutex);
+ external_common_state->hpd_state = FALSE;
+ mutex_unlock(&external_common_state_hpd_mutex);
+ hdmi_msm_state->hpd_cable_chg_detected = TRUE;
+ mutex_unlock(&hdmi_msm_state_mutex);
+ mod_timer(&hdmi_msm_state->hpd_state_timer,
+ jiffies + HZ/2);
+ }
+
+ hdmi_msm_state->hpd_initialized = TRUE;
+ }
+ hdmi_msm_set_mode(TRUE);
+
+ return 0;
+}
+
+static int hdmi_msm_power_on(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
+ bool changed;
+
+ if (!hdmi_msm_state || !hdmi_msm_state->hdmi_app_clk || !MSM_HDMI_BASE)
+ return -ENODEV;
+#ifdef CONFIG_SUSPEND
+ mutex_lock(&hdmi_msm_state_mutex);
+ if (hdmi_msm_state->pm_suspended) {
+ mutex_unlock(&hdmi_msm_state_mutex);
+ DEV_WARN("%s: ignored, pm_suspended\n", __func__);
+ return -ENODEV;
+ }
+ mutex_unlock(&hdmi_msm_state_mutex);
+#endif
+
+ DEV_INFO("power: ON (%dx%d %d)\n", mfd->var_xres, mfd->var_yres,
+ mfd->var_pixclock);
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ mutex_lock(&hdmi_msm_state_mutex);
+ if (hdmi_msm_state->hdcp_activating) {
+ hdmi_msm_state->panel_power_on = TRUE;
+ DEV_INFO("HDCP: activating, returning\n");
+ }
+ mutex_unlock(&hdmi_msm_state_mutex);
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
+
+ changed = hdmi_common_get_video_format_from_drv_data(mfd);
+ if (!external_common_state->hpd_feature_on) {
+ int rc = hdmi_msm_hpd_on(true);
+ DEV_INFO("HPD: panel power without 'hpd' feature on\n");
+ if (rc) {
+ DEV_WARN("HPD: activation failed: rc=%d\n", rc);
+ return rc;
+ }
+ }
+ hdmi_msm_audio_info_setup(TRUE, 0, 0, FALSE);
+
+ mutex_lock(&external_common_state_hpd_mutex);
+ hdmi_msm_state->panel_power_on = TRUE;
+ if ((external_common_state->hpd_state && !hdmi_msm_is_power_on())
+ || changed) {
+ mutex_unlock(&external_common_state_hpd_mutex);
+ hdmi_msm_turn_on();
+ } else
+ mutex_unlock(&external_common_state_hpd_mutex);
+
+ hdmi_msm_dump_regs("HDMI-ON: ");
+
+ DEV_INFO("power=%s DVI= %s\n",
+ hdmi_msm_is_power_on() ? "ON" : "OFF" ,
+ hdmi_msm_is_dvi_mode() ? "ON" : "OFF");
+ return 0;
+}
+
+/* Note that power-off will also be called when the cable-remove event is
+ * processed on the user-space and as a result the framebuffer is powered
+ * down. However, we are still required to be able to detect a cable-insert
+ * event; so for now leave the HDMI engine running; so that the HPD IRQ is
+ * still being processed.
+ */
+static int hdmi_msm_power_off(struct platform_device *pdev)
+{
+ if (!hdmi_msm_state->hdmi_app_clk)
+ return -ENODEV;
+#ifdef CONFIG_SUSPEND
+ mutex_lock(&hdmi_msm_state_mutex);
+ if (hdmi_msm_state->pm_suspended) {
+ mutex_unlock(&hdmi_msm_state_mutex);
+ DEV_WARN("%s: ignored, pm_suspended\n", __func__);
+ return -ENODEV;
+ }
+ mutex_unlock(&hdmi_msm_state_mutex);
+#endif
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ mutex_lock(&hdmi_msm_state_mutex);
+ if (hdmi_msm_state->hdcp_activating) {
+ hdmi_msm_state->panel_power_on = FALSE;
+ mutex_unlock(&hdmi_msm_state_mutex);
+ DEV_INFO("HDCP: activating, returning\n");
+ return 0;
+ }
+ mutex_unlock(&hdmi_msm_state_mutex);
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
+
+ DEV_INFO("power: OFF (audio off, Reset Core)\n");
+ hdmi_msm_audio_off();
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ hdcp_deauthenticate();
+#endif
+ hdmi_msm_hpd_off();
+ hdmi_msm_powerdown_phy();
+ hdmi_msm_dump_regs("HDMI-OFF: ");
+ hdmi_msm_hpd_on(false);
+
+ mutex_lock(&external_common_state_hpd_mutex);
+ if (!external_common_state->hpd_feature_on)
+ hdmi_msm_hpd_off();
+ mutex_unlock(&external_common_state_hpd_mutex);
+
+ hdmi_msm_state->panel_power_on = FALSE;
+ return 0;
+}
+
+static int __devinit hdmi_msm_probe(struct platform_device *pdev)
+{
+ int rc;
+ struct platform_device *fb_dev;
+
+ if (!hdmi_msm_state) {
+ pr_err("%s: hdmi_msm_state is NULL\n", __func__);
+ return -ENOMEM;
+ }
+
+ external_common_state->dev = &pdev->dev;
+ DEV_DBG("probe\n");
+ if (pdev->id == 0) {
+ struct resource *res;
+
+ #define GET_RES(name, mode) do { \
+ res = platform_get_resource_byname(pdev, mode, name); \
+ if (!res) { \
+ DEV_ERR("'" name "' resource not found\n"); \
+ rc = -ENODEV; \
+ goto error; \
+ } \
+ } while (0)
+
+ #define IO_REMAP(var, name) do { \
+ GET_RES(name, IORESOURCE_MEM); \
+ var = ioremap(res->start, resource_size(res)); \
+ if (!var) { \
+ DEV_ERR("'" name "' ioremap failed\n"); \
+ rc = -ENOMEM; \
+ goto error; \
+ } \
+ } while (0)
+
+ #define GET_IRQ(var, name) do { \
+ GET_RES(name, IORESOURCE_IRQ); \
+ var = res->start; \
+ } while (0)
+
+ IO_REMAP(hdmi_msm_state->qfprom_io, "hdmi_msm_qfprom_addr");
+ hdmi_msm_state->hdmi_io = MSM_HDMI_BASE;
+ GET_IRQ(hdmi_msm_state->irq, "hdmi_msm_irq");
+
+ hdmi_msm_state->pd = pdev->dev.platform_data;
+
+ #undef GET_RES
+ #undef IO_REMAP
+ #undef GET_IRQ
+ return 0;
+ }
+
+ hdmi_msm_state->hdmi_app_clk = clk_get(NULL, "hdmi_app_clk");
+ if (IS_ERR(hdmi_msm_state->hdmi_app_clk)) {
+ DEV_ERR("'hdmi_app_clk' clk not found\n");
+ rc = IS_ERR(hdmi_msm_state->hdmi_app_clk);
+ goto error;
+ }
+
+ hdmi_msm_state->hdmi_m_pclk = clk_get(NULL, "hdmi_m_pclk");
+ if (IS_ERR(hdmi_msm_state->hdmi_m_pclk)) {
+ DEV_ERR("'hdmi_m_pclk' clk not found\n");
+ rc = IS_ERR(hdmi_msm_state->hdmi_m_pclk);
+ goto error;
+ }
+
+ hdmi_msm_state->hdmi_s_pclk = clk_get(NULL, "hdmi_s_pclk");
+ if (IS_ERR(hdmi_msm_state->hdmi_s_pclk)) {
+ DEV_ERR("'hdmi_s_pclk' clk not found\n");
+ rc = IS_ERR(hdmi_msm_state->hdmi_s_pclk);
+ goto error;
+ }
+
+ rc = check_hdmi_features();
+ if (rc) {
+ DEV_ERR("Init FAILED: check_hdmi_features rc=%d\n", rc);
+ goto error;
+ }
+
+ if (!hdmi_msm_state->pd->core_power) {
+ DEV_ERR("Init FAILED: core_power function missing\n");
+ rc = -ENODEV;
+ goto error;
+ }
+ if (!hdmi_msm_state->pd->enable_5v) {
+ DEV_ERR("Init FAILED: enable_5v function missing\n");
+ rc = -ENODEV;
+ goto error;
+ }
+
+ rc = request_threaded_irq(hdmi_msm_state->irq, NULL, &hdmi_msm_isr,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "hdmi_msm_isr", NULL);
+ if (rc) {
+ DEV_ERR("Init FAILED: IRQ request, rc=%d\n", rc);
+ goto error;
+ }
+ disable_irq(hdmi_msm_state->irq);
+
+ init_timer(&hdmi_msm_state->hpd_state_timer);
+ hdmi_msm_state->hpd_state_timer.function =
+ hdmi_msm_hpd_state_timer;
+ hdmi_msm_state->hpd_state_timer.data = (uint32)NULL;
+
+ hdmi_msm_state->hpd_state_timer.expires = 0xffffffffL;
+ add_timer(&hdmi_msm_state->hpd_state_timer);
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ init_timer(&hdmi_msm_state->hdcp_timer);
+ hdmi_msm_state->hdcp_timer.function =
+ hdmi_msm_hdcp_timer;
+ hdmi_msm_state->hdcp_timer.data = (uint32)NULL;
+
+ hdmi_msm_state->hdcp_timer.expires = 0xffffffffL;
+ add_timer(&hdmi_msm_state->hdcp_timer);
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
+
+ fb_dev = msm_fb_add_device(pdev);
+ if (fb_dev) {
+ rc = external_common_state_create(fb_dev);
+ if (rc) {
+ DEV_ERR("Init FAILED: hdmi_msm_state_create, rc=%d\n",
+ rc);
+ goto error;
+ }
+ } else
+ DEV_ERR("Init FAILED: failed to add fb device\n");
+
+ DEV_INFO("HDMI HPD: ON\n");
+
+ rc = hdmi_msm_hpd_on(true);
+ if (rc)
+ goto error;
+
+ if (hdmi_msm_has_hdcp())
+ external_common_state->present_hdcp = TRUE;
+ else {
+ external_common_state->present_hdcp = FALSE;
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ /*
+ * If the device is not hdcp capable do
+ * not start hdcp timer.
+ */
+ del_timer(&hdmi_msm_state->hdcp_timer);
+#endif
+ }
+
+ queue_work(hdmi_work_queue, &hdmi_msm_state->hpd_read_work);
+ return 0;
+
+error:
+ if (hdmi_msm_state->qfprom_io)
+ iounmap(hdmi_msm_state->qfprom_io);
+ hdmi_msm_state->qfprom_io = NULL;
+
+ if (hdmi_msm_state->hdmi_io)
+ iounmap(hdmi_msm_state->hdmi_io);
+ hdmi_msm_state->hdmi_io = NULL;
+
+ external_common_state_remove();
+
+ if (hdmi_msm_state->hdmi_app_clk)
+ clk_put(hdmi_msm_state->hdmi_app_clk);
+ if (hdmi_msm_state->hdmi_m_pclk)
+ clk_put(hdmi_msm_state->hdmi_m_pclk);
+ if (hdmi_msm_state->hdmi_s_pclk)
+ clk_put(hdmi_msm_state->hdmi_s_pclk);
+
+ hdmi_msm_state->hdmi_app_clk = NULL;
+ hdmi_msm_state->hdmi_m_pclk = NULL;
+ hdmi_msm_state->hdmi_s_pclk = NULL;
+
+ return rc;
+}
+
+static int __devexit hdmi_msm_remove(struct platform_device *pdev)
+{
+ DEV_INFO("HDMI device: remove\n");
+
+ DEV_INFO("HDMI HPD: OFF\n");
+ hdmi_msm_hpd_off();
+ free_irq(hdmi_msm_state->irq, NULL);
+
+ if (hdmi_msm_state->qfprom_io)
+ iounmap(hdmi_msm_state->qfprom_io);
+ hdmi_msm_state->qfprom_io = NULL;
+
+ if (hdmi_msm_state->hdmi_io)
+ iounmap(hdmi_msm_state->hdmi_io);
+ hdmi_msm_state->hdmi_io = NULL;
+
+ external_common_state_remove();
+
+ if (hdmi_msm_state->hdmi_app_clk)
+ clk_put(hdmi_msm_state->hdmi_app_clk);
+ if (hdmi_msm_state->hdmi_m_pclk)
+ clk_put(hdmi_msm_state->hdmi_m_pclk);
+ if (hdmi_msm_state->hdmi_s_pclk)
+ clk_put(hdmi_msm_state->hdmi_s_pclk);
+
+ hdmi_msm_state->hdmi_app_clk = NULL;
+ hdmi_msm_state->hdmi_m_pclk = NULL;
+ hdmi_msm_state->hdmi_s_pclk = NULL;
+
+ kfree(hdmi_msm_state);
+ hdmi_msm_state = NULL;
+
+ return 0;
+}
+
+static int hdmi_msm_hpd_feature(int on)
+{
+ int rc = 0;
+
+ DEV_INFO("%s: %d\n", __func__, on);
+ if (on)
+ rc = hdmi_msm_hpd_on(true);
+ else
+ hdmi_msm_hpd_off();
+
+ return rc;
+}
+
+
+#ifdef CONFIG_SUSPEND
+static int hdmi_msm_device_pm_suspend(struct device *dev)
+{
+ mutex_lock(&hdmi_msm_state_mutex);
+ if (hdmi_msm_state->pm_suspended) {
+ mutex_unlock(&hdmi_msm_state_mutex);
+ return 0;
+ }
+
+ DEV_DBG("pm_suspend\n");
+
+ del_timer(&hdmi_msm_state->hpd_state_timer);
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ del_timer(&hdmi_msm_state->hdcp_timer);
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
+
+ disable_irq(hdmi_msm_state->irq);
+ clk_disable(hdmi_msm_state->hdmi_app_clk);
+ clk_disable(hdmi_msm_state->hdmi_m_pclk);
+ clk_disable(hdmi_msm_state->hdmi_s_pclk);
+
+ hdmi_msm_state->pm_suspended = TRUE;
+ mutex_unlock(&hdmi_msm_state_mutex);
+
+ hdmi_msm_powerdown_phy();
+ hdmi_msm_state->pd->enable_5v(0);
+ hdmi_msm_state->pd->core_power(0, 1);
+ return 0;
+}
+
+static int hdmi_msm_device_pm_resume(struct device *dev)
+{
+ mutex_lock(&hdmi_msm_state_mutex);
+ if (!hdmi_msm_state->pm_suspended) {
+ mutex_unlock(&hdmi_msm_state_mutex);
+ return 0;
+ }
+
+ DEV_DBG("pm_resume\n");
+
+ hdmi_msm_state->pd->core_power(1, 1);
+ hdmi_msm_state->pd->enable_5v(1);
+ clk_enable(hdmi_msm_state->hdmi_app_clk);
+ clk_enable(hdmi_msm_state->hdmi_m_pclk);
+ clk_enable(hdmi_msm_state->hdmi_s_pclk);
+
+ hdmi_msm_state->pm_suspended = FALSE;
+ mutex_unlock(&hdmi_msm_state_mutex);
+ enable_irq(hdmi_msm_state->irq);
+ return 0;
+}
+#else
+#define hdmi_msm_device_pm_suspend NULL
+#define hdmi_msm_device_pm_resume NULL
+#endif
+
+static const struct dev_pm_ops hdmi_msm_device_pm_ops = {
+ .suspend = hdmi_msm_device_pm_suspend,
+ .resume = hdmi_msm_device_pm_resume,
+};
+
+static struct platform_driver this_driver = {
+ .probe = hdmi_msm_probe,
+ .remove = hdmi_msm_remove,
+ .driver.name = "hdmi_msm",
+ .driver.pm = &hdmi_msm_device_pm_ops,
+};
+
+static struct msm_fb_panel_data hdmi_msm_panel_data = {
+ .on = hdmi_msm_power_on,
+ .off = hdmi_msm_power_off,
+};
+
+static struct platform_device this_device = {
+ .name = "hdmi_msm",
+ .id = 1,
+ .dev.platform_data = &hdmi_msm_panel_data,
+};
+
+static int __init hdmi_msm_init(void)
+{
+ int rc;
+
+ hdmi_msm_setup_video_mode_lut();
+ hdmi_msm_state = kzalloc(sizeof(*hdmi_msm_state), GFP_KERNEL);
+ if (!hdmi_msm_state) {
+ pr_err("hdmi_msm_init FAILED: out of memory\n");
+ rc = -ENOMEM;
+ goto init_exit;
+ }
+
+ external_common_state = &hdmi_msm_state->common;
+ external_common_state->video_resolution = HDMI_VFRMT_1920x1080p60_16_9;
+#ifdef CONFIG_FB_MSM_HDMI_3D
+ external_common_state->switch_3d = hdmi_msm_switch_3d;
+#endif
+
+ /*
+ * Create your work queue
+ * allocs and returns ptr
+ */
+ hdmi_work_queue = create_workqueue("hdmi_hdcp");
+ external_common_state->hpd_feature = hdmi_msm_hpd_feature;
+
+ rc = platform_driver_register(&this_driver);
+ if (rc) {
+ pr_err("hdmi_msm_init FAILED: platform_driver_register rc=%d\n",
+ rc);
+ goto init_exit;
+ }
+
+ hdmi_common_init_panel_info(&hdmi_msm_panel_data.panel_info);
+ init_completion(&hdmi_msm_state->ddc_sw_done);
+ INIT_WORK(&hdmi_msm_state->hpd_state_work, hdmi_msm_hpd_state_work);
+ INIT_WORK(&hdmi_msm_state->hpd_read_work, hdmi_msm_hpd_read_work);
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ init_completion(&hdmi_msm_state->hdcp_success_done);
+ INIT_WORK(&hdmi_msm_state->hdcp_reauth_work, hdmi_msm_hdcp_reauth_work);
+ INIT_WORK(&hdmi_msm_state->hdcp_work, hdmi_msm_hdcp_work);
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
+
+ rc = platform_device_register(&this_device);
+ if (rc) {
+ pr_err("hdmi_msm_init FAILED: platform_device_register rc=%d\n",
+ rc);
+ platform_driver_unregister(&this_driver);
+ goto init_exit;
+ }
+
+ pr_debug("%s: success:"
+#ifdef DEBUG
+ " DEBUG"
+#else
+ " RELEASE"
+#endif
+ " AUDIO EDID HPD HDCP"
+#ifndef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ ":0"
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
+ " DVI"
+#ifndef CONFIG_FB_MSM_HDMI_MSM_PANEL_DVI_SUPPORT
+ ":0"
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_DVI_SUPPORT */
+ "\n", __func__);
+
+ return 0;
+
+init_exit:
+ kfree(hdmi_msm_state);
+ hdmi_msm_state = NULL;
+
+ return rc;
+}
+
+static void __exit hdmi_msm_exit(void)
+{
+ platform_device_unregister(&this_device);
+ platform_driver_unregister(&this_driver);
+}
+
+module_init(hdmi_msm_init);
+module_exit(hdmi_msm_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("0.3");
+MODULE_AUTHOR("Qualcomm Innovation Center, Inc.");
+MODULE_DESCRIPTION("HDMI MSM TX driver");
diff --git a/drivers/video/msm/hdmi_msm.h b/drivers/video/msm/hdmi_msm.h
new file mode 100644
index 0000000..41c756f
--- /dev/null
+++ b/drivers/video/msm/hdmi_msm.h
@@ -0,0 +1,84 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __HDMI_MSM_H__
+#define __HDMI_MSM_H__
+
+#include <mach/msm_iomap.h>
+#include "external_common.h"
+/* #define PORT_DEBUG */
+
+#ifdef PORT_DEBUG
+const char *hdmi_msm_name(uint32 offset);
+void hdmi_outp(uint32 offset, uint32 value);
+uint32 hdmi_inp(uint32 offset);
+
+#define HDMI_OUTP_ND(offset, value) outpdw(MSM_HDMI_BASE+(offset), (value))
+#define HDMI_OUTP(offset, value) hdmi_outp((offset), (value))
+#define HDMI_INP_ND(offset) inpdw(MSM_HDMI_BASE+(offset))
+#define HDMI_INP(offset) hdmi_inp((offset))
+#else
+#define HDMI_OUTP_ND(offset, value) outpdw(MSM_HDMI_BASE+(offset), (value))
+#define HDMI_OUTP(offset, value) outpdw(MSM_HDMI_BASE+(offset), (value))
+#define HDMI_INP_ND(offset) inpdw(MSM_HDMI_BASE+(offset))
+#define HDMI_INP(offset) inpdw(MSM_HDMI_BASE+(offset))
+#endif
+
+#define QFPROM_BASE ((uint32)hdmi_msm_state->qfprom_io)
+
+struct hdmi_msm_state_type {
+ boolean panel_power_on;
+ boolean hpd_initialized;
+#ifdef CONFIG_SUSPEND
+ boolean pm_suspended;
+#endif
+ int hpd_stable;
+ boolean hpd_prev_state;
+ boolean hpd_cable_chg_detected;
+ boolean full_auth_done;
+ boolean hpd_during_auth;
+ struct work_struct hpd_state_work, hpd_read_work;
+ struct timer_list hpd_state_timer;
+ struct completion ddc_sw_done;
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ boolean hdcp_activating;
+ boolean reauth ;
+ struct work_struct hdcp_reauth_work, hdcp_work;
+ struct completion hdcp_success_done;
+ struct timer_list hdcp_timer;
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
+
+ int irq;
+ struct msm_hdmi_platform_data *pd;
+ struct clk *hdmi_app_clk;
+ struct clk *hdmi_m_pclk;
+ struct clk *hdmi_s_pclk;
+ void __iomem *qfprom_io;
+ void __iomem *hdmi_io;
+
+ struct external_common_state_type common;
+};
+
+extern struct hdmi_msm_state_type *hdmi_msm_state;
+
+uint32 hdmi_msm_get_io_base(void);
+
+#ifdef CONFIG_FB_MSM_HDMI_COMMON
+void hdmi_phy_reset(void);
+void hdmi_msm_init_phy(int video_format);
+void hdmi_msm_powerdown_phy(void);
+void hdmi_frame_ctrl_cfg(const struct hdmi_disp_mode_timing_type *timing);
+void hdmi_msm_phy_status_poll(void);
+#endif
+
+#endif /* __HDMI_MSM_H__ */
diff --git a/drivers/video/msm/hdmi_sii9022.c b/drivers/video/msm/hdmi_sii9022.c
new file mode 100644
index 0000000..3d27488
--- /dev/null
+++ b/drivers/video/msm/hdmi_sii9022.c
@@ -0,0 +1,245 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include "msm_fb.h"
+
+#define DEVICE_NAME "sii9022"
+#define SII9022_DEVICE_ID 0xB0
+
+struct sii9022_i2c_addr_data{
+ u8 addr;
+ u8 data;
+};
+
+/* video mode data */
+static u8 video_mode_data[] = {
+ 0x00,
+ 0xF9, 0x1C, 0x70, 0x17, 0x72, 0x06, 0xEE, 0x02,
+};
+
+static u8 avi_io_format[] = {
+ 0x09,
+ 0x00, 0x00,
+};
+
+/* power state */
+static struct sii9022_i2c_addr_data regset0[] = {
+ { 0x60, 0x04 },
+ { 0x63, 0x00 },
+ { 0x1E, 0x00 },
+};
+
+static u8 video_infoframe[] = {
+ 0x0C,
+ 0xF0, 0x00, 0x68, 0x00, 0x04, 0x00, 0x19, 0x00,
+ 0xE9, 0x02, 0x04, 0x01, 0x04, 0x06,
+};
+
+/* configure audio */
+static struct sii9022_i2c_addr_data regset1[] = {
+ { 0x26, 0x90 },
+ { 0x20, 0x90 },
+ { 0x1F, 0x80 },
+ { 0x26, 0x80 },
+ { 0x24, 0x02 },
+ { 0x25, 0x0B },
+ { 0xBC, 0x02 },
+ { 0xBD, 0x24 },
+ { 0xBE, 0x02 },
+};
+
+/* enable audio */
+static u8 misc_infoframe[] = {
+ 0xBF,
+ 0xC2, 0x84, 0x01, 0x0A, 0x6F, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+/* set HDMI, active */
+static struct sii9022_i2c_addr_data regset2[] = {
+ { 0x1A, 0x01 },
+ { 0x3D, 0x00 },
+};
+
+static int send_i2c_data(struct i2c_client *client,
+ struct sii9022_i2c_addr_data *regset,
+ int size)
+{
+ int i;
+ int rc = 0;
+
+ for (i = 0; i < size; i++) {
+ rc = i2c_smbus_write_byte_data(
+ client,
+ regset[i].addr, regset[i].data);
+ if (rc)
+ break;
+ }
+ return rc;
+}
+
+static int hdmi_sii_enable(struct i2c_client *client)
+{
+ int rc;
+ int retries = 10;
+ int count;
+
+ rc = i2c_smbus_write_byte_data(client, 0xC7, 0x00);
+ if (rc)
+ goto enable_exit;
+
+ do {
+ msleep(1);
+ rc = i2c_smbus_read_byte_data(client, 0x1B);
+ } while ((rc != SII9022_DEVICE_ID) && retries--);
+
+ if (rc != SII9022_DEVICE_ID)
+ return -ENODEV;
+
+ rc = i2c_smbus_write_byte_data(client, 0x1A, 0x11);
+ if (rc)
+ goto enable_exit;
+
+ count = ARRAY_SIZE(video_mode_data);
+ rc = i2c_master_send(client, video_mode_data, count);
+ if (rc != count) {
+ rc = -EIO;
+ goto enable_exit;
+ }
+
+ rc = i2c_smbus_write_byte_data(client, 0x08, 0x20);
+ if (rc)
+ goto enable_exit;
+ count = ARRAY_SIZE(avi_io_format);
+ rc = i2c_master_send(client, avi_io_format, count);
+ if (rc != count) {
+ rc = -EIO;
+ goto enable_exit;
+ }
+
+ rc = send_i2c_data(client, regset0, ARRAY_SIZE(regset0));
+ if (rc)
+ goto enable_exit;
+
+ count = ARRAY_SIZE(video_infoframe);
+ rc = i2c_master_send(client, video_infoframe, count);
+ if (rc != count) {
+ rc = -EIO;
+ goto enable_exit;
+ }
+
+ rc = send_i2c_data(client, regset1, ARRAY_SIZE(regset1));
+ if (rc)
+ goto enable_exit;
+
+ count = ARRAY_SIZE(misc_infoframe);
+ rc = i2c_master_send(client, misc_infoframe, count);
+ if (rc != count) {
+ rc = -EIO;
+ goto enable_exit;
+ }
+
+ rc = send_i2c_data(client, regset2, ARRAY_SIZE(regset2));
+ if (rc)
+ goto enable_exit;
+
+ return 0;
+enable_exit:
+ printk(KERN_ERR "%s: exited rc=%d\n", __func__, rc);
+ return rc;
+}
+
+static const struct i2c_device_id hmdi_sii_id[] = {
+ { DEVICE_NAME, 0 },
+ { }
+};
+
+static int hdmi_sii_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int rc;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
+ return -ENODEV;
+ rc = hdmi_sii_enable(client);
+ return rc;
+}
+
+
+static struct i2c_driver hdmi_sii_i2c_driver = {
+ .driver = {
+ .name = DEVICE_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = hdmi_sii_probe,
+ .remove = __exit_p(hdmi_sii_remove),
+ .id_table = hmdi_sii_id,
+};
+
+static int __init hdmi_sii_init(void)
+{
+ int ret;
+ struct msm_panel_info pinfo;
+
+ if (msm_fb_detect_client("hdmi_sii9022"))
+ return 0;
+
+ pinfo.xres = 1280;
+ pinfo.yres = 720;
+ MSM_FB_SINGLE_MODE_PANEL(&pinfo);
+ pinfo.type = HDMI_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 18;
+ pinfo.fb_num = 2;
+ pinfo.clk_rate = 74250000;
+
+ pinfo.lcdc.h_back_porch = 124;
+ pinfo.lcdc.h_front_porch = 110;
+ pinfo.lcdc.h_pulse_width = 136;
+ pinfo.lcdc.v_back_porch = 19;
+ pinfo.lcdc.v_front_porch = 5;
+ pinfo.lcdc.v_pulse_width = 6;
+ pinfo.lcdc.border_clr = 0;
+ pinfo.lcdc.underflow_clr = 0xff;
+ pinfo.lcdc.hsync_skew = 0;
+
+ ret = lcdc_device_register(&pinfo);
+ if (ret) {
+ printk(KERN_ERR "%s: failed to register device\n", __func__);
+ goto init_exit;
+ }
+
+ ret = i2c_add_driver(&hdmi_sii_i2c_driver);
+ if (ret)
+ printk(KERN_ERR "%s: failed to add i2c driver\n", __func__);
+
+init_exit:
+ return ret;
+}
+
+static void __exit hdmi_sii_exit(void)
+{
+ i2c_del_driver(&hdmi_sii_i2c_driver);
+}
+
+module_init(hdmi_sii_init);
+module_exit(hdmi_sii_exit);
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("0.1");
+MODULE_AUTHOR("Qualcomm Innovation Center, Inc.");
+MODULE_DESCRIPTION("SiI9022 HDMI driver");
+MODULE_ALIAS("platform:hdmi-sii9022");
diff --git a/drivers/video/msm/lcdc.c b/drivers/video/msm/lcdc.c
new file mode 100644
index 0000000..e3f1907
--- /dev/null
+++ b/drivers/video/msm/lcdc.c
@@ -0,0 +1,294 @@
+/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <mach/msm_reqs.h>
+
+#include "msm_fb.h"
+
+static int lcdc_probe(struct platform_device *pdev);
+static int lcdc_remove(struct platform_device *pdev);
+
+static int lcdc_off(struct platform_device *pdev);
+static int lcdc_on(struct platform_device *pdev);
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+
+static struct clk *pixel_mdp_clk; /* drives the lcdc block in mdp */
+static struct clk *pixel_lcdc_clk; /* drives the lcdc interface */
+
+static struct platform_driver lcdc_driver = {
+ .probe = lcdc_probe,
+ .remove = lcdc_remove,
+ .suspend = NULL,
+ .resume = NULL,
+ .shutdown = NULL,
+ .driver = {
+ .name = "lcdc",
+ },
+};
+
+static struct lcdc_platform_data *lcdc_pdata;
+
+static int lcdc_off(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct msm_fb_data_type *mfd;
+
+ mfd = platform_get_drvdata(pdev);
+ ret = panel_next_off(pdev);
+
+ clk_disable(pixel_mdp_clk);
+ clk_disable(pixel_lcdc_clk);
+
+ if (lcdc_pdata && lcdc_pdata->lcdc_power_save)
+ lcdc_pdata->lcdc_power_save(0);
+
+ if (lcdc_pdata && lcdc_pdata->lcdc_gpio_config)
+ ret = lcdc_pdata->lcdc_gpio_config(0);
+
+#ifndef CONFIG_MSM_BUS_SCALING
+ if (mdp_rev != MDP_REV_303) {
+ if (mfd->ebi1_clk)
+ clk_disable(mfd->ebi1_clk);
+ }
+#else
+ mdp_bus_scale_update_request(0);
+#endif
+
+ return ret;
+}
+
+static int lcdc_on(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct msm_fb_data_type *mfd;
+ unsigned long panel_pixclock_freq = 0;
+#ifndef CONFIG_MSM_BUS_SCALING
+ unsigned long pm_qos_rate;
+#endif
+ mfd = platform_get_drvdata(pdev);
+
+ if (lcdc_pdata && lcdc_pdata->lcdc_get_clk)
+ panel_pixclock_freq = lcdc_pdata->lcdc_get_clk();
+
+ if (!panel_pixclock_freq)
+ panel_pixclock_freq = mfd->fbi->var.pixclock;
+#ifdef CONFIG_MSM_BUS_SCALING
+ mdp_bus_scale_update_request(2);
+#else
+#ifdef CONFIG_MSM_NPA_SYSTEM_BUS
+ pm_qos_rate = MSM_AXI_FLOW_MDP_LCDC_WVGA_2BPP;
+#else
+ if (panel_pixclock_freq > 65000000)
+ /* pm_qos_rate should be in Khz */
+ pm_qos_rate = panel_pixclock_freq / 1000 ;
+ else
+ pm_qos_rate = 65000;
+#endif
+
+ if (mdp_rev != MDP_REV_303) {
+ if (mfd->ebi1_clk) {
+ clk_set_rate(mfd->ebi1_clk, pm_qos_rate * 1000);
+ clk_enable(mfd->ebi1_clk);
+ }
+ }
+#endif
+ mfd = platform_get_drvdata(pdev);
+
+ mfd->fbi->var.pixclock = clk_round_rate(pixel_mdp_clk,
+ mfd->fbi->var.pixclock);
+ ret = clk_set_rate(pixel_mdp_clk, mfd->fbi->var.pixclock);
+ if (ret) {
+ pr_err("%s: Can't set MDP LCDC pixel clock to rate %u\n",
+ __func__, mfd->fbi->var.pixclock);
+ goto out;
+ }
+
+ clk_enable(pixel_mdp_clk);
+ clk_enable(pixel_lcdc_clk);
+
+ if (lcdc_pdata && lcdc_pdata->lcdc_power_save)
+ lcdc_pdata->lcdc_power_save(1);
+ if (lcdc_pdata && lcdc_pdata->lcdc_gpio_config)
+ ret = lcdc_pdata->lcdc_gpio_config(1);
+
+ ret = panel_next_on(pdev);
+
+out:
+ return ret;
+}
+
+static int lcdc_probe(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct fb_info *fbi;
+ struct platform_device *mdp_dev = NULL;
+ struct msm_fb_panel_data *pdata = NULL;
+ int rc;
+
+ if (pdev->id == 0) {
+ lcdc_pdata = pdev->dev.platform_data;
+ return 0;
+ }
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+ return -ENOMEM;
+
+ mdp_dev = platform_device_alloc("mdp", pdev->id);
+ if (!mdp_dev)
+ return -ENOMEM;
+
+ /*
+ * link to the latest pdev
+ */
+ mfd->pdev = mdp_dev;
+ mfd->dest = DISPLAY_LCDC;
+
+ /*
+ * alloc panel device data
+ */
+ if (platform_device_add_data
+ (mdp_dev, pdev->dev.platform_data,
+ sizeof(struct msm_fb_panel_data))) {
+ printk(KERN_ERR "lcdc_probe: platform_device_add_data failed!\n");
+ platform_device_put(mdp_dev);
+ return -ENOMEM;
+ }
+ /*
+ * data chain
+ */
+ pdata = (struct msm_fb_panel_data *)mdp_dev->dev.platform_data;
+ pdata->on = lcdc_on;
+ pdata->off = lcdc_off;
+ pdata->next = pdev;
+
+ /*
+ * get/set panel specific fb info
+ */
+ mfd->panel_info = pdata->panel_info;
+
+ if (mfd->index == 0)
+ mfd->fb_imgType = MSMFB_DEFAULT_TYPE;
+ else
+ mfd->fb_imgType = MDP_RGB_565;
+
+ fbi = mfd->fbi;
+ fbi->var.pixclock = clk_round_rate(pixel_mdp_clk,
+ mfd->panel_info.clk_rate);
+ fbi->var.left_margin = mfd->panel_info.lcdc.h_back_porch;
+ fbi->var.right_margin = mfd->panel_info.lcdc.h_front_porch;
+ fbi->var.upper_margin = mfd->panel_info.lcdc.v_back_porch;
+ fbi->var.lower_margin = mfd->panel_info.lcdc.v_front_porch;
+ fbi->var.hsync_len = mfd->panel_info.lcdc.h_pulse_width;
+ fbi->var.vsync_len = mfd->panel_info.lcdc.v_pulse_width;
+
+#ifndef CONFIG_MSM_BUS_SCALING
+ mfd->ebi1_clk = clk_get(NULL, "ebi1_lcdc_clk");
+ if (IS_ERR(mfd->ebi1_clk))
+ return PTR_ERR(mfd->ebi1_clk);
+#endif
+ /*
+ * set driver data
+ */
+ platform_set_drvdata(mdp_dev, mfd);
+ /*
+ * register in mdp driver
+ */
+ rc = platform_device_add(mdp_dev);
+ if (rc)
+ goto lcdc_probe_err;
+
+ pdev_list[pdev_list_cnt++] = pdev;
+
+ return 0;
+
+lcdc_probe_err:
+ platform_device_put(mdp_dev);
+ return rc;
+}
+
+static int lcdc_remove(struct platform_device *pdev)
+{
+#ifndef CONFIG_MSM_BUS_SCALING
+ struct msm_fb_data_type *mfd;
+
+ mfd = platform_get_drvdata(pdev);
+
+ clk_put(mfd->ebi1_clk);
+#endif
+ return 0;
+}
+
+static int lcdc_register_driver(void)
+{
+ return platform_driver_register(&lcdc_driver);
+}
+
+static int __init lcdc_driver_init(void)
+{
+
+ pixel_mdp_clk = clk_get(NULL, "pixel_mdp_clk");
+ if (IS_ERR(pixel_mdp_clk))
+ pixel_mdp_clk = NULL;
+
+ if (pixel_mdp_clk) {
+ pixel_lcdc_clk = clk_get(NULL, "pixel_lcdc_clk");
+ if (IS_ERR(pixel_lcdc_clk)) {
+ printk(KERN_ERR "Couldnt find pixel_lcdc_clk\n");
+ return -EINVAL;
+ }
+ } else {
+ pixel_mdp_clk = clk_get(NULL, "mdp_lcdc_pclk_clk");
+ if (IS_ERR(pixel_mdp_clk)) {
+ printk(KERN_ERR "Couldnt find mdp_lcdc_pclk_clk\n");
+ return -EINVAL;
+ }
+
+ pixel_lcdc_clk = clk_get(NULL, "mdp_lcdc_pad_pclk_clk");
+ if (IS_ERR(pixel_lcdc_clk)) {
+ printk(KERN_ERR "Couldnt find mdp_lcdc_pad_pclk_clk\n");
+ return -EINVAL;
+ }
+ }
+
+ return lcdc_register_driver();
+}
+
+module_init(lcdc_driver_init);
diff --git a/drivers/video/msm/lcdc_auo_wvga.c b/drivers/video/msm/lcdc_auo_wvga.c
new file mode 100644
index 0000000..b1c3af0
--- /dev/null
+++ b/drivers/video/msm/lcdc_auo_wvga.c
@@ -0,0 +1,413 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/pwm.h>
+#ifdef CONFIG_SPI_QUP
+#include <linux/spi/spi.h>
+#else
+#include <mach/gpio.h>
+#endif
+#include "msm_fb.h"
+
+#define MAX_BACKLIGHT_LEVEL 15
+#define PANEL_CMD_BACKLIGHT_LEVEL 0x6A18
+#define PANEL_CMD_FORMAT 0x3A00
+#define PANEL_CMD_RGBCTRL 0x3B00
+#define PANEL_CMD_BCTRL 0x5300
+#define PANEL_CMD_PWM_EN 0x6A17
+
+#define PANEL_CMD_SLEEP_OUT 0x1100
+#define PANEL_CMD_DISP_ON 0x2900
+#define PANEL_CMD_DISP_OFF 0x2800
+#define PANEL_CMD_SLEEP_IN 0x1000
+
+#define LCDC_AUO_PANEL_NAME "lcdc_auo_wvga"
+
+#ifdef CONFIG_SPI_QUP
+#define LCDC_AUO_SPI_DEVICE_NAME "lcdc_auo_nt35582"
+static struct spi_device *lcdc_spi_client;
+#else
+static int spi_cs;
+static int spi_sclk;
+static int spi_mosi;
+#endif
+
+struct auo_state_type {
+ boolean display_on;
+ int bl_level;
+};
+
+
+static struct auo_state_type auo_state = { .bl_level = 10 };
+static struct msm_panel_common_pdata *lcdc_auo_pdata;
+
+#ifndef CONFIG_SPI_QUP
+static void auo_spi_write_byte(u8 data)
+{
+ uint32 bit;
+ int bnum;
+
+ bnum = 8; /* 8 data bits */
+ bit = 0x80;
+ while (bnum--) {
+ gpio_set_value(spi_sclk, 0); /* clk low */
+ gpio_set_value(spi_mosi, (data & bit) ? 1 : 0);
+ udelay(1);
+ gpio_set_value(spi_sclk, 1); /* clk high */
+ udelay(1);
+ bit >>= 1;
+ }
+ gpio_set_value(spi_mosi, 0);
+}
+
+static void auo_spi_read_byte(u16 cmd_16, u8 *data)
+{
+ int bnum;
+ u8 cmd_hi = (u8)(cmd_16 >> 8);
+ u8 cmd_low = (u8)(cmd_16);
+
+ /* Chip Select - low */
+ gpio_set_value(spi_cs, 0);
+ udelay(2);
+
+ /* command byte first */
+ auo_spi_write_byte(0x20);
+ udelay(2);
+ auo_spi_write_byte(cmd_hi);
+ udelay(2);
+ auo_spi_write_byte(0x00);
+ udelay(2);
+ auo_spi_write_byte(cmd_low);
+ udelay(2);
+ auo_spi_write_byte(0xc0);
+ udelay(2);
+
+ gpio_direction_input(spi_mosi);
+
+ /* followed by data bytes */
+ bnum = 1 * 8; /* number of bits */
+ *data = 0;
+ while (bnum) {
+ gpio_set_value(spi_sclk, 0); /* clk low */
+ udelay(1);
+ *data <<= 1;
+ *data |= gpio_get_value(spi_mosi) ? 1 : 0;
+ gpio_set_value(spi_sclk, 1); /* clk high */
+ udelay(1);
+ --bnum;
+ if ((bnum % 8) == 0)
+ ++data;
+ }
+
+ gpio_direction_output(spi_mosi, 0);
+
+ /* Chip Select - high */
+ udelay(2);
+ gpio_set_value(spi_cs, 1);
+}
+#endif
+
+static int auo_serigo(u8 *input_data, int input_len)
+{
+#ifdef CONFIG_SPI_QUP
+ int rc;
+ struct spi_message m;
+ struct spi_transfer t;
+
+ if (!lcdc_spi_client) {
+ pr_err("%s lcdc_spi_client is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ memset(&t, 0, sizeof t);
+
+ t.tx_buf = input_data;
+ t.len = input_len;
+ t.bits_per_word = 16;
+
+ spi_setup(lcdc_spi_client);
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+
+ rc = spi_sync(lcdc_spi_client, &m);
+
+ return rc;
+#else
+ int i;
+
+ /* Chip Select - low */
+ gpio_set_value(spi_cs, 0);
+ udelay(2);
+
+ for (i = 0; i < input_len; ++i) {
+ auo_spi_write_byte(input_data[i]);
+ udelay(2);
+ }
+
+ /* Chip Select - high */
+ gpio_set_value(spi_cs, 1);
+
+ return 0;
+#endif
+}
+
+#ifndef CONFIG_SPI_QUP
+static void auo_spi_init(void)
+{
+ spi_sclk = *(lcdc_auo_pdata->gpio_num);
+ spi_cs = *(lcdc_auo_pdata->gpio_num + 1);
+ spi_mosi = *(lcdc_auo_pdata->gpio_num + 2);
+
+ /* Set the output so that we don't disturb the slave device */
+ gpio_set_value(spi_sclk, 1);
+ gpio_set_value(spi_mosi, 0);
+
+ /* Set the Chip Select deasserted (active low) */
+ gpio_set_value(spi_cs, 1);
+}
+#endif
+
+static struct work_struct disp_on_delayed_work;
+static void auo_write_cmd(u16 cmd)
+{
+ u8 local_data[4];
+
+ local_data[0] = 0x20;
+ local_data[1] = (u8)(cmd >> 8);
+ local_data[2] = 0;
+ local_data[3] = (u8)cmd;
+ auo_serigo(local_data, 4);
+}
+static void auo_write_cmd_1param(u16 cmd, u8 para1)
+{
+ u8 local_data[6];
+
+ local_data[0] = 0x20;
+ local_data[1] = (u8)(cmd >> 8);
+ local_data[2] = 0;
+ local_data[3] = (u8)cmd;
+ local_data[4] = 0x40;
+ local_data[5] = para1;
+ auo_serigo(local_data, 6);
+}
+static void lcdc_auo_set_backlight(struct msm_fb_data_type *mfd)
+{
+ int bl_level;
+
+ bl_level = mfd->bl_level;
+ if (auo_state.display_on) {
+ auo_write_cmd_1param(PANEL_CMD_BACKLIGHT_LEVEL,
+ bl_level * 255 / MAX_BACKLIGHT_LEVEL);
+ auo_state.bl_level = bl_level;
+ }
+
+}
+static void auo_disp_on_delayed_work(struct work_struct *work_ptr)
+{
+ /* 0x1100: Sleep Out */
+ auo_write_cmd(PANEL_CMD_SLEEP_OUT);
+
+ msleep(180);
+
+ /* SET_PIXEL_FORMAT: Set how many bits per pixel are used (3A00h)*/
+ auo_write_cmd_1param(PANEL_CMD_FORMAT, 0x66); /* 18 bits */
+
+ /* RGBCTRL: RGB Interface Signal Control (3B00h) */
+ auo_write_cmd_1param(PANEL_CMD_RGBCTRL, 0x2B);
+
+ /* Display ON command */
+ auo_write_cmd(PANEL_CMD_DISP_ON);
+ msleep(20);
+
+ /*Backlight on */
+ auo_write_cmd_1param(PANEL_CMD_BCTRL, 0x24); /*BCTRL, BL */
+ auo_write_cmd_1param(PANEL_CMD_PWM_EN, 0x01); /*Enable PWM Level */
+
+ msleep(20);
+}
+
+static void auo_disp_on(void)
+{
+ if (!auo_state.display_on) {
+ INIT_WORK(&disp_on_delayed_work, auo_disp_on_delayed_work);
+#ifdef CONFIG_SPI_QUP
+ if (lcdc_spi_client)
+#endif
+ schedule_work(&disp_on_delayed_work);
+ auo_state.display_on = TRUE;
+ }
+}
+
+static int lcdc_auo_panel_on(struct platform_device *pdev)
+{
+ pr_info("%s\n", __func__);
+ if (!auo_state.display_on) {
+#ifndef CONFIG_SPI_QUP
+ lcdc_auo_pdata->panel_config_gpio(1);
+ auo_spi_init();
+#endif
+ auo_disp_on();
+ }
+ return 0;
+}
+
+static int lcdc_auo_panel_off(struct platform_device *pdev)
+{
+ pr_info("%s\n", __func__);
+ if (auo_state.display_on) {
+ /* 0x2800: Display Off */
+ auo_write_cmd(PANEL_CMD_DISP_OFF);
+ msleep(120);
+ /* 0x1000: Sleep In */
+ auo_write_cmd(PANEL_CMD_SLEEP_IN);
+ msleep(120);
+
+ auo_state.display_on = FALSE;
+ }
+ return 0;
+}
+
+static int auo_probe(struct platform_device *pdev)
+{
+ pr_info("%s: id=%d\n", __func__, pdev->id);
+ if (pdev->id == 0) {
+ lcdc_auo_pdata = pdev->dev.platform_data;
+ return 0;
+ }
+
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+#ifdef CONFIG_SPI_QUP
+static int __devinit lcdc_auo_spi_probe(struct spi_device *spi)
+{
+ pr_info("%s\n", __func__);
+ lcdc_spi_client = spi;
+ lcdc_spi_client->bits_per_word = 32;
+ if (auo_state.display_on)
+ schedule_work(&disp_on_delayed_work);
+ return 0;
+}
+static int __devexit lcdc_auo_spi_remove(struct spi_device *spi)
+{
+ lcdc_spi_client = NULL;
+ return 0;
+}
+static struct spi_driver lcdc_auo_spi_driver = {
+ .driver.name = LCDC_AUO_SPI_DEVICE_NAME,
+ .driver.owner = THIS_MODULE,
+ .probe = lcdc_auo_spi_probe,
+ .remove = __devexit_p(lcdc_auo_spi_remove),
+};
+#endif
+
+static struct platform_driver this_driver = {
+ .probe = auo_probe,
+ .driver.name = LCDC_AUO_PANEL_NAME,
+};
+
+static struct msm_fb_panel_data auo_panel_data = {
+ .on = lcdc_auo_panel_on,
+ .off = lcdc_auo_panel_off,
+ .set_backlight = lcdc_auo_set_backlight,
+};
+
+static struct platform_device this_device = {
+ .name = LCDC_AUO_PANEL_NAME,
+ .id = 1,
+ .dev.platform_data = &auo_panel_data,
+};
+
+static int __init lcdc_auo_panel_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_LCDC_AUTO_DETECT
+ if (msm_fb_detect_client(LCDC_AUO_PANEL_NAME)) {
+ pr_err("%s: detect failed\n", __func__);
+ return 0;
+ }
+#endif
+
+ ret = platform_driver_register(&this_driver);
+ if (ret) {
+ pr_err("%s: driver register failed, rc=%d\n", __func__, ret);
+ return ret;
+ }
+
+ pinfo = &auo_panel_data.panel_info;
+ pinfo->xres = 480;
+ pinfo->yres = 800;
+ pinfo->type = LCDC_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 18;
+ pinfo->fb_num = 2;
+ pinfo->clk_rate = 25600000;
+ pinfo->bl_max = MAX_BACKLIGHT_LEVEL;
+ pinfo->bl_min = 1;
+
+ pinfo->lcdc.h_back_porch = 16-2; /* HBP-HLW */
+ pinfo->lcdc.h_front_porch = 16;
+ pinfo->lcdc.h_pulse_width = 2;
+
+ pinfo->lcdc.v_back_porch = 3-2; /* VBP-VLW */
+ pinfo->lcdc.v_front_porch = 28;
+ pinfo->lcdc.v_pulse_width = 2;
+
+ pinfo->lcdc.border_clr = 0;
+ pinfo->lcdc.underflow_clr = 0xff;
+ pinfo->lcdc.hsync_skew = 0;
+
+ ret = platform_device_register(&this_device);
+ if (ret) {
+ pr_err("%s: device register failed, rc=%d\n", __func__, ret);
+ goto fail_driver;
+ }
+#ifdef CONFIG_SPI_QUP
+ ret = spi_register_driver(&lcdc_auo_spi_driver);
+
+ if (ret) {
+ pr_err("%s: spi register failed: rc=%d\n", __func__, ret);
+ goto fail_device;
+ }
+ pr_info("%s: SUCCESS (SPI)\n", __func__);
+#else
+ pr_info("%s: SUCCESS (BitBang)\n", __func__);
+#endif
+ return ret;
+
+#ifdef CONFIG_SPI_QUP
+fail_device:
+ platform_device_unregister(&this_device);
+#endif
+fail_driver:
+ platform_driver_unregister(&this_driver);
+
+ return ret;
+}
+
+module_init(lcdc_auo_panel_init);
+static void __exit lcdc_auo_panel_exit(void)
+{
+ pr_info("%s\n", __func__);
+ platform_device_unregister(&this_device);
+ platform_driver_unregister(&this_driver);
+#ifdef CONFIG_SPI_QUP
+ spi_unregister_driver(&lcdc_auo_spi_driver);
+#endif
+}
+module_exit(lcdc_auo_panel_exit);
diff --git a/drivers/video/msm/lcdc_chimei_wxga.c b/drivers/video/msm/lcdc_chimei_wxga.c
new file mode 100644
index 0000000..b5cce2c
--- /dev/null
+++ b/drivers/video/msm/lcdc_chimei_wxga.c
@@ -0,0 +1,233 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/pwm.h>
+#ifdef CONFIG_PMIC8058_PWM
+#include <linux/mfd/pmic8058.h>
+#include <linux/pmic8058-pwm.h>
+#endif
+#include <mach/gpio.h>
+#include "msm_fb.h"
+
+
+
+
+static struct pwm_device *bl_pwm;
+
+#define PWM_FREQ_HZ 210
+#define PWM_PERIOD_USEC (USEC_PER_SEC / PWM_FREQ_HZ)
+#define PWM_DUTY_LEVEL (PWM_PERIOD_USEC / PWM_LEVEL)
+#define PWM_LEVEL 15
+
+static struct msm_panel_common_pdata *cm_pdata;
+static struct platform_device *cm_fbpdev;
+static int led_pwm; /* pm8058 gpio 24, channel 0 */
+static int led_en; /* pm8058 gpio 1 */
+static int lvds_pwr_down; /* msm gpio 30 */
+static int chimei_bl_level = 1;
+
+
+static void lcdc_chimei_set_backlight(int level)
+{
+ int ret;
+
+ if (bl_pwm) {
+ ret = pwm_config(bl_pwm, PWM_DUTY_LEVEL * level,
+ PWM_PERIOD_USEC);
+ if (ret) {
+ pr_err("%s: pwm_config on pwm failed %d\n",
+ __func__, ret);
+ return;
+ }
+
+ ret = pwm_enable(bl_pwm);
+ if (ret) {
+ pr_err("%s: pwm_enable on pwm failed %d\n",
+ __func__, ret);
+ return;
+ }
+ }
+
+ chimei_bl_level = level;
+}
+
+static int lcdc_chimei_panel_on(struct platform_device *pdev)
+{
+ int ret;
+
+ /* panel powered on here */
+
+ ret = gpio_request(lvds_pwr_down, "lvds_pwr_down");
+ if (ret == 0) {
+ /* output, pull high to enable */
+ gpio_direction_output(lvds_pwr_down, 1);
+ } else {
+ pr_err("%s: lvds_pwr_down=%d, gpio_request failed\n",
+ __func__, lvds_pwr_down);
+ }
+
+ msleep(200);
+ /* power on led pwm power >= 200 ms */
+
+ if (chimei_bl_level == 0)
+ chimei_bl_level = 1;
+ lcdc_chimei_set_backlight(chimei_bl_level);
+
+ msleep(10);
+
+ ret = gpio_request(led_en, "led_en");
+ if (ret == 0) {
+ /* output, pull high */
+ gpio_direction_output(led_en, 1);
+ } else {
+ pr_err("%s: led_en=%d, gpio_request failed\n",
+ __func__, led_en);
+ }
+ return ret;
+}
+
+static int lcdc_chimei_panel_off(struct platform_device *pdev)
+{
+ /* pull low to disable */
+ gpio_set_value_cansleep(led_en, 0);
+ gpio_free(led_en);
+
+ msleep(10);
+
+ lcdc_chimei_set_backlight(0);
+
+ msleep(200);
+ /* power off led pwm power >= 200 ms */
+
+ /* pull low to shut down lvds */
+ gpio_set_value_cansleep(lvds_pwr_down, 0);
+ gpio_free(lvds_pwr_down);
+
+ /* panel power off here */
+
+ return 0;
+}
+
+static void lcdc_chimei_panel_backlight(struct msm_fb_data_type *mfd)
+{
+ lcdc_chimei_set_backlight(mfd->bl_level);
+}
+
+static int __devinit chimei_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+
+ if (pdev->id == 0) {
+ cm_pdata = pdev->dev.platform_data;
+ if (cm_pdata == NULL) {
+ pr_err("%s: no PWM gpio specified\n", __func__);
+ return 0;
+ }
+ led_pwm = cm_pdata->gpio_num[0];
+ led_en = cm_pdata->gpio_num[1];
+ lvds_pwr_down = cm_pdata->gpio_num[2];
+ pr_info("%s: led_pwm=%d led_en=%d lvds_pwr_down=%d\n",
+ __func__, led_pwm, led_en, lvds_pwr_down);
+ return 0;
+ }
+
+ if (cm_pdata == NULL)
+ return -ENODEV;
+
+ bl_pwm = pwm_request(led_pwm, "backlight");
+ if (bl_pwm == NULL || IS_ERR(bl_pwm)) {
+ pr_err("%s pwm_request() failed\n", __func__);
+ bl_pwm = NULL;
+ }
+
+ cm_fbpdev = msm_fb_add_device(pdev);
+ if (!cm_fbpdev) {
+ dev_err(&pdev->dev, "failed to add msm_fb device\n");
+ rc = -ENODEV;
+ goto probe_exit;
+ }
+
+probe_exit:
+ return rc;
+}
+
+static struct platform_driver this_driver = {
+ .probe = chimei_probe,
+ .driver = {
+ .name = "lcdc_chimei_lvds_wxga",
+ },
+};
+
+static struct msm_fb_panel_data chimei_panel_data = {
+ .on = lcdc_chimei_panel_on,
+ .off = lcdc_chimei_panel_off,
+ .set_backlight = lcdc_chimei_panel_backlight,
+};
+
+static struct platform_device this_device = {
+ .name = "lcdc_chimei_lvds_wxga",
+ .id = 1,
+ .dev = {
+ .platform_data = &chimei_panel_data,
+ }
+};
+
+static int __init lcdc_chimei_lvds_panel_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_MIPI_PANEL_DETECT
+ if (msm_fb_detect_client("lcdc_chimei_lvds_wxga"))
+ return 0;
+#endif
+
+ ret = platform_driver_register(&this_driver);
+ if (ret)
+ return ret;
+
+ pinfo = &chimei_panel_data.panel_info;
+ pinfo->xres = 1366;
+ pinfo->yres = 768;
+ MSM_FB_SINGLE_MODE_PANEL(pinfo);
+ pinfo->type = LCDC_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 18;
+ pinfo->fb_num = 2;
+ pinfo->clk_rate = 69300000;
+ pinfo->bl_max = PWM_LEVEL;
+ pinfo->bl_min = 1;
+
+ /*
+ * this panel is operated by de,
+ * vsycn and hsync are ignored
+ */
+ pinfo->lcdc.h_back_porch = 108;
+ pinfo->lcdc.h_front_porch = 0;
+ pinfo->lcdc.h_pulse_width = 1;
+ pinfo->lcdc.v_back_porch = 0;
+ pinfo->lcdc.v_front_porch = 16;
+ pinfo->lcdc.v_pulse_width = 1;
+ pinfo->lcdc.border_clr = 0;
+ pinfo->lcdc.underflow_clr = 0xff;
+ pinfo->lcdc.hsync_skew = 0;
+
+ ret = platform_device_register(&this_device);
+ if (ret)
+ platform_driver_unregister(&this_driver);
+
+ return ret;
+}
+
+module_init(lcdc_chimei_lvds_panel_init);
diff --git a/drivers/video/msm/lcdc_external.c b/drivers/video/msm/lcdc_external.c
new file mode 100644
index 0000000..ca82def
--- /dev/null
+++ b/drivers/video/msm/lcdc_external.c
@@ -0,0 +1,51 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+
+static int __init lcdc_external_init(void)
+{
+ int ret;
+ struct msm_panel_info pinfo;
+
+ if (msm_fb_detect_client("lcdc_external"))
+ return 0;
+
+ pinfo.xres = 1280;
+ pinfo.yres = 720;
+ MSM_FB_SINGLE_MODE_PANEL(&pinfo);
+ pinfo.type = LCDC_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 24;
+ pinfo.fb_num = 2;
+ pinfo.clk_rate = 74250000;
+
+ pinfo.lcdc.h_back_porch = 124;
+ pinfo.lcdc.h_front_porch = 110;
+ pinfo.lcdc.h_pulse_width = 136;
+ pinfo.lcdc.v_back_porch = 19;
+ pinfo.lcdc.v_front_porch = 5;
+ pinfo.lcdc.v_pulse_width = 6;
+ pinfo.lcdc.border_clr = 0; /* blk */
+ pinfo.lcdc.underflow_clr = 0xff; /* blue */
+ pinfo.lcdc.hsync_skew = 0;
+
+ ret = lcdc_device_register(&pinfo);
+ if (ret)
+ printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(lcdc_external_init);
diff --git a/drivers/video/msm/lcdc_gordon.c b/drivers/video/msm/lcdc_gordon.c
new file mode 100644
index 0000000..f9532b4
--- /dev/null
+++ b/drivers/video/msm/lcdc_gordon.c
@@ -0,0 +1,443 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/delay.h>
+#include <mach/gpio.h>
+#include "msm_fb.h"
+
+/* registers */
+#define GORDON_REG_NOP 0x00
+#define GORDON_REG_IMGCTL1 0x10
+#define GORDON_REG_IMGCTL2 0x11
+#define GORDON_REG_IMGSET1 0x12
+#define GORDON_REG_IMGSET2 0x13
+#define GORDON_REG_IVBP1 0x14
+#define GORDON_REG_IHBP1 0x15
+#define GORDON_REG_IVNUM1 0x16
+#define GORDON_REG_IHNUM1 0x17
+#define GORDON_REG_IVBP2 0x18
+#define GORDON_REG_IHBP2 0x19
+#define GORDON_REG_IVNUM2 0x1A
+#define GORDON_REG_IHNUM2 0x1B
+#define GORDON_REG_LCDIFCTL1 0x30
+#define GORDON_REG_VALTRAN 0x31
+#define GORDON_REG_AVCTL 0x33
+#define GORDON_REG_LCDIFCTL2 0x34
+#define GORDON_REG_LCDIFCTL3 0x35
+#define GORDON_REG_LCDIFSET1 0x36
+#define GORDON_REG_PCCTL 0x3C
+#define GORDON_REG_TPARAM1 0x40
+#define GORDON_REG_TLCDIF1 0x41
+#define GORDON_REG_TSSPB_ST1 0x42
+#define GORDON_REG_TSSPB_ED1 0x43
+#define GORDON_REG_TSCK_ST1 0x44
+#define GORDON_REG_TSCK_WD1 0x45
+#define GORDON_REG_TGSPB_VST1 0x46
+#define GORDON_REG_TGSPB_VED1 0x47
+#define GORDON_REG_TGSPB_CH1 0x48
+#define GORDON_REG_TGCK_ST1 0x49
+#define GORDON_REG_TGCK_ED1 0x4A
+#define GORDON_REG_TPCTL_ST1 0x4B
+#define GORDON_REG_TPCTL_ED1 0x4C
+#define GORDON_REG_TPCHG_ED1 0x4D
+#define GORDON_REG_TCOM_CH1 0x4E
+#define GORDON_REG_THBP1 0x4F
+#define GORDON_REG_TPHCTL1 0x50
+#define GORDON_REG_EVPH1 0x51
+#define GORDON_REG_EVPL1 0x52
+#define GORDON_REG_EVNH1 0x53
+#define GORDON_REG_EVNL1 0x54
+#define GORDON_REG_TBIAS1 0x55
+#define GORDON_REG_TPARAM2 0x56
+#define GORDON_REG_TLCDIF2 0x57
+#define GORDON_REG_TSSPB_ST2 0x58
+#define GORDON_REG_TSSPB_ED2 0x59
+#define GORDON_REG_TSCK_ST2 0x5A
+#define GORDON_REG_TSCK_WD2 0x5B
+#define GORDON_REG_TGSPB_VST2 0x5C
+#define GORDON_REG_TGSPB_VED2 0x5D
+#define GORDON_REG_TGSPB_CH2 0x5E
+#define GORDON_REG_TGCK_ST2 0x5F
+#define GORDON_REG_TGCK_ED2 0x60
+#define GORDON_REG_TPCTL_ST2 0x61
+#define GORDON_REG_TPCTL_ED2 0x62
+#define GORDON_REG_TPCHG_ED2 0x63
+#define GORDON_REG_TCOM_CH2 0x64
+#define GORDON_REG_THBP2 0x65
+#define GORDON_REG_TPHCTL2 0x66
+#define GORDON_REG_POWCTL 0x80
+
+static int lcdc_gordon_panel_off(struct platform_device *pdev);
+
+static int spi_cs;
+static int spi_sclk;
+static int spi_sdo;
+static int spi_sdi;
+static int spi_dac;
+static unsigned char bit_shift[8] = { (1 << 7), /* MSB */
+ (1 << 6),
+ (1 << 5),
+ (1 << 4),
+ (1 << 3),
+ (1 << 2),
+ (1 << 1),
+ (1 << 0) /* LSB */
+};
+
+struct gordon_state_type{
+ boolean disp_initialized;
+ boolean display_on;
+ boolean disp_powered_up;
+};
+
+static struct gordon_state_type gordon_state = { 0 };
+static struct msm_panel_common_pdata *lcdc_gordon_pdata;
+
+static void serigo(uint16 reg, uint8 data)
+{
+ unsigned int tx_val = ((0x00FF & reg) << 8) | data;
+ unsigned char i, val = 0;
+
+ /* Enable the Chip Select */
+ gpio_set_value(spi_cs, 1);
+ udelay(33);
+
+ /* Transmit it in two parts, Higher Byte first, then Lower Byte */
+ val = (unsigned char)((tx_val & 0xFF00) >> 8);
+
+ /* Clock should be Low before entering ! */
+ for (i = 0; i < 8; i++) {
+ /* #1: Drive the Data (High or Low) */
+ if (val & bit_shift[i])
+ gpio_set_value(spi_sdi, 1);
+ else
+ gpio_set_value(spi_sdi, 0);
+
+ /* #2: Drive the Clk High and then Low */
+ udelay(33);
+ gpio_set_value(spi_sclk, 1);
+ udelay(33);
+ gpio_set_value(spi_sclk, 0);
+ }
+
+ /* Idle state of SDO (MOSI) is Low */
+ gpio_set_value(spi_sdi, 0);
+ /* ..then Lower Byte */
+ val = (uint8) (tx_val & 0x00FF);
+ /* Before we enter here the Clock should be Low ! */
+
+ for (i = 0; i < 8; i++) {
+ /* #1: Drive the Data (High or Low) */
+ if (val & bit_shift[i])
+ gpio_set_value(spi_sdi, 1);
+ else
+ gpio_set_value(spi_sdi, 0);
+
+ /* #2: Drive the Clk High and then Low */
+ udelay(33);
+
+ gpio_set_value(spi_sclk, 1);
+ udelay(33);
+ gpio_set_value(spi_sclk, 0);
+ }
+
+ /* Idle state of SDO (MOSI) is Low */
+ gpio_set_value(spi_sdi, 0);
+
+ /* Now Disable the Chip Select */
+ udelay(33);
+ gpio_set_value(spi_cs, 0);
+}
+
+static void spi_init(void)
+{
+ /* Setting the Default GPIO's */
+ spi_sclk = *(lcdc_gordon_pdata->gpio_num);
+ spi_cs = *(lcdc_gordon_pdata->gpio_num + 1);
+ spi_sdi = *(lcdc_gordon_pdata->gpio_num + 2);
+ spi_sdo = *(lcdc_gordon_pdata->gpio_num + 3);
+
+ /* Set the output so that we dont disturb the slave device */
+ gpio_set_value(spi_sclk, 0);
+ gpio_set_value(spi_sdi, 0);
+
+ /* Set the Chip Select De-asserted */
+ gpio_set_value(spi_cs, 0);
+
+}
+
+static void gordon_disp_powerup(void)
+{
+ if (!gordon_state.disp_powered_up && !gordon_state.display_on) {
+ /* Reset the hardware first */
+ /* Include DAC power up implementation here */
+ gordon_state.disp_powered_up = TRUE;
+ }
+}
+
+static void gordon_init(void)
+{
+ /* Image interface settings */
+ serigo(GORDON_REG_IMGCTL2, 0x00);
+ serigo(GORDON_REG_IMGSET1, 0x00);
+
+ /* Exchange the RGB signal for J510(Softbank mobile) */
+ serigo(GORDON_REG_IMGSET2, 0x12);
+ serigo(GORDON_REG_LCDIFSET1, 0x00);
+
+ /* Pre-charge settings */
+ serigo(GORDON_REG_PCCTL, 0x09);
+ serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+
+ mdelay(1);
+}
+
+static void gordon_disp_on(void)
+{
+ if (gordon_state.disp_powered_up && !gordon_state.display_on) {
+ gordon_init();
+ mdelay(20);
+ /* gordon_dispmode setting */
+ serigo(GORDON_REG_TPARAM1, 0x30);
+ serigo(GORDON_REG_TLCDIF1, 0x00);
+ serigo(GORDON_REG_TSSPB_ST1, 0x8B);
+ serigo(GORDON_REG_TSSPB_ED1, 0x93);
+ serigo(GORDON_REG_TSCK_ST1, 0x88);
+ serigo(GORDON_REG_TSCK_WD1, 0x00);
+ serigo(GORDON_REG_TGSPB_VST1, 0x01);
+ serigo(GORDON_REG_TGSPB_VED1, 0x02);
+ serigo(GORDON_REG_TGSPB_CH1, 0x5E);
+ serigo(GORDON_REG_TGCK_ST1, 0x80);
+ serigo(GORDON_REG_TGCK_ED1, 0x3C);
+ serigo(GORDON_REG_TPCTL_ST1, 0x50);
+ serigo(GORDON_REG_TPCTL_ED1, 0x74);
+ serigo(GORDON_REG_TPCHG_ED1, 0x78);
+ serigo(GORDON_REG_TCOM_CH1, 0x50);
+ serigo(GORDON_REG_THBP1, 0x84);
+ serigo(GORDON_REG_TPHCTL1, 0x00);
+ serigo(GORDON_REG_EVPH1, 0x70);
+ serigo(GORDON_REG_EVPL1, 0x64);
+ serigo(GORDON_REG_EVNH1, 0x56);
+ serigo(GORDON_REG_EVNL1, 0x48);
+ serigo(GORDON_REG_TBIAS1, 0x88);
+
+ /* QVGA settings */
+ serigo(GORDON_REG_TPARAM2, 0x28);
+ serigo(GORDON_REG_TLCDIF2, 0x14);
+ serigo(GORDON_REG_TSSPB_ST2, 0x49);
+ serigo(GORDON_REG_TSSPB_ED2, 0x4B);
+ serigo(GORDON_REG_TSCK_ST2, 0x4A);
+ serigo(GORDON_REG_TSCK_WD2, 0x02);
+ serigo(GORDON_REG_TGSPB_VST2, 0x02);
+ serigo(GORDON_REG_TGSPB_VED2, 0x03);
+ serigo(GORDON_REG_TGSPB_CH2, 0x2F);
+ serigo(GORDON_REG_TGCK_ST2, 0x40);
+ serigo(GORDON_REG_TGCK_ED2, 0x1E);
+ serigo(GORDON_REG_TPCTL_ST2, 0x2C);
+ serigo(GORDON_REG_TPCTL_ED2, 0x3A);
+ serigo(GORDON_REG_TPCHG_ED2, 0x3C);
+ serigo(GORDON_REG_TCOM_CH2, 0x28);
+ serigo(GORDON_REG_THBP2, 0x4D);
+ serigo(GORDON_REG_TPHCTL2, 0x1A);
+
+ /* VGA settings */
+ serigo(GORDON_REG_IVBP1, 0x02);
+ serigo(GORDON_REG_IHBP1, 0x90);
+ serigo(GORDON_REG_IVNUM1, 0xA0);
+ serigo(GORDON_REG_IHNUM1, 0x78);
+
+ /* QVGA settings */
+ serigo(GORDON_REG_IVBP2, 0x02);
+ serigo(GORDON_REG_IHBP2, 0x48);
+ serigo(GORDON_REG_IVNUM2, 0x50);
+ serigo(GORDON_REG_IHNUM2, 0x3C);
+
+ /* Gordon Charge pump settings and ON */
+ serigo(GORDON_REG_POWCTL, 0x03);
+ mdelay(15);
+ serigo(GORDON_REG_POWCTL, 0x07);
+ mdelay(15);
+
+ serigo(GORDON_REG_POWCTL, 0x0F);
+ mdelay(15);
+
+ serigo(GORDON_REG_AVCTL, 0x03);
+ mdelay(15);
+
+ serigo(GORDON_REG_POWCTL, 0x1F);
+ mdelay(15);
+
+ serigo(GORDON_REG_POWCTL, 0x5F);
+ mdelay(15);
+
+ serigo(GORDON_REG_POWCTL, 0x7F);
+ mdelay(15);
+
+ serigo(GORDON_REG_LCDIFCTL1, 0x02);
+ mdelay(15);
+
+ serigo(GORDON_REG_IMGCTL1, 0x00);
+ mdelay(15);
+
+ serigo(GORDON_REG_LCDIFCTL3, 0x00);
+ mdelay(15);
+
+ serigo(GORDON_REG_VALTRAN, 0x01);
+ mdelay(15);
+
+ serigo(GORDON_REG_LCDIFCTL1, 0x03);
+ mdelay(1);
+ gordon_state.display_on = TRUE;
+ }
+}
+
+static int lcdc_gordon_panel_on(struct platform_device *pdev)
+{
+ if (!gordon_state.disp_initialized) {
+ /* Configure reset GPIO that drives DAC */
+ lcdc_gordon_pdata->panel_config_gpio(1);
+ spi_dac = *(lcdc_gordon_pdata->gpio_num + 4);
+ gpio_set_value(spi_dac, 0);
+ udelay(15);
+ gpio_set_value(spi_dac, 1);
+ spi_init(); /* LCD needs SPI */
+ gordon_disp_powerup();
+ gordon_disp_on();
+ gordon_state.disp_initialized = TRUE;
+ }
+ return 0;
+}
+
+static int lcdc_gordon_panel_off(struct platform_device *pdev)
+{
+ if (gordon_state.disp_powered_up && gordon_state.display_on) {
+ serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+ serigo(GORDON_REG_VALTRAN, 0x01);
+ serigo(GORDON_REG_LCDIFCTL1, 0x02);
+ serigo(GORDON_REG_LCDIFCTL3, 0x01);
+ mdelay(20);
+ serigo(GORDON_REG_VALTRAN, 0x01);
+ serigo(GORDON_REG_IMGCTL1, 0x01);
+ serigo(GORDON_REG_LCDIFCTL1, 0x00);
+ mdelay(20);
+
+ serigo(GORDON_REG_POWCTL, 0x1F);
+ mdelay(40);
+
+ serigo(GORDON_REG_POWCTL, 0x07);
+ mdelay(40);
+
+ serigo(GORDON_REG_POWCTL, 0x03);
+ mdelay(40);
+
+ serigo(GORDON_REG_POWCTL, 0x00);
+ mdelay(40);
+ lcdc_gordon_pdata->panel_config_gpio(0);
+ gordon_state.display_on = FALSE;
+ gordon_state.disp_initialized = FALSE;
+ }
+ return 0;
+}
+
+static void lcdc_gordon_set_backlight(struct msm_fb_data_type *mfd)
+{
+ int bl_level = mfd->bl_level;
+
+ if (bl_level <= 1) {
+ /* keep back light OFF */
+ serigo(GORDON_REG_LCDIFCTL2, 0x0B);
+ udelay(15);
+ serigo(GORDON_REG_VALTRAN, 0x01);
+ } else {
+ /* keep back light ON */
+ serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+ udelay(15);
+ serigo(GORDON_REG_VALTRAN, 0x01);
+ }
+}
+
+static int __devinit gordon_probe(struct platform_device *pdev)
+{
+ if (pdev->id == 0) {
+ lcdc_gordon_pdata = pdev->dev.platform_data;
+ return 0;
+ }
+ msm_fb_add_device(pdev);
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = gordon_probe,
+ .driver = {
+ .name = "lcdc_gordon_vga",
+ },
+};
+
+static struct msm_fb_panel_data gordon_panel_data = {
+ .on = lcdc_gordon_panel_on,
+ .off = lcdc_gordon_panel_off,
+ .set_backlight = lcdc_gordon_set_backlight,
+};
+
+static struct platform_device this_device = {
+ .name = "lcdc_gordon_vga",
+ .id = 1,
+ .dev = {
+ .platform_data = &gordon_panel_data,
+ }
+};
+
+static int __init lcdc_gordon_panel_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+ if (msm_fb_detect_client("lcdc_gordon_vga"))
+ return 0;
+#endif
+ ret = platform_driver_register(&this_driver);
+ if (ret)
+ return ret;
+
+ pinfo = &gordon_panel_data.panel_info;
+ pinfo->xres = 480;
+ pinfo->yres = 640;
+ MSM_FB_SINGLE_MODE_PANEL(pinfo);
+ pinfo->type = LCDC_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 24;
+ pinfo->fb_num = 2;
+ pinfo->clk_rate = 24500000;
+ pinfo->bl_max = 4;
+ pinfo->bl_min = 1;
+
+ pinfo->lcdc.h_back_porch = 84;
+ pinfo->lcdc.h_front_porch = 33;
+ pinfo->lcdc.h_pulse_width = 60;
+ pinfo->lcdc.v_back_porch = 0;
+ pinfo->lcdc.v_front_porch = 2;
+ pinfo->lcdc.v_pulse_width = 2;
+ pinfo->lcdc.border_clr = 0; /* blk */
+ pinfo->lcdc.underflow_clr = 0xff; /* blue */
+ pinfo->lcdc.hsync_skew = 0;
+
+ ret = platform_device_register(&this_device);
+ if (ret)
+ platform_driver_unregister(&this_driver);
+
+ return ret;
+}
+
+module_init(lcdc_gordon_panel_init);
diff --git a/drivers/video/msm/lcdc_panel.c b/drivers/video/msm/lcdc_panel.c
new file mode 100644
index 0000000..5705325
--- /dev/null
+++ b/drivers/video/msm/lcdc_panel.c
@@ -0,0 +1,84 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+
+static int lcdc_panel_on(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int lcdc_panel_off(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int __devinit lcdc_panel_probe(struct platform_device *pdev)
+{
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = lcdc_panel_probe,
+ .driver = {
+ .name = "lcdc_panel",
+ },
+};
+
+static struct msm_fb_panel_data lcdc_panel_data = {
+ .on = lcdc_panel_on,
+ .off = lcdc_panel_off,
+};
+
+static int lcdc_dev_id;
+
+int lcdc_device_register(struct msm_panel_info *pinfo)
+{
+ struct platform_device *pdev = NULL;
+ int ret;
+
+ pdev = platform_device_alloc("lcdc_panel", ++lcdc_dev_id);
+ if (!pdev)
+ return -ENOMEM;
+
+ lcdc_panel_data.panel_info = *pinfo;
+ ret = platform_device_add_data(pdev, &lcdc_panel_data,
+ sizeof(lcdc_panel_data));
+ if (ret) {
+ printk(KERN_ERR
+ "%s: platform_device_add_data failed!\n", __func__);
+ goto err_device_put;
+ }
+
+ ret = platform_device_add(pdev);
+ if (ret) {
+ printk(KERN_ERR
+ "%s: platform_device_register failed!\n", __func__);
+ goto err_device_put;
+ }
+
+ return 0;
+
+err_device_put:
+ platform_device_put(pdev);
+ return ret;
+}
+
+static int __init lcdc_panel_init(void)
+{
+ return platform_driver_register(&this_driver);
+}
+
+module_init(lcdc_panel_init);
diff --git a/drivers/video/msm/lcdc_prism.c b/drivers/video/msm/lcdc_prism.c
new file mode 100644
index 0000000..d127f63
--- /dev/null
+++ b/drivers/video/msm/lcdc_prism.c
@@ -0,0 +1,61 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+#include "mddihosti.h"
+#endif
+
+static int __init lcdc_prism_init(void)
+{
+ int ret;
+ struct msm_panel_info pinfo;
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+ ret = msm_fb_detect_client("lcdc_prism_wvga");
+ if (ret == -ENODEV)
+ return 0;
+
+ if (ret && (mddi_get_client_id() != 0))
+ return 0;
+#endif
+
+ pinfo.xres = 800;
+ pinfo.yres = 480;
+ MSM_FB_SINGLE_MODE_PANEL(&pinfo);
+ pinfo.type = LCDC_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 24;
+ pinfo.fb_num = 2;
+ pinfo.clk_rate = 30720000;
+
+ pinfo.lcdc.h_back_porch = 21;
+ pinfo.lcdc.h_front_porch = 81;
+ pinfo.lcdc.h_pulse_width = 60;
+ pinfo.lcdc.v_back_porch = 18;
+ pinfo.lcdc.v_front_porch = 27;
+ pinfo.lcdc.v_pulse_width = 2;
+ pinfo.lcdc.border_clr = 0; /* blk */
+ pinfo.lcdc.underflow_clr = 0xff; /* blue */
+ pinfo.lcdc.hsync_skew = 0;
+
+ ret = lcdc_device_register(&pinfo);
+ if (ret)
+ printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(lcdc_prism_init);
diff --git a/drivers/video/msm/lcdc_samsung_oled_pt.c b/drivers/video/msm/lcdc_samsung_oled_pt.c
new file mode 100644
index 0000000..dccc997
--- /dev/null
+++ b/drivers/video/msm/lcdc_samsung_oled_pt.c
@@ -0,0 +1,590 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/pwm.h>
+#ifdef CONFIG_SPI_QUP
+#include <linux/spi/spi.h>
+#else
+#include <mach/gpio.h>
+#endif
+#include "msm_fb.h"
+
+#define DEBUG
+/* #define SYSFS_DEBUG_CMD */
+
+#ifdef CONFIG_SPI_QUP
+#define LCDC_SAMSUNG_SPI_DEVICE_NAME "lcdc_samsung_ams367pe02"
+static struct spi_device *lcdc_spi_client;
+#else
+static int spi_cs;
+static int spi_sclk;
+static int spi_mosi;
+#endif
+
+struct samsung_state_type {
+ boolean disp_initialized;
+ boolean display_on;
+ boolean disp_powered_up;
+ int brightness;
+};
+
+struct samsung_spi_data {
+ u8 addr;
+ u8 len;
+ u8 data[22];
+};
+
+static struct samsung_spi_data panel_sequence[] = {
+ { .addr = 0xf8, .len = 14, .data = { 0x01, 0x27, 0x27, 0x07, 0x07,
+ 0x54, 0x9f, 0x63, 0x86, 0x1a, 0x33, 0x0d, 0x00, 0x00 } },
+};
+static struct samsung_spi_data display_sequence[] = {
+ { .addr = 0xf2, .len = 5, .data = { 0x02, 0x03, 0x1c, 0x10, 0x10 } },
+ { .addr = 0xf7, .len = 3, .data = { 0x00, 0x00, 0x30 } },
+};
+
+/* lum=300 cd/m2 */
+static struct samsung_spi_data gamma_sequence_300[] = {
+ { .addr = 0xfa, .len = 22, .data = { 0x02, 0x18, 0x08, 0x24, 0x7d, 0x77,
+ 0x5b, 0xbe, 0xc1, 0xb1, 0xb3, 0xb7, 0xa6, 0xc3, 0xc5, 0xb9, 0x00, 0xb3,
+ 0x00, 0xaf, 0x00, 0xe8 } },
+ { .addr = 0xFA, .len = 1, .data = { 0x03 } },
+};
+/* lum = 180 cd/m2*/
+static struct samsung_spi_data gamma_sequence_180[] = {
+ { .addr = 0xfa, .len = 22, .data = { 0x02, 0x18, 0x08, 0x24, 0x83, 0x78,
+ 0x60, 0xc5, 0xc6, 0xb8, 0xba, 0xbe, 0xad, 0xcb, 0xcd, 0xc2, 0x00, 0x92,
+ 0x00, 0x8e, 0x00, 0xbc } },
+ { .addr = 0xFA, .len = 1, .data = { 0x03 } },
+};
+/* lum = 80 cd/m2*/
+static struct samsung_spi_data gamma_sequence_80[] = {
+ { .addr = 0xfa, .len = 22, .data = { 0x02, 0x18, 0x08, 0x24, 0x94, 0x73,
+ 0x6c, 0xcb, 0xca, 0xbe, 0xc4, 0xc7, 0xb8, 0xd3, 0xd5, 0xcb, 0x00, 0x6d,
+ 0x00, 0x69, 0x00, 0x8b } },
+ { .addr = 0xFA, .len = 1, .data = { 0x03 } },
+};
+
+static struct samsung_spi_data etc_sequence[] = {
+ { .addr = 0xF6, .len = 3, .data = { 0x00, 0x8e, 0x07 } },
+ { .addr = 0xB3, .len = 1, .data = { 0x0C } },
+};
+
+static struct samsung_state_type samsung_state = { .brightness = 180 };
+static struct msm_panel_common_pdata *lcdc_samsung_pdata;
+
+#ifndef CONFIG_SPI_QUP
+static void samsung_spi_write_byte(boolean dc, u8 data)
+{
+ uint32 bit;
+ int bnum;
+
+ gpio_set_value(spi_sclk, 0);
+ gpio_set_value(spi_mosi, dc ? 1 : 0);
+ udelay(1); /* at least 20 ns */
+ gpio_set_value(spi_sclk, 1); /* clk high */
+ udelay(1); /* at least 20 ns */
+
+ bnum = 8; /* 8 data bits */
+ bit = 0x80;
+ while (bnum--) {
+ gpio_set_value(spi_sclk, 0); /* clk low */
+ gpio_set_value(spi_mosi, (data & bit) ? 1 : 0);
+ udelay(1);
+ gpio_set_value(spi_sclk, 1); /* clk high */
+ udelay(1);
+ bit >>= 1;
+ }
+ gpio_set_value(spi_mosi, 0);
+
+}
+
+static void samsung_spi_read_bytes(u8 cmd, u8 *data, int num)
+{
+ int bnum;
+
+ /* Chip Select - low */
+ gpio_set_value(spi_cs, 0);
+ udelay(2);
+
+ /* command byte first */
+ samsung_spi_write_byte(0, cmd);
+ udelay(2);
+
+ gpio_direction_input(spi_mosi);
+
+ if (num > 1) {
+ /* extra dummy clock */
+ gpio_set_value(spi_sclk, 0);
+ udelay(1);
+ gpio_set_value(spi_sclk, 1);
+ udelay(1);
+ }
+
+ /* followed by data bytes */
+ bnum = num * 8; /* number of bits */
+ *data = 0;
+ while (bnum) {
+ gpio_set_value(spi_sclk, 0); /* clk low */
+ udelay(1);
+ *data <<= 1;
+ *data |= gpio_get_value(spi_mosi) ? 1 : 0;
+ gpio_set_value(spi_sclk, 1); /* clk high */
+ udelay(1);
+ --bnum;
+ if ((bnum % 8) == 0)
+ ++data;
+ }
+
+ gpio_direction_output(spi_mosi, 0);
+
+ /* Chip Select - high */
+ udelay(2);
+ gpio_set_value(spi_cs, 1);
+}
+#endif
+
+#ifdef DEBUG
+static const char *byte_to_binary(const u8 *buf, int len)
+{
+ static char b[32*8+1];
+ char *p = b;
+ int i, z;
+
+ for (i = 0; i < len; ++i) {
+ u8 val = *buf++;
+ for (z = 1 << 7; z > 0; z >>= 1)
+ *p++ = (val & z) ? '1' : '0';
+ }
+ *p = 0;
+
+ return b;
+}
+#endif
+
+#define BIT_OFFSET (bit_size % 8)
+#define ADD_BIT(val) do { \
+ tx_buf[bit_size / 8] |= \
+ (u8)((val ? 1 : 0) << (7 - BIT_OFFSET)); \
+ ++bit_size; \
+ } while (0)
+
+#define ADD_BYTE(data) do { \
+ tx_buf[bit_size / 8] |= (u8)(data >> BIT_OFFSET); \
+ bit_size += 8; \
+ if (BIT_OFFSET != 0) \
+ tx_buf[bit_size / 8] |= (u8)(data << (8 - BIT_OFFSET));\
+ } while (0)
+
+static int samsung_serigo(struct samsung_spi_data data)
+{
+#ifdef CONFIG_SPI_QUP
+ char tx_buf[32];
+ int bit_size = 0, i, rc;
+ struct spi_message m;
+ struct spi_transfer t;
+
+ if (!lcdc_spi_client) {
+ pr_err("%s lcdc_spi_client is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ memset(&t, 0, sizeof t);
+ memset(tx_buf, 0, sizeof tx_buf);
+ t.tx_buf = tx_buf;
+ spi_setup(lcdc_spi_client);
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+
+ ADD_BIT(FALSE);
+ ADD_BYTE(data.addr);
+ for (i = 0; i < data.len; ++i) {
+ ADD_BIT(TRUE);
+ ADD_BYTE(data.data[i]);
+ }
+
+ /* add padding bits so we round to next byte */
+ t.len = (bit_size+7) / 8;
+ if (t.len <= 4)
+ t.bits_per_word = bit_size;
+
+ rc = spi_sync(lcdc_spi_client, &m);
+#ifdef DEBUG
+ pr_info("%s: addr=0x%02x, #args=%d[%d] [%s], rc=%d\n",
+ __func__, data.addr, t.len, t.bits_per_word,
+ byte_to_binary(tx_buf, t.len), rc);
+#endif
+ return rc;
+#else
+ int i;
+
+ /* Chip Select - low */
+ gpio_set_value(spi_cs, 0);
+ udelay(2);
+
+ samsung_spi_write_byte(FALSE, data.addr);
+ udelay(2);
+
+ for (i = 0; i < data.len; ++i) {
+ samsung_spi_write_byte(TRUE, data.data[i]);
+ udelay(2);
+ }
+
+ /* Chip Select - high */
+ gpio_set_value(spi_cs, 1);
+#ifdef DEBUG
+ pr_info("%s: cmd=0x%02x, #args=%d\n", __func__, data.addr, data.len);
+#endif
+ return 0;
+#endif
+}
+
+static int samsung_write_cmd(u8 cmd)
+{
+#ifdef CONFIG_SPI_QUP
+ char tx_buf[2];
+ int bit_size = 0, rc;
+ struct spi_message m;
+ struct spi_transfer t;
+
+ if (!lcdc_spi_client) {
+ pr_err("%s lcdc_spi_client is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ memset(&t, 0, sizeof t);
+ memset(tx_buf, 0, sizeof tx_buf);
+ t.tx_buf = tx_buf;
+ spi_setup(lcdc_spi_client);
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+
+ ADD_BIT(FALSE);
+ ADD_BYTE(cmd);
+
+ t.len = 2;
+ t.bits_per_word = 9;
+
+ rc = spi_sync(lcdc_spi_client, &m);
+#ifdef DEBUG
+ pr_info("%s: addr=0x%02x, #args=%d[%d] [%s], rc=%d\n",
+ __func__, cmd, t.len, t.bits_per_word,
+ byte_to_binary(tx_buf, t.len), rc);
+#endif
+ return rc;
+#else
+ /* Chip Select - low */
+ gpio_set_value(spi_cs, 0);
+ udelay(2);
+
+ samsung_spi_write_byte(FALSE, cmd);
+
+ /* Chip Select - high */
+ udelay(2);
+ gpio_set_value(spi_cs, 1);
+#ifdef DEBUG
+ pr_info("%s: cmd=0x%02x\n", __func__, cmd);
+#endif
+ return 0;
+#endif
+}
+
+static int samsung_serigo_list(struct samsung_spi_data *data, int count)
+{
+ int i, rc;
+ for (i = 0; i < count; ++i, ++data) {
+ rc = samsung_serigo(*data);
+ if (rc)
+ return rc;
+ msleep(10);
+ }
+ return 0;
+}
+
+#ifndef CONFIG_SPI_QUP
+static void samsung_spi_init(void)
+{
+ spi_sclk = *(lcdc_samsung_pdata->gpio_num);
+ spi_cs = *(lcdc_samsung_pdata->gpio_num + 1);
+ spi_mosi = *(lcdc_samsung_pdata->gpio_num + 2);
+
+ /* Set the output so that we don't disturb the slave device */
+ gpio_set_value(spi_sclk, 1);
+ gpio_set_value(spi_mosi, 0);
+
+ /* Set the Chip Select deasserted (active low) */
+ gpio_set_value(spi_cs, 1);
+}
+#endif
+
+static void samsung_disp_powerup(void)
+{
+ if (!samsung_state.disp_powered_up && !samsung_state.display_on)
+ samsung_state.disp_powered_up = TRUE;
+}
+
+static struct work_struct disp_on_delayed_work;
+static void samsung_disp_on_delayed_work(struct work_struct *work_ptr)
+{
+ /* 0x01: Software Reset */
+ samsung_write_cmd(0x01);
+ msleep(120);
+
+ msleep(300);
+ samsung_serigo_list(panel_sequence,
+ sizeof(panel_sequence)/sizeof(*panel_sequence));
+ samsung_serigo_list(display_sequence,
+ sizeof(display_sequence)/sizeof(*display_sequence));
+
+ switch (samsung_state.brightness) {
+ case 300:
+ samsung_serigo_list(gamma_sequence_300,
+ sizeof(gamma_sequence_300)/sizeof(*gamma_sequence_300));
+ break;
+ case 180:
+ default:
+ samsung_serigo_list(gamma_sequence_180,
+ sizeof(gamma_sequence_180)/sizeof(*gamma_sequence_180));
+ break;
+ case 80:
+ samsung_serigo_list(gamma_sequence_80,
+ sizeof(gamma_sequence_80)/sizeof(*gamma_sequence_80));
+ break;
+ }
+
+ samsung_serigo_list(etc_sequence,
+ sizeof(etc_sequence)/sizeof(*etc_sequence));
+
+ /* 0x11: Sleep Out */
+ samsung_write_cmd(0x11);
+ msleep(120);
+ /* 0x13: Normal Mode On */
+ samsung_write_cmd(0x13);
+
+#ifndef CONFIG_SPI_QUP
+ {
+ u8 data;
+
+ msleep(120);
+ /* 0x0A: Read Display Power Mode */
+ samsung_spi_read_bytes(0x0A, &data, 1);
+ pr_info("%s: power=[%s]\n", __func__,
+ byte_to_binary(&data, 1));
+
+ msleep(120);
+ /* 0x0C: Read Display Pixel Format */
+ samsung_spi_read_bytes(0x0C, &data, 1);
+ pr_info("%s: pixel-format=[%s]\n", __func__,
+ byte_to_binary(&data, 1));
+ }
+#endif
+ msleep(120);
+ /* 0x29: Display On */
+ samsung_write_cmd(0x29);
+}
+
+static void samsung_disp_on(void)
+{
+ if (samsung_state.disp_powered_up && !samsung_state.display_on) {
+ INIT_WORK(&disp_on_delayed_work, samsung_disp_on_delayed_work);
+ schedule_work(&disp_on_delayed_work);
+
+ samsung_state.display_on = TRUE;
+ }
+}
+
+static int lcdc_samsung_panel_on(struct platform_device *pdev)
+{
+ pr_info("%s\n", __func__);
+ if (!samsung_state.disp_initialized) {
+#ifndef CONFIG_SPI_QUP
+ lcdc_samsung_pdata->panel_config_gpio(1);
+ samsung_spi_init();
+#endif
+ samsung_disp_powerup();
+ samsung_disp_on();
+ samsung_state.disp_initialized = TRUE;
+ }
+ return 0;
+}
+
+static int lcdc_samsung_panel_off(struct platform_device *pdev)
+{
+ pr_info("%s\n", __func__);
+ if (samsung_state.disp_powered_up && samsung_state.display_on) {
+ /* 0x10: Sleep In */
+ samsung_write_cmd(0x10);
+ msleep(120);
+
+ samsung_state.display_on = FALSE;
+ samsung_state.disp_initialized = FALSE;
+ }
+ return 0;
+}
+
+#ifdef SYSFS_DEBUG_CMD
+static ssize_t samsung_rda_cmd(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = snprintf(buf, PAGE_SIZE, "n/a\n");
+ pr_info("%s: 'n/a'\n", __func__);
+ return ret;
+}
+
+static ssize_t samsung_wta_cmd(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ ssize_t ret = strnlen(buf, PAGE_SIZE);
+ uint32 cmd;
+
+ sscanf(buf, "%x", &cmd);
+ samsung_write_cmd((u8)cmd);
+
+ return ret;
+}
+
+static DEVICE_ATTR(cmd, S_IRUGO | S_IWUGO, samsung_rda_cmd, samsung_wta_cmd);
+static struct attribute *fs_attrs[] = {
+ &dev_attr_cmd.attr,
+ NULL,
+};
+static struct attribute_group fs_attr_group = {
+ .attrs = fs_attrs,
+};
+#endif
+
+static struct msm_fb_panel_data samsung_panel_data = {
+ .on = lcdc_samsung_panel_on,
+ .off = lcdc_samsung_panel_off,
+};
+
+static int __devinit samsung_probe(struct platform_device *pdev)
+{
+ struct msm_panel_info *pinfo;
+#ifdef SYSFS_DEBUG_CMD
+ struct platform_device *fb_dev;
+ struct msm_fb_data_type *mfd;
+ int rc;
+#endif
+
+ pr_info("%s: id=%d\n", __func__, pdev->id);
+ lcdc_samsung_pdata = pdev->dev.platform_data;
+
+ pinfo = &samsung_panel_data.panel_info;
+ pinfo->xres = 480;
+ pinfo->yres = 800;
+ pinfo->type = LCDC_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 24;
+ pinfo->fb_num = 2;
+ pinfo->clk_rate = 25600000; /* Max 27.77MHz */
+ pinfo->bl_max = 15;
+ pinfo->bl_min = 1;
+
+ /* AMS367PE02 Operation Manual, Page 7 */
+ pinfo->lcdc.h_back_porch = 16-2; /* HBP-HLW */
+ pinfo->lcdc.h_front_porch = 16;
+ pinfo->lcdc.h_pulse_width = 2;
+ /* AMS367PE02 Operation Manual, Page 6 */
+ pinfo->lcdc.v_back_porch = 3-2; /* VBP-VLW */
+ pinfo->lcdc.v_front_porch = 28;
+ pinfo->lcdc.v_pulse_width = 2;
+
+ pinfo->lcdc.border_clr = 0;
+ pinfo->lcdc.underflow_clr = 0xff;
+ pinfo->lcdc.hsync_skew = 0;
+ pdev->dev.platform_data = &samsung_panel_data;
+
+#ifndef SYSFS_DEBUG_CMD
+ msm_fb_add_device(pdev);
+#else
+ fb_dev = msm_fb_add_device(pdev);
+ mfd = platform_get_drvdata(fb_dev);
+ rc = sysfs_create_group(&mfd->fbi->dev->kobj, &fs_attr_group);
+ if (rc) {
+ pr_err("%s: sysfs group creation failed, rc=%d\n", __func__,
+ rc);
+ return rc;
+ }
+#endif
+ return 0;
+}
+
+#ifdef CONFIG_SPI_QUP
+static int __devinit lcdc_samsung_spi_probe(struct spi_device *spi)
+{
+ pr_info("%s\n", __func__);
+ lcdc_spi_client = spi;
+ lcdc_spi_client->bits_per_word = 32;
+ return 0;
+}
+static int __devexit lcdc_samsung_spi_remove(struct spi_device *spi)
+{
+ lcdc_spi_client = NULL;
+ return 0;
+}
+static struct spi_driver lcdc_samsung_spi_driver = {
+ .driver.name = LCDC_SAMSUNG_SPI_DEVICE_NAME,
+ .driver.owner = THIS_MODULE,
+ .probe = lcdc_samsung_spi_probe,
+ .remove = __devexit_p(lcdc_samsung_spi_remove),
+};
+#endif
+
+static struct platform_driver this_driver = {
+ .probe = samsung_probe,
+ .driver.name = "lcdc_samsung_oled",
+};
+
+static int __init lcdc_samsung_panel_init(void)
+{
+ int ret;
+
+#ifdef CONFIG_FB_MSM_LCDC_AUTO_DETECT
+ if (msm_fb_detect_client("lcdc_samsung_oled")) {
+ pr_err("%s: detect failed\n", __func__);
+ return 0;
+ }
+#endif
+
+ ret = platform_driver_register(&this_driver);
+ if (ret) {
+ pr_err("%s: driver register failed, rc=%d\n", __func__, ret);
+ return ret;
+ }
+
+#ifdef CONFIG_SPI_QUP
+ ret = spi_register_driver(&lcdc_samsung_spi_driver);
+
+ if (ret) {
+ pr_err("%s: spi register failed: rc=%d\n", __func__, ret);
+ platform_driver_unregister(&this_driver);
+ } else
+ pr_info("%s: SUCCESS (SPI)\n", __func__);
+#else
+ pr_info("%s: SUCCESS (BitBang)\n", __func__);
+#endif
+ return ret;
+}
+
+module_init(lcdc_samsung_panel_init);
+static void __exit lcdc_samsung_panel_exit(void)
+{
+ pr_info("%s\n", __func__);
+#ifdef CONFIG_SPI_QUP
+ spi_unregister_driver(&lcdc_samsung_spi_driver);
+#endif
+ platform_driver_unregister(&this_driver);
+}
+module_exit(lcdc_samsung_panel_exit);
diff --git a/drivers/video/msm/lcdc_samsung_wsvga.c b/drivers/video/msm/lcdc_samsung_wsvga.c
new file mode 100644
index 0000000..b4bf8cf
--- /dev/null
+++ b/drivers/video/msm/lcdc_samsung_wsvga.c
@@ -0,0 +1,272 @@
+/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/pwm.h>
+#ifdef CONFIG_PMIC8058_PWM
+#include <linux/mfd/pmic8058.h>
+#include <linux/pmic8058-pwm.h>
+#endif
+#include <mach/gpio.h>
+#include "msm_fb.h"
+
+
+
+#ifdef CONFIG_PMIC8058_PWM
+static struct pwm_device *bl_pwm0;
+static struct pwm_device *bl_pwm1;
+
+/* for samsung panel 300hz was the minimum freq where flickering wasnt
+ * observed as the screen was dimmed
+ */
+
+#define PWM_FREQ_HZ 300
+#define PWM_PERIOD_USEC (USEC_PER_SEC / PWM_FREQ_HZ)
+#define PWM_LEVEL 100
+#define PWM_DUTY_LEVEL (PWM_PERIOD_USEC / PWM_LEVEL)
+#endif
+
+struct lcdc_samsung_data {
+ struct msm_panel_common_pdata *pdata;
+#ifdef CONFIG_FB_MSM_LCDC_DSUB
+ int vga_enabled;
+#endif
+ struct platform_device *fbpdev;
+};
+
+static struct lcdc_samsung_data *dd;
+
+
+static void lcdc_samsung_panel_set_backlight(struct msm_fb_data_type *mfd)
+{
+ int bl_level;
+ int ret;
+
+ bl_level = mfd->bl_level;
+
+#ifdef CONFIG_PMIC8058_PWM
+ if (bl_pwm0) {
+ ret = pwm_config(bl_pwm0, PWM_DUTY_LEVEL * bl_level,
+ PWM_PERIOD_USEC);
+ if (ret)
+ printk(KERN_ERR "pwm_config on pwm 0 failed %d\n", ret);
+ }
+
+ if (bl_pwm1) {
+ ret = pwm_config(bl_pwm1,
+ PWM_PERIOD_USEC - (PWM_DUTY_LEVEL * bl_level),
+ PWM_PERIOD_USEC);
+ if (ret)
+ printk(KERN_ERR "pwm_config on pwm 1 failed %d\n", ret);
+ }
+
+ if (bl_pwm0) {
+ ret = pwm_enable(bl_pwm0);
+ if (ret)
+ printk(KERN_ERR "pwm_enable on pwm 0 failed %d\n", ret);
+ }
+
+ if (bl_pwm1) {
+ ret = pwm_enable(bl_pwm1);
+ if (ret)
+ printk(KERN_ERR "pwm_enable on pwm 1 failed %d\n", ret);
+ }
+#endif
+
+}
+
+#ifdef CONFIG_FB_MSM_LCDC_DSUB
+static ssize_t show_vga_enable(struct device *device,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", dd->vga_enabled);
+}
+
+static ssize_t store_vga_enable(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long enable;
+ int rc;
+
+ rc = strict_strtoul(buf, 10, &enable);
+ if (rc)
+ return -EINVAL;
+
+ if (dd->pdata && dd->pdata->vga_switch)
+ rc = dd->pdata->vga_switch(enable);
+ else
+ rc = -ENODEV;
+ if (!rc) {
+ dd->vga_enabled = enable;
+ rc = count;
+ }
+ return rc;
+}
+
+static DEVICE_ATTR(vga_enable, S_IRUGO|S_IWUSR, show_vga_enable,
+ store_vga_enable);
+static struct attribute *attrs[] = {
+ &dev_attr_vga_enable.attr,
+ NULL,
+};
+static struct attribute_group attr_group = {
+ .attrs = attrs,
+};
+#endif
+
+static int __devinit samsung_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+#ifdef CONFIG_FB_MSM_LCDC_DSUB
+ struct msm_fb_data_type *mfd;
+#endif
+
+ if (pdev->id == 0) {
+ dd = kzalloc(sizeof *dd, GFP_KERNEL);
+ if (!dd)
+ return -ENOMEM;
+#ifdef CONFIG_FB_MSM_LCDC_DSUB
+ dd->vga_enabled = 0;
+#endif
+ dd->pdata = pdev->dev.platform_data;
+ return 0;
+ } else if (!dd)
+ return -ENODEV;
+
+#ifdef CONFIG_PMIC8058_PWM
+ bl_pwm0 = pwm_request(dd->pdata->gpio_num[0], "backlight1");
+ if (bl_pwm0 == NULL || IS_ERR(bl_pwm0)) {
+ pr_err("%s pwm_request() failed\n", __func__);
+ bl_pwm0 = NULL;
+ }
+
+ bl_pwm1 = pwm_request(dd->pdata->gpio_num[1], "backlight2");
+ if (bl_pwm1 == NULL || IS_ERR(bl_pwm1)) {
+ pr_err("%s pwm_request() failed\n", __func__);
+ bl_pwm1 = NULL;
+ }
+
+ pr_debug("samsung_probe: bl_pwm0=%p LPG_chan0=%d "
+ "bl_pwm1=%p LPG_chan1=%d\n",
+ bl_pwm0, (int)dd->pdata->gpio_num[0],
+ bl_pwm1, (int)dd->pdata->gpio_num[1]
+ );
+#endif
+
+
+ dd->fbpdev = msm_fb_add_device(pdev);
+ if (!dd->fbpdev) {
+ dev_err(&pdev->dev, "failed to add msm_fb device\n");
+ rc = -ENODEV;
+ goto probe_exit;
+ }
+
+#ifdef CONFIG_FB_MSM_LCDC_DSUB
+ mfd = platform_get_drvdata(dd->fbpdev);
+ if (mfd && mfd->fbi && mfd->fbi->dev) {
+ rc = sysfs_create_group(&mfd->fbi->dev->kobj, &attr_group);
+ if (rc)
+ dev_err(&pdev->dev, "failed to create sysfs group\n");
+ } else {
+ dev_err(&pdev->dev, "no dev to create sysfs group\n");
+ rc = -ENODEV;
+ }
+#endif
+
+probe_exit:
+ return rc;
+}
+
+#ifdef CONFIG_FB_MSM_LCDC_DSUB
+static int __devexit samsung_remove(struct platform_device *pdev)
+{
+ sysfs_remove_group(&dd->fbpdev->dev.kobj, &attr_group);
+ return 0;
+}
+#endif
+
+static struct platform_driver this_driver = {
+ .probe = samsung_probe,
+#ifdef CONFIG_FB_MSM_LCDC_DSUB
+ .remove = samsung_remove,
+#endif
+ .driver = {
+ .name = "lcdc_samsung_wsvga",
+ },
+};
+
+static struct msm_fb_panel_data samsung_panel_data = {
+ .set_backlight = lcdc_samsung_panel_set_backlight,
+};
+
+static struct platform_device this_device = {
+ .name = "lcdc_samsung_wsvga",
+ .id = 1,
+ .dev = {
+ .platform_data = &samsung_panel_data,
+ }
+};
+
+static int __init lcdc_samsung_panel_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_LCDC_AUTO_DETECT
+ if (msm_fb_detect_client("lcdc_samsung_wsvga"))
+ return 0;
+#endif
+
+ ret = platform_driver_register(&this_driver);
+ if (ret)
+ return ret;
+
+ pinfo = &samsung_panel_data.panel_info;
+ pinfo->xres = 1024;
+ pinfo->yres = 600;
+#ifdef CONFIG_FB_MSM_LCDC_DSUB
+ /* DSUB (VGA) is on the same bus, this allows us to allocate for the
+ * max resolution of the DSUB display */
+ pinfo->mode2_xres = 1440;
+ pinfo->mode2_yres = 900;
+ pinfo->mode2_bpp = 16;
+#else
+ MSM_FB_SINGLE_MODE_PANEL(pinfo);
+#endif
+ pinfo->type = LCDC_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 18;
+ pinfo->fb_num = 2;
+ pinfo->clk_rate = 43192000;
+ pinfo->bl_max = PWM_LEVEL;
+ pinfo->bl_min = 1;
+
+ pinfo->lcdc.h_back_porch = 80;
+ pinfo->lcdc.h_front_porch = 48;
+ pinfo->lcdc.h_pulse_width = 32;
+ pinfo->lcdc.v_back_porch = 4;
+ pinfo->lcdc.v_front_porch = 3;
+ pinfo->lcdc.v_pulse_width = 1;
+ pinfo->lcdc.border_clr = 0;
+ pinfo->lcdc.underflow_clr = 0xff;
+ pinfo->lcdc.hsync_skew = 0;
+
+ ret = platform_device_register(&this_device);
+ if (ret)
+ platform_driver_unregister(&this_driver);
+
+ return ret;
+}
+
+module_init(lcdc_samsung_panel_init);
diff --git a/drivers/video/msm/lcdc_sharp_wvga_pt.c b/drivers/video/msm/lcdc_sharp_wvga_pt.c
new file mode 100644
index 0000000..2ba2618
--- /dev/null
+++ b/drivers/video/msm/lcdc_sharp_wvga_pt.c
@@ -0,0 +1,414 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/pwm.h>
+#ifdef CONFIG_PMIC8058_PWM
+#include <linux/mfd/pmic8058.h>
+#include <linux/pmic8058-pwm.h>
+#endif
+#ifdef CONFIG_SPI_QSD
+#include <linux/spi/spi.h>
+#endif
+#include <mach/gpio.h>
+#include "msm_fb.h"
+
+#ifdef CONFIG_SPI_QSD
+#define LCDC_SHARP_SPI_DEVICE_NAME "lcdc_sharp_ls038y7dx01"
+static struct spi_device *lcdc_spi_client;
+#endif
+static int lcdc_sharp_panel_off(struct platform_device *pdev);
+
+#define BL_MAX 16
+
+#ifdef CONFIG_PMIC8058_PWM
+static struct pwm_device *bl_pwm;
+
+#define PWM_PERIOD 1000 /* us, period of 1Khz */
+#define DUTY_LEVEL (PWM_PERIOD / BL_MAX)
+#endif
+
+#ifndef CONFIG_SPI_QSD
+static int spi_cs;
+static int spi_sclk;
+static int spi_mosi;
+static int spi_miso;
+static unsigned char bit_shift[8] = { (1 << 7), /* MSB */
+ (1 << 6),
+ (1 << 5),
+ (1 << 4),
+ (1 << 3),
+ (1 << 2),
+ (1 << 1),
+ (1 << 0) /* LSB */
+};
+#endif
+
+struct sharp_state_type {
+ boolean disp_initialized;
+ boolean display_on;
+ boolean disp_powered_up;
+};
+
+struct sharp_spi_data {
+ u8 addr;
+ u8 data;
+};
+
+static struct sharp_spi_data init_sequence[] = {
+ { 15, 0x01 },
+ { 5, 0x01 },
+ { 7, 0x10 },
+ { 9, 0x1E },
+ { 10, 0x04 },
+ { 17, 0xFF },
+ { 21, 0x8A },
+ { 22, 0x00 },
+ { 23, 0x82 },
+ { 24, 0x24 },
+ { 25, 0x22 },
+ { 26, 0x6D },
+ { 27, 0xEB },
+ { 28, 0xB9 },
+ { 29, 0x3A },
+ { 49, 0x1A },
+ { 50, 0x16 },
+ { 51, 0x05 },
+ { 55, 0x7F },
+ { 56, 0x15 },
+ { 57, 0x7B },
+ { 60, 0x05 },
+ { 61, 0x0C },
+ { 62, 0x80 },
+ { 63, 0x00 },
+ { 92, 0x90 },
+ { 97, 0x01 },
+ { 98, 0xFF },
+ { 113, 0x11 },
+ { 114, 0x02 },
+ { 115, 0x08 },
+ { 123, 0xAB },
+ { 124, 0x04 },
+ { 6, 0x02 },
+ { 133, 0x00 },
+ { 134, 0xFE },
+ { 135, 0x22 },
+ { 136, 0x0B },
+ { 137, 0xFF },
+ { 138, 0x0F },
+ { 139, 0x00 },
+ { 140, 0xFE },
+ { 141, 0x22 },
+ { 142, 0x0B },
+ { 143, 0xFF },
+ { 144, 0x0F },
+ { 145, 0x00 },
+ { 146, 0xFE },
+ { 147, 0x22 },
+ { 148, 0x0B },
+ { 149, 0xFF },
+ { 150, 0x0F },
+ { 202, 0x30 },
+ { 30, 0x01 },
+ { 4, 0x01 },
+ { 31, 0x41 },
+};
+
+static struct sharp_state_type sharp_state = { 0 };
+static struct msm_panel_common_pdata *lcdc_sharp_pdata;
+
+#ifndef CONFIG_SPI_QSD
+static void sharp_spi_write_byte(u8 val)
+{
+ int i;
+
+ /* Clock should be Low before entering */
+ for (i = 0; i < 8; i++) {
+ /* #1: Drive the Data (High or Low) */
+ if (val & bit_shift[i])
+ gpio_set_value(spi_mosi, 1);
+ else
+ gpio_set_value(spi_mosi, 0);
+
+ /* #2: Drive the Clk High and then Low */
+ gpio_set_value(spi_sclk, 1);
+ gpio_set_value(spi_sclk, 0);
+ }
+}
+#endif
+
+static int serigo(u8 reg, u8 data)
+{
+#ifdef CONFIG_SPI_QSD
+ char tx_buf[2];
+ int rc;
+ struct spi_message m;
+ struct spi_transfer t;
+
+ if (!lcdc_spi_client) {
+ printk(KERN_ERR "%s lcdc_spi_client is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ memset(&t, 0, sizeof t);
+ t.tx_buf = tx_buf;
+ spi_setup(lcdc_spi_client);
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+
+ tx_buf[0] = reg;
+ tx_buf[1] = data;
+ t.rx_buf = NULL;
+ t.len = 2;
+ rc = spi_sync(lcdc_spi_client, &m);
+ return rc;
+#else
+ /* Enable the Chip Select - low */
+ gpio_set_value(spi_cs, 0);
+ udelay(1);
+
+ /* Transmit register address first, then data */
+ sharp_spi_write_byte(reg);
+
+ /* Idle state of MOSI is Low */
+ gpio_set_value(spi_mosi, 0);
+ udelay(1);
+ sharp_spi_write_byte(data);
+
+ gpio_set_value(spi_mosi, 0);
+ gpio_set_value(spi_cs, 1);
+ return 0;
+#endif
+}
+
+#ifndef CONFIG_SPI_QSD
+static void sharp_spi_init(void)
+{
+ spi_sclk = *(lcdc_sharp_pdata->gpio_num);
+ spi_cs = *(lcdc_sharp_pdata->gpio_num + 1);
+ spi_mosi = *(lcdc_sharp_pdata->gpio_num + 2);
+ spi_miso = *(lcdc_sharp_pdata->gpio_num + 3);
+
+ /* Set the output so that we don't disturb the slave device */
+ gpio_set_value(spi_sclk, 0);
+ gpio_set_value(spi_mosi, 0);
+
+ /* Set the Chip Select deasserted (active low) */
+ gpio_set_value(spi_cs, 1);
+}
+#endif
+
+static void sharp_disp_powerup(void)
+{
+ if (!sharp_state.disp_powered_up && !sharp_state.display_on)
+ sharp_state.disp_powered_up = TRUE;
+}
+
+static void sharp_disp_on(void)
+{
+ int i;
+
+ if (sharp_state.disp_powered_up && !sharp_state.display_on) {
+ for (i = 0; i < ARRAY_SIZE(init_sequence); i++) {
+ serigo(init_sequence[i].addr,
+ init_sequence[i].data);
+ }
+ mdelay(10);
+ serigo(31, 0xC1);
+ mdelay(10);
+ serigo(31, 0xD9);
+ serigo(31, 0xDF);
+
+ sharp_state.display_on = TRUE;
+ }
+}
+
+static int lcdc_sharp_panel_on(struct platform_device *pdev)
+{
+ if (!sharp_state.disp_initialized) {
+#ifndef CONFIG_SPI_QSD
+ lcdc_sharp_pdata->panel_config_gpio(1);
+ sharp_spi_init();
+#endif
+ sharp_disp_powerup();
+ sharp_disp_on();
+ sharp_state.disp_initialized = TRUE;
+ }
+ return 0;
+}
+
+static int lcdc_sharp_panel_off(struct platform_device *pdev)
+{
+ if (sharp_state.disp_powered_up && sharp_state.display_on) {
+ serigo(4, 0x00);
+ mdelay(40);
+ serigo(31, 0xC1);
+ mdelay(40);
+ serigo(31, 0x00);
+ msleep(16);
+ sharp_state.display_on = FALSE;
+ sharp_state.disp_initialized = FALSE;
+ }
+ return 0;
+}
+
+static void lcdc_sharp_panel_set_backlight(struct msm_fb_data_type *mfd)
+{
+ int bl_level;
+
+ bl_level = mfd->bl_level;
+
+#ifdef CONFIG_PMIC8058_PWM
+ if (bl_pwm) {
+ pwm_config(bl_pwm, DUTY_LEVEL * bl_level, PWM_PERIOD);
+ pwm_enable(bl_pwm);
+ }
+#endif
+}
+
+static int __devinit sharp_probe(struct platform_device *pdev)
+{
+ if (pdev->id == 0) {
+ lcdc_sharp_pdata = pdev->dev.platform_data;
+ return 0;
+ }
+
+#ifdef CONFIG_PMIC8058_PWM
+ bl_pwm = pwm_request(lcdc_sharp_pdata->gpio, "backlight");
+ if (bl_pwm == NULL || IS_ERR(bl_pwm)) {
+ pr_err("%s pwm_request() failed\n", __func__);
+ bl_pwm = NULL;
+ }
+
+ printk(KERN_INFO "sharp_probe: bl_pwm=%x LPG_chan=%d\n",
+ (int) bl_pwm, (int)lcdc_sharp_pdata->gpio);
+#endif
+
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+#ifdef CONFIG_SPI_QSD
+static int __devinit lcdc_sharp_spi_probe(struct spi_device *spi)
+{
+ lcdc_spi_client = spi;
+ lcdc_spi_client->bits_per_word = 32;
+ return 0;
+}
+static int __devexit lcdc_sharp_spi_remove(struct spi_device *spi)
+{
+ lcdc_spi_client = NULL;
+ return 0;
+}
+static struct spi_driver lcdc_sharp_spi_driver = {
+ .driver = {
+ .name = LCDC_SHARP_SPI_DEVICE_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = lcdc_sharp_spi_probe,
+ .remove = __devexit_p(lcdc_sharp_spi_remove),
+};
+#endif
+static struct platform_driver this_driver = {
+ .probe = sharp_probe,
+ .driver = {
+ .name = "lcdc_sharp_wvga",
+ },
+};
+
+static struct msm_fb_panel_data sharp_panel_data = {
+ .on = lcdc_sharp_panel_on,
+ .off = lcdc_sharp_panel_off,
+ .set_backlight = lcdc_sharp_panel_set_backlight,
+};
+
+static struct platform_device this_device = {
+ .name = "lcdc_sharp_wvga",
+ .id = 1,
+ .dev = {
+ .platform_data = &sharp_panel_data,
+ }
+};
+
+static int __init lcdc_sharp_panel_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ if (msm_fb_detect_client("lcdc_sharp_wvga_pt"))
+ return 0;
+#endif
+
+ ret = platform_driver_register(&this_driver);
+ if (ret)
+ return ret;
+
+ pinfo = &sharp_panel_data.panel_info;
+ pinfo->xres = 480;
+ pinfo->yres = 800;
+ MSM_FB_SINGLE_MODE_PANEL(pinfo);
+ pinfo->type = LCDC_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 18;
+ pinfo->fb_num = 2;
+ pinfo->clk_rate = 24500000;
+ pinfo->bl_max = BL_MAX;
+ pinfo->bl_min = 1;
+
+ pinfo->lcdc.h_back_porch = 20;
+ pinfo->lcdc.h_front_porch = 10;
+ pinfo->lcdc.h_pulse_width = 10;
+ pinfo->lcdc.v_back_porch = 2;
+ pinfo->lcdc.v_front_porch = 2;
+ pinfo->lcdc.v_pulse_width = 2;
+ pinfo->lcdc.border_clr = 0;
+ pinfo->lcdc.underflow_clr = 0xff;
+ pinfo->lcdc.hsync_skew = 0;
+
+ ret = platform_device_register(&this_device);
+ if (ret) {
+ printk(KERN_ERR "%s not able to register the device\n",
+ __func__);
+ goto fail_driver;
+ }
+#ifdef CONFIG_SPI_QSD
+ ret = spi_register_driver(&lcdc_sharp_spi_driver);
+
+ if (ret) {
+ printk(KERN_ERR "%s not able to register spi\n", __func__);
+ goto fail_device;
+ }
+#endif
+ return ret;
+#ifdef CONFIG_SPI_QSD
+fail_device:
+ platform_device_unregister(&this_device);
+#endif
+fail_driver:
+ platform_driver_unregister(&this_driver);
+
+ return ret;
+}
+
+module_init(lcdc_sharp_panel_init);
+#ifdef CONFIG_SPI_QSD
+static void __exit lcdc_sharp_panel_exit(void)
+{
+ spi_unregister_driver(&lcdc_sharp_spi_driver);
+}
+module_exit(lcdc_sharp_panel_exit);
+#endif
+
diff --git a/drivers/video/msm/lcdc_st15.c b/drivers/video/msm/lcdc_st15.c
new file mode 100644
index 0000000..cdae358
--- /dev/null
+++ b/drivers/video/msm/lcdc_st15.c
@@ -0,0 +1,413 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include "msm_fb.h"
+
+#define DEVICE_NAME "sii9022"
+#define SII9022_DEVICE_ID 0xB0
+#define SII9022_ISR 0x3D
+#define SII9022_ISR_RXS_STATUS 0x08
+
+static int lcdc_sii9022_panel_on(struct platform_device *pdev);
+static int lcdc_sii9022_panel_off(struct platform_device *pdev);
+
+static struct i2c_client *sii9022_i2c_client;
+
+struct sii9022_data {
+ struct msm_hdmi_platform_data *pd;
+ struct platform_device *pdev;
+ struct work_struct work;
+ int x_res;
+ int y_res;
+ int sysfs_entry_created;
+ int hdmi_attached;
+};
+static struct sii9022_data *dd;
+
+struct sii9022_i2c_addr_data{
+ u8 addr;
+ u8 data;
+};
+
+/* video mode data */
+static u8 video_mode_data[] = {
+ 0x00,
+ 0xF9, 0x1C, 0x70, 0x17, 0x72, 0x06, 0xEE, 0x02,
+};
+
+static u8 avi_io_format[] = {
+ 0x09,
+ 0x00, 0x00,
+};
+
+/* power state */
+static struct sii9022_i2c_addr_data regset0[] = {
+ { 0x60, 0x04 },
+ { 0x63, 0x00 },
+ { 0x1E, 0x00 },
+};
+
+static u8 video_infoframe[] = {
+ 0x0C,
+ 0xF0, 0x00, 0x68, 0x00, 0x04, 0x00, 0x19, 0x00,
+ 0xE9, 0x02, 0x04, 0x01, 0x04, 0x06,
+};
+
+/* configure audio */
+static struct sii9022_i2c_addr_data regset1[] = {
+ { 0x26, 0x90 },
+ { 0x20, 0x90 },
+ { 0x1F, 0x80 },
+ { 0x26, 0x80 },
+ { 0x24, 0x02 },
+ { 0x25, 0x0B },
+ { 0xBC, 0x02 },
+ { 0xBD, 0x24 },
+ { 0xBE, 0x02 },
+};
+
+/* enable audio */
+static u8 misc_infoframe[] = {
+ 0xBF,
+ 0xC2, 0x84, 0x01, 0x0A, 0x6F, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+/* set HDMI, active */
+static struct sii9022_i2c_addr_data regset2[] = {
+ { 0x1A, 0x01 },
+ { 0x3D, 0x00 },
+ { 0x3C, 0x02 },
+};
+
+static struct msm_fb_panel_data sii9022_panel_data = {
+ .on = lcdc_sii9022_panel_on,
+ .off = lcdc_sii9022_panel_off,
+};
+
+static struct platform_device sii9022_device = {
+ .name = DEVICE_NAME,
+ .id = 1,
+ .dev = {
+ .platform_data = &sii9022_panel_data,
+ }
+};
+
+static int send_i2c_data(struct i2c_client *client,
+ struct sii9022_i2c_addr_data *regset,
+ int size)
+{
+ int i;
+ int rc = 0;
+
+ for (i = 0; i < size; i++) {
+ rc = i2c_smbus_write_byte_data(
+ client,
+ regset[i].addr, regset[i].data);
+ if (rc)
+ break;
+ }
+ return rc;
+}
+
+static void sii9022_work_f(struct work_struct *work)
+{
+ int isr;
+
+ isr = i2c_smbus_read_byte_data(sii9022_i2c_client, SII9022_ISR);
+ if (isr < 0) {
+ dev_err(&sii9022_i2c_client->dev,
+ "i2c read of isr failed rc = 0x%x\n", isr);
+ return;
+ }
+ if (isr == 0)
+ return;
+
+ /* reset any set bits */
+ i2c_smbus_write_byte_data(sii9022_i2c_client, SII9022_ISR, isr);
+ dd->hdmi_attached = isr & SII9022_ISR_RXS_STATUS;
+ if (dd->pd->cable_detect)
+ dd->pd->cable_detect(dd->hdmi_attached);
+ if (dd->hdmi_attached) {
+ dd->x_res = 1280;
+ dd->y_res = 720;
+ } else {
+ dd->x_res = sii9022_panel_data.panel_info.xres;
+ dd->y_res = sii9022_panel_data.panel_info.yres;
+ }
+}
+
+static irqreturn_t sii9022_interrupt(int irq, void *dev_id)
+{
+ struct sii9022_data *dd = dev_id;
+
+ schedule_work(&dd->work);
+ return IRQ_HANDLED;
+}
+
+static int hdmi_sii_enable(struct i2c_client *client)
+{
+ int rc;
+ int retries = 10;
+ int count;
+
+ rc = i2c_smbus_write_byte_data(client, 0xC7, 0x00);
+ if (rc)
+ goto enable_exit;
+
+ do {
+ msleep(1);
+ rc = i2c_smbus_read_byte_data(client, 0x1B);
+ } while ((rc != SII9022_DEVICE_ID) && retries--);
+
+ if (rc != SII9022_DEVICE_ID)
+ return -ENODEV;
+
+ rc = i2c_smbus_write_byte_data(client, 0x1A, 0x11);
+ if (rc)
+ goto enable_exit;
+
+ count = ARRAY_SIZE(video_mode_data);
+ rc = i2c_master_send(client, video_mode_data, count);
+ if (rc != count) {
+ rc = -EIO;
+ goto enable_exit;
+ }
+
+ rc = i2c_smbus_write_byte_data(client, 0x08, 0x20);
+ if (rc)
+ goto enable_exit;
+ count = ARRAY_SIZE(avi_io_format);
+ rc = i2c_master_send(client, avi_io_format, count);
+ if (rc != count) {
+ rc = -EIO;
+ goto enable_exit;
+ }
+
+ rc = send_i2c_data(client, regset0, ARRAY_SIZE(regset0));
+ if (rc)
+ goto enable_exit;
+
+ count = ARRAY_SIZE(video_infoframe);
+ rc = i2c_master_send(client, video_infoframe, count);
+ if (rc != count) {
+ rc = -EIO;
+ goto enable_exit;
+ }
+
+ rc = send_i2c_data(client, regset1, ARRAY_SIZE(regset1));
+ if (rc)
+ goto enable_exit;
+
+ count = ARRAY_SIZE(misc_infoframe);
+ rc = i2c_master_send(client, misc_infoframe, count);
+ if (rc != count) {
+ rc = -EIO;
+ goto enable_exit;
+ }
+
+ rc = send_i2c_data(client, regset2, ARRAY_SIZE(regset2));
+ if (rc)
+ goto enable_exit;
+
+ return 0;
+enable_exit:
+ printk(KERN_ERR "%s: exited rc=%d\n", __func__, rc);
+ return rc;
+}
+
+static ssize_t show_res(struct device *device,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%dx%d\n", dd->x_res, dd->y_res);
+}
+
+static struct device_attribute device_attrs[] = {
+ __ATTR(screen_resolution, S_IRUGO|S_IWUSR, show_res, NULL),
+};
+
+static int lcdc_sii9022_panel_on(struct platform_device *pdev)
+{
+ int rc;
+ if (!dd->sysfs_entry_created) {
+ dd->pdev = pdev;
+ rc = device_create_file(&pdev->dev, &device_attrs[0]);
+ if (!rc)
+ dd->sysfs_entry_created = 1;
+ }
+
+ rc = hdmi_sii_enable(sii9022_i2c_client);
+ if (rc) {
+ dd->hdmi_attached = 0;
+ dd->x_res = sii9022_panel_data.panel_info.xres;
+ dd->y_res = sii9022_panel_data.panel_info.yres;
+ }
+ if (dd->pd->irq)
+ enable_irq(dd->pd->irq);
+ /* Don't return the value from hdmi_sii_enable().
+ * It may fail on some ST1.5s, but we must return 0 from this
+ * function in order for the on-board display to turn on.
+ */
+ return 0;
+}
+
+static int lcdc_sii9022_panel_off(struct platform_device *pdev)
+{
+ if (dd->pd->irq)
+ disable_irq(dd->pd->irq);
+ return 0;
+}
+
+static const struct i2c_device_id hmdi_sii_id[] = {
+ { DEVICE_NAME, 0 },
+ { }
+};
+
+static int hdmi_sii_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int rc;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
+ return -ENODEV;
+
+ dd = kzalloc(sizeof *dd, GFP_KERNEL);
+ if (!dd) {
+ rc = -ENOMEM;
+ goto probe_exit;
+ }
+ sii9022_i2c_client = client;
+ i2c_set_clientdata(client, dd);
+ dd->pd = client->dev.platform_data;
+ if (!dd->pd) {
+ rc = -ENODEV;
+ goto probe_free;
+ }
+ if (dd->pd->irq) {
+ INIT_WORK(&dd->work, sii9022_work_f);
+ rc = request_irq(dd->pd->irq,
+ &sii9022_interrupt,
+ IRQF_TRIGGER_FALLING,
+ "sii9022_cable", dd);
+ if (rc)
+ goto probe_free;
+ disable_irq(dd->pd->irq);
+ }
+ msm_fb_add_device(&sii9022_device);
+ dd->x_res = sii9022_panel_data.panel_info.xres;
+ dd->y_res = sii9022_panel_data.panel_info.yres;
+
+ return 0;
+
+probe_free:
+ i2c_set_clientdata(client, NULL);
+ kfree(dd);
+probe_exit:
+ return rc;
+}
+
+static int __devexit hdmi_sii_remove(struct i2c_client *client)
+{
+ int err = 0 ;
+ struct msm_hdmi_platform_data *pd;
+
+ if (dd->sysfs_entry_created)
+ device_remove_file(&dd->pdev->dev, &device_attrs[0]);
+ pd = client->dev.platform_data;
+ if (pd && pd->irq)
+ free_irq(pd->irq, dd);
+ i2c_set_clientdata(client, NULL);
+ kfree(dd);
+
+ return err ;
+}
+
+#ifdef CONFIG_PM
+static int sii9022_suspend(struct device *dev)
+{
+ if (dd && dd->pd && dd->pd->irq)
+ disable_irq(dd->pd->irq);
+ return 0;
+}
+
+static int sii9022_resume(struct device *dev)
+{
+ if (dd && dd->pd && dd->pd->irq)
+ enable_irq(dd->pd->irq);
+ return 0;
+}
+
+static struct dev_pm_ops sii9022_pm_ops = {
+ .suspend = sii9022_suspend,
+ .resume = sii9022_resume,
+};
+#endif
+
+static struct i2c_driver hdmi_sii_i2c_driver = {
+ .driver = {
+ .name = DEVICE_NAME,
+ .owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &sii9022_pm_ops,
+#endif
+ },
+ .probe = hdmi_sii_probe,
+ .remove = __exit_p(hdmi_sii_remove),
+ .id_table = hmdi_sii_id,
+};
+
+static int __init lcdc_st15_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+ if (msm_fb_detect_client("lcdc_st15"))
+ return 0;
+
+ pinfo = &sii9022_panel_data.panel_info;
+ pinfo->xres = 1366;
+ pinfo->yres = 768;
+ MSM_FB_SINGLE_MODE_PANEL(pinfo);
+ pinfo->type = LCDC_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 24;
+ pinfo->fb_num = 2;
+ pinfo->clk_rate = 74250000;
+
+ pinfo->lcdc.h_back_porch = 120;
+ pinfo->lcdc.h_front_porch = 20;
+ pinfo->lcdc.h_pulse_width = 40;
+ pinfo->lcdc.v_back_porch = 25;
+ pinfo->lcdc.v_front_porch = 1;
+ pinfo->lcdc.v_pulse_width = 7;
+ pinfo->lcdc.border_clr = 0; /* blk */
+ pinfo->lcdc.underflow_clr = 0xff; /* blue */
+ pinfo->lcdc.hsync_skew = 0;
+
+ ret = i2c_add_driver(&hdmi_sii_i2c_driver);
+ if (ret)
+ printk(KERN_ERR "%s: failed to add i2c driver\n", __func__);
+
+ return ret;
+}
+
+static void __exit hdmi_sii_exit(void)
+{
+ i2c_del_driver(&hdmi_sii_i2c_driver);
+}
+
+module_init(lcdc_st15_init);
+module_exit(hdmi_sii_exit);
diff --git a/drivers/video/msm/lcdc_toshiba_fwvga_pt.c b/drivers/video/msm/lcdc_toshiba_fwvga_pt.c
new file mode 100644
index 0000000..3e81471
--- /dev/null
+++ b/drivers/video/msm/lcdc_toshiba_fwvga_pt.c
@@ -0,0 +1,471 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <mach/gpio.h>
+#include <mach/pmic.h>
+#include <mach/socinfo.h>
+#include "msm_fb.h"
+
+static int spi_cs0_N;
+static int spi_sclk;
+static int spi_mosi;
+static int spi_miso;
+
+struct toshiba_state_type {
+ boolean disp_initialized;
+ boolean display_on;
+ boolean disp_powered_up;
+};
+
+static struct toshiba_state_type toshiba_state = { 0 };
+static struct msm_panel_common_pdata *lcdc_toshiba_pdata;
+
+static int toshiba_spi_write(char data1, char data2, int rs)
+{
+ uint32 bitdata = 0, bnum = 24, bmask = 0x800000;
+
+ gpio_set_value_cansleep(spi_cs0_N, 0); /* cs* low */
+ udelay(1);
+
+ if (rs)
+ bitdata = (0x72 << 16);
+ else
+ bitdata = (0x70 << 16);
+
+ bitdata |= ((data1 << 8) | data2);
+
+ while (bnum) {
+ gpio_set_value_cansleep(spi_sclk, 0); /* clk low */
+ udelay(1);
+
+ if (bitdata & bmask)
+ gpio_set_value_cansleep(spi_mosi, 1);
+ else
+ gpio_set_value_cansleep(spi_mosi, 0);
+
+ udelay(1);
+ gpio_set_value_cansleep(spi_sclk, 1); /* clk high */
+ udelay(1);
+ bmask >>= 1;
+ bnum--;
+ }
+
+ gpio_set_value_cansleep(spi_cs0_N, 1); /* cs* high */
+ udelay(1);
+ return 0;
+}
+
+static void spi_pin_assign(void)
+{
+ /* Setting the Default GPIO's */
+ spi_mosi = *(lcdc_toshiba_pdata->gpio_num);
+ spi_miso = *(lcdc_toshiba_pdata->gpio_num + 1);
+ spi_sclk = *(lcdc_toshiba_pdata->gpio_num + 2);
+ spi_cs0_N = *(lcdc_toshiba_pdata->gpio_num + 3);
+}
+
+static void toshiba_disp_powerup(void)
+{
+ if (!toshiba_state.disp_powered_up && !toshiba_state.display_on) {
+ /* Reset the hardware first */
+ /* Include DAC power up implementation here */
+ toshiba_state.disp_powered_up = TRUE;
+ }
+}
+
+static void toshiba_disp_on(void)
+{
+ if (toshiba_state.disp_powered_up && !toshiba_state.display_on) {
+ toshiba_spi_write(0x01, 0x00, 0);
+ toshiba_spi_write(0x30, 0x00, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x01, 0x01, 0);
+ toshiba_spi_write(0x40, 0x10, 1);
+
+#ifdef TOSHIBA_FWVGA_FULL_INIT
+ udelay(500);
+ toshiba_spi_write(0x01, 0x06, 0);
+ toshiba_spi_write(0x00, 0x00, 1);
+ msleep(20);
+
+ toshiba_spi_write(0x00, 0x01, 0);
+ toshiba_spi_write(0x03, 0x10, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x00, 0x02, 0);
+ toshiba_spi_write(0x01, 0x00, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x00, 0x03, 0);
+ toshiba_spi_write(0x00, 0x00, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x00, 0x07, 0);
+ toshiba_spi_write(0x00, 0x00, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x00, 0x08, 0);
+ toshiba_spi_write(0x00, 0x04, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x00, 0x09, 0);
+ toshiba_spi_write(0x00, 0x0c, 1);
+#endif
+ udelay(500);
+ toshiba_spi_write(0x00, 0x0c, 0);
+ toshiba_spi_write(0x40, 0x10, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x00, 0x0e, 0);
+ toshiba_spi_write(0x00, 0x00, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x00, 0x20, 0);
+ toshiba_spi_write(0x01, 0x3f, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x00, 0x22, 0);
+ toshiba_spi_write(0x76, 0x00, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x00, 0x23, 0);
+ toshiba_spi_write(0x1c, 0x0a, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x00, 0x24, 0);
+ toshiba_spi_write(0x1c, 0x2c, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x00, 0x25, 0);
+ toshiba_spi_write(0x1c, 0x4e, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x00, 0x27, 0);
+ toshiba_spi_write(0x00, 0x00, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x00, 0x28, 0);
+ toshiba_spi_write(0x76, 0x0c, 1);
+
+#ifdef TOSHIBA_FWVGA_FULL_INIT
+ udelay(500);
+ toshiba_spi_write(0x03, 0x00, 0);
+ toshiba_spi_write(0x00, 0x00, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x01, 0);
+ toshiba_spi_write(0x05, 0x02, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x02, 0);
+ toshiba_spi_write(0x07, 0x05, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x03, 0);
+ toshiba_spi_write(0x00, 0x00, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x04, 0);
+ toshiba_spi_write(0x02, 0x00, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x05, 0);
+ toshiba_spi_write(0x07, 0x07, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x06, 0);
+ toshiba_spi_write(0x10, 0x10, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x07, 0);
+ toshiba_spi_write(0x02, 0x02, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x08, 0);
+ toshiba_spi_write(0x07, 0x04, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x09, 0);
+ toshiba_spi_write(0x07, 0x07, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x0a, 0);
+ toshiba_spi_write(0x00, 0x00, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x0b, 0);
+ toshiba_spi_write(0x00, 0x00, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x0c, 0);
+ toshiba_spi_write(0x07, 0x07, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x0d, 0);
+ toshiba_spi_write(0x10, 0x10, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x10, 0);
+ toshiba_spi_write(0x01, 0x04, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x11, 0);
+ toshiba_spi_write(0x05, 0x03, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x12, 0);
+ toshiba_spi_write(0x03, 0x04, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x15, 0);
+ toshiba_spi_write(0x03, 0x04, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x16, 0);
+ toshiba_spi_write(0x03, 0x1c, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x17, 0);
+ toshiba_spi_write(0x02, 0x04, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x18, 0);
+ toshiba_spi_write(0x04, 0x02, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x19, 0);
+ toshiba_spi_write(0x03, 0x05, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x1c, 0);
+ toshiba_spi_write(0x07, 0x07, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x1d, 0);
+ toshiba_spi_write(0x02, 0x1f, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x20, 0);
+ toshiba_spi_write(0x05, 0x07, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x21, 0);
+ toshiba_spi_write(0x06, 0x04, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x22, 0);
+ toshiba_spi_write(0x04, 0x05, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x27, 0);
+ toshiba_spi_write(0x02, 0x03, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x28, 0);
+ toshiba_spi_write(0x03, 0x00, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x03, 0x29, 0);
+ toshiba_spi_write(0x00, 0x02, 1);
+
+#endif
+ udelay(500);
+ toshiba_spi_write(0x01, 0x00, 0);
+ toshiba_spi_write(0x36, 0x3c, 1);
+ udelay(500);
+
+ toshiba_spi_write(0x01, 0x01, 0);
+ toshiba_spi_write(0x40, 0x03, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x01, 0x02, 0);
+ toshiba_spi_write(0x00, 0x01, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x01, 0x03, 0);
+ toshiba_spi_write(0x3c, 0x58, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x01, 0x0c, 0);
+ toshiba_spi_write(0x01, 0x35, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x01, 0x06, 0);
+ toshiba_spi_write(0x00, 0x02, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x00, 0x29, 0);
+ toshiba_spi_write(0x03, 0xbf, 1);
+
+ udelay(500);
+ toshiba_spi_write(0x01, 0x06, 0);
+ toshiba_spi_write(0x00, 0x03, 1);
+ msleep(32);
+
+ toshiba_spi_write(0x01, 0x01, 0);
+ toshiba_spi_write(0x40, 0x10, 1);
+ msleep(80);
+
+ toshiba_state.display_on = TRUE;
+ }
+}
+
+static int lcdc_toshiba_panel_on(struct platform_device *pdev)
+{
+ if (!toshiba_state.disp_initialized) {
+ /* Configure reset GPIO that drives DAC */
+ if (lcdc_toshiba_pdata->panel_config_gpio)
+ lcdc_toshiba_pdata->panel_config_gpio(1);
+ toshiba_disp_powerup();
+ toshiba_disp_on();
+ toshiba_state.disp_initialized = TRUE;
+ }
+ return 0;
+}
+
+static int lcdc_toshiba_panel_off(struct platform_device *pdev)
+{
+ if (toshiba_state.disp_powered_up && toshiba_state.display_on) {
+ toshiba_spi_write(0x01, 0x06, 1);
+ toshiba_spi_write(0x00, 0x02, 1);
+ msleep(80);
+
+ toshiba_spi_write(0x01, 0x06, 1);
+ toshiba_spi_write(0x00, 0x00, 1);
+
+ toshiba_spi_write(0x00, 0x29, 1);
+ toshiba_spi_write(0x00, 0x02, 1);
+
+ toshiba_spi_write(0x01, 0x00, 1);
+ toshiba_spi_write(0x30, 0x00, 1);
+
+ if (lcdc_toshiba_pdata->panel_config_gpio)
+ lcdc_toshiba_pdata->panel_config_gpio(0);
+ toshiba_state.display_on = FALSE;
+ toshiba_state.disp_initialized = FALSE;
+ }
+
+ return 0;
+}
+
+static void lcdc_toshiba_set_backlight(struct msm_fb_data_type *mfd)
+{
+ int ret;
+ int bl_level;
+
+ bl_level = mfd->bl_level;
+
+ if (lcdc_toshiba_pdata && lcdc_toshiba_pdata->pmic_backlight)
+ ret = lcdc_toshiba_pdata->pmic_backlight(bl_level);
+ else
+ pr_err("%s(): Backlight level set failed", __func__);
+
+ return;
+}
+
+static int __devinit toshiba_probe(struct platform_device *pdev)
+{
+ if (pdev->id == 0) {
+ lcdc_toshiba_pdata = pdev->dev.platform_data;
+ spi_pin_assign();
+ return 0;
+ }
+ msm_fb_add_device(pdev);
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = toshiba_probe,
+ .driver = {
+ .name = "lcdc_toshiba_fwvga_pt",
+ },
+};
+
+static struct msm_fb_panel_data toshiba_panel_data = {
+ .on = lcdc_toshiba_panel_on,
+ .off = lcdc_toshiba_panel_off,
+ .set_backlight = lcdc_toshiba_set_backlight,
+};
+
+static struct platform_device this_device = {
+ .name = "lcdc_toshiba_fwvga_pt",
+ .id = 1,
+ .dev = {
+ .platform_data = &toshiba_panel_data,
+ }
+};
+
+static int __init lcdc_toshiba_panel_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+ ret = msm_fb_detect_client("lcdc_toshiba_fwvga_pt");
+ if (ret)
+ return 0;
+
+
+ ret = platform_driver_register(&this_driver);
+ if (ret)
+ return ret;
+
+ pinfo = &toshiba_panel_data.panel_info;
+ pinfo->xres = 480;
+ pinfo->yres = 864;
+ MSM_FB_SINGLE_MODE_PANEL(pinfo);
+ pinfo->type = LCDC_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 18;
+ pinfo->fb_num = 2;
+ /* 30Mhz mdp_lcdc_pclk and mdp_lcdc_pad_pcl */
+ pinfo->clk_rate = 30720000;
+ pinfo->bl_max = 100;
+ pinfo->bl_min = 1;
+
+ if (cpu_is_msm7x25a() || cpu_is_msm7x25aa()) {
+ pinfo->yres = 320;
+ pinfo->lcdc.h_back_porch = 10;
+ pinfo->lcdc.h_front_porch = 21;
+ pinfo->lcdc.h_pulse_width = 5;
+ pinfo->lcdc.v_back_porch = 8;
+ pinfo->lcdc.v_front_porch = 540;
+ pinfo->lcdc.v_pulse_width = 42;
+ pinfo->lcdc.border_clr = 0; /* blk */
+ pinfo->lcdc.underflow_clr = 0xff; /* blue */
+ pinfo->lcdc.hsync_skew = 0;
+ } else {
+ pinfo->lcdc.h_back_porch = 8;
+ pinfo->lcdc.h_front_porch = 16;
+ pinfo->lcdc.h_pulse_width = 8;
+ pinfo->lcdc.v_back_porch = 2;
+ pinfo->lcdc.v_front_porch = 2;
+ pinfo->lcdc.v_pulse_width = 2;
+ pinfo->lcdc.border_clr = 0; /* blk */
+ pinfo->lcdc.underflow_clr = 0xff; /* blue */
+ pinfo->lcdc.hsync_skew = 0;
+ }
+
+ ret = platform_device_register(&this_device);
+ if (ret) {
+ printk(KERN_ERR "%s not able to register the device\n",
+ __func__);
+ platform_driver_unregister(&this_driver);
+ }
+ return ret;
+}
+
+device_initcall(lcdc_toshiba_panel_init);
diff --git a/drivers/video/msm/lcdc_toshiba_wvga_pt.c b/drivers/video/msm/lcdc_toshiba_wvga_pt.c
new file mode 100644
index 0000000..f0aa8f5
--- /dev/null
+++ b/drivers/video/msm/lcdc_toshiba_wvga_pt.c
@@ -0,0 +1,519 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#ifdef CONFIG_SPI_QSD
+#include <linux/spi/spi.h>
+#endif
+#include <mach/gpio.h>
+#include <mach/pmic.h>
+#include "msm_fb.h"
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+#include "mddihosti.h"
+#endif
+
+#ifdef CONFIG_SPI_QSD
+#define LCDC_TOSHIBA_SPI_DEVICE_NAME "lcdc_toshiba_ltm030dd40"
+static struct spi_device *lcdc_toshiba_spi_client;
+#else
+static int spi_cs;
+static int spi_sclk;
+static int spi_mosi;
+static int spi_miso;
+#endif
+struct toshiba_state_type{
+ boolean disp_initialized;
+ boolean display_on;
+ boolean disp_powered_up;
+};
+
+static struct toshiba_state_type toshiba_state = { 0 };
+static struct msm_panel_common_pdata *lcdc_toshiba_pdata;
+
+#ifndef CONFIG_SPI_QSD
+static void toshiba_spi_write_byte(char dc, uint8 data)
+{
+ uint32 bit;
+ int bnum;
+
+ gpio_set_value(spi_sclk, 0); /* clk low */
+ /* dc: 0 for command, 1 for parameter */
+ gpio_set_value(spi_mosi, dc);
+ udelay(1); /* at least 20 ns */
+ gpio_set_value(spi_sclk, 1); /* clk high */
+ udelay(1); /* at least 20 ns */
+ bnum = 8; /* 8 data bits */
+ bit = 0x80;
+ while (bnum) {
+ gpio_set_value(spi_sclk, 0); /* clk low */
+ if (data & bit)
+ gpio_set_value(spi_mosi, 1);
+ else
+ gpio_set_value(spi_mosi, 0);
+ udelay(1);
+ gpio_set_value(spi_sclk, 1); /* clk high */
+ udelay(1);
+ bit >>= 1;
+ bnum--;
+ }
+}
+#endif
+
+static int toshiba_spi_write(char cmd, uint32 data, int num)
+{
+ char *bp;
+#ifdef CONFIG_SPI_QSD
+ char tx_buf[4];
+ int rc, i;
+ struct spi_message m;
+ struct spi_transfer t;
+ uint32 final_data = 0;
+
+ if (!lcdc_toshiba_spi_client) {
+ printk(KERN_ERR "%s lcdc_toshiba_spi_client is NULL\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ memset(&t, 0, sizeof t);
+ t.tx_buf = tx_buf;
+ spi_setup(lcdc_toshiba_spi_client);
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+
+ /* command byte first */
+ final_data |= cmd << 23;
+ t.len = num + 2;
+ if (t.len < 4)
+ t.bits_per_word = 8 * t.len;
+ /* followed by parameter bytes */
+ if (num) {
+ bp = (char *)&data;;
+ bp += (num - 1);
+ i = 1;
+ while (num) {
+ final_data |= 1 << (((4 - i) << 3) - i - 1);
+ final_data |= *bp << (((4 - i - 1) << 3) - i - 1);
+ num--;
+ bp--;
+ i++;
+ }
+ }
+
+ bp = (char *)&final_data;
+ for (i = 0; i < t.len; i++)
+ tx_buf[i] = bp[3 - i];
+ t.rx_buf = NULL;
+ rc = spi_sync(lcdc_toshiba_spi_client, &m);
+ if (rc)
+ printk(KERN_ERR "spi_sync _write failed %d\n", rc);
+ return rc;
+#else
+ gpio_set_value(spi_cs, 1); /* cs high */
+
+ /* command byte first */
+ toshiba_spi_write_byte(0, cmd);
+
+ /* followed by parameter bytes */
+ if (num) {
+ bp = (char *)&data;;
+ bp += (num - 1);
+ while (num) {
+ toshiba_spi_write_byte(1, *bp);
+ num--;
+ bp--;
+ }
+ }
+
+ gpio_set_value(spi_cs, 0); /* cs low */
+ udelay(1);
+ return 0;
+#endif
+}
+
+static int toshiba_spi_read_bytes(char cmd, uint32 *data, int num)
+{
+#ifdef CONFIG_SPI_QSD
+ char tx_buf[5];
+ char rx_buf[5];
+ int rc;
+ struct spi_message m;
+ struct spi_transfer t;
+
+ if (!lcdc_toshiba_spi_client) {
+ printk(KERN_ERR "%s lcdc_toshiba_spi_client is NULL\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ memset(&t, 0, sizeof t);
+ t.tx_buf = tx_buf;
+ t.rx_buf = rx_buf;
+ spi_setup(lcdc_toshiba_spi_client);
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+
+ /* command byte first */
+ tx_buf[0] = 0 | ((cmd >> 1) & 0x7f);
+ tx_buf[1] = (cmd & 0x01) << 7;
+ tx_buf[2] = 0;
+ tx_buf[3] = 0;
+ tx_buf[4] = 0;
+
+ t.len = 5;
+
+ rc = spi_sync(lcdc_toshiba_spi_client, &m);
+ *data = 0;
+ *data = ((rx_buf[1] & 0x1f) << 19) | (rx_buf[2] << 11) |
+ (rx_buf[3] << 3) | ((rx_buf[4] & 0xe0) >> 5);
+ if (rc)
+ printk(KERN_ERR "spi_sync _read failed %d\n", rc);
+ return rc;
+#else
+ uint32 dbit, bits;
+ int bnum;
+
+ gpio_set_value(spi_cs, 1); /* cs high */
+
+ /* command byte first */
+ toshiba_spi_write_byte(0, cmd);
+
+ if (num > 1) {
+ /* extra dc bit */
+ gpio_set_value(spi_sclk, 0); /* clk low */
+ udelay(1);
+ dbit = gpio_get_value(spi_miso);/* dc bit */
+ udelay(1);
+ gpio_set_value(spi_sclk, 1); /* clk high */
+ }
+
+ /* followed by data bytes */
+ bnum = num * 8; /* number of bits */
+ bits = 0;
+ while (bnum) {
+ bits <<= 1;
+ gpio_set_value(spi_sclk, 0); /* clk low */
+ udelay(1);
+ dbit = gpio_get_value(spi_miso);
+ udelay(1);
+ gpio_set_value(spi_sclk, 1); /* clk high */
+ bits |= dbit;
+ bnum--;
+ }
+
+ *data = bits;
+
+ udelay(1);
+ gpio_set_value(spi_cs, 0); /* cs low */
+ udelay(1);
+ return 0;
+#endif
+}
+
+#ifndef CONFIG_SPI_QSD
+static void spi_pin_assign(void)
+{
+ /* Setting the Default GPIO's */
+ spi_sclk = *(lcdc_toshiba_pdata->gpio_num);
+ spi_cs = *(lcdc_toshiba_pdata->gpio_num + 1);
+ spi_mosi = *(lcdc_toshiba_pdata->gpio_num + 2);
+ spi_miso = *(lcdc_toshiba_pdata->gpio_num + 3);
+}
+#endif
+
+static void toshiba_disp_powerup(void)
+{
+ if (!toshiba_state.disp_powered_up && !toshiba_state.display_on) {
+ /* Reset the hardware first */
+ /* Include DAC power up implementation here */
+ toshiba_state.disp_powered_up = TRUE;
+ }
+}
+
+static void toshiba_disp_on(void)
+{
+ uint32 data;
+
+#ifndef CONFIG_SPI_QSD
+ gpio_set_value(spi_cs, 0); /* low */
+ gpio_set_value(spi_sclk, 1); /* high */
+ gpio_set_value(spi_mosi, 0);
+ gpio_set_value(spi_miso, 0);
+#endif
+
+ if (toshiba_state.disp_powered_up && !toshiba_state.display_on) {
+ toshiba_spi_write(0, 0, 0);
+ mdelay(7);
+ toshiba_spi_write(0, 0, 0);
+ mdelay(7);
+ toshiba_spi_write(0, 0, 0);
+ mdelay(7);
+ toshiba_spi_write(0xba, 0x11, 1);
+ toshiba_spi_write(0x36, 0x00, 1);
+ mdelay(1);
+ toshiba_spi_write(0x3a, 0x60, 1);
+ toshiba_spi_write(0xb1, 0x5d, 1);
+ mdelay(1);
+ toshiba_spi_write(0xb2, 0x33, 1);
+ toshiba_spi_write(0xb3, 0x22, 1);
+ mdelay(1);
+ toshiba_spi_write(0xb4, 0x02, 1);
+ toshiba_spi_write(0xb5, 0x1e, 1); /* vcs -- adjust brightness */
+ mdelay(1);
+ toshiba_spi_write(0xb6, 0x27, 1);
+ toshiba_spi_write(0xb7, 0x03, 1);
+ mdelay(1);
+ toshiba_spi_write(0xb9, 0x24, 1);
+ toshiba_spi_write(0xbd, 0xa1, 1);
+ mdelay(1);
+ toshiba_spi_write(0xbb, 0x00, 1);
+ toshiba_spi_write(0xbf, 0x01, 1);
+ mdelay(1);
+ toshiba_spi_write(0xbe, 0x00, 1);
+ toshiba_spi_write(0xc0, 0x11, 1);
+ mdelay(1);
+ toshiba_spi_write(0xc1, 0x11, 1);
+ toshiba_spi_write(0xc2, 0x11, 1);
+ mdelay(1);
+ toshiba_spi_write(0xc3, 0x3232, 2);
+ mdelay(1);
+ toshiba_spi_write(0xc4, 0x3232, 2);
+ mdelay(1);
+ toshiba_spi_write(0xc5, 0x3232, 2);
+ mdelay(1);
+ toshiba_spi_write(0xc6, 0x3232, 2);
+ mdelay(1);
+ toshiba_spi_write(0xc7, 0x6445, 2);
+ mdelay(1);
+ toshiba_spi_write(0xc8, 0x44, 1);
+ toshiba_spi_write(0xc9, 0x52, 1);
+ mdelay(1);
+ toshiba_spi_write(0xca, 0x00, 1);
+ mdelay(1);
+ toshiba_spi_write(0xec, 0x02a4, 2); /* 0x02a4 */
+ mdelay(1);
+ toshiba_spi_write(0xcf, 0x01, 1);
+ mdelay(1);
+ toshiba_spi_write(0xd0, 0xc003, 2); /* c003 */
+ mdelay(1);
+ toshiba_spi_write(0xd1, 0x01, 1);
+ mdelay(1);
+ toshiba_spi_write(0xd2, 0x0028, 2);
+ mdelay(1);
+ toshiba_spi_write(0xd3, 0x0028, 2);
+ mdelay(1);
+ toshiba_spi_write(0xd4, 0x26a4, 2);
+ mdelay(1);
+ toshiba_spi_write(0xd5, 0x20, 1);
+ mdelay(1);
+ toshiba_spi_write(0xef, 0x3200, 2);
+ mdelay(32);
+ toshiba_spi_write(0xbc, 0x80, 1); /* wvga pass through */
+ toshiba_spi_write(0x3b, 0x00, 1);
+ mdelay(1);
+ toshiba_spi_write(0xb0, 0x16, 1);
+ mdelay(1);
+ toshiba_spi_write(0xb8, 0xfff5, 2);
+ mdelay(1);
+ toshiba_spi_write(0x11, 0, 0);
+ mdelay(5);
+ toshiba_spi_write(0x29, 0, 0);
+ mdelay(5);
+ toshiba_state.display_on = TRUE;
+ }
+
+ data = 0;
+ toshiba_spi_read_bytes(0x04, &data, 3);
+ printk(KERN_INFO "toshiba_disp_on: id=%x\n", data);
+
+}
+
+static int lcdc_toshiba_panel_on(struct platform_device *pdev)
+{
+ if (!toshiba_state.disp_initialized) {
+ /* Configure reset GPIO that drives DAC */
+ if (lcdc_toshiba_pdata->panel_config_gpio)
+ lcdc_toshiba_pdata->panel_config_gpio(1);
+ toshiba_disp_powerup();
+ toshiba_disp_on();
+ toshiba_state.disp_initialized = TRUE;
+ }
+ return 0;
+}
+
+static int lcdc_toshiba_panel_off(struct platform_device *pdev)
+{
+ if (toshiba_state.disp_powered_up && toshiba_state.display_on) {
+ /* Main panel power off (Deep standby in) */
+
+ toshiba_spi_write(0x28, 0, 0); /* display off */
+ mdelay(1);
+ toshiba_spi_write(0xb8, 0x8002, 2); /* output control */
+ mdelay(1);
+ toshiba_spi_write(0x10, 0x00, 1); /* sleep mode in */
+ mdelay(85); /* wait 85 msec */
+ toshiba_spi_write(0xb0, 0x00, 1); /* deep standby in */
+ mdelay(1);
+ if (lcdc_toshiba_pdata->panel_config_gpio)
+ lcdc_toshiba_pdata->panel_config_gpio(0);
+ toshiba_state.display_on = FALSE;
+ toshiba_state.disp_initialized = FALSE;
+ }
+ return 0;
+}
+
+static void lcdc_toshiba_set_backlight(struct msm_fb_data_type *mfd)
+{
+ int bl_level;
+ int ret = -EPERM;
+ int i = 0;
+
+ bl_level = mfd->bl_level;
+
+ while (i++ < 3) {
+ ret = pmic_set_led_intensity(LED_LCD, bl_level);
+ if (ret == 0)
+ return;
+ msleep(10);
+ }
+
+ printk(KERN_WARNING "%s: can't set lcd backlight!\n",
+ __func__);
+}
+
+static int __devinit toshiba_probe(struct platform_device *pdev)
+{
+ if (pdev->id == 0) {
+ lcdc_toshiba_pdata = pdev->dev.platform_data;
+#ifndef CONFIG_SPI_QSD
+ spi_pin_assign();
+#endif
+ return 0;
+ }
+ msm_fb_add_device(pdev);
+ return 0;
+}
+
+#ifdef CONFIG_SPI_QSD
+static int __devinit lcdc_toshiba_spi_probe(struct spi_device *spi)
+{
+ lcdc_toshiba_spi_client = spi;
+ lcdc_toshiba_spi_client->bits_per_word = 32;
+ return 0;
+}
+static int __devexit lcdc_toshiba_spi_remove(struct spi_device *spi)
+{
+ lcdc_toshiba_spi_client = NULL;
+ return 0;
+}
+
+static struct spi_driver lcdc_toshiba_spi_driver = {
+ .driver = {
+ .name = LCDC_TOSHIBA_SPI_DEVICE_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = lcdc_toshiba_spi_probe,
+ .remove = __devexit_p(lcdc_toshiba_spi_remove),
+};
+#endif
+static struct platform_driver this_driver = {
+ .probe = toshiba_probe,
+ .driver = {
+ .name = "lcdc_toshiba_wvga",
+ },
+};
+
+static struct msm_fb_panel_data toshiba_panel_data = {
+ .on = lcdc_toshiba_panel_on,
+ .off = lcdc_toshiba_panel_off,
+ .set_backlight = lcdc_toshiba_set_backlight,
+};
+
+static struct platform_device this_device = {
+ .name = "lcdc_toshiba_wvga",
+ .id = 1,
+ .dev = {
+ .platform_data = &toshiba_panel_data,
+ }
+};
+
+static int __init lcdc_toshiba_panel_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+ if (mddi_get_client_id() != 0)
+ return 0;
+
+ ret = msm_fb_detect_client("lcdc_toshiba_wvga_pt");
+ if (ret)
+ return 0;
+
+#endif
+
+ ret = platform_driver_register(&this_driver);
+ if (ret)
+ return ret;
+
+ pinfo = &toshiba_panel_data.panel_info;
+ pinfo->xres = 480;
+ pinfo->yres = 800;
+ MSM_FB_SINGLE_MODE_PANEL(pinfo);
+ pinfo->type = LCDC_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 18;
+ pinfo->fb_num = 2;
+ /* 30Mhz mdp_lcdc_pclk and mdp_lcdc_pad_pcl */
+ pinfo->clk_rate = 30720000;
+ pinfo->bl_max = 15;
+ pinfo->bl_min = 1;
+
+ pinfo->lcdc.h_back_porch = 184; /* hsw = 8 + hbp=184 */
+ pinfo->lcdc.h_front_porch = 4;
+ pinfo->lcdc.h_pulse_width = 8;
+ pinfo->lcdc.v_back_porch = 2; /* vsw=1 + vbp = 2 */
+ pinfo->lcdc.v_front_porch = 3;
+ pinfo->lcdc.v_pulse_width = 1;
+ pinfo->lcdc.border_clr = 0; /* blk */
+ pinfo->lcdc.underflow_clr = 0xff; /* blue */
+ pinfo->lcdc.hsync_skew = 0;
+
+ ret = platform_device_register(&this_device);
+ if (ret) {
+ printk(KERN_ERR "%s not able to register the device\n",
+ __func__);
+ goto fail_driver;
+ }
+#ifdef CONFIG_SPI_QSD
+ ret = spi_register_driver(&lcdc_toshiba_spi_driver);
+
+ if (ret) {
+ printk(KERN_ERR "%s not able to register spi\n", __func__);
+ goto fail_device;
+ }
+#endif
+ return ret;
+
+#ifdef CONFIG_SPI_QSD
+fail_device:
+ platform_device_unregister(&this_device);
+#endif
+fail_driver:
+ platform_driver_unregister(&this_driver);
+ return ret;
+}
+
+device_initcall(lcdc_toshiba_panel_init);
diff --git a/drivers/video/msm/lcdc_wxga.c b/drivers/video/msm/lcdc_wxga.c
new file mode 100644
index 0000000..3204704
--- /dev/null
+++ b/drivers/video/msm/lcdc_wxga.c
@@ -0,0 +1,53 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+
+static int __init lcdc_wxga_init(void)
+{
+ int ret;
+ struct msm_panel_info pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ if (msm_fb_detect_client("lcdc_wxga"))
+ return 0;
+#endif
+
+ pinfo.xres = 1280;
+ pinfo.yres = 720;
+ MSM_FB_SINGLE_MODE_PANEL(&pinfo);
+ pinfo.type = LCDC_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 24;
+ pinfo.fb_num = 2;
+ pinfo.clk_rate = 74250000;
+
+ pinfo.lcdc.h_back_porch = 124;
+ pinfo.lcdc.h_front_porch = 110;
+ pinfo.lcdc.h_pulse_width = 136;
+ pinfo.lcdc.v_back_porch = 19;
+ pinfo.lcdc.v_front_porch = 5;
+ pinfo.lcdc.v_pulse_width = 6;
+ pinfo.lcdc.border_clr = 0; /* blk */
+ pinfo.lcdc.underflow_clr = 0xff; /* blue */
+ pinfo.lcdc.hsync_skew = 0;
+
+ ret = lcdc_device_register(&pinfo);
+ if (ret)
+ printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(lcdc_wxga_init);
diff --git a/drivers/video/msm/logo.c b/drivers/video/msm/logo.c
new file mode 100644
index 0000000..c061e86
--- /dev/null
+++ b/drivers/video/msm/logo.c
@@ -0,0 +1,97 @@
+/* drivers/video/msm/logo.c
+ *
+ * Show Logo in RLE 565 format
+ *
+ * Copyright (C) 2008 Google Incorporated
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/fb.h>
+#include <linux/vt_kern.h>
+#include <linux/unistd.h>
+#include <linux/syscalls.h>
+
+#include <linux/irq.h>
+#include <asm/system.h>
+
+#define fb_width(fb) ((fb)->var.xres)
+#define fb_height(fb) ((fb)->var.yres)
+#define fb_size(fb) ((fb)->var.xres * (fb)->var.yres * 2)
+
+static void memset16(void *_ptr, unsigned short val, unsigned count)
+{
+ unsigned short *ptr = _ptr;
+ count >>= 1;
+ while (count--)
+ *ptr++ = val;
+}
+
+/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */
+int load_565rle_image(char *filename)
+{
+ struct fb_info *info;
+ int fd, count, err = 0;
+ unsigned max;
+ unsigned short *data, *bits, *ptr;
+
+ info = registered_fb[0];
+ if (!info) {
+ printk(KERN_WARNING "%s: Can not access framebuffer\n",
+ __func__);
+ return -ENODEV;
+ }
+
+ fd = sys_open(filename, O_RDONLY, 0);
+ if (fd < 0) {
+ printk(KERN_WARNING "%s: Can not open %s\n",
+ __func__, filename);
+ return -ENOENT;
+ }
+ count = sys_lseek(fd, (off_t)0, 2);
+ if (count <= 0) {
+ err = -EIO;
+ goto err_logo_close_file;
+ }
+ sys_lseek(fd, (off_t)0, 0);
+ data = kmalloc(count, GFP_KERNEL);
+ if (!data) {
+ printk(KERN_WARNING "%s: Can not alloc data\n", __func__);
+ err = -ENOMEM;
+ goto err_logo_close_file;
+ }
+ if (sys_read(fd, (char *)data, count) != count) {
+ err = -EIO;
+ goto err_logo_free_data;
+ }
+
+ max = fb_width(info) * fb_height(info);
+ ptr = data;
+ bits = (unsigned short *)(info->screen_base);
+ while (count > 3) {
+ unsigned n = ptr[0];
+ if (n > max)
+ break;
+ memset16(bits, ptr[1], n << 1);
+ bits += n;
+ max -= n;
+ ptr += 2;
+ count -= 4;
+ }
+
+err_logo_free_data:
+ kfree(data);
+err_logo_close_file:
+ sys_close(fd);
+ return err;
+}
+EXPORT_SYMBOL(load_565rle_image);
diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c
index 178b072..9b9ee94 100644
--- a/drivers/video/msm/mddi.c
+++ b/drivers/video/msm/mddi.c
@@ -2,7 +2,7 @@
* MSM MDDI Transport
*
* Copyright (C) 2007 Google Incorporated
- * Copyright (C) 2007 QUALCOMM Incorporated
+ * Copyright (c) 2007-2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -10,816 +10,578 @@
*
* 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
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/gfp.h>
-#include <linux/spinlock.h>
-#include <linux/clk.h>
-#include <linux/io.h>
#include <linux/sched.h>
-#include <mach/msm_iomap.h>
-#include <mach/irqs.h>
-#include <mach/board.h>
-#include <mach/msm_fb.h>
-#include "mddi_hw.h"
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <asm/io.h>
-#define FLAG_DISABLE_HIBERNATION 0x0001
-#define FLAG_HAVE_CAPS 0x0002
-#define FLAG_HAS_VSYNC_IRQ 0x0004
-#define FLAG_HAVE_STATUS 0x0008
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include "msm_fb.h"
+#include "mddihosti.h"
+#include "mddihost.h"
+#include <mach/gpio.h>
+#include <mach/clk.h>
-#define CMD_GET_CLIENT_CAP 0x0601
-#define CMD_GET_CLIENT_STATUS 0x0602
+static int mddi_probe(struct platform_device *pdev);
+static int mddi_remove(struct platform_device *pdev);
-union mddi_rev {
- unsigned char raw[MDDI_REV_BUFFER_SIZE];
- struct mddi_rev_packet hdr;
- struct mddi_client_status status;
- struct mddi_client_caps caps;
- struct mddi_register_access reg;
-};
+static int mddi_off(struct platform_device *pdev);
+static int mddi_on(struct platform_device *pdev);
-struct reg_read_info {
- struct completion done;
- uint32_t reg;
- uint32_t status;
- uint32_t result;
-};
+#ifdef CONFIG_PM
+static int mddi_suspend(struct platform_device *pdev, pm_message_t state);
+static int mddi_resume(struct platform_device *pdev);
+#endif
-struct mddi_info {
- uint16_t flags;
- uint16_t version;
- char __iomem *base;
- int irq;
- struct clk *clk;
- struct msm_mddi_client_data client_data;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mddi_early_suspend(struct early_suspend *h);
+static void mddi_early_resume(struct early_suspend *h);
+#endif
- /* buffer for rev encap packets */
- void *rev_data;
- dma_addr_t rev_addr;
- struct mddi_llentry *reg_write_data;
- dma_addr_t reg_write_addr;
- struct mddi_llentry *reg_read_data;
- dma_addr_t reg_read_addr;
- size_t rev_data_curr;
+static void pmdh_clk_disable(void);
+static void pmdh_clk_enable(void);
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+static struct clk *mddi_clk;
+static struct clk *mddi_pclk;
+static struct mddi_platform_data *mddi_pdata;
- spinlock_t int_lock;
- uint32_t int_enable;
- uint32_t got_int;
- wait_queue_head_t int_wait;
+DEFINE_MUTEX(mddi_timer_lock);
- struct mutex reg_write_lock;
- struct mutex reg_read_lock;
- struct reg_read_info *reg_read;
-
- struct mddi_client_caps caps;
- struct mddi_client_status status;
-
- void (*power_client)(struct msm_mddi_client_data *, int);
-
- /* client device published to bind us to the
- * appropriate mddi_client driver
- */
- char client_name[20];
-
- struct platform_device client_pdev;
-};
-
-static void mddi_init_rev_encap(struct mddi_info *mddi);
-
-#define mddi_readl(r) readl(mddi->base + (MDDI_##r))
-#define mddi_writel(v, r) writel((v), mddi->base + (MDDI_##r))
-
-void mddi_activate_link(struct msm_mddi_client_data *cdata)
+static int mddi_runtime_suspend(struct device *dev)
{
- struct mddi_info *mddi = container_of(cdata, struct mddi_info,
- client_data);
-
- mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
-}
-
-static void mddi_handle_link_list_done(struct mddi_info *mddi)
-{
-}
-
-static void mddi_reset_rev_encap_ptr(struct mddi_info *mddi)
-{
- printk(KERN_INFO "mddi: resetting rev ptr\n");
- mddi->rev_data_curr = 0;
- mddi_writel(mddi->rev_addr, REV_PTR);
- mddi_writel(mddi->rev_addr, REV_PTR);
- mddi_writel(MDDI_CMD_FORCE_NEW_REV_PTR, CMD);
-}
-
-static void mddi_handle_rev_data(struct mddi_info *mddi, union mddi_rev *rev)
-{
- int i;
- struct reg_read_info *ri;
-
- if ((rev->hdr.length <= MDDI_REV_BUFFER_SIZE - 2) &&
- (rev->hdr.length >= sizeof(struct mddi_rev_packet) - 2)) {
-
- switch (rev->hdr.type) {
- case TYPE_CLIENT_CAPS:
- memcpy(&mddi->caps, &rev->caps,
- sizeof(struct mddi_client_caps));
- mddi->flags |= FLAG_HAVE_CAPS;
- wake_up(&mddi->int_wait);
- break;
- case TYPE_CLIENT_STATUS:
- memcpy(&mddi->status, &rev->status,
- sizeof(struct mddi_client_status));
- mddi->flags |= FLAG_HAVE_STATUS;
- wake_up(&mddi->int_wait);
- break;
- case TYPE_REGISTER_ACCESS:
- ri = mddi->reg_read;
- if (ri == 0) {
- printk(KERN_INFO "rev: got reg %x = %x without "
- " pending read\n",
- rev->reg.register_address,
- rev->reg.register_data_list);
- break;
- }
- if (ri->reg != rev->reg.register_address) {
- printk(KERN_INFO "rev: got reg %x = %x for "
- "wrong register, expected "
- "%x\n",
- rev->reg.register_address,
- rev->reg.register_data_list, ri->reg);
- break;
- }
- mddi->reg_read = NULL;
- ri->status = 0;
- ri->result = rev->reg.register_data_list;
- complete(&ri->done);
- break;
- default:
- printk(KERN_INFO "rev: unknown reverse packet: "
- "len=%04x type=%04x CURR_REV_PTR=%x\n",
- rev->hdr.length, rev->hdr.type,
- mddi_readl(CURR_REV_PTR));
- for (i = 0; i < rev->hdr.length + 2; i++) {
- if ((i % 16) == 0)
- printk(KERN_INFO "\n");
- printk(KERN_INFO " %02x", rev->raw[i]);
- }
- printk(KERN_INFO "\n");
- mddi_reset_rev_encap_ptr(mddi);
- }
- } else {
- printk(KERN_INFO "bad rev length, %d, CURR_REV_PTR %x\n",
- rev->hdr.length, mddi_readl(CURR_REV_PTR));
- mddi_reset_rev_encap_ptr(mddi);
- }
-}
-
-static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask);
-
-static void mddi_handle_rev_data_avail(struct mddi_info *mddi)
-{
- uint32_t rev_data_count;
- uint32_t rev_crc_err_count;
- struct reg_read_info *ri;
- size_t prev_offset;
- uint16_t length;
-
- union mddi_rev *crev = mddi->rev_data + mddi->rev_data_curr;
-
- /* clear the interrupt */
- mddi_writel(MDDI_INT_REV_DATA_AVAIL, INT);
- rev_data_count = mddi_readl(REV_PKT_CNT);
- rev_crc_err_count = mddi_readl(REV_CRC_ERR);
- if (rev_data_count > 1)
- printk(KERN_INFO "rev_data_count %d\n", rev_data_count);
-
- if (rev_crc_err_count) {
- printk(KERN_INFO "rev_crc_err_count %d, INT %x\n",
- rev_crc_err_count, mddi_readl(INT));
- ri = mddi->reg_read;
- if (ri == 0) {
- printk(KERN_INFO "rev: got crc error without pending "
- "read\n");
- } else {
- mddi->reg_read = NULL;
- ri->status = -EIO;
- ri->result = -1;
- complete(&ri->done);
- }
- }
-
- if (rev_data_count == 0)
- return;
-
- prev_offset = mddi->rev_data_curr;
-
- length = *((uint8_t *)mddi->rev_data + mddi->rev_data_curr);
- mddi->rev_data_curr++;
- if (mddi->rev_data_curr == MDDI_REV_BUFFER_SIZE)
- mddi->rev_data_curr = 0;
- length += *((uint8_t *)mddi->rev_data + mddi->rev_data_curr) << 8;
- mddi->rev_data_curr += 1 + length;
- if (mddi->rev_data_curr >= MDDI_REV_BUFFER_SIZE)
- mddi->rev_data_curr =
- mddi->rev_data_curr % MDDI_REV_BUFFER_SIZE;
-
- if (length > MDDI_REV_BUFFER_SIZE - 2) {
- printk(KERN_INFO "mddi: rev data length greater than buffer"
- "size\n");
- mddi_reset_rev_encap_ptr(mddi);
- return;
- }
-
- if (prev_offset + 2 + length >= MDDI_REV_BUFFER_SIZE) {
- union mddi_rev tmprev;
- size_t rem = MDDI_REV_BUFFER_SIZE - prev_offset;
- memcpy(&tmprev.raw[0], mddi->rev_data + prev_offset, rem);
- memcpy(&tmprev.raw[rem], mddi->rev_data, 2 + length - rem);
- mddi_handle_rev_data(mddi, &tmprev);
- } else {
- mddi_handle_rev_data(mddi, crev);
- }
-
- if (prev_offset < MDDI_REV_BUFFER_SIZE / 2 &&
- mddi->rev_data_curr >= MDDI_REV_BUFFER_SIZE / 2) {
- mddi_writel(mddi->rev_addr, REV_PTR);
- }
-}
-
-static irqreturn_t mddi_isr(int irq, void *data)
-{
- struct msm_mddi_client_data *cdata = data;
- struct mddi_info *mddi = container_of(cdata, struct mddi_info,
- client_data);
- uint32_t active, status;
-
- spin_lock(&mddi->int_lock);
-
- active = mddi_readl(INT);
- status = mddi_readl(STAT);
-
- mddi_writel(active, INT);
-
- /* ignore any interrupts we have disabled */
- active &= mddi->int_enable;
-
- mddi->got_int |= active;
- wake_up(&mddi->int_wait);
-
- if (active & MDDI_INT_PRI_LINK_LIST_DONE) {
- mddi->int_enable &= (~MDDI_INT_PRI_LINK_LIST_DONE);
- mddi_handle_link_list_done(mddi);
- }
- if (active & MDDI_INT_REV_DATA_AVAIL)
- mddi_handle_rev_data_avail(mddi);
-
- if (active & ~MDDI_INT_NEED_CLEAR)
- mddi->int_enable &= ~(active & ~MDDI_INT_NEED_CLEAR);
-
- if (active & MDDI_INT_LINK_ACTIVE) {
- mddi->int_enable &= (~MDDI_INT_LINK_ACTIVE);
- mddi->int_enable |= MDDI_INT_IN_HIBERNATION;
- }
-
- if (active & MDDI_INT_IN_HIBERNATION) {
- mddi->int_enable &= (~MDDI_INT_IN_HIBERNATION);
- mddi->int_enable |= MDDI_INT_LINK_ACTIVE;
- }
-
- mddi_writel(mddi->int_enable, INTEN);
- spin_unlock(&mddi->int_lock);
-
- return IRQ_HANDLED;
-}
-
-static long mddi_wait_interrupt_timeout(struct mddi_info *mddi,
- uint32_t intmask, int timeout)
-{
- unsigned long irq_flags;
-
- spin_lock_irqsave(&mddi->int_lock, irq_flags);
- mddi->got_int &= ~intmask;
- mddi->int_enable |= intmask;
- mddi_writel(mddi->int_enable, INTEN);
- spin_unlock_irqrestore(&mddi->int_lock, irq_flags);
- return wait_event_timeout(mddi->int_wait, mddi->got_int & intmask,
- timeout);
-}
-
-static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask)
-{
- if (mddi_wait_interrupt_timeout(mddi, intmask, HZ/10) == 0)
- printk(KERN_INFO "mddi_wait_interrupt %d, timeout "
- "waiting for %x, INT = %x, STAT = %x gotint = %x\n",
- current->pid, intmask, mddi_readl(INT), mddi_readl(STAT),
- mddi->got_int);
-}
-
-static void mddi_init_rev_encap(struct mddi_info *mddi)
-{
- memset(mddi->rev_data, 0xee, MDDI_REV_BUFFER_SIZE);
- mddi_writel(mddi->rev_addr, REV_PTR);
- mddi_writel(MDDI_CMD_FORCE_NEW_REV_PTR, CMD);
- mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-}
-
-void mddi_set_auto_hibernate(struct msm_mddi_client_data *cdata, int on)
-{
- struct mddi_info *mddi = container_of(cdata, struct mddi_info,
- client_data);
- mddi_writel(MDDI_CMD_POWERDOWN, CMD);
- mddi_wait_interrupt(mddi, MDDI_INT_IN_HIBERNATION);
- mddi_writel(MDDI_CMD_HIBERNATE | !!on, CMD);
- mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-}
-
-
-static uint16_t mddi_init_registers(struct mddi_info *mddi)
-{
- mddi_writel(0x0001, VERSION);
- mddi_writel(MDDI_HOST_BYTES_PER_SUBFRAME, BPS);
- mddi_writel(0x0003, SPM); /* subframes per media */
- mddi_writel(0x0005, TA1_LEN);
- mddi_writel(MDDI_HOST_TA2_LEN, TA2_LEN);
- mddi_writel(0x0096, DRIVE_HI);
- /* 0x32 normal, 0x50 for Toshiba display */
- mddi_writel(0x0050, DRIVE_LO);
- mddi_writel(0x003C, DISP_WAKE); /* wakeup counter */
- mddi_writel(MDDI_HOST_REV_RATE_DIV, REV_RATE_DIV);
-
- mddi_writel(MDDI_REV_BUFFER_SIZE, REV_SIZE);
- mddi_writel(MDDI_MAX_REV_PKT_SIZE, REV_ENCAP_SZ);
-
- /* disable periodic rev encap */
- mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP, CMD);
- mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-
- if (mddi_readl(PAD_CTL) == 0) {
- /* If we are turning on band gap, need to wait 5us before
- * turning on the rest of the PAD */
- mddi_writel(0x08000, PAD_CTL);
- udelay(5);
- }
-
- /* Recommendation from PAD hw team */
- mddi_writel(0xa850f, PAD_CTL);
-
-
- /* Need an even number for counts */
- mddi_writel(0x60006, DRIVER_START_CNT);
-
- mddi_set_auto_hibernate(&mddi->client_data, 0);
-
- mddi_writel(MDDI_CMD_DISP_IGNORE, CMD);
- mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-
- mddi_init_rev_encap(mddi);
- return mddi_readl(CORE_VER) & 0xffff;
-}
-
-static void mddi_suspend(struct msm_mddi_client_data *cdata)
-{
- struct mddi_info *mddi = container_of(cdata, struct mddi_info,
- client_data);
- /* turn off the client */
- if (mddi->power_client)
- mddi->power_client(&mddi->client_data, 0);
- /* turn off the link */
- mddi_writel(MDDI_CMD_RESET, CMD);
- mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
- /* turn off the clock */
- clk_disable(mddi->clk);
-}
-
-static void mddi_resume(struct msm_mddi_client_data *cdata)
-{
- struct mddi_info *mddi = container_of(cdata, struct mddi_info,
- client_data);
- mddi_set_auto_hibernate(&mddi->client_data, 0);
- /* turn on the client */
- if (mddi->power_client)
- mddi->power_client(&mddi->client_data, 1);
- /* turn on the clock */
- clk_enable(mddi->clk);
- /* set up the local registers */
- mddi->rev_data_curr = 0;
- mddi_init_registers(mddi);
- mddi_writel(mddi->int_enable, INTEN);
- mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
- mddi_writel(MDDI_CMD_SEND_RTD, CMD);
- mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
- mddi_set_auto_hibernate(&mddi->client_data, 1);
-}
-
-static int __init mddi_get_client_caps(struct mddi_info *mddi)
-{
- int i, j;
-
- /* clear any stale interrupts */
- mddi_writel(0xffffffff, INT);
-
- mddi->int_enable = MDDI_INT_LINK_ACTIVE |
- MDDI_INT_IN_HIBERNATION |
- MDDI_INT_PRI_LINK_LIST_DONE |
- MDDI_INT_REV_DATA_AVAIL |
- MDDI_INT_REV_OVERFLOW |
- MDDI_INT_REV_OVERWRITE |
- MDDI_INT_RTD_FAILURE;
- mddi_writel(mddi->int_enable, INTEN);
-
- mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
- mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-
- for (j = 0; j < 3; j++) {
- /* the toshiba vga panel does not respond to get
- * caps unless you SEND_RTD, but the first SEND_RTD
- * will fail...
- */
- for (i = 0; i < 4; i++) {
- uint32_t stat;
-
- mddi_writel(MDDI_CMD_SEND_RTD, CMD);
- mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
- stat = mddi_readl(STAT);
- printk(KERN_INFO "mddi cmd send rtd: int %x, stat %x, "
- "rtd val %x\n", mddi_readl(INT), stat,
- mddi_readl(RTD_VAL));
- if ((stat & MDDI_STAT_RTD_MEAS_FAIL) == 0)
- break;
- msleep(1);
- }
-
- mddi_writel(CMD_GET_CLIENT_CAP, CMD);
- mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
- wait_event_timeout(mddi->int_wait, mddi->flags & FLAG_HAVE_CAPS,
- HZ / 100);
-
- if (mddi->flags & FLAG_HAVE_CAPS)
- break;
- printk(KERN_INFO "mddi_init, timeout waiting for caps\n");
- }
- return mddi->flags & FLAG_HAVE_CAPS;
-}
-
-/* link must be active when this is called */
-int mddi_check_status(struct mddi_info *mddi)
-{
- int ret = -1, retry = 3;
- mutex_lock(&mddi->reg_read_lock);
- mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 1, CMD);
- mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-
- do {
- mddi->flags &= ~FLAG_HAVE_STATUS;
- mddi_writel(CMD_GET_CLIENT_STATUS, CMD);
- mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
- wait_event_timeout(mddi->int_wait,
- mddi->flags & FLAG_HAVE_STATUS,
- HZ / 100);
-
- if (mddi->flags & FLAG_HAVE_STATUS) {
- if (mddi->status.crc_error_count)
- printk(KERN_INFO "mddi status: crc_error "
- "count: %d\n",
- mddi->status.crc_error_count);
- else
- ret = 0;
- break;
- } else
- printk(KERN_INFO "mddi status: failed to get client "
- "status\n");
- mddi_writel(MDDI_CMD_SEND_RTD, CMD);
- mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
- } while (--retry);
-
- mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 0, CMD);
- mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
- mutex_unlock(&mddi->reg_read_lock);
- return ret;
-}
-
-
-void mddi_remote_write(struct msm_mddi_client_data *cdata, uint32_t val,
- uint32_t reg)
-{
- struct mddi_info *mddi = container_of(cdata, struct mddi_info,
- client_data);
- struct mddi_llentry *ll;
- struct mddi_register_access *ra;
-
- mutex_lock(&mddi->reg_write_lock);
-
- ll = mddi->reg_write_data;
-
- ra = &(ll->u.r);
- ra->length = 14 + 4;
- ra->type = TYPE_REGISTER_ACCESS;
- ra->client_id = 0;
- ra->read_write_info = MDDI_WRITE | 1;
- ra->crc16 = 0;
-
- ra->register_address = reg;
- ra->register_data_list = val;
-
- ll->flags = 1;
- ll->header_count = 14;
- ll->data_count = 4;
- ll->data = mddi->reg_write_addr + offsetof(struct mddi_llentry,
- u.r.register_data_list);
- ll->next = 0;
- ll->reserved = 0;
-
- mddi_writel(mddi->reg_write_addr, PRI_PTR);
-
- mddi_wait_interrupt(mddi, MDDI_INT_PRI_LINK_LIST_DONE);
- mutex_unlock(&mddi->reg_write_lock);
-}
-
-uint32_t mddi_remote_read(struct msm_mddi_client_data *cdata, uint32_t reg)
-{
- struct mddi_info *mddi = container_of(cdata, struct mddi_info,
- client_data);
- struct mddi_llentry *ll;
- struct mddi_register_access *ra;
- struct reg_read_info ri;
- unsigned s;
- int retry_count = 2;
- unsigned long irq_flags;
-
- mutex_lock(&mddi->reg_read_lock);
-
- ll = mddi->reg_read_data;
-
- ra = &(ll->u.r);
- ra->length = 14;
- ra->type = TYPE_REGISTER_ACCESS;
- ra->client_id = 0;
- ra->read_write_info = MDDI_READ | 1;
- ra->crc16 = 0;
-
- ra->register_address = reg;
-
- ll->flags = 0x11;
- ll->header_count = 14;
- ll->data_count = 0;
- ll->data = 0;
- ll->next = 0;
- ll->reserved = 0;
-
- s = mddi_readl(STAT);
-
- ri.reg = reg;
- ri.status = -1;
-
- do {
- init_completion(&ri.done);
- mddi->reg_read = &ri;
- mddi_writel(mddi->reg_read_addr, PRI_PTR);
-
- mddi_wait_interrupt(mddi, MDDI_INT_PRI_LINK_LIST_DONE);
-
- /* Enable Periodic Reverse Encapsulation. */
- mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 1, CMD);
- mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
- if (wait_for_completion_timeout(&ri.done, HZ/10) == 0 &&
- !ri.done.done) {
- printk(KERN_INFO "mddi_remote_read(%x) timeout "
- "(%d %d %d)\n",
- reg, ri.status, ri.result, ri.done.done);
- spin_lock_irqsave(&mddi->int_lock, irq_flags);
- mddi->reg_read = NULL;
- spin_unlock_irqrestore(&mddi->int_lock, irq_flags);
- ri.status = -1;
- ri.result = -1;
- }
- if (ri.status == 0)
- break;
-
- mddi_writel(MDDI_CMD_SEND_RTD, CMD);
- mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
- mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
- printk(KERN_INFO "mddi_remote_read: failed, sent "
- "MDDI_CMD_SEND_RTD: int %x, stat %x, rtd val %x "
- "curr_rev_ptr %x\n", mddi_readl(INT), mddi_readl(STAT),
- mddi_readl(RTD_VAL), mddi_readl(CURR_REV_PTR));
- } while (retry_count-- > 0);
- /* Disable Periodic Reverse Encapsulation. */
- mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 0, CMD);
- mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
- mddi->reg_read = NULL;
- mutex_unlock(&mddi->reg_read_lock);
- return ri.result;
-}
-
-static struct mddi_info mddi_info[2];
-
-static int __init mddi_clk_setup(struct platform_device *pdev,
- struct mddi_info *mddi,
- unsigned long clk_rate)
-{
- int ret;
-
- /* set up the clocks */
- mddi->clk = clk_get(&pdev->dev, "mddi_clk");
- if (IS_ERR(mddi->clk)) {
- printk(KERN_INFO "mddi: failed to get clock\n");
- return PTR_ERR(mddi->clk);
- }
- ret = clk_enable(mddi->clk);
- if (ret)
- goto fail;
- ret = clk_set_rate(mddi->clk, clk_rate);
- if (ret)
- goto fail;
- return 0;
-
-fail:
- clk_put(mddi->clk);
- return ret;
-}
-
-static int __init mddi_rev_data_setup(struct mddi_info *mddi)
-{
- void *dma;
- dma_addr_t dma_addr;
-
- /* set up dma buffer */
- dma = dma_alloc_coherent(NULL, 0x1000, &dma_addr, GFP_KERNEL);
- if (dma == 0)
- return -ENOMEM;
- mddi->rev_data = dma;
- mddi->rev_data_curr = 0;
- mddi->rev_addr = dma_addr;
- mddi->reg_write_data = dma + MDDI_REV_BUFFER_SIZE;
- mddi->reg_write_addr = dma_addr + MDDI_REV_BUFFER_SIZE;
- mddi->reg_read_data = mddi->reg_write_data + 1;
- mddi->reg_read_addr = mddi->reg_write_addr +
- sizeof(*mddi->reg_write_data);
+ dev_dbg(dev, "pm_runtime: suspending...\n");
return 0;
}
-static int __devinit mddi_probe(struct platform_device *pdev)
+static int mddi_runtime_resume(struct device *dev)
{
- struct msm_mddi_platform_data *pdata = pdev->dev.platform_data;
- struct mddi_info *mddi = &mddi_info[pdev->id];
- struct resource *resource;
- int ret, i;
-
- resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!resource) {
- printk(KERN_ERR "mddi: no associated mem resource!\n");
- return -ENOMEM;
- }
- mddi->base = ioremap(resource->start, resource_size(resource));
- if (!mddi->base) {
- printk(KERN_ERR "mddi: failed to remap base!\n");
- ret = -EINVAL;
- goto error_ioremap;
- }
- resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!resource) {
- printk(KERN_ERR "mddi: no associated irq resource!\n");
- ret = -EINVAL;
- goto error_get_irq_resource;
- }
- mddi->irq = resource->start;
- printk(KERN_INFO "mddi: init() base=0x%p irq=%d\n", mddi->base,
- mddi->irq);
- mddi->power_client = pdata->power_client;
-
- mutex_init(&mddi->reg_write_lock);
- mutex_init(&mddi->reg_read_lock);
- spin_lock_init(&mddi->int_lock);
- init_waitqueue_head(&mddi->int_wait);
-
- ret = mddi_clk_setup(pdev, mddi, pdata->clk_rate);
- if (ret) {
- printk(KERN_ERR "mddi: failed to setup clock!\n");
- goto error_clk_setup;
- }
-
- ret = mddi_rev_data_setup(mddi);
- if (ret) {
- printk(KERN_ERR "mddi: failed to setup rev data!\n");
- goto error_rev_data;
- }
-
- mddi->int_enable = 0;
- mddi_writel(mddi->int_enable, INTEN);
- ret = request_irq(mddi->irq, mddi_isr, IRQF_DISABLED, "mddi",
- &mddi->client_data);
- if (ret) {
- printk(KERN_ERR "mddi: failed to request enable irq!\n");
- goto error_request_irq;
- }
-
- /* turn on the mddi client bridge chip */
- if (mddi->power_client)
- mddi->power_client(&mddi->client_data, 1);
-
- /* initialize the mddi registers */
- mddi_set_auto_hibernate(&mddi->client_data, 0);
- mddi_writel(MDDI_CMD_RESET, CMD);
- mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
- mddi->version = mddi_init_registers(mddi);
- if (mddi->version < 0x20) {
- printk(KERN_ERR "mddi: unsupported version 0x%x\n",
- mddi->version);
- ret = -ENODEV;
- goto error_mddi_version;
- }
-
- /* read the capabilities off the client */
- if (!mddi_get_client_caps(mddi)) {
- printk(KERN_INFO "mddi: no client found\n");
- /* power down the panel */
- mddi_writel(MDDI_CMD_POWERDOWN, CMD);
- printk(KERN_INFO "mddi powerdown: stat %x\n", mddi_readl(STAT));
- msleep(100);
- printk(KERN_INFO "mddi powerdown: stat %x\n", mddi_readl(STAT));
- return 0;
- }
- mddi_set_auto_hibernate(&mddi->client_data, 1);
-
- if (mddi->caps.Mfr_Name == 0 && mddi->caps.Product_Code == 0)
- pdata->fixup(&mddi->caps.Mfr_Name, &mddi->caps.Product_Code);
-
- mddi->client_pdev.id = 0;
- for (i = 0; i < pdata->num_clients; i++) {
- if (pdata->client_platform_data[i].product_id ==
- (mddi->caps.Mfr_Name << 16 | mddi->caps.Product_Code)) {
- mddi->client_data.private_client_data =
- pdata->client_platform_data[i].client_data;
- mddi->client_pdev.name =
- pdata->client_platform_data[i].name;
- mddi->client_pdev.id =
- pdata->client_platform_data[i].id;
- /* XXX: possibly set clock */
- break;
- }
- }
-
- if (i >= pdata->num_clients)
- mddi->client_pdev.name = "mddi_c_dummy";
- printk(KERN_INFO "mddi: registering panel %s\n",
- mddi->client_pdev.name);
-
- mddi->client_data.suspend = mddi_suspend;
- mddi->client_data.resume = mddi_resume;
- mddi->client_data.activate_link = mddi_activate_link;
- mddi->client_data.remote_write = mddi_remote_write;
- mddi->client_data.remote_read = mddi_remote_read;
- mddi->client_data.auto_hibernate = mddi_set_auto_hibernate;
- mddi->client_data.fb_resource = pdata->fb_resource;
- if (pdev->id == 0)
- mddi->client_data.interface_type = MSM_MDDI_PMDH_INTERFACE;
- else if (pdev->id == 1)
- mddi->client_data.interface_type = MSM_MDDI_EMDH_INTERFACE;
- else {
- printk(KERN_ERR "mddi: can not determine interface %d!\n",
- pdev->id);
- ret = -EINVAL;
- goto error_mddi_interface;
- }
-
- mddi->client_pdev.dev.platform_data = &mddi->client_data;
- printk(KERN_INFO "mddi: publish: %s\n", mddi->client_name);
- platform_device_register(&mddi->client_pdev);
+ dev_dbg(dev, "pm_runtime: resuming...\n");
return 0;
-
-error_mddi_interface:
-error_mddi_version:
- free_irq(mddi->irq, 0);
-error_request_irq:
- dma_free_coherent(NULL, 0x1000, mddi->rev_data, mddi->rev_addr);
-error_rev_data:
-error_clk_setup:
-error_get_irq_resource:
- iounmap(mddi->base);
-error_ioremap:
-
- printk(KERN_INFO "mddi: mddi_init() failed (%d)\n", ret);
- return ret;
}
+static int mddi_runtime_idle(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: idling...\n");
+ return 0;
+}
+
+static struct dev_pm_ops mddi_dev_pm_ops = {
+ .runtime_suspend = mddi_runtime_suspend,
+ .runtime_resume = mddi_runtime_resume,
+ .runtime_idle = mddi_runtime_idle,
+};
+
+static int pmdh_clk_status;
+int irq_enabled;
+unsigned char mddi_timer_shutdown_flag;
static struct platform_driver mddi_driver = {
.probe = mddi_probe,
- .driver = { .name = "msm_mddi" },
+ .remove = mddi_remove,
+#ifndef CONFIG_HAS_EARLYSUSPEND
+#ifdef CONFIG_PM
+ .suspend = mddi_suspend,
+ .resume = mddi_resume,
+#endif
+#endif
+ .shutdown = NULL,
+ .driver = {
+ .name = "mddi",
+ .pm = &mddi_dev_pm_ops,
+ },
};
-static int __init _mddi_init(void)
+extern int int_mddi_pri_flag;
+DEFINE_MUTEX(pmdh_clk_lock);
+
+int pmdh_clk_func(int value)
+{
+ int ret = 0;
+
+ switch (value) {
+ case 0:
+ pmdh_clk_disable();
+ break;
+ case 1:
+ pmdh_clk_enable();
+ break;
+ case 2:
+ default:
+ mutex_lock(&pmdh_clk_lock);
+ ret = pmdh_clk_status;
+ mutex_unlock(&pmdh_clk_lock);
+ break;
+ }
+ return ret;
+}
+
+static void pmdh_clk_disable()
+{
+ mutex_lock(&pmdh_clk_lock);
+ if (pmdh_clk_status == 0) {
+ mutex_unlock(&pmdh_clk_lock);
+ return;
+ }
+
+ if (mddi_host_timer.function) {
+ mutex_lock(&mddi_timer_lock);
+ mddi_timer_shutdown_flag = 1;
+ mutex_unlock(&mddi_timer_lock);
+ del_timer_sync(&mddi_host_timer);
+ mutex_lock(&mddi_timer_lock);
+ mddi_timer_shutdown_flag = 0;
+ mutex_unlock(&mddi_timer_lock);
+ }
+ if (int_mddi_pri_flag && irq_enabled) {
+ disable_irq(INT_MDDI_PRI);
+ irq_enabled = 0;
+ }
+
+ if (mddi_clk) {
+ clk_disable(mddi_clk);
+ pmdh_clk_status = 0;
+ }
+ if (mddi_pclk)
+ clk_disable(mddi_pclk);
+ mutex_unlock(&pmdh_clk_lock);
+}
+
+static void pmdh_clk_enable()
+{
+ mutex_lock(&pmdh_clk_lock);
+ if (pmdh_clk_status == 1) {
+ mutex_unlock(&pmdh_clk_lock);
+ return;
+ }
+
+ if (mddi_clk) {
+ clk_enable(mddi_clk);
+ pmdh_clk_status = 1;
+ }
+ if (mddi_pclk)
+ clk_enable(mddi_pclk);
+
+ if (int_mddi_pri_flag && !irq_enabled) {
+ enable_irq(INT_MDDI_PRI);
+ irq_enabled = 1;
+ }
+
+ if (mddi_host_timer.function)
+ mddi_host_timer_service(0);
+
+ mutex_unlock(&pmdh_clk_lock);
+}
+
+static int mddi_off(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ boolean dma_pending, dma_update_flag;
+ int ret, i;
+
+ mfd = platform_get_drvdata(pdev);
+
+ for (i = 0; i < 6; i++) {
+ dma_update_flag = mfd->dma_update_flag;
+ dma_pending = mfd->dma->busy;
+ if (dma_update_flag && !dma_pending)
+ break;
+ msleep(5);
+ }
+
+ pmdh_clk_enable();
+ ret = panel_next_off(pdev);
+ pmdh_clk_disable();
+
+ if (mddi_pdata && mddi_pdata->mddi_power_save)
+ mddi_pdata->mddi_power_save(0);
+#ifdef CONFIG_MSM_BUS_SCALING
+ mdp_bus_scale_update_request(0);
+#else
+ if (mfd->ebi1_clk)
+ clk_disable(mfd->ebi1_clk);
+#endif
+ pm_runtime_put(&pdev->dev);
+ return ret;
+}
+
+static int mddi_on(struct platform_device *pdev)
+{
+ int ret = 0;
+ u32 clk_rate;
+ struct msm_fb_data_type *mfd;
+#ifdef ENABLE_FWD_LINK_SKEW_CALIBRATION
+ mddi_host_type host_idx = MDDI_HOST_PRIM;
+ u32 stat_reg;
+#endif
+
+ mfd = platform_get_drvdata(pdev);
+ pm_runtime_get(&pdev->dev);
+ if (mddi_pdata && mddi_pdata->mddi_power_save)
+ mddi_pdata->mddi_power_save(1);
+
+ pmdh_clk_enable();
+#ifdef ENABLE_FWD_LINK_SKEW_CALIBRATION
+ if (mddi_client_type < 2) {
+ /* For skew calibration, clock should be less than 50MHz */
+ if (!clk_set_min_rate(mddi_clk, 49000000)) {
+ stat_reg = mddi_host_reg_in(STAT);
+ printk(KERN_DEBUG "\n stat_reg = 0x%x", stat_reg);
+ mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
+ if (stat_reg & (0x1 << 4))
+ mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
+
+ mddi_host_reg_out(CMD, MDDI_CMD_SEND_RTD);
+ mddi_send_fw_link_skew_cal(host_idx);
+ mddi_host_reg_out(CMD, MDDI_CMD_SEND_RTD);
+ mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
+ } else {
+ printk(KERN_ERR "%s: clk_set_min_rate failed\n",
+ __func__);
+ }
+ }
+#endif
+
+ clk_rate = mfd->fbi->var.pixclock;
+ clk_rate = min(clk_rate, mfd->panel_info.clk_max);
+
+ if (mddi_pdata &&
+ mddi_pdata->mddi_sel_clk &&
+ mddi_pdata->mddi_sel_clk(&clk_rate))
+ printk(KERN_ERR
+ "%s: can't select mddi io clk targate rate = %d\n",
+ __func__, clk_rate);
+
+ if (clk_set_min_rate(mddi_clk, clk_rate) < 0)
+ printk(KERN_ERR "%s: clk_set_min_rate failed\n",
+ __func__);
+
+#ifdef CONFIG_MSM_BUS_SCALING
+ mdp_bus_scale_update_request(2);
+#else
+ if (mfd->ebi1_clk)
+ clk_enable(mfd->ebi1_clk);
+#endif
+ ret = panel_next_on(pdev);
+
+ return ret;
+}
+
+static int mddi_resource_initialized;
+
+static int mddi_probe(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct platform_device *mdp_dev = NULL;
+ struct msm_fb_panel_data *pdata = NULL;
+ int rc;
+ resource_size_t size ;
+ u32 clk_rate;
+
+ if ((pdev->id == 0) && (pdev->num_resources >= 0)) {
+ mddi_pdata = pdev->dev.platform_data;
+
+ size = resource_size(&pdev->resource[0]);
+ msm_pmdh_base = ioremap(pdev->resource[0].start, size);
+
+ MSM_FB_INFO("primary mddi base phy_addr = 0x%x virt = 0x%x\n",
+ pdev->resource[0].start, (int) msm_pmdh_base);
+
+ if (unlikely(!msm_pmdh_base))
+ return -ENOMEM;
+
+ if (mddi_pdata && mddi_pdata->mddi_power_save)
+ mddi_pdata->mddi_power_save(1);
+
+ mddi_resource_initialized = 1;
+ return 0;
+ }
+
+ if (!mddi_resource_initialized)
+ return -EPERM;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+ return -ENOMEM;
+
+ mdp_dev = platform_device_alloc("mdp", pdev->id);
+ if (!mdp_dev)
+ return -ENOMEM;
+
+ /*
+ * link to the latest pdev
+ */
+ mfd->pdev = mdp_dev;
+ mfd->dest = DISPLAY_LCD;
+
+ /*
+ * alloc panel device data
+ */
+ if (platform_device_add_data
+ (mdp_dev, pdev->dev.platform_data,
+ sizeof(struct msm_fb_panel_data))) {
+ printk(KERN_ERR "mddi_probe: platform_device_add_data failed!\n");
+ platform_device_put(mdp_dev);
+ return -ENOMEM;
+ }
+ /*
+ * data chain
+ */
+ pdata = mdp_dev->dev.platform_data;
+ pdata->on = mddi_on;
+ pdata->off = mddi_off;
+ pdata->next = pdev;
+ pdata->clk_func = pmdh_clk_func;
+ /*
+ * get/set panel specific fb info
+ */
+ mfd->panel_info = pdata->panel_info;
+
+ if (mfd->index == 0)
+ mfd->fb_imgType = MSMFB_DEFAULT_TYPE;
+ else
+ mfd->fb_imgType = MDP_RGB_565;
+
+ clk_rate = mfd->panel_info.clk_max;
+ if (mddi_pdata &&
+ mddi_pdata->mddi_sel_clk &&
+ mddi_pdata->mddi_sel_clk(&clk_rate))
+ printk(KERN_ERR
+ "%s: can't select mddi io clk targate rate = %d\n",
+ __func__, clk_rate);
+
+ if (clk_set_max_rate(mddi_clk, clk_rate) < 0)
+ printk(KERN_ERR "%s: clk_set_max_rate failed\n", __func__);
+ mfd->panel_info.clk_rate = mfd->panel_info.clk_min;
+
+ if (!mddi_client_type)
+ mddi_client_type = mfd->panel_info.lcd.rev;
+ else if (!mfd->panel_info.lcd.rev)
+ printk(KERN_ERR
+ "%s: mddi client is trying to revert back to type 1 !!!\n",
+ __func__);
+
+ /*
+ * set driver data
+ */
+ platform_set_drvdata(mdp_dev, mfd);
+ rc = pm_runtime_set_active(&pdev->dev);
+ if (rc < 0)
+ printk(KERN_ERR "pm_runtime: fail to set active\n");
+
+ rc = 0;
+ pm_runtime_enable(&pdev->dev);
+#ifndef CONFIG_MSM_BUS_SCALING
+ mfd->ebi1_clk = clk_get(NULL, "ebi1_mddi_clk");
+ if (IS_ERR(mfd->ebi1_clk))
+ return PTR_ERR(mfd->ebi1_clk);
+ clk_set_rate(mfd->ebi1_clk, 65000000);
+#endif
+ /*
+ * register in mdp driver
+ */
+ rc = platform_device_add(mdp_dev);
+ if (rc)
+ goto mddi_probe_err;
+
+ pdev_list[pdev_list_cnt++] = pdev;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ mfd->mddi_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
+ mfd->mddi_early_suspend.suspend = mddi_early_suspend;
+ mfd->mddi_early_suspend.resume = mddi_early_resume;
+ register_early_suspend(&mfd->mddi_early_suspend);
+#endif
+
+ return 0;
+
+mddi_probe_err:
+ platform_device_put(mdp_dev);
+ return rc;
+}
+
+static int mddi_pad_ctrl;
+static int mddi_power_locked;
+
+int mddi_client_power(unsigned int client_id)
+{
+ int ret = 0;
+ if (mddi_pdata && mddi_pdata->mddi_client_power)
+ ret = mddi_pdata->mddi_client_power(client_id);
+ return ret;
+}
+
+void mddi_disable(int lock)
+{
+ mddi_host_type host_idx = MDDI_HOST_PRIM;
+
+ if (mddi_power_locked)
+ return;
+
+ if (lock)
+ mddi_power_locked = 1;
+ pmdh_clk_enable();
+
+ mddi_pad_ctrl = mddi_host_reg_in(PAD_CTL);
+ mddi_host_reg_out(PAD_CTL, 0x0);
+
+ if (clk_set_min_rate(mddi_clk, 0) < 0)
+ printk(KERN_ERR "%s: clk_set_min_rate failed\n", __func__);
+
+ pmdh_clk_disable();
+
+ if (mddi_pdata && mddi_pdata->mddi_power_save)
+ mddi_pdata->mddi_power_save(0);
+}
+
+#ifdef CONFIG_PM
+static int mddi_is_in_suspend;
+
+static int mddi_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ mddi_host_type host_idx = MDDI_HOST_PRIM;
+ if (mddi_is_in_suspend)
+ return 0;
+
+ mddi_is_in_suspend = 1;
+
+ if (mddi_power_locked)
+ return 0;
+
+ pmdh_clk_enable();
+
+ mddi_pad_ctrl = mddi_host_reg_in(PAD_CTL);
+ mddi_host_reg_out(PAD_CTL, 0x0);
+
+ if (clk_set_min_rate(mddi_clk, 0) < 0)
+ printk(KERN_ERR "%s: clk_set_min_rate failed\n", __func__);
+
+ pmdh_clk_disable();
+
+ return 0;
+}
+
+static int mddi_resume(struct platform_device *pdev)
+{
+ mddi_host_type host_idx = MDDI_HOST_PRIM;
+
+ if (!mddi_is_in_suspend)
+ return 0;
+
+ mddi_is_in_suspend = 0;
+
+ if (mddi_power_locked)
+ return 0;
+
+ pmdh_clk_enable();
+
+ mddi_host_reg_out(PAD_CTL, mddi_pad_ctrl);
+
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mddi_early_suspend(struct early_suspend *h)
+{
+ pm_message_t state;
+ struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+ mddi_early_suspend);
+
+ state.event = PM_EVENT_SUSPEND;
+ mddi_suspend(mfd->pdev, state);
+}
+
+static void mddi_early_resume(struct early_suspend *h)
+{
+ struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+ mddi_early_suspend);
+ mddi_resume(mfd->pdev);
+}
+#endif
+
+static int mddi_remove(struct platform_device *pdev)
+{
+ pm_runtime_disable(&pdev->dev);
+ if (mddi_host_timer.function) {
+ mutex_lock(&mddi_timer_lock);
+ mddi_timer_shutdown_flag = 1;
+ mutex_unlock(&mddi_timer_lock);
+ del_timer_sync(&mddi_host_timer);
+ mutex_lock(&mddi_timer_lock);
+ mddi_timer_shutdown_flag = 0;
+ mutex_unlock(&mddi_timer_lock);
+ }
+
+ iounmap(msm_pmdh_base);
+
+ return 0;
+}
+
+static int mddi_register_driver(void)
{
return platform_driver_register(&mddi_driver);
}
-module_init(_mddi_init);
+static int __init mddi_driver_init(void)
+{
+ int ret;
+ pmdh_clk_status = 0;
+
+ mddi_clk = clk_get(NULL, "mddi_clk");
+ if (IS_ERR(mddi_clk)) {
+ printk(KERN_ERR "can't find mddi_clk\n");
+ return PTR_ERR(mddi_clk);
+ }
+ ret = clk_set_min_rate(mddi_clk, 49000000);
+ if (ret)
+ printk(KERN_ERR "Can't set mddi_clk min rate to 49000000\n");
+
+ printk(KERN_INFO "mddi_clk init rate is %lu\n",
+ clk_get_rate(mddi_clk));
+ mddi_pclk = clk_get(NULL, "mddi_pclk");
+ if (IS_ERR(mddi_pclk))
+ mddi_pclk = NULL;
+ pmdh_clk_enable();
+
+ ret = mddi_register_driver();
+ if (ret) {
+ pmdh_clk_disable();
+ clk_put(mddi_clk);
+ if (mddi_pclk)
+ clk_put(mddi_pclk);
+ printk(KERN_ERR "mddi_register_driver() failed!\n");
+ return ret;
+ }
+
+ mddi_init();
+
+ return ret;
+}
+
+module_init(mddi_driver_init);
diff --git a/drivers/video/msm/mddi_client_dummy.c b/drivers/video/msm/mddi_client_dummy.c
index d2a091c..ebbae87 100644
--- a/drivers/video/msm/mddi_client_dummy.c
+++ b/drivers/video/msm/mddi_client_dummy.c
@@ -15,7 +15,6 @@
* GNU General Public License for more details.
*/
-#include <linux/slab.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
diff --git a/drivers/video/msm/mddi_client_nt35399.c b/drivers/video/msm/mddi_client_nt35399.c
index f239f4a..c9e9349 100644
--- a/drivers/video/msm/mddi_client_nt35399.c
+++ b/drivers/video/msm/mddi_client_nt35399.c
@@ -21,7 +21,6 @@
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/gpio.h>
-#include <linux/slab.h>
#include <mach/msm_fb.h>
static DECLARE_WAIT_QUEUE_HEAD(nt35399_vsync_wait);
diff --git a/drivers/video/msm/mddi_client_toshiba.c b/drivers/video/msm/mddi_client_toshiba.c
index f9bc932..8868781 100644
--- a/drivers/video/msm/mddi_client_toshiba.c
+++ b/drivers/video/msm/mddi_client_toshiba.c
@@ -21,7 +21,6 @@
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/sched.h>
-#include <linux/slab.h>
#include <mach/msm_fb.h>
@@ -60,6 +59,7 @@
struct msm_panel_data panel_data;
struct msmfb_callback *toshiba_callback;
int toshiba_got_int;
+ int irq;
};
@@ -175,47 +175,6 @@
return IRQ_HANDLED;
}
-static int setup_vsync(struct panel_info *panel,
- int init)
-{
- int ret;
- int gpio = 97;
- unsigned int irq;
-
- if (!init) {
- ret = 0;
- goto uninit;
- }
- ret = gpio_request(gpio, "vsync");
- if (ret)
- goto err_request_gpio_failed;
-
- ret = gpio_direction_input(gpio);
- if (ret)
- goto err_gpio_direction_input_failed;
-
- ret = irq = gpio_to_irq(gpio);
- if (ret < 0)
- goto err_get_irq_num_failed;
-
- ret = request_irq(irq, toshiba_vsync_interrupt, IRQF_TRIGGER_RISING,
- "vsync", panel);
- if (ret)
- goto err_request_irq_failed;
- printk(KERN_INFO "vsync on gpio %d now %d\n",
- gpio, gpio_get_value(gpio));
- return 0;
-
-uninit:
- free_irq(gpio_to_irq(gpio), panel);
-err_request_irq_failed:
-err_get_irq_num_failed:
-err_gpio_direction_input_failed:
- gpio_free(gpio);
-err_request_gpio_failed:
- return ret;
-}
-
static int mddi_toshiba_probe(struct platform_device *pdev)
{
int ret;
@@ -232,10 +191,16 @@
client_data->remote_write(client_data, GPIOSEL_VWAKEINT, GPIOSEL);
client_data->remote_write(client_data, INTMASK_VWAKEOUT, INTMASK);
- ret = setup_vsync(panel, 1);
+ ret = platform_get_irq_byname(pdev, "vsync");
+ if (ret < 0)
+ goto err_plat_get_irq;
+
+ panel->irq = ret;
+ ret = request_irq(panel->irq, toshiba_vsync_interrupt,
+ IRQF_TRIGGER_RISING, "vsync", panel);
if (ret) {
dev_err(&pdev->dev, "mddi_bridge_setup_vsync failed\n");
- return ret;
+ goto err_req_irq;
}
panel->client_data = client_data;
@@ -258,13 +223,19 @@
platform_device_register(&panel->pdev);
return 0;
+
+err_req_irq:
+err_plat_get_irq:
+ kfree(panel);
+ return ret;
}
static int mddi_toshiba_remove(struct platform_device *pdev)
{
struct panel_info *panel = platform_get_drvdata(pdev);
- setup_vsync(panel, 0);
+ platform_set_drvdata(pdev, NULL);
+ free_irq(panel->irq, panel);
kfree(panel);
return 0;
}
diff --git a/drivers/video/msm/mddi_ext.c b/drivers/video/msm/mddi_ext.c
new file mode 100644
index 0000000..0ecd593
--- /dev/null
+++ b/drivers/video/msm/mddi_ext.c
@@ -0,0 +1,363 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <asm/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <mach/clk.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#include "msm_fb.h"
+#include "mddihosti.h"
+
+static int mddi_ext_probe(struct platform_device *pdev);
+static int mddi_ext_remove(struct platform_device *pdev);
+
+static int mddi_ext_off(struct platform_device *pdev);
+static int mddi_ext_on(struct platform_device *pdev);
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+
+static int mddi_ext_suspend(struct platform_device *pdev, pm_message_t state);
+static int mddi_ext_resume(struct platform_device *pdev);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mddi_ext_early_suspend(struct early_suspend *h);
+static void mddi_ext_early_resume(struct early_suspend *h);
+#endif
+
+static int mddi_ext_runtime_suspend(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: suspending...\n");
+ return 0;
+}
+
+static int mddi_ext_runtime_resume(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: resuming...\n");
+ return 0;
+}
+
+static int mddi_ext_runtime_idle(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: idling...\n");
+ return 0;
+}
+static struct dev_pm_ops mddi_ext_dev_pm_ops = {
+ .runtime_suspend = mddi_ext_runtime_suspend,
+ .runtime_resume = mddi_ext_runtime_resume,
+ .runtime_idle = mddi_ext_runtime_idle,
+};
+
+static struct platform_driver mddi_ext_driver = {
+ .probe = mddi_ext_probe,
+ .remove = mddi_ext_remove,
+#ifndef CONFIG_HAS_EARLYSUSPEND
+#ifdef CONFIG_PM
+ .suspend = mddi_ext_suspend,
+ .resume = mddi_ext_resume,
+#endif
+#endif
+ .resume_early = NULL,
+ .resume = NULL,
+ .shutdown = NULL,
+ .driver = {
+ .name = "mddi_ext",
+ .pm = &mddi_ext_dev_pm_ops,
+ },
+};
+
+static struct clk *mddi_ext_clk;
+static struct clk *mddi_ext_pclk;
+static struct mddi_platform_data *mddi_ext_pdata;
+
+extern int int_mddi_ext_flag;
+
+static int mddi_ext_off(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ ret = panel_next_off(pdev);
+ mddi_host_stop_ext_display();
+ pm_runtime_put(&pdev->dev);
+ return ret;
+}
+
+static int mddi_ext_on(struct platform_device *pdev)
+{
+ int ret = 0;
+ u32 clk_rate;
+ struct msm_fb_data_type *mfd;
+
+ mfd = platform_get_drvdata(pdev);
+ pm_runtime_get(&pdev->dev);
+ clk_rate = mfd->fbi->var.pixclock;
+ clk_rate = min(clk_rate, mfd->panel_info.clk_max);
+
+ if (mddi_ext_pdata &&
+ mddi_ext_pdata->mddi_sel_clk &&
+ mddi_ext_pdata->mddi_sel_clk(&clk_rate))
+ printk(KERN_ERR
+ "%s: can't select mddi io clk targate rate = %d\n",
+ __func__, clk_rate);
+
+ if (clk_set_min_rate(mddi_ext_clk, clk_rate) < 0)
+ printk(KERN_ERR "%s: clk_set_min_rate failed\n",
+ __func__);
+
+ mddi_host_start_ext_display();
+ ret = panel_next_on(pdev);
+
+ return ret;
+}
+
+static int mddi_ext_resource_initialized;
+
+static int mddi_ext_probe(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct platform_device *mdp_dev = NULL;
+ struct msm_fb_panel_data *pdata = NULL;
+ int rc;
+ resource_size_t size ;
+ u32 clk_rate;
+
+ if ((pdev->id == 0) && (pdev->num_resources >= 0)) {
+ mddi_ext_pdata = pdev->dev.platform_data;
+
+ size = resource_size(&pdev->resource[0]);
+ msm_emdh_base = ioremap(pdev->resource[0].start, size);
+
+ MSM_FB_INFO("external mddi base address = 0x%x\n",
+ pdev->resource[0].start);
+
+ if (unlikely(!msm_emdh_base))
+ return -ENOMEM;
+
+ mddi_ext_resource_initialized = 1;
+ return 0;
+ }
+
+ if (!mddi_ext_resource_initialized)
+ return -EPERM;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+ return -ENOMEM;
+
+ mdp_dev = platform_device_alloc("mdp", pdev->id);
+ if (!mdp_dev)
+ return -ENOMEM;
+
+ /*
+ * link to the latest pdev
+ */
+ mfd->pdev = mdp_dev;
+ mfd->dest = DISPLAY_EXT_MDDI;
+
+ /*
+ * alloc panel device data
+ */
+ if (platform_device_add_data
+ (mdp_dev, pdev->dev.platform_data,
+ sizeof(struct msm_fb_panel_data))) {
+ printk(KERN_ERR "mddi_ext_probe: platform_device_add_data failed!\n");
+ platform_device_put(mdp_dev);
+ return -ENOMEM;
+ }
+ /*
+ * data chain
+ */
+ pdata = mdp_dev->dev.platform_data;
+ pdata->on = mddi_ext_on;
+ pdata->off = mddi_ext_off;
+ pdata->next = pdev;
+
+ /*
+ * get/set panel specific fb info
+ */
+ mfd->panel_info = pdata->panel_info;
+ mfd->fb_imgType = MDP_RGB_565;
+
+ clk_rate = mfd->panel_info.clk_max;
+ if (mddi_ext_pdata &&
+ mddi_ext_pdata->mddi_sel_clk &&
+ mddi_ext_pdata->mddi_sel_clk(&clk_rate))
+ printk(KERN_ERR
+ "%s: can't select mddi io clk targate rate = %d\n",
+ __func__, clk_rate);
+
+ if (clk_set_max_rate(mddi_ext_clk, clk_rate) < 0)
+ printk(KERN_ERR "%s: clk_set_max_rate failed\n", __func__);
+ mfd->panel_info.clk_rate = mfd->panel_info.clk_min;
+
+ /*
+ * set driver data
+ */
+ platform_set_drvdata(mdp_dev, mfd);
+ rc = pm_runtime_set_active(&pdev->dev);
+ if (rc < 0)
+ printk(KERN_ERR "pm_runtime: fail to set active\n");
+
+ rc = 0;
+ pm_runtime_enable(&pdev->dev);
+ /*
+ * register in mdp driver
+ */
+ rc = platform_device_add(mdp_dev);
+ if (rc)
+ goto mddi_ext_probe_err;
+
+ pdev_list[pdev_list_cnt++] = pdev;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ mfd->mddi_ext_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
+ mfd->mddi_ext_early_suspend.suspend = mddi_ext_early_suspend;
+ mfd->mddi_ext_early_suspend.resume = mddi_ext_early_resume;
+ register_early_suspend(&mfd->mddi_ext_early_suspend);
+#endif
+
+ return 0;
+
+mddi_ext_probe_err:
+ platform_device_put(mdp_dev);
+ return rc;
+}
+
+static int mddi_ext_is_in_suspend;
+
+static int mddi_ext_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ if (mddi_ext_is_in_suspend)
+ return 0;
+
+ mddi_ext_is_in_suspend = 1;
+
+ if (clk_set_min_rate(mddi_ext_clk, 0) < 0)
+ printk(KERN_ERR "%s: clk_set_min_rate failed\n", __func__);
+
+ clk_disable(mddi_ext_clk);
+ if (mddi_ext_pclk)
+ clk_disable(mddi_ext_pclk);
+
+ disable_irq(INT_MDDI_EXT);
+
+ return 0;
+}
+
+static int mddi_ext_resume(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mddi_ext_is_in_suspend)
+ return 0;
+
+ mddi_ext_is_in_suspend = 0;
+ enable_irq(INT_MDDI_EXT);
+
+ clk_enable(mddi_ext_clk);
+ if (mddi_ext_pclk)
+ clk_enable(mddi_ext_pclk);
+
+ return 0;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mddi_ext_early_suspend(struct early_suspend *h)
+{
+ pm_message_t state;
+ struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+ mddi_ext_early_suspend);
+
+ state.event = PM_EVENT_SUSPEND;
+ mddi_ext_suspend(mfd->pdev, state);
+}
+
+static void mddi_ext_early_resume(struct early_suspend *h)
+{
+ struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+ mddi_ext_early_suspend);
+ mddi_ext_resume(mfd->pdev);
+}
+#endif
+
+static int mddi_ext_remove(struct platform_device *pdev)
+{
+ pm_runtim_disable(&pdev->dev);
+ iounmap(msm_emdh_base);
+ return 0;
+}
+
+static int mddi_ext_register_driver(void)
+{
+ return platform_driver_register(&mddi_ext_driver);
+}
+
+static int __init mddi_ext_driver_init(void)
+{
+ int ret;
+
+ mddi_ext_clk = clk_get(NULL, "emdh_clk");
+ if (IS_ERR(mddi_ext_clk)) {
+ printk(KERN_ERR "can't find emdh_clk\n");
+ return PTR_ERR(mddi_ext_clk);
+ }
+ clk_enable(mddi_ext_clk);
+
+ mddi_ext_pclk = clk_get(NULL, "emdh_pclk");
+ if (IS_ERR(mddi_ext_pclk))
+ mddi_ext_pclk = NULL;
+ else
+ clk_enable(mddi_ext_pclk);
+
+ ret = mddi_ext_register_driver();
+ if (ret) {
+ clk_disable(mddi_ext_clk);
+ clk_put(mddi_ext_clk);
+ if (mddi_ext_pclk) {
+ clk_disable(mddi_ext_pclk);
+ clk_put(mddi_ext_pclk);
+ }
+ printk(KERN_ERR "mddi_ext_register_driver() failed!\n");
+ return ret;
+ }
+ mddi_init();
+
+ return ret;
+}
+
+module_init(mddi_ext_driver_init);
diff --git a/drivers/video/msm/mddi_ext_lcd.c b/drivers/video/msm/mddi_ext_lcd.c
new file mode 100644
index 0000000..da79513
--- /dev/null
+++ b/drivers/video/msm/mddi_ext_lcd.c
@@ -0,0 +1,90 @@
+/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+static int mddi_ext_lcd_on(struct platform_device *pdev);
+static int mddi_ext_lcd_off(struct platform_device *pdev);
+
+static int mddi_ext_lcd_on(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int mddi_ext_lcd_off(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int __init mddi_ext_lcd_probe(struct platform_device *pdev)
+{
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = mddi_ext_lcd_probe,
+ .driver = {
+ .name = "extmddi_svga",
+ },
+};
+
+static struct msm_fb_panel_data mddi_ext_lcd_panel_data = {
+ .panel_info.xres = 800,
+ .panel_info.yres = 600,
+ .panel_info.mode2_xres = 0;
+ .panel_info.mode2_yres = 0;
+ .panel_info.mode2_bpp = 0;
+ .panel_info.type = EXT_MDDI_PANEL,
+ .panel_info.pdest = DISPLAY_1,
+ .panel_info.wait_cycle = 0,
+ .panel_info.bpp = 18,
+ .panel_info.fb_num = 2,
+ .panel_info.clk_rate = 122880000,
+ .panel_info.clk_min = 120000000,
+ .panel_info.clk_max = 125000000,
+ .on = mddi_ext_lcd_on,
+ .off = mddi_ext_lcd_off,
+};
+
+static struct platform_device this_device = {
+ .name = "extmddi_svga",
+ .id = 0,
+ .dev = {
+ .platform_data = &mddi_ext_lcd_panel_data,
+ }
+};
+
+static int __init mddi_ext_lcd_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+ ret = platform_driver_register(&this_driver);
+ if (!ret) {
+ pinfo = &mddi_ext_lcd_panel_data.panel_info;
+ pinfo->lcd.vsync_enable = FALSE;
+ pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+
+ ret = platform_device_register(&this_device);
+ if (ret)
+ platform_driver_unregister(&this_driver);
+ }
+
+ return ret;
+}
+
+module_init(mddi_ext_lcd_init);
diff --git a/drivers/video/msm/mddi_hw.h b/drivers/video/msm/mddi_hw.h
index 45cc01f..47bb449 100644
--- a/drivers/video/msm/mddi_hw.h
+++ b/drivers/video/msm/mddi_hw.h
@@ -53,6 +53,9 @@
#define MDDI_MF_CNT 0x0084
#define MDDI_CURR_REV_PTR 0x0088
#define MDDI_CORE_VER 0x008c
+#define MDDI_FIFO_ALLOC 0x0090
+#define MDDI_PAD_IO_CTL 0x00a0
+#define MDDI_PAD_CAL 0x00a4
#define MDDI_INT_PRI_PTR_READ 0x0001
#define MDDI_INT_SEC_PTR_READ 0x0002
@@ -125,8 +128,14 @@
/* MDP sends 256 pixel packets, so lower value hibernates more without
* significantly increasing latency of waiting for next subframe */
#define MDDI_HOST_BYTES_PER_SUBFRAME 0x3C00
+
+#if defined(CONFIG_MSM_MDP31) || defined(CONFIG_MSM_MDP40)
+#define MDDI_HOST_TA2_LEN 0x001a
+#define MDDI_HOST_REV_RATE_DIV 0x0004
+#else
#define MDDI_HOST_TA2_LEN 0x000c
#define MDDI_HOST_REV_RATE_DIV 0x0002
+#endif
struct __attribute__((packed)) mddi_rev_packet {
diff --git a/drivers/video/msm/mddi_orise.c b/drivers/video/msm/mddi_orise.c
new file mode 100644
index 0000000..dc913e6
--- /dev/null
+++ b/drivers/video/msm/mddi_orise.c
@@ -0,0 +1,127 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+#define MDDI_ORISE_1_2 1
+#define write_client_reg(__X, __Y, __Z) {\
+ mddi_queue_register_write(__X, __Y, TRUE, 0);\
+}
+
+static int mddi_orise_lcd_on(struct platform_device *pdev);
+static int mddi_orise_lcd_off(struct platform_device *pdev);
+static int __init mddi_orise_probe(struct platform_device *pdev);
+static int __init mddi_orise_init(void);
+
+/* function used to turn on the display */
+static void mddi_orise_prim_lcd_init(void)
+{
+ write_client_reg(0x00110000, 0, TRUE);
+ mddi_wait(150);
+ write_client_reg(0x00290000, 0, TRUE);
+}
+
+static struct platform_driver this_driver = {
+ .driver = {
+ .name = "mddi_orise",
+ },
+};
+
+static struct msm_fb_panel_data mddi_orise_panel_data = {
+ .on = mddi_orise_lcd_on,
+ .off = mddi_orise_lcd_off,
+};
+
+static struct platform_device this_device = {
+ .name = "mddi_orise",
+ .id = MDDI_ORISE_1_2,
+ .dev = {
+ .platform_data = &mddi_orise_panel_data,
+ }
+};
+
+static int mddi_orise_lcd_on(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ mfd = platform_get_drvdata(pdev);
+ if (!mfd)
+ return -ENODEV;
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ mddi_orise_prim_lcd_init();
+
+ return 0;
+}
+
+static int mddi_orise_lcd_off(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int __init mddi_orise_probe(struct platform_device *pdev)
+{
+ msm_fb_add_device(pdev);
+ return 0;
+}
+
+static int __init mddi_orise_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ u32 id;
+ ret = msm_fb_detect_client("mddi_orise");
+ if (ret == -ENODEV)
+ return 0;
+
+ if (ret) {
+ id = mddi_get_client_id();
+ if (((id >> 16) != 0xbe8d) || ((id & 0xffff) != 0x8031))
+ return 0;
+ }
+#endif
+ ret = platform_driver_probe(&this_driver, mddi_orise_probe);
+ if (!ret) {
+ pinfo = &mddi_orise_panel_data.panel_info;
+ pinfo->xres = 480;
+ pinfo->yres = 800;
+ MSM_FB_SINGLE_MODE_PANEL(pinfo);
+ pinfo->type = MDDI_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 18;
+ pinfo->fb_num = 2;
+ pinfo->clk_rate = 192000000;
+ pinfo->clk_min = 192000000;
+ pinfo->clk_max = 192000000;
+ pinfo->lcd.rev = 2;
+ pinfo->lcd.vsync_enable = FALSE;
+ pinfo->lcd.refx100 = 6050;
+ pinfo->lcd.v_back_porch = 2;
+ pinfo->lcd.v_front_porch = 2;
+ pinfo->lcd.v_pulse_width = 105;
+ pinfo->lcd.hw_vsync_mode = TRUE;
+ pinfo->lcd.vsync_notifier_period = 0;
+
+ ret = platform_device_register(&this_device);
+ if (ret)
+ platform_driver_unregister(&this_driver);
+ }
+ return ret;
+}
+module_init(mddi_orise_init);
diff --git a/drivers/video/msm/mddi_prism.c b/drivers/video/msm/mddi_prism.c
new file mode 100644
index 0000000..5269b22
--- /dev/null
+++ b/drivers/video/msm/mddi_prism.c
@@ -0,0 +1,111 @@
+/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+static int prism_lcd_on(struct platform_device *pdev);
+static int prism_lcd_off(struct platform_device *pdev);
+
+static int prism_lcd_on(struct platform_device *pdev)
+{
+ /* Set the MDP pixel data attributes for Primary Display */
+ mddi_host_write_pix_attr_reg(0x00C3);
+
+ return 0;
+}
+
+static int prism_lcd_off(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int __devinit prism_probe(struct platform_device *pdev)
+{
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = prism_probe,
+ .driver = {
+ .name = "mddi_prism_wvga",
+ },
+};
+
+static struct msm_fb_panel_data prism_panel_data = {
+ .on = prism_lcd_on,
+ .off = prism_lcd_off,
+};
+
+static struct platform_device this_device = {
+ .name = "mddi_prism_wvga",
+ .id = 0,
+ .dev = {
+ .platform_data = &prism_panel_data,
+ }
+};
+
+static int __init prism_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ u32 id;
+
+ ret = msm_fb_detect_client("mddi_prism_wvga");
+ if (ret == -ENODEV)
+ return 0;
+
+ if (ret) {
+ id = mddi_get_client_id();
+
+ if (((id >> 16) != 0x4474) || ((id & 0xffff) == 0x8960))
+ return 0;
+ }
+#endif
+ ret = platform_driver_register(&this_driver);
+ if (!ret) {
+ pinfo = &prism_panel_data.panel_info;
+ pinfo->xres = 800;
+ pinfo->yres = 480;
+ MSM_FB_SINGLE_MODE_PANEL(pinfo);
+ pinfo->type = MDDI_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 18;
+ pinfo->fb_num = 2;
+ pinfo->clk_rate = 153600000;
+ pinfo->clk_min = 140000000;
+ pinfo->clk_max = 160000000;
+ pinfo->lcd.vsync_enable = TRUE;
+ pinfo->lcd.refx100 = 6050;
+ pinfo->lcd.v_back_porch = 23;
+ pinfo->lcd.v_front_porch = 20;
+ pinfo->lcd.v_pulse_width = 105;
+ pinfo->lcd.hw_vsync_mode = TRUE;
+ pinfo->lcd.vsync_notifier_period = 0;
+
+ ret = platform_device_register(&this_device);
+ if (ret)
+ platform_driver_unregister(&this_driver);
+ }
+
+ return ret;
+}
+
+module_init(prism_init);
diff --git a/drivers/video/msm/mddi_quickvx.c b/drivers/video/msm/mddi_quickvx.c
new file mode 100644
index 0000000..330e679
--- /dev/null
+++ b/drivers/video/msm/mddi_quickvx.c
@@ -0,0 +1,718 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <mach/pmic.h>
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+/* WVGA Primary Display */
+#define MDDI_QUICKVX_1_2 1
+/* MDDI Manufacturer Code */
+#define QUICKVX_MDDI_MFR_CODE 0xc583
+/* MDDI Product Code */
+#define QUICKVX_MDDI_PRD_CODE 0x5800
+
+/* Register Address Maps */
+/* MDDI Address Anti-fuse values for bits [31:22] */
+#define QUICKVX_ADDR_31_22_AF (0X000 << 22)
+
+/* MDDI Address Maps */
+/* VEE Block Address Base */
+#define QUICKVX_VEE_BASE (QUICKVX_ADDR_31_22_AF | 0x00000000)
+/* SPI Block Address Base */
+#define QUICKVX_SPI_BASE (QUICKVX_ADDR_31_22_AF | 0x00010000)
+/* Clock and Reset (CAR) Address Base */
+#define QUICKVX_CAR_BASE (QUICKVX_ADDR_31_22_AF | 0x00020000)
+/* Register Control Block (RCB) Address Base */
+#define QUICKVX_RCB_BASE (QUICKVX_ADDR_31_22_AF | 0x00030000)
+/* Cellular RAM Address Base */
+#define QUICKVX_CELLRAM_BASE (QUICKVX_ADDR_31_22_AF | 0x00100000)
+/* FB through A2F Address Base */
+#define QUICKVX_FB_A2F_BASE (QUICKVX_ADDR_31_22_AF | 0x00200000)
+
+
+/***************************************************
+ * Common Registers in Register Control Block (RCB) Registers
+ ***************************************************/
+ /* CellRAM Configuration RCR Register */
+#define QUICKVX_RCB_RCR_REG (QUICKVX_RCB_BASE | 0x00000000)
+/* Image Effect Register */
+#define QUICKVX_RCB_IER_REG (QUICKVX_RCB_BASE | 0x00000004)
+/* Row Number Register */
+#define QUICKVX_RCB_ROWNUM_REG (QUICKVX_RCB_BASE | 0x00000008)
+/* TCON Timing0 Register */
+#define QUICKVX_RCB_TCON0_REG (QUICKVX_RCB_BASE | 0x0000000C)
+/* TCON Timing1 Register */
+#define QUICKVX_RCB_TCON1_REG (QUICKVX_RCB_BASE | 0x00000010)
+/* TCON Timing2 Register */
+#define QUICKVX_RCB_TCON2_REG (QUICKVX_RCB_BASE | 0x00000014)
+/* PWM Control Register */
+#define QUICKVX_RCB_PWMC_REG (QUICKVX_RCB_BASE | 0x00000018)
+/* PWM Width Register */
+#define QUICKVX_RCB_PWMW_REG (QUICKVX_RCB_BASE | 0x0000001C)
+/* VEE Configuration Register */
+#define QUICKVX_RCB_VEECONF_REG (QUICKVX_RCB_BASE | 0x00000020)
+/* CellRAM Configuration BCR Register */
+#define QUICKVX_RCB_CELLBCR_REG (QUICKVX_RCB_BASE | 0x00000024)
+/* CellRAM Configuration Control Register */
+#define QUICKVX_RCB_CELLCC_REG (QUICKVX_RCB_BASE | 0x00000028)
+/* Use Case Register */
+#define QUICKVX_RCB_USECASE_REG (QUICKVX_RCB_BASE | 0x00000100)
+/* Video Parameter Register */
+#define QUICKVX_RCB_VPARM_REG (QUICKVX_RCB_BASE | 0x00000104)
+/* MDDI Client Wake-up Register */
+#define QUICKVX_RCB_MCW_REG (QUICKVX_RCB_BASE | 0x00000108)
+/* Burst Length Register */
+#define QUICKVX_RCB_BURSTLN_REG (QUICKVX_RCB_BASE | 0x0000010C)
+/* Display Attributes Register */
+#define QUICKVX_RCB_DISPATTR_REG (QUICKVX_RCB_BASE | 0x00000110)
+/* Error Status Register */
+#define QUICKVX_RCB_ERRSTAT_REG (QUICKVX_RCB_BASE | 0x00000114)
+/* Error Mask Register */
+#define QUICKVX_RCB_ERRMSK_REG (QUICKVX_RCB_BASE | 0x00000118)
+/* MDDI ASSP FIFO Overflow Address Register */
+#define QUICKVX_RCB_ASSPFOA_REG (QUICKVX_RCB_BASE | 0x0000011C)
+/* MDDI Fabric FIFO Overflow Address Register */
+#define QUICKVX_RCB_FABFOA_REG (QUICKVX_RCB_BASE | 0x00000120)
+/* Incoming RGB FIFO Overflow Address Register */
+#define QUICKVX_RCB_IRFOA_REG (QUICKVX_RCB_BASE | 0x00000124)
+/* SPI Overflow Address Register */
+#define QUICKVX_RCB_SPIOA_REG (QUICKVX_RCB_BASE | 0x00000128)
+/* Ping Buffer Address Register */
+#define QUICKVX_RCB_PINGBA_REG (QUICKVX_RCB_BASE | 0x0000012C)
+/* Pong Buffer Address Register */
+#define QUICKVX_RCB_PONGBA_REG (QUICKVX_RCB_BASE | 0x00000130)
+/* Configuration Done Register */
+#define QUICKVX_RCB_CONFDONE_REG (QUICKVX_RCB_BASE | 0x00000134)
+/* FIFO Flush Register */
+#define QUICKVX_RCB_FFLUSH_REG (QUICKVX_RCB_BASE | 0x00000138)
+
+
+/***************************************************
+ * SPI Block Registers
+ ***************************************************/
+/* SPI Rx0 Register */
+#define QUICKVX_SPI_RX0_REG (QUICKVX_SPI_BASE | 0x00000000)
+/* SPI Rx1 Register */
+#define QUICKVX_SPI_RX1_REG (QUICKVX_SPI_BASE | 0x00000004)
+/* SPI Rx2 Register */
+#define QUICKVX_SPI_RX2_REG (QUICKVX_SPI_BASE | 0x00000008)
+/* SPI Rx3 Register */
+#define QUICKVX_SPI_RX3_REG (QUICKVX_SPI_BASE | 0x0000000C)
+/* SPI Rx4 Register */
+#define QUICKVX_SPI_RX4_REG (QUICKVX_SPI_BASE | 0x00000010)
+/* SPI Rx5 Register */
+#define QUICKVX_SPI_RX5_REG (QUICKVX_SPI_BASE | 0x00000014)
+/* SPI Rx6 Register */
+#define QUICKVX_SPI_RX6_REG (QUICKVX_SPI_BASE | 0x00000018)
+/* SPI Rx7 Register */
+#define QUICKVX_SPI_RX7_REG (QUICKVX_SPI_BASE | 0x0000001C)
+/* SPI Tx0 Register */
+#define QUICKVX_SPI_TX0_REG (QUICKVX_SPI_BASE | 0x00000020)
+/* SPI Tx1 Register */
+#define QUICKVX_SPI_TX1_REG (QUICKVX_SPI_BASE | 0x00000024)
+/* SPI Tx2 Register */
+#define QUICKVX_SPI_TX2_REG (QUICKVX_SPI_BASE | 0x00000028)
+/* SPI Tx3 Register */
+#define QUICKVX_SPI_TX3_REG (QUICKVX_SPI_BASE | 0x0000002C)
+/* SPI Tx4 Register */
+#define QUICKVX_SPI_TX4_REG (QUICKVX_SPI_BASE | 0x00000030)
+/* SPI Tx5 Register */
+#define QUICKVX_SPI_TX5_REG (QUICKVX_SPI_BASE | 0x00000034)
+/* SPI Tx6 Register */
+#define QUICKVX_SPI_TX6_REG (QUICKVX_SPI_BASE | 0x00000038)
+/* SPI Tx7 Register */
+#define QUICKVX_SPI_TX7_REG (QUICKVX_SPI_BASE | 0x0000003C)
+/* SPI Control Register */
+#define QUICKVX_SPI_CTRL_REG (QUICKVX_SPI_BASE | 0x00000040)
+/* SPI Transfer Length Register */
+#define QUICKVX_SPI_TLEN_REG (QUICKVX_SPI_BASE | 0x00000044)
+
+
+/***************************************************
+ * Clock and Reset (CAR) Block Registers
+ ***************************************************/
+/* ASSP Global Clock Enable Register */
+#define QUICKVX_CAR_ASSP_GCE_REG (QUICKVX_CAR_BASE | 0x00000000)
+/* VLP Control1 Register */
+#define QUICKVX_CAR_VLPCTRL1_REG (QUICKVX_CAR_BASE | 0x00000004)
+/* VLP Control2 Register */
+#define QUICKVX_CAR_VLPCTRL2_REG (QUICKVX_CAR_BASE | 0x00000008)
+/* Clock Selection Register */
+#define QUICKVX_CAR_CLKSEL_REG (QUICKVX_CAR_BASE | 0x0000000C)
+/* PLL Control Register */
+#define QUICKVX_CAR_PLLCTRL_REG (QUICKVX_CAR_BASE | 0x00000010)
+/* PLL Clock Ratio Register */
+#define QUICKVX_CAR_PLLCLKRATIO_REG (QUICKVX_CAR_BASE | 0x00000014)
+
+
+/***************************************************
+ * VEE Block Registers
+ ***************************************************/
+/* VEE Control Register */
+#define QUICKVX_VEE_VEECTRL_REG (QUICKVX_VEE_BASE | 0x00000000)
+/* Strength Register */
+#define QUICKVX_VEE_STRENGTH_REG (QUICKVX_VEE_BASE | 0x0000000C)
+/* Variance Register */
+#define QUICKVX_VEE_VARIANCE_REG (QUICKVX_VEE_BASE | 0x00000010)
+/* Slope Register */
+#define QUICKVX_VEE_SLOPE_REG (QUICKVX_VEE_BASE | 0x00000014)
+/* Sharpen Control0 Register */
+#define QUICKVX_VEE_SHRPCTRL0_REG (QUICKVX_VEE_BASE | 0x0000001C)
+/* Sharpen Control1 Register */
+#define QUICKVX_VEE_SHRPCTRL1_REG (QUICKVX_VEE_BASE | 0x00000020)
+/* Upper Horizontal Positon Register */
+#define QUICKVX_VEE_UHPOS_REG (QUICKVX_VEE_BASE | 0x00000024)
+/* Lower Horizontal Positon Register */
+#define QUICKVX_VEE_LHPOS_REG (QUICKVX_VEE_BASE | 0x00000028)
+/* Upper Vertical Positon Register */
+#define QUICKVX_VEE_UVPOS_REG (QUICKVX_VEE_BASE | 0x0000002C)
+/* Lower Vertical Positon Register */
+#define QUICKVX_VEE_LVPOS_REG (QUICKVX_VEE_BASE | 0x00000030)
+/* Upper Frame Width Register */
+#define QUICKVX_VEE_UFWDTH_REG (QUICKVX_VEE_BASE | 0x00000034)
+/* Lower Frame Width Register */
+#define QUICKVX_VEE_LFWDTH_REG (QUICKVX_VEE_BASE | 0x00000038)
+/* Upper Frame Height Register */
+#define QUICKVX_VEE_UFHGHT_REG (QUICKVX_VEE_BASE | 0x0000003C)
+/* Lower Frame Height Register */
+#define QUICKVX_VEE_LFHGHT_REG (QUICKVX_VEE_BASE | 0x00000040)
+/* Control0 Register */
+#define QUICKVX_VEE_CTRL0_REG (QUICKVX_VEE_BASE | 0x00000044)
+/* Control1 Register */
+#define QUICKVX_VEE_CTRL1_REG (QUICKVX_VEE_BASE | 0x00000048)
+/* Video Enhancement Enable Register */
+#define QUICKVX_VEE_VDOEEN_REG (QUICKVX_VEE_BASE | 0x0000004C)
+/* Black Level Register */
+#define QUICKVX_VEE_BLCKLEV_REG (QUICKVX_VEE_BASE | 0x00000050)
+/* White Level Register */
+#define QUICKVX_VEE_WHTLEV_REG (QUICKVX_VEE_BASE | 0x00000054)
+/* Amplification Limits Register */
+#define QUICKVX_VEE_AMPLMTS_REG (QUICKVX_VEE_BASE | 0x00000060)
+/* Dithering Mode Register */
+#define QUICKVX_VEE_DITHMOD_REG (QUICKVX_VEE_BASE | 0x00000064)
+/* Upper Look-up Data Register */
+#define QUICKVX_VEE_ULUD_REG (QUICKVX_VEE_BASE | 0x00000080)
+/* Lower Look-up Data Register */
+#define QUICKVX_VEE_LLUD_REG (QUICKVX_VEE_BASE | 0x00000084)
+/* Look-up Address Register */
+#define QUICKVX_VEE_LUADDR_REG (QUICKVX_VEE_BASE | 0x00000088)
+/* Look-up Write Enable Register */
+#define QUICKVX_VEE_LUWREN_REG (QUICKVX_VEE_BASE | 0x0000008C)
+/* VEE ID Register */
+#define QUICKVX_VEE_VEEID_REG (QUICKVX_VEE_BASE | 0x000003FC)
+/* M_11 Register */
+#define QUICKVX_VEE_M_11_REG (QUICKVX_VEE_BASE | 0x000000C0)
+/* M_12 Register */
+#define QUICKVX_VEE_M_12_REG (QUICKVX_VEE_BASE | 0x000000C4)
+/* M_13 Register */
+#define QUICKVX_VEE_M_13_REG (QUICKVX_VEE_BASE | 0x000000C8)
+/* M_21 Register */
+#define QUICKVX_VEE_M_21_REG (QUICKVX_VEE_BASE | 0x000000CC)
+/* M_22 Register */
+#define QUICKVX_VEE_M_22_REG (QUICKVX_VEE_BASE | 0x000000D0)
+/* M_23 Register */
+#define QUICKVX_VEE_M_23_REG (QUICKVX_VEE_BASE | 0x000000D4)
+/* M_31 Register */
+#define QUICKVX_VEE_M_31_REG (QUICKVX_VEE_BASE | 0x000000D8)
+/* M_32 Register */
+#define QUICKVX_VEE_M_32_REG (QUICKVX_VEE_BASE | 0x000000DC)
+/* M_33 Register */
+#define QUICKVX_VEE_M_33_REG (QUICKVX_VEE_BASE | 0x000000E0)
+/* R Offset Register */
+#define QUICKVX_VEE_OFFSET_R_REG (QUICKVX_VEE_BASE | 0x000000E8)
+/* G Offset Register */
+#define QUICKVX_VEE_OFFSET_G_REG (QUICKVX_VEE_BASE | 0x000000EC)
+/* B Offset Register */
+#define QUICKVX_VEE_OFFSET_B_REG (QUICKVX_VEE_BASE | 0x000000F0)
+
+/* LCD Reset Register */
+#define QUICKVX_FB_A2F_LCD_RESET_REG (QUICKVX_FB_A2F_BASE | 0x00000000)
+
+/* Register bit defines */
+/* PLL Lock bit in the PLL Control Register */
+#define QUICKVX_PLL_LOCK_BIT (1 << 7)
+
+#define QL_SPI_CTRL_rSPISTart(x) (x)
+#define QL_SPI_CTRL_rCPHA(x) (x << 1)
+#define QL_SPI_CTRL_rCPOL(x) (x << 2)
+#define QL_SPI_CTRL_rLSB(x) (x << 3)
+#define QL_SPI_CTRL_rSLVSEL(x) (x << 4)
+#define QL_SPI_CTRL_MASK_rTxDone (1 << 9)
+
+#define QL_SPI_LCD_DEV_ID 0x1c
+#define QL_SPI_LCD_RS(x) (x << 1)
+#define QL_SPI_LCD_RW(x) (x)
+#define QL_SPI_LCD_INDEX_START_BYTE ((QL_SPI_LCD_DEV_ID << 2) | \
+ QL_SPI_LCD_RS(0) | QL_SPI_LCD_RW(0))
+#define QL_SPI_LCD_CMD_START_BYTE ((QL_SPI_LCD_DEV_ID << 2) | \
+ QL_SPI_LCD_RS(1) | QL_SPI_LCD_RW(0))
+#define QL_SPI_CTRL_LCD_START (QL_SPI_CTRL_rSPISTart(1) | \
+ QL_SPI_CTRL_rCPHA(1) | QL_SPI_CTRL_rCPOL(1) | \
+ QL_SPI_CTRL_rLSB(0) | QL_SPI_CTRL_rSLVSEL(0))
+
+int ql_mddi_write(uint32 address, uint32 value)
+{
+ uint32 regval = 0;
+ int ret = 0;
+
+ ret = mddi_queue_register_write(address, value, TRUE, 0);
+
+ if (!ret) {
+ ret = mddi_queue_register_read(address, ®val, TRUE, 0);
+ if (regval != value) {
+ MDDI_MSG_DEBUG("\nMismatch: ql_mddi_write[0x%x]->0x%x "
+ "r0x%x\n", address, value, regval);
+ } else {
+ MDDI_MSG_DEBUG("\nMatch: ql_mddi_write[0x%x]->0x%x "
+ "r0x%x\n", address, value, regval);
+ }
+ }
+
+ return ret;
+}
+
+int ql_mddi_read(uint32 address, uint32 *regval)
+{
+ int ret = 0;
+
+ ret = mddi_queue_register_read(address, regval, TRUE, 0);
+ MDDI_MSG_DEBUG("\nql_mddi_read[0x%x]=0x%x", address, *regval);
+
+ return ret;
+}
+
+int ql_send_spi_cmd_to_lcd(uint32 index, uint32 cmd)
+{
+ int retry, ret;
+ uint32 readval;
+
+ MDDI_MSG_DEBUG("\n %s(): index 0x%x, cmd 0x%x", __func__, index, cmd);
+ /* do the index phase */
+ /* send 24 bits in the index phase */
+ ql_mddi_write(QUICKVX_SPI_TLEN_REG, 23);
+
+ /* send 24 bits in the index phase, starting at bit 23 of TX0 reg */
+ ql_mddi_write(QUICKVX_SPI_TX0_REG,
+ (QL_SPI_LCD_INDEX_START_BYTE << 16) | index);
+
+ /* set start */
+ ql_mddi_write(QUICKVX_SPI_CTRL_REG, QL_SPI_CTRL_LCD_START);
+ retry = 0;
+
+ do {
+ ret = ql_mddi_read(QUICKVX_SPI_CTRL_REG, &readval);
+
+ if (ret || ++retry > 5) {
+ MDDI_MSG_DEBUG("\n ql_send_spi_cmd_to_lcd: retry "
+ "timeout at index phase, ret = %d", ret);
+ return -EIO;
+ }
+ mddi_wait(1);
+ } while ((readval & QL_SPI_CTRL_MASK_rTxDone) == 0);
+
+ /* do the command phase */
+ /* send 24 bits in the cmd phase */
+ ql_mddi_write(QUICKVX_SPI_TLEN_REG, 23);
+
+ /* send 24 bits in the cmd phase, starting at bit 23 of TX0 reg. */
+ ql_mddi_write(QUICKVX_SPI_TX0_REG,
+ (QL_SPI_LCD_CMD_START_BYTE << 16) | cmd);
+
+ /* set start */
+ ql_mddi_write(QUICKVX_SPI_CTRL_REG, QL_SPI_CTRL_LCD_START);
+ retry = 0;
+
+ do {
+ ret = ql_mddi_read(QUICKVX_SPI_CTRL_REG, &readval);
+
+ if (ret || ++retry > 5) {
+ MDDI_MSG_DEBUG("\n ql_send_spi_cmd_to_lcd: retry "
+ "timeout at cmd phase, ret = %d", ret);
+ return -EIO;
+ }
+ mddi_wait(1);
+ } while ((readval & QL_SPI_CTRL_MASK_rTxDone) == 0);
+
+ return 0;
+}
+
+
+int ql_send_spi_data_from_lcd(uint32 index, uint32 *value)
+{
+ int retry, ret;
+ uint32 readval;
+
+ MDDI_MSG_DEBUG("\n %s(): index 0x%x", __func__, index);
+ /* do the index phase */
+ /* send 24 bits in the index phase */
+ ql_mddi_write(QUICKVX_SPI_TLEN_REG, 23);
+
+ /* send 24 bits in the index phase, starting at bit 23 of TX0 reg */
+ ql_mddi_write(QUICKVX_SPI_TX0_REG,
+ (QL_SPI_LCD_INDEX_START_BYTE << 16) | index);
+
+ /* set start */
+ ql_mddi_write(QUICKVX_SPI_CTRL_REG, QL_SPI_CTRL_LCD_START);
+ retry = 0;
+
+ do {
+ ret = ql_mddi_read(QUICKVX_SPI_CTRL_REG, &readval);
+
+ if (ret || ++retry > 5) {
+ MDDI_MSG_DEBUG("\n ql_send_spi_cmd_to_lcd: retry "
+ "timeout at index phase, ret = %d", ret);
+ return -EIO;
+ }
+ mddi_wait(1);
+ } while ((readval & QL_SPI_CTRL_MASK_rTxDone) == 0);
+
+ /* do the command phase */
+ /* send 8 bits and read 24 bits in the cmd phase, so total 32 bits */
+ ql_mddi_write(QUICKVX_SPI_TLEN_REG, 31);
+
+ /* send 24 bits in the cmd phase, starting at bit 31 of TX0 reg */
+ ql_mddi_write(QUICKVX_SPI_TX0_REG,
+ ((QL_SPI_LCD_CMD_START_BYTE << 16)) << 8);
+
+ /* set start */
+ ql_mddi_write(QUICKVX_SPI_CTRL_REG, QL_SPI_CTRL_LCD_START);
+ retry = 0;
+
+ do {
+ ret = ql_mddi_read(QUICKVX_SPI_CTRL_REG, &readval);
+
+ if (ret || ++retry > 5) {
+ MDDI_MSG_DEBUG("\n ql_send_spi_cmd_to_lcd: retry "
+ "timeout at cmd phase, ret = %d", ret);
+ return -EIO;
+ }
+ mddi_wait(1);
+ } while ((readval & QL_SPI_CTRL_MASK_rTxDone) == 0);
+
+ /* value will appear at lower 16 bits */
+ ret = ql_mddi_read(QUICKVX_SPI_RX0_REG, value);
+
+ if (!ret) {
+ *value = *value & 0xffff;
+ MDDI_MSG_DEBUG("\n QUICKVX_SPI_RX0_REG value = 0x%x", *value);
+ } else
+ MDDI_MSG_DEBUG("\n Read QUICKVX_SPI_RX0_REG Failed");
+
+ return ret;
+}
+
+/* Global Variables */
+static uint32 mddi_quickvx_rows_per_second;
+static uint32 mddi_quickvx_usecs_per_refresh;
+static uint32 mddi_quickvx_rows_per_refresh;
+
+void mddi_quickvx_configure_registers(void)
+{
+ MDDI_MSG_DEBUG("\n%s(): ", __func__);
+ ql_mddi_write(QUICKVX_CAR_CLKSEL_REG, 0x00007000);
+
+ ql_mddi_write(QUICKVX_RCB_PWMW_REG, 0x0000FFFF);
+
+ ql_mddi_write(QUICKVX_RCB_PWMC_REG, 0x00000001);
+
+ ql_mddi_write(QUICKVX_RCB_CONFDONE_REG, 0x00000000);
+
+ /* display is x width = 480, y width = 864 */
+ ql_mddi_write(QUICKVX_RCB_TCON0_REG, 0x035f01df);
+
+ /* VFP=2, VBP=4, HFP=16, HBP=16 */
+ ql_mddi_write(QUICKVX_RCB_TCON1_REG, 0x01e301e1);
+
+ /* VSW =2, HSW=8 */
+ ql_mddi_write(QUICKVX_RCB_TCON2_REG, 0x000000e1);
+
+ ql_mddi_write(QUICKVX_RCB_DISPATTR_REG, 0x00000000);
+
+ ql_mddi_write(QUICKVX_RCB_USECASE_REG, 0x00000025);
+
+ ql_mddi_write(QUICKVX_RCB_VPARM_REG, 0x00000888);
+
+ ql_mddi_write(QUICKVX_RCB_VEECONF_REG, 0x00000001);
+
+ ql_mddi_write(QUICKVX_RCB_IER_REG, 0x00000000);
+
+ ql_mddi_write(QUICKVX_RCB_RCR_REG, 0x80000010);
+
+ ql_mddi_write(QUICKVX_RCB_CELLBCR_REG, 0x8008746F);
+
+ ql_mddi_write(QUICKVX_RCB_CELLCC_REG, 0x800000A3);
+
+ ql_mddi_write(QUICKVX_RCB_CONFDONE_REG, 0x00000001);
+}
+
+void mddi_quickvx_prim_lcd_init(void)
+{
+ uint32 value;
+
+ MDDI_MSG_DEBUG("\n%s(): ", __func__);
+ ql_send_spi_data_from_lcd(0, &value);
+
+ ql_send_spi_cmd_to_lcd(0x0100, 0x3000); /* power control1 */
+ ql_send_spi_cmd_to_lcd(0x0101, 0x4010); /* power control2 */
+ ql_send_spi_cmd_to_lcd(0x0106, 0x0000); /* auto seq setting */
+ mddi_wait(3);
+
+ ql_mddi_write(QUICKVX_FB_A2F_LCD_RESET_REG, 0x00000001);
+ mddi_wait(1);
+ ql_mddi_write(QUICKVX_FB_A2F_LCD_RESET_REG, 0x00000000);
+ mddi_wait(1);
+ ql_mddi_write(QUICKVX_FB_A2F_LCD_RESET_REG, 0x00000001);
+ mddi_wait(10);
+
+ ql_send_spi_cmd_to_lcd(0x0001, 0x0310); /* driver out control */
+ ql_send_spi_cmd_to_lcd(0x0002, 0x0100); /* lcd ac control */
+ ql_send_spi_cmd_to_lcd(0x0003, 0x0000); /* entry mode */
+ ql_send_spi_cmd_to_lcd(0x0007, 0x0000); /* disp cont1 */
+ ql_send_spi_cmd_to_lcd(0x0008, 0x0004); /* disp cont2 */
+ ql_send_spi_cmd_to_lcd(0x0009, 0x000C); /* disp cont3 */
+ ql_send_spi_cmd_to_lcd(0x000C, 0x4010); /* disp if cont1 */
+ ql_send_spi_cmd_to_lcd(0x000E, 0x0000); /* disp if cont2 */
+ ql_send_spi_cmd_to_lcd(0x0020, 0x013F); /* panel if cont1 */
+ ql_send_spi_cmd_to_lcd(0x0022, 0x7600); /* panel if cont3 */
+ ql_send_spi_cmd_to_lcd(0x0023, 0x1C0A); /* panel if cont4 */
+ ql_send_spi_cmd_to_lcd(0x0024, 0x1C2C); /* panel if cont5 */
+ ql_send_spi_cmd_to_lcd(0x0025, 0x1C4E); /* panel if cont6 */
+ ql_send_spi_cmd_to_lcd(0x0027, 0x0000); /* panel if cont8 */
+ ql_send_spi_cmd_to_lcd(0x0028, 0x760C); /* panel if cont9 */
+ ql_send_spi_cmd_to_lcd(0x0300, 0x0000); /* gamma adj0 */
+ ql_send_spi_cmd_to_lcd(0x0301, 0x0502); /* gamma adj1 */
+ ql_send_spi_cmd_to_lcd(0x0302, 0x0705); /* gamma adj2 */
+ ql_send_spi_cmd_to_lcd(0x0303, 0x0000); /* gamma adj3 */
+ ql_send_spi_cmd_to_lcd(0x0304, 0x0200); /* gamma adj4 */
+ ql_send_spi_cmd_to_lcd(0x0305, 0x0707); /* gamma adj5 */
+ ql_send_spi_cmd_to_lcd(0x0306, 0x1010); /* gamma adj6 */
+ ql_send_spi_cmd_to_lcd(0x0307, 0x0202); /* gamma adj7 */
+ ql_send_spi_cmd_to_lcd(0x0308, 0x0704); /* gamma adj8 */
+ ql_send_spi_cmd_to_lcd(0x0309, 0x0707); /* gamma adj9 */
+ ql_send_spi_cmd_to_lcd(0x030A, 0x0000); /* gamma adja */
+ ql_send_spi_cmd_to_lcd(0x030B, 0x0000); /* gamma adjb */
+ ql_send_spi_cmd_to_lcd(0x030C, 0x0707); /* gamma adjc */
+ ql_send_spi_cmd_to_lcd(0x030D, 0x1010); /* gamma adjd */
+ ql_send_spi_cmd_to_lcd(0x0310, 0x0104); /* gamma adj10 */
+ ql_send_spi_cmd_to_lcd(0x0311, 0x0503); /* gamma adj11 */
+ ql_send_spi_cmd_to_lcd(0x0312, 0x0304); /* gamma adj12 */
+ ql_send_spi_cmd_to_lcd(0x0315, 0x0304); /* gamma adj15 */
+ ql_send_spi_cmd_to_lcd(0x0316, 0x031C); /* gamma adj16 */
+ ql_send_spi_cmd_to_lcd(0x0317, 0x0204); /* gamma adj17 */
+ ql_send_spi_cmd_to_lcd(0x0318, 0x0402); /* gamma adj18 */
+ ql_send_spi_cmd_to_lcd(0x0319, 0x0305); /* gamma adj19 */
+ ql_send_spi_cmd_to_lcd(0x031C, 0x0707); /* gamma adj1c */
+ ql_send_spi_cmd_to_lcd(0x031D, 0x021F); /* gamma adj1d */
+ ql_send_spi_cmd_to_lcd(0x0320, 0x0507); /* gamma adj20 */
+ ql_send_spi_cmd_to_lcd(0x0321, 0x0604); /* gamma adj21 */
+ ql_send_spi_cmd_to_lcd(0x0322, 0x0405); /* gamma adj22 */
+ ql_send_spi_cmd_to_lcd(0x0327, 0x0203); /* gamma adj27 */
+ ql_send_spi_cmd_to_lcd(0x0328, 0x0300); /* gamma adj28 */
+ ql_send_spi_cmd_to_lcd(0x0329, 0x0002); /* gamma adj29 */
+ ql_send_spi_cmd_to_lcd(0x0100, 0x363C); /* power cont1 */
+ mddi_wait(1);
+ ql_send_spi_cmd_to_lcd(0x0101, 0x4003); /* power cont2 */
+ ql_send_spi_cmd_to_lcd(0x0102, 0x0001); /* power cont3 */
+ ql_send_spi_cmd_to_lcd(0x0103, 0x3C58); /* power cont4 */
+ ql_send_spi_cmd_to_lcd(0x010C, 0x0135); /* power cont6 */
+ ql_send_spi_cmd_to_lcd(0x0106, 0x0002); /* auto seq */
+ ql_send_spi_cmd_to_lcd(0x0029, 0x03BF); /* panel if cont10 */
+ ql_send_spi_cmd_to_lcd(0x0106, 0x0003); /* auto seq */
+ mddi_wait(5);
+ ql_send_spi_cmd_to_lcd(0x0101, 0x4010); /* power cont2 */
+ mddi_wait(10);
+}
+
+/* Function to Power On the Primary and Secondary LCD panels */
+static int mddi_quickvx_lcd_on(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+
+ MDDI_MSG_DEBUG("\n%s(): ", __func__);
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd) {
+ MDDI_MSG_DEBUG("\n mddi_quickvx_lcd_on: Device not found!");
+ return -ENODEV;
+ }
+
+ if (mfd->key != MFD_KEY) {
+ MDDI_MSG_DEBUG("\n mddi_quickvx_lcd_on: Invalid MFD key!");
+ return -EINVAL;
+ }
+
+ mddi_host_client_cnt_reset();
+ mddi_quickvx_configure_registers();
+ mddi_quickvx_prim_lcd_init();
+
+ return 0;
+}
+
+
+/* Function to Power Off the Primary and Secondary LCD panels */
+static int mddi_quickvx_lcd_off(struct platform_device *pdev)
+{
+ MDDI_MSG_DEBUG("\n%s(): ", __func__);
+ mddi_wait(1);
+ ql_send_spi_cmd_to_lcd(0x0106, 0x0002); /* Auto Sequencer setting */
+ mddi_wait(10);
+ ql_send_spi_cmd_to_lcd(0x0106, 0x0000); /* Auto Sequencer setting */
+ ql_send_spi_cmd_to_lcd(0x0029, 0x0002); /* Panel IF control 10 */
+ ql_send_spi_cmd_to_lcd(0x0100, 0x300D); /* Power Control 1 */
+ mddi_wait(1);
+
+ return 0;
+}
+
+/* Function to set the Backlight brightness level */
+static void mddi_quickvx_lcd_set_backlight(struct msm_fb_data_type *mfd)
+{
+ int32 level, i = 0, ret;
+
+ MDDI_MSG_DEBUG("%s(): ", __func__);
+
+ level = mfd->bl_level;
+ MDDI_MSG_DEBUG("\n level = %d", level);
+ if (level < 0) {
+ MDDI_MSG_DEBUG("mddi_quickvx_lcd_set_backlight: "
+ "Invalid backlight level (%d)!\n", level);
+ return;
+ }
+ while (i++ < 3) {
+ ret = pmic_set_led_intensity(LED_LCD, level);
+ if (ret == 0)
+ return;
+ msleep(10);
+ }
+
+ MDDI_MSG_DEBUG("%s: can't set lcd backlight!\n",
+ __func__);
+}
+
+/* Driver Probe function */
+static int __devinit mddi_quickvx_lcd_probe(struct platform_device *pdev)
+{
+ MDDI_MSG_DEBUG("\n%s(): id is %d", __func__, pdev->id);
+ msm_fb_add_device(pdev);
+ return 0;
+}
+
+/* Driver data structure */
+static struct platform_driver this_driver = {
+ .probe = mddi_quickvx_lcd_probe,
+ .driver = {
+ .name = "mddi_quickvx",
+ },
+};
+
+
+/* Primary LCD panel data structure */
+static struct msm_fb_panel_data mddi_quickvx_panel_data0 = {
+ .on = mddi_quickvx_lcd_on,
+ .off = mddi_quickvx_lcd_off,
+ .set_backlight = mddi_quickvx_lcd_set_backlight,
+};
+
+
+/* Primary LCD panel device structure */
+static struct platform_device this_device0 = {
+ .name = "mddi_quickvx",
+ .id = MDDI_QUICKVX_1_2,
+ .dev = {
+ .platform_data = &mddi_quickvx_panel_data0,
+ }
+};
+
+/* Module init - driver main entry point */
+static int __init mddi_quickvx_lcd_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ u32 cid;
+ MDDI_MSG_DEBUG("\n%s(): ", __func__);
+
+ ret = msm_fb_detect_client("mddi_quickvx");
+
+ if (ret == -ENODEV) {
+ /* Device not found */
+ MDDI_MSG_DEBUG("\n mddi_quickvx_lcd_init: No device found!");
+ return 0;
+ }
+
+ if (ret) {
+ cid = mddi_get_client_id();
+
+ MDDI_MSG_DEBUG("\n cid = 0x%x", cid);
+ if (((cid >> 16) != QUICKVX_MDDI_MFR_CODE) ||
+ ((cid & 0xFFFF) != QUICKVX_MDDI_PRD_CODE)) {
+ /* MDDI Client ID not matching */
+ MDDI_MSG_DEBUG("\n mddi_quickvx_lcd_init: "
+ "Client ID missmatch!");
+
+ return 0;
+ }
+ MDDI_MSG_DEBUG("\n mddi_quickvx_lcd_init: "
+ "QuickVX LCD panel detected!");
+ }
+
+#endif /* CONFIG_FB_MSM_MDDI_AUTO_DETECT */
+
+ mddi_quickvx_rows_per_refresh = 872;
+ mddi_quickvx_rows_per_second = 52364;
+ mddi_quickvx_usecs_per_refresh = 16574;
+
+ ret = platform_driver_register(&this_driver);
+
+ if (!ret) {
+ pinfo = &mddi_quickvx_panel_data0.panel_info;
+ pinfo->xres = 480;
+ pinfo->yres = 864;
+ MSM_FB_SINGLE_MODE_PANEL(pinfo);
+ pinfo->type = MDDI_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 24;
+ pinfo->fb_num = 2;
+
+ pinfo->clk_rate = 192000000;
+ pinfo->clk_min = 192000000;
+ pinfo->clk_max = 200000000;
+ pinfo->lcd.rev = 1;
+ pinfo->lcd.vsync_enable = TRUE;
+ pinfo->lcd.refx100 = (mddi_quickvx_rows_per_second \
+ * 100)/mddi_quickvx_rows_per_refresh;
+ pinfo->lcd.v_back_porch = 4;
+ pinfo->lcd.v_front_porch = 2;
+ pinfo->lcd.v_pulse_width = 2;
+ pinfo->lcd.hw_vsync_mode = TRUE;
+ pinfo->lcd.vsync_notifier_period = (1 * HZ);
+ pinfo->bl_max = 10;
+ pinfo->bl_min = 0;
+
+ ret = platform_device_register(&this_device0);
+ if (ret) {
+ platform_driver_unregister(&this_driver);
+ MDDI_MSG_DEBUG("mddi_quickvx_lcd_init: "
+ "Primary device registration failed!\n");
+ }
+ }
+
+ return ret;
+}
+
+module_init(mddi_quickvx_lcd_init);
+
diff --git a/drivers/video/msm/mddi_sharp.c b/drivers/video/msm/mddi_sharp.c
new file mode 100644
index 0000000..b2a7188
--- /dev/null
+++ b/drivers/video/msm/mddi_sharp.c
@@ -0,0 +1,900 @@
+/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+#define SHARP_QVGA_PRIM 1
+#define SHARP_128X128_SECD 2
+
+extern uint32 mddi_host_core_version;
+static boolean mddi_debug_prim_wait = FALSE;
+static boolean mddi_sharp_vsync_wake = TRUE;
+static boolean mddi_sharp_monitor_refresh_value = TRUE;
+static boolean mddi_sharp_report_refresh_measurements = FALSE;
+static uint32 mddi_sharp_rows_per_second = 13830; /* 5200000/376 */
+static uint32 mddi_sharp_rows_per_refresh = 338;
+static uint32 mddi_sharp_usecs_per_refresh = 24440; /* (376+338)/5200000 */
+static boolean mddi_sharp_debug_60hz_refresh = FALSE;
+
+extern mddi_gpio_info_type mddi_gpio;
+extern boolean mddi_vsync_detect_enabled;
+static msm_fb_vsync_handler_type mddi_sharp_vsync_handler;
+static void *mddi_sharp_vsync_handler_arg;
+static uint16 mddi_sharp_vsync_attempts;
+
+static void mddi_sharp_prim_lcd_init(void);
+static void mddi_sharp_sub_lcd_init(void);
+static void mddi_sharp_lcd_set_backlight(struct msm_fb_data_type *mfd);
+static void mddi_sharp_vsync_set_handler(msm_fb_vsync_handler_type handler,
+ void *);
+static void mddi_sharp_lcd_vsync_detected(boolean detected);
+static struct msm_panel_common_pdata *mddi_sharp_pdata;
+
+#define REG_SYSCTL 0x0000
+#define REG_INTR 0x0006
+#define REG_CLKCNF 0x000C
+#define REG_CLKDIV1 0x000E
+#define REG_CLKDIV2 0x0010
+
+#define REG_GIOD 0x0040
+#define REG_GIOA 0x0042
+
+#define REG_AGM 0x010A
+#define REG_FLFT 0x0110
+#define REG_FRGT 0x0112
+#define REG_FTOP 0x0114
+#define REG_FBTM 0x0116
+#define REG_FSTRX 0x0118
+#define REG_FSTRY 0x011A
+#define REG_VRAM 0x0202
+#define REG_SSDCTL 0x0330
+#define REG_SSD0 0x0332
+#define REG_PSTCTL1 0x0400
+#define REG_PSTCTL2 0x0402
+#define REG_PTGCTL 0x042A
+#define REG_PTHP 0x042C
+#define REG_PTHB 0x042E
+#define REG_PTHW 0x0430
+#define REG_PTHF 0x0432
+#define REG_PTVP 0x0434
+#define REG_PTVB 0x0436
+#define REG_PTVW 0x0438
+#define REG_PTVF 0x043A
+#define REG_VBLKS 0x0458
+#define REG_VBLKE 0x045A
+#define REG_SUBCTL 0x0700
+#define REG_SUBTCMD 0x0702
+#define REG_SUBTCMDD 0x0704
+#define REG_REVBYTE 0x0A02
+#define REG_REVCNT 0x0A04
+#define REG_REVATTR 0x0A06
+#define REG_REVFMT 0x0A08
+
+#define SHARP_SUB_UNKNOWN 0xffffffff
+#define SHARP_SUB_HYNIX 1
+#define SHARP_SUB_ROHM 2
+
+static uint32 sharp_subpanel_type = SHARP_SUB_UNKNOWN;
+
+static void sub_through_write(int sub_rs, uint32 sub_data)
+{
+ mddi_queue_register_write(REG_SUBTCMDD, sub_data, FALSE, 0);
+
+ /* CS=1,RD=1,WE=1,RS=sub_rs */
+ mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, FALSE, 0);
+
+ /* CS=0,RD=1,WE=1,RS=sub_rs */
+ mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
+
+ /* CS=0,RD=1,WE=0,RS=sub_rs */
+ mddi_queue_register_write(REG_SUBTCMD, 0x0004 | sub_rs, FALSE, 0);
+
+ /* CS=0,RD=1,WE=1,RS=sub_rs */
+ mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
+
+ /* CS=1,RD=1,WE=1,RS=sub_rs */
+ mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, TRUE, 0);
+}
+
+static uint32 sub_through_read(int sub_rs)
+{
+ uint32 sub_data;
+
+ /* CS=1,RD=1,WE=1,RS=sub_rs */
+ mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, FALSE, 0);
+
+ /* CS=0,RD=1,WE=1,RS=sub_rs */
+ mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
+
+ /* CS=0,RD=1,WE=0,RS=sub_rs */
+ mddi_queue_register_write(REG_SUBTCMD, 0x0002 | sub_rs, TRUE, 0);
+
+ mddi_queue_register_read(REG_SUBTCMDD, &sub_data, TRUE, 0);
+
+ /* CS=0,RD=1,WE=1,RS=sub_rs */
+ mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
+
+ /* CS=1,RD=1,WE=1,RS=sub_rs */
+ mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, TRUE, 0);
+
+ return sub_data;
+}
+
+static void serigo(uint32 ssd)
+{
+ uint32 ssdctl;
+
+ mddi_queue_register_read(REG_SSDCTL, &ssdctl, TRUE, 0);
+ ssdctl = ((ssdctl & 0xE7) | 0x02);
+
+ mddi_queue_register_write(REG_SSD0, ssd, FALSE, 0);
+ mddi_queue_register_write(REG_SSDCTL, ssdctl, TRUE, 0);
+
+ do {
+ mddi_queue_register_read(REG_SSDCTL, &ssdctl, TRUE, 0);
+ } while ((ssdctl & 0x0002) != 0);
+
+ if (mddi_debug_prim_wait)
+ mddi_wait(2);
+}
+
+static void mddi_sharp_lcd_powerdown(void)
+{
+ serigo(0x0131);
+ serigo(0x0300);
+ mddi_wait(40);
+ serigo(0x0135);
+ mddi_wait(20);
+ serigo(0x2122);
+ mddi_wait(20);
+ serigo(0x0201);
+ mddi_wait(20);
+ serigo(0x2100);
+ mddi_wait(20);
+ serigo(0x2000);
+ mddi_wait(20);
+
+ mddi_queue_register_write(REG_PSTCTL1, 0x1, TRUE, 0);
+ mddi_wait(100);
+ mddi_queue_register_write(REG_PSTCTL1, 0x0, TRUE, 0);
+ mddi_wait(2);
+ mddi_queue_register_write(REG_SYSCTL, 0x1, TRUE, 0);
+ mddi_wait(2);
+ mddi_queue_register_write(REG_CLKDIV1, 0x3, TRUE, 0);
+ mddi_wait(2);
+ mddi_queue_register_write(REG_SSDCTL, 0x0000, TRUE, 0); /* SSDRESET */
+ mddi_queue_register_write(REG_SYSCTL, 0x0, TRUE, 0);
+ mddi_wait(2);
+}
+
+static void mddi_sharp_lcd_set_backlight(struct msm_fb_data_type *mfd)
+{
+ uint32 regdata;
+ int32 level;
+ int max = mfd->panel_info.bl_max;
+ int min = mfd->panel_info.bl_min;
+
+ if (mddi_sharp_pdata && mddi_sharp_pdata->backlight_level) {
+ level = mddi_sharp_pdata->backlight_level(mfd->bl_level,
+ max,
+ min);
+
+ if (level < 0)
+ return;
+
+ /* use Rodem GPIO(2:0) to give 8 levels of backlight (7-0) */
+ /* Set lower 3 GPIOs as Outputs (set to 0) */
+ mddi_queue_register_read(REG_GIOA, ®data, TRUE, 0);
+ mddi_queue_register_write(REG_GIOA, regdata & 0xfff8, TRUE, 0);
+
+ /* Set lower 3 GPIOs as level */
+ mddi_queue_register_read(REG_GIOD, ®data, TRUE, 0);
+ mddi_queue_register_write(REG_GIOD,
+ (regdata & 0xfff8) | (0x07 & level), TRUE, 0);
+ }
+}
+
+static void mddi_sharp_prim_lcd_init(void)
+{
+ mddi_queue_register_write(REG_SYSCTL, 0x4000, TRUE, 0);
+ mddi_wait(1);
+ mddi_queue_register_write(REG_SYSCTL, 0x0000, TRUE, 0);
+ mddi_wait(5);
+ mddi_queue_register_write(REG_SYSCTL, 0x0001, FALSE, 0);
+ mddi_queue_register_write(REG_CLKDIV1, 0x000b, FALSE, 0);
+
+ /* new reg write below */
+ if (mddi_sharp_debug_60hz_refresh)
+ mddi_queue_register_write(REG_CLKCNF, 0x070d, FALSE, 0);
+ else
+ mddi_queue_register_write(REG_CLKCNF, 0x0708, FALSE, 0);
+
+ mddi_queue_register_write(REG_SYSCTL, 0x0201, FALSE, 0);
+ mddi_queue_register_write(REG_PTGCTL, 0x0010, FALSE, 0);
+ mddi_queue_register_write(REG_PTHP, 4, FALSE, 0);
+ mddi_queue_register_write(REG_PTHB, 40, FALSE, 0);
+ mddi_queue_register_write(REG_PTHW, 240, FALSE, 0);
+ if (mddi_sharp_debug_60hz_refresh)
+ mddi_queue_register_write(REG_PTHF, 12, FALSE, 0);
+ else
+ mddi_queue_register_write(REG_PTHF, 92, FALSE, 0);
+
+ mddi_wait(1);
+
+ mddi_queue_register_write(REG_PTVP, 1, FALSE, 0);
+ mddi_queue_register_write(REG_PTVB, 2, FALSE, 0);
+ mddi_queue_register_write(REG_PTVW, 320, FALSE, 0);
+ mddi_queue_register_write(REG_PTVF, 15, FALSE, 0);
+
+ mddi_wait(1);
+
+ /* vram_color set REG_AGM???? */
+ mddi_queue_register_write(REG_AGM, 0x0000, TRUE, 0);
+
+ mddi_queue_register_write(REG_SSDCTL, 0x0000, FALSE, 0);
+ mddi_queue_register_write(REG_SSDCTL, 0x0001, TRUE, 0);
+ mddi_wait(1);
+ mddi_queue_register_write(REG_PSTCTL1, 0x0001, TRUE, 0);
+ mddi_wait(10);
+
+ serigo(0x0701);
+ /* software reset */
+ mddi_wait(1);
+ /* Wait over 50us */
+
+ serigo(0x0400);
+ /* DCLK~ACHSYNC~ACVSYNC polarity setting */
+ serigo(0x2900);
+ /* EEPROM start read address setting */
+ serigo(0x2606);
+ /* EEPROM start read register setting */
+ mddi_wait(20);
+ /* Wait over 20ms */
+
+ serigo(0x0503);
+ /* Horizontal timing setting */
+ serigo(0x062C);
+ /* Veritical timing setting */
+ serigo(0x2001);
+ /* power initialize setting(VDC2) */
+ mddi_wait(20);
+ /* Wait over 20ms */
+
+ serigo(0x2120);
+ /* Initialize power setting(CPS) */
+ mddi_wait(20);
+ /* Wait over 20ms */
+
+ serigo(0x2130);
+ /* Initialize power setting(CPS) */
+ mddi_wait(20);
+ /* Wait over 20ms */
+
+ serigo(0x2132);
+ /* Initialize power setting(CPS) */
+ mddi_wait(10);
+ /* Wait over 10ms */
+
+ serigo(0x2133);
+ /* Initialize power setting(CPS) */
+ mddi_wait(20);
+ /* Wait over 20ms */
+
+ serigo(0x0200);
+ /* Panel initialize release(INIT) */
+ mddi_wait(1);
+ /* Wait over 1ms */
+
+ serigo(0x0131);
+ /* Panel setting(CPS) */
+ mddi_wait(1);
+ /* Wait over 1ms */
+
+ mddi_queue_register_write(REG_PSTCTL1, 0x0003, TRUE, 0);
+
+ /* if (FFA LCD is upside down) -> serigo(0x0100); */
+ serigo(0x0130);
+
+ /* Black mask release(display ON) */
+ mddi_wait(1);
+ /* Wait over 1ms */
+
+ if (mddi_sharp_vsync_wake) {
+ mddi_queue_register_write(REG_VBLKS, 0x1001, TRUE, 0);
+ mddi_queue_register_write(REG_VBLKE, 0x1002, TRUE, 0);
+ }
+
+ /* Set the MDP pixel data attributes for Primary Display */
+ mddi_host_write_pix_attr_reg(0x00C3);
+ return;
+
+}
+
+void mddi_sharp_sub_lcd_init(void)
+{
+
+ mddi_queue_register_write(REG_SYSCTL, 0x4000, FALSE, 0);
+ mddi_queue_register_write(REG_SYSCTL, 0x0000, TRUE, 0);
+ mddi_wait(100);
+
+ mddi_queue_register_write(REG_SYSCTL, 0x0001, FALSE, 0);
+ mddi_queue_register_write(REG_CLKDIV1, 0x000b, FALSE, 0);
+ mddi_queue_register_write(REG_CLKCNF, 0x0708, FALSE, 0);
+ mddi_queue_register_write(REG_SYSCTL, 0x0201, FALSE, 0);
+ mddi_queue_register_write(REG_PTGCTL, 0x0010, FALSE, 0);
+ mddi_queue_register_write(REG_PTHP, 4, FALSE, 0);
+ mddi_queue_register_write(REG_PTHB, 40, FALSE, 0);
+ mddi_queue_register_write(REG_PTHW, 128, FALSE, 0);
+ mddi_queue_register_write(REG_PTHF, 92, FALSE, 0);
+ mddi_queue_register_write(REG_PTVP, 1, FALSE, 0);
+ mddi_queue_register_write(REG_PTVB, 2, FALSE, 0);
+ mddi_queue_register_write(REG_PTVW, 128, FALSE, 0);
+ mddi_queue_register_write(REG_PTVF, 15, FALSE, 0);
+
+ /* Now the sub display..... */
+ /* Reset High */
+ mddi_queue_register_write(REG_SUBCTL, 0x0200, FALSE, 0);
+ /* CS=1,RD=1,WE=1,RS=1 */
+ mddi_queue_register_write(REG_SUBTCMD, 0x000f, TRUE, 0);
+ mddi_wait(1);
+ /* Wait 5us */
+
+ if (sharp_subpanel_type == SHARP_SUB_UNKNOWN) {
+ uint32 data;
+
+ sub_through_write(1, 0x05);
+ sub_through_write(1, 0x6A);
+ sub_through_write(1, 0x1D);
+ sub_through_write(1, 0x05);
+ data = sub_through_read(1);
+ if (data == 0x6A) {
+ sharp_subpanel_type = SHARP_SUB_HYNIX;
+ } else {
+ sub_through_write(0, 0x36);
+ sub_through_write(1, 0xA8);
+ sub_through_write(0, 0x09);
+ data = sub_through_read(1);
+ data = sub_through_read(1);
+ if (data == 0x54) {
+ sub_through_write(0, 0x36);
+ sub_through_write(1, 0x00);
+ sharp_subpanel_type = SHARP_SUB_ROHM;
+ }
+ }
+ }
+
+ if (sharp_subpanel_type == SHARP_SUB_HYNIX) {
+ sub_through_write(1, 0x00); /* Display setting 1 */
+ sub_through_write(1, 0x04);
+ sub_through_write(1, 0x01);
+ sub_through_write(1, 0x05);
+ sub_through_write(1, 0x0280);
+ sub_through_write(1, 0x0301);
+ sub_through_write(1, 0x0402);
+ sub_through_write(1, 0x0500);
+ sub_through_write(1, 0x0681);
+ sub_through_write(1, 0x077F);
+ sub_through_write(1, 0x08C0);
+ sub_through_write(1, 0x0905);
+ sub_through_write(1, 0x0A02);
+ sub_through_write(1, 0x0B00);
+ sub_through_write(1, 0x0C00);
+ sub_through_write(1, 0x0D00);
+ sub_through_write(1, 0x0E00);
+ sub_through_write(1, 0x0F00);
+
+ sub_through_write(1, 0x100B); /* Display setting 2 */
+ sub_through_write(1, 0x1103);
+ sub_through_write(1, 0x1237);
+ sub_through_write(1, 0x1300);
+ sub_through_write(1, 0x1400);
+ sub_through_write(1, 0x1500);
+ sub_through_write(1, 0x1605);
+ sub_through_write(1, 0x1700);
+ sub_through_write(1, 0x1800);
+ sub_through_write(1, 0x192E);
+ sub_through_write(1, 0x1A00);
+ sub_through_write(1, 0x1B00);
+ sub_through_write(1, 0x1C00);
+
+ sub_through_write(1, 0x151A); /* Power setting */
+
+ sub_through_write(1, 0x2002); /* Gradation Palette setting */
+ sub_through_write(1, 0x2107);
+ sub_through_write(1, 0x220C);
+ sub_through_write(1, 0x2310);
+ sub_through_write(1, 0x2414);
+ sub_through_write(1, 0x2518);
+ sub_through_write(1, 0x261C);
+ sub_through_write(1, 0x2720);
+ sub_through_write(1, 0x2824);
+ sub_through_write(1, 0x2928);
+ sub_through_write(1, 0x2A2B);
+ sub_through_write(1, 0x2B2E);
+ sub_through_write(1, 0x2C31);
+ sub_through_write(1, 0x2D34);
+ sub_through_write(1, 0x2E37);
+ sub_through_write(1, 0x2F3A);
+ sub_through_write(1, 0x303C);
+ sub_through_write(1, 0x313E);
+ sub_through_write(1, 0x323F);
+ sub_through_write(1, 0x3340);
+ sub_through_write(1, 0x3441);
+ sub_through_write(1, 0x3543);
+ sub_through_write(1, 0x3646);
+ sub_through_write(1, 0x3749);
+ sub_through_write(1, 0x384C);
+ sub_through_write(1, 0x394F);
+ sub_through_write(1, 0x3A52);
+ sub_through_write(1, 0x3B59);
+ sub_through_write(1, 0x3C60);
+ sub_through_write(1, 0x3D67);
+ sub_through_write(1, 0x3E6E);
+ sub_through_write(1, 0x3F7F);
+ sub_through_write(1, 0x4001);
+ sub_through_write(1, 0x4107);
+ sub_through_write(1, 0x420C);
+ sub_through_write(1, 0x4310);
+ sub_through_write(1, 0x4414);
+ sub_through_write(1, 0x4518);
+ sub_through_write(1, 0x461C);
+ sub_through_write(1, 0x4720);
+ sub_through_write(1, 0x4824);
+ sub_through_write(1, 0x4928);
+ sub_through_write(1, 0x4A2B);
+ sub_through_write(1, 0x4B2E);
+ sub_through_write(1, 0x4C31);
+ sub_through_write(1, 0x4D34);
+ sub_through_write(1, 0x4E37);
+ sub_through_write(1, 0x4F3A);
+ sub_through_write(1, 0x503C);
+ sub_through_write(1, 0x513E);
+ sub_through_write(1, 0x523F);
+ sub_through_write(1, 0x5340);
+ sub_through_write(1, 0x5441);
+ sub_through_write(1, 0x5543);
+ sub_through_write(1, 0x5646);
+ sub_through_write(1, 0x5749);
+ sub_through_write(1, 0x584C);
+ sub_through_write(1, 0x594F);
+ sub_through_write(1, 0x5A52);
+ sub_through_write(1, 0x5B59);
+ sub_through_write(1, 0x5C60);
+ sub_through_write(1, 0x5D67);
+ sub_through_write(1, 0x5E6E);
+ sub_through_write(1, 0x5F7E);
+ sub_through_write(1, 0x6000);
+ sub_through_write(1, 0x6107);
+ sub_through_write(1, 0x620C);
+ sub_through_write(1, 0x6310);
+ sub_through_write(1, 0x6414);
+ sub_through_write(1, 0x6518);
+ sub_through_write(1, 0x661C);
+ sub_through_write(1, 0x6720);
+ sub_through_write(1, 0x6824);
+ sub_through_write(1, 0x6928);
+ sub_through_write(1, 0x6A2B);
+ sub_through_write(1, 0x6B2E);
+ sub_through_write(1, 0x6C31);
+ sub_through_write(1, 0x6D34);
+ sub_through_write(1, 0x6E37);
+ sub_through_write(1, 0x6F3A);
+ sub_through_write(1, 0x703C);
+ sub_through_write(1, 0x713E);
+ sub_through_write(1, 0x723F);
+ sub_through_write(1, 0x7340);
+ sub_through_write(1, 0x7441);
+ sub_through_write(1, 0x7543);
+ sub_through_write(1, 0x7646);
+ sub_through_write(1, 0x7749);
+ sub_through_write(1, 0x784C);
+ sub_through_write(1, 0x794F);
+ sub_through_write(1, 0x7A52);
+ sub_through_write(1, 0x7B59);
+ sub_through_write(1, 0x7C60);
+ sub_through_write(1, 0x7D67);
+ sub_through_write(1, 0x7E6E);
+ sub_through_write(1, 0x7F7D);
+
+ sub_through_write(1, 0x1851); /* Display on */
+
+ mddi_queue_register_write(REG_AGM, 0x0000, TRUE, 0);
+
+ /* 1 pixel / 1 post clock */
+ mddi_queue_register_write(REG_CLKDIV2, 0x3b00, FALSE, 0);
+
+ /* SUB LCD select */
+ mddi_queue_register_write(REG_PSTCTL2, 0x0080, FALSE, 0);
+
+ /* RS=0,command initiate number=0,select master mode */
+ mddi_queue_register_write(REG_SUBCTL, 0x0202, FALSE, 0);
+
+ /* Sub LCD Data transform start */
+ mddi_queue_register_write(REG_PSTCTL1, 0x0003, FALSE, 0);
+
+ } else if (sharp_subpanel_type == SHARP_SUB_ROHM) {
+
+ sub_through_write(0, 0x01); /* Display setting */
+ sub_through_write(1, 0x00);
+
+ mddi_wait(1);
+ /* Wait 100us <----- ******* Update 2005/01/24 */
+
+ sub_through_write(0, 0xB6);
+ sub_through_write(1, 0x0C);
+ sub_through_write(1, 0x4A);
+ sub_through_write(1, 0x20);
+ sub_through_write(0, 0x3A);
+ sub_through_write(1, 0x05);
+ sub_through_write(0, 0xB7);
+ sub_through_write(1, 0x01);
+ sub_through_write(0, 0xBA);
+ sub_through_write(1, 0x20);
+ sub_through_write(1, 0x02);
+ sub_through_write(0, 0x25);
+ sub_through_write(1, 0x4F);
+ sub_through_write(0, 0xBB);
+ sub_through_write(1, 0x00);
+ sub_through_write(0, 0x36);
+ sub_through_write(1, 0x00);
+ sub_through_write(0, 0xB1);
+ sub_through_write(1, 0x05);
+ sub_through_write(0, 0xBE);
+ sub_through_write(1, 0x80);
+ sub_through_write(0, 0x26);
+ sub_through_write(1, 0x01);
+ sub_through_write(0, 0x2A);
+ sub_through_write(1, 0x02);
+ sub_through_write(1, 0x81);
+ sub_through_write(0, 0x2B);
+ sub_through_write(1, 0x00);
+ sub_through_write(1, 0x7F);
+
+ sub_through_write(0, 0x2C);
+ sub_through_write(0, 0x11); /* Sleep mode off */
+
+ mddi_wait(1);
+ /* Wait 100 ms <----- ******* Update 2005/01/24 */
+
+ sub_through_write(0, 0x29); /* Display on */
+ sub_through_write(0, 0xB3);
+ sub_through_write(1, 0x20);
+ sub_through_write(1, 0xAA);
+ sub_through_write(1, 0xA0);
+ sub_through_write(1, 0x20);
+ sub_through_write(1, 0x30);
+ sub_through_write(1, 0xA6);
+ sub_through_write(1, 0xFF);
+ sub_through_write(1, 0x9A);
+ sub_through_write(1, 0x9F);
+ sub_through_write(1, 0xAF);
+ sub_through_write(1, 0xBC);
+ sub_through_write(1, 0xCF);
+ sub_through_write(1, 0xDF);
+ sub_through_write(1, 0x20);
+ sub_through_write(1, 0x9C);
+ sub_through_write(1, 0x8A);
+
+ sub_through_write(0, 0x002C); /* Display on */
+
+ /* 1 pixel / 2 post clock */
+ mddi_queue_register_write(REG_CLKDIV2, 0x7b00, FALSE, 0);
+
+ /* SUB LCD select */
+ mddi_queue_register_write(REG_PSTCTL2, 0x0080, FALSE, 0);
+
+ /* RS=1,command initiate number=0,select master mode */
+ mddi_queue_register_write(REG_SUBCTL, 0x0242, FALSE, 0);
+
+ /* Sub LCD Data transform start */
+ mddi_queue_register_write(REG_PSTCTL1, 0x0003, FALSE, 0);
+
+ }
+
+ /* Set the MDP pixel data attributes for Sub Display */
+ mddi_host_write_pix_attr_reg(0x00C0);
+}
+
+void mddi_sharp_lcd_vsync_detected(boolean detected)
+{
+ /* static timetick_type start_time = 0; */
+ static struct timeval start_time;
+ static boolean first_time = TRUE;
+ /* uint32 mdp_cnt_val = 0; */
+ /* timetick_type elapsed_us; */
+ struct timeval now;
+ uint32 elapsed_us;
+ uint32 num_vsyncs;
+
+ if ((detected) || (mddi_sharp_vsync_attempts > 5)) {
+ if ((detected) && (mddi_sharp_monitor_refresh_value)) {
+ /* if (start_time != 0) */
+ if (!first_time) {
+ jiffies_to_timeval(jiffies, &now);
+ elapsed_us =
+ (now.tv_sec - start_time.tv_sec) * 1000000 +
+ now.tv_usec - start_time.tv_usec;
+ /*
+ * LCD is configured for a refresh every usecs,
+ * so to determine the number of vsyncs that
+ * have occurred since the last measurement add
+ * half that to the time difference and divide
+ * by the refresh rate.
+ */
+ num_vsyncs = (elapsed_us +
+ (mddi_sharp_usecs_per_refresh >>
+ 1)) /
+ mddi_sharp_usecs_per_refresh;
+ /*
+ * LCD is configured for * hsyncs (rows) per
+ * refresh cycle. Calculate new rows_per_second
+ * value based upon these new measurements.
+ * MDP can update with this new value.
+ */
+ mddi_sharp_rows_per_second =
+ (mddi_sharp_rows_per_refresh * 1000 *
+ num_vsyncs) / (elapsed_us / 1000);
+ }
+ /* start_time = timetick_get(); */
+ first_time = FALSE;
+ jiffies_to_timeval(jiffies, &start_time);
+ if (mddi_sharp_report_refresh_measurements) {
+ /* mdp_cnt_val = MDP_LINE_COUNT; */
+ }
+ }
+ /* if detected = TRUE, client initiated wakeup was detected */
+ if (mddi_sharp_vsync_handler != NULL) {
+ (*mddi_sharp_vsync_handler)
+ (mddi_sharp_vsync_handler_arg);
+ mddi_sharp_vsync_handler = NULL;
+ }
+ mddi_vsync_detect_enabled = FALSE;
+ mddi_sharp_vsync_attempts = 0;
+ /* need to clear this vsync wakeup */
+ if (!mddi_queue_register_write_int(REG_INTR, 0x0000)) {
+ MDDI_MSG_ERR("Vsync interrupt clear failed!\n");
+ }
+ if (!detected) {
+ /* give up after 5 failed attempts but show error */
+ MDDI_MSG_NOTICE("Vsync detection failed!\n");
+ } else if ((mddi_sharp_monitor_refresh_value) &&
+ (mddi_sharp_report_refresh_measurements)) {
+ MDDI_MSG_NOTICE(" Lines Per Second=%d!\n",
+ mddi_sharp_rows_per_second);
+ }
+ } else
+ /* if detected = FALSE, we woke up from hibernation, but did not
+ * detect client initiated wakeup.
+ */
+ mddi_sharp_vsync_attempts++;
+}
+
+/* ISR to be executed */
+void mddi_sharp_vsync_set_handler(msm_fb_vsync_handler_type handler, void *arg)
+{
+ boolean error = FALSE;
+ unsigned long flags;
+
+ /* Disable interrupts */
+ spin_lock_irqsave(&mddi_host_spin_lock, flags);
+ /* INTLOCK(); */
+
+ if (mddi_sharp_vsync_handler != NULL)
+ error = TRUE;
+
+ /* Register the handler for this particular GROUP interrupt source */
+ mddi_sharp_vsync_handler = handler;
+ mddi_sharp_vsync_handler_arg = arg;
+
+ /* Restore interrupts */
+ spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+ /* INTFREE(); */
+
+ if (error)
+ MDDI_MSG_ERR("MDDI: Previous Vsync handler never called\n");
+
+ /* Enable the vsync wakeup */
+ mddi_queue_register_write(REG_INTR, 0x8100, FALSE, 0);
+
+ mddi_sharp_vsync_attempts = 1;
+ mddi_vsync_detect_enabled = TRUE;
+} /* mddi_sharp_vsync_set_handler */
+
+static int mddi_sharp_lcd_on(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ mddi_host_client_cnt_reset();
+
+ if (mfd->panel.id == SHARP_QVGA_PRIM)
+ mddi_sharp_prim_lcd_init();
+ else
+ mddi_sharp_sub_lcd_init();
+
+ return 0;
+}
+
+static int mddi_sharp_lcd_off(struct platform_device *pdev)
+{
+ if (mddi_sharp_vsync_handler != NULL) {
+ (*mddi_sharp_vsync_handler)
+ (mddi_sharp_vsync_handler_arg);
+ mddi_sharp_vsync_handler = NULL;
+ printk(KERN_INFO "%s: clean up vsyn_handler=%x\n", __func__,
+ (int)mddi_sharp_vsync_handler);
+ }
+
+ mddi_sharp_lcd_powerdown();
+ return 0;
+}
+
+static int __devinit mddi_sharp_probe(struct platform_device *pdev)
+{
+ if (pdev->id == 0) {
+ mddi_sharp_pdata = pdev->dev.platform_data;
+ return 0;
+ }
+
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = mddi_sharp_probe,
+ .driver = {
+ .name = "mddi_sharp_qvga",
+ },
+};
+
+static struct msm_fb_panel_data mddi_sharp_panel_data0 = {
+ .on = mddi_sharp_lcd_on,
+ .off = mddi_sharp_lcd_off,
+ .set_backlight = mddi_sharp_lcd_set_backlight,
+ .set_vsync_notifier = mddi_sharp_vsync_set_handler,
+};
+
+static struct platform_device this_device_0 = {
+ .name = "mddi_sharp_qvga",
+ .id = SHARP_QVGA_PRIM,
+ .dev = {
+ .platform_data = &mddi_sharp_panel_data0,
+ }
+};
+
+static struct msm_fb_panel_data mddi_sharp_panel_data1 = {
+ .on = mddi_sharp_lcd_on,
+ .off = mddi_sharp_lcd_off,
+};
+
+static struct platform_device this_device_1 = {
+ .name = "mddi_sharp_qvga",
+ .id = SHARP_128X128_SECD,
+ .dev = {
+ .platform_data = &mddi_sharp_panel_data1,
+ }
+};
+
+static int __init mddi_sharp_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ u32 id;
+
+ ret = msm_fb_detect_client("mddi_sharp_qvga");
+ if (ret == -ENODEV)
+ return 0;
+
+ if (ret) {
+ id = mddi_get_client_id();
+
+ if (((id >> 16) != 0x0) || ((id & 0xffff) != 0x8835))
+ return 0;
+ }
+#endif
+ if (mddi_host_core_version > 8) {
+ /* can use faster refresh with newer hw revisions */
+ mddi_sharp_debug_60hz_refresh = TRUE;
+
+ /* Timing variables for tracking vsync */
+ /* dot_clock = 6.00MHz
+ * horizontal count = 296
+ * vertical count = 338
+ * refresh rate = 6000000/(296+338) = 60Hz
+ */
+ mddi_sharp_rows_per_second = 20270; /* 6000000/296 */
+ mddi_sharp_rows_per_refresh = 338;
+ mddi_sharp_usecs_per_refresh = 16674; /* (296+338)/6000000 */
+ } else {
+ /* Timing variables for tracking vsync */
+ /* dot_clock = 5.20MHz
+ * horizontal count = 376
+ * vertical count = 338
+ * refresh rate = 5200000/(376+338) = 41Hz
+ */
+ mddi_sharp_rows_per_second = 13830; /* 5200000/376 */
+ mddi_sharp_rows_per_refresh = 338;
+ mddi_sharp_usecs_per_refresh = 24440; /* (376+338)/5200000 */
+ }
+
+ ret = platform_driver_register(&this_driver);
+ if (!ret) {
+ pinfo = &mddi_sharp_panel_data0.panel_info;
+ pinfo->xres = 240;
+ pinfo->yres = 320;
+ MSM_FB_SINGLE_MODE_PANEL(pinfo);
+ pinfo->type = MDDI_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 18;
+ pinfo->fb_num = 2;
+ pinfo->clk_rate = 122880000;
+ pinfo->clk_min = 120000000;
+ pinfo->clk_max = 125000000;
+ pinfo->lcd.vsync_enable = TRUE;
+ pinfo->lcd.refx100 =
+ (mddi_sharp_rows_per_second * 100) /
+ mddi_sharp_rows_per_refresh;
+ pinfo->lcd.v_back_porch = 12;
+ pinfo->lcd.v_front_porch = 6;
+ pinfo->lcd.v_pulse_width = 0;
+ pinfo->lcd.hw_vsync_mode = FALSE;
+ pinfo->lcd.vsync_notifier_period = (1 * HZ);
+ pinfo->bl_max = 7;
+ pinfo->bl_min = 1;
+
+ ret = platform_device_register(&this_device_0);
+ if (ret)
+ platform_driver_unregister(&this_driver);
+
+ pinfo = &mddi_sharp_panel_data1.panel_info;
+ pinfo->xres = 128;
+ pinfo->yres = 128;
+ MSM_FB_SINGLE_MODE_PANEL(pinfo);
+ pinfo->type = MDDI_PANEL;
+ pinfo->pdest = DISPLAY_2;
+ pinfo->mddi.vdopkt = 0x400;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 18;
+ pinfo->clk_rate = 122880000;
+ pinfo->clk_min = 120000000;
+ pinfo->clk_max = 125000000;
+ pinfo->fb_num = 2;
+
+ ret = platform_device_register(&this_device_1);
+ if (ret) {
+ platform_device_unregister(&this_device_0);
+ platform_driver_unregister(&this_driver);
+ }
+ }
+
+ if (!ret)
+ mddi_lcd.vsync_detected = mddi_sharp_lcd_vsync_detected;
+
+ return ret;
+}
+
+module_init(mddi_sharp_init);
diff --git a/drivers/video/msm/mddi_toshiba.c b/drivers/video/msm/mddi_toshiba.c
new file mode 100644
index 0000000..9727453
--- /dev/null
+++ b/drivers/video/msm/mddi_toshiba.c
@@ -0,0 +1,1753 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+#include "mddi_toshiba.h"
+
+#define TM_GET_DID(id) ((id) & 0xff)
+#define TM_GET_PID(id) (((id) & 0xff00)>>8)
+
+#define MDDI_CLIENT_CORE_BASE 0x108000
+#define LCD_CONTROL_BLOCK_BASE 0x110000
+#define SPI_BLOCK_BASE 0x120000
+#define PWM_BLOCK_BASE 0x140000
+#define SYSTEM_BLOCK1_BASE 0x160000
+
+#define TTBUSSEL (MDDI_CLIENT_CORE_BASE|0x18)
+#define DPSET0 (MDDI_CLIENT_CORE_BASE|0x1C)
+#define DPSET1 (MDDI_CLIENT_CORE_BASE|0x20)
+#define DPSUS (MDDI_CLIENT_CORE_BASE|0x24)
+#define DPRUN (MDDI_CLIENT_CORE_BASE|0x28)
+#define SYSCKENA (MDDI_CLIENT_CORE_BASE|0x2C)
+
+#define BITMAP0 (MDDI_CLIENT_CORE_BASE|0x44)
+#define BITMAP1 (MDDI_CLIENT_CORE_BASE|0x48)
+#define BITMAP2 (MDDI_CLIENT_CORE_BASE|0x4C)
+#define BITMAP3 (MDDI_CLIENT_CORE_BASE|0x50)
+#define BITMAP4 (MDDI_CLIENT_CORE_BASE|0x54)
+
+#define SRST (LCD_CONTROL_BLOCK_BASE|0x00)
+#define PORT_ENB (LCD_CONTROL_BLOCK_BASE|0x04)
+#define START (LCD_CONTROL_BLOCK_BASE|0x08)
+#define PORT (LCD_CONTROL_BLOCK_BASE|0x0C)
+
+#define INTFLG (LCD_CONTROL_BLOCK_BASE|0x18)
+#define INTMSK (LCD_CONTROL_BLOCK_BASE|0x1C)
+#define MPLFBUF (LCD_CONTROL_BLOCK_BASE|0x20)
+
+#define PXL (LCD_CONTROL_BLOCK_BASE|0x30)
+#define HCYCLE (LCD_CONTROL_BLOCK_BASE|0x34)
+#define HSW (LCD_CONTROL_BLOCK_BASE|0x38)
+#define HDE_START (LCD_CONTROL_BLOCK_BASE|0x3C)
+#define HDE_SIZE (LCD_CONTROL_BLOCK_BASE|0x40)
+#define VCYCLE (LCD_CONTROL_BLOCK_BASE|0x44)
+#define VSW (LCD_CONTROL_BLOCK_BASE|0x48)
+#define VDE_START (LCD_CONTROL_BLOCK_BASE|0x4C)
+#define VDE_SIZE (LCD_CONTROL_BLOCK_BASE|0x50)
+#define WAKEUP (LCD_CONTROL_BLOCK_BASE|0x54)
+#define REGENB (LCD_CONTROL_BLOCK_BASE|0x5C)
+#define VSYNIF (LCD_CONTROL_BLOCK_BASE|0x60)
+#define WRSTB (LCD_CONTROL_BLOCK_BASE|0x64)
+#define RDSTB (LCD_CONTROL_BLOCK_BASE|0x68)
+#define ASY_DATA (LCD_CONTROL_BLOCK_BASE|0x6C)
+#define ASY_DATB (LCD_CONTROL_BLOCK_BASE|0x70)
+#define ASY_DATC (LCD_CONTROL_BLOCK_BASE|0x74)
+#define ASY_DATD (LCD_CONTROL_BLOCK_BASE|0x78)
+#define ASY_DATE (LCD_CONTROL_BLOCK_BASE|0x7C)
+#define ASY_DATF (LCD_CONTROL_BLOCK_BASE|0x80)
+#define ASY_DATG (LCD_CONTROL_BLOCK_BASE|0x84)
+#define ASY_DATH (LCD_CONTROL_BLOCK_BASE|0x88)
+#define ASY_CMDSET (LCD_CONTROL_BLOCK_BASE|0x8C)
+#define MONI (LCD_CONTROL_BLOCK_BASE|0xB0)
+#define VPOS (LCD_CONTROL_BLOCK_BASE|0xC0)
+
+#define SSICTL (SPI_BLOCK_BASE|0x00)
+#define SSITIME (SPI_BLOCK_BASE|0x04)
+#define SSITX (SPI_BLOCK_BASE|0x08)
+#define SSIINTS (SPI_BLOCK_BASE|0x14)
+
+#define TIMER0LOAD (PWM_BLOCK_BASE|0x00)
+#define TIMER0CTRL (PWM_BLOCK_BASE|0x08)
+#define PWM0OFF (PWM_BLOCK_BASE|0x1C)
+#define TIMER1LOAD (PWM_BLOCK_BASE|0x20)
+#define TIMER1CTRL (PWM_BLOCK_BASE|0x28)
+#define PWM1OFF (PWM_BLOCK_BASE|0x3C)
+#define TIMER2LOAD (PWM_BLOCK_BASE|0x40)
+#define TIMER2CTRL (PWM_BLOCK_BASE|0x48)
+#define PWM2OFF (PWM_BLOCK_BASE|0x5C)
+#define PWMCR (PWM_BLOCK_BASE|0x68)
+
+#define GPIOIS (GPIO_BLOCK_BASE|0x08)
+#define GPIOIEV (GPIO_BLOCK_BASE|0x10)
+#define GPIOIC (GPIO_BLOCK_BASE|0x20)
+
+#define WKREQ (SYSTEM_BLOCK1_BASE|0x00)
+#define CLKENB (SYSTEM_BLOCK1_BASE|0x04)
+#define DRAMPWR (SYSTEM_BLOCK1_BASE|0x08)
+#define INTMASK (SYSTEM_BLOCK1_BASE|0x0C)
+#define CNT_DIS (SYSTEM_BLOCK1_BASE|0x10)
+
+typedef enum {
+ TOSHIBA_STATE_OFF,
+ TOSHIBA_STATE_PRIM_SEC_STANDBY,
+ TOSHIBA_STATE_PRIM_SEC_READY,
+ TOSHIBA_STATE_PRIM_NORMAL_MODE,
+ TOSHIBA_STATE_SEC_NORMAL_MODE
+} mddi_toshiba_state_t;
+
+static uint32 mddi_toshiba_curr_vpos;
+static boolean mddi_toshiba_monitor_refresh_value = FALSE;
+static boolean mddi_toshiba_report_refresh_measurements = FALSE;
+
+boolean mddi_toshiba_61Hz_refresh = TRUE;
+
+/* Modifications to timing to increase refresh rate to > 60Hz.
+ * 20MHz dot clock.
+ * 646 total rows.
+ * 506 total columns.
+ * refresh rate = 61.19Hz
+ */
+static uint32 mddi_toshiba_rows_per_second = 39526;
+static uint32 mddi_toshiba_usecs_per_refresh = 16344;
+static uint32 mddi_toshiba_rows_per_refresh = 646;
+extern boolean mddi_vsync_detect_enabled;
+
+static msm_fb_vsync_handler_type mddi_toshiba_vsync_handler;
+static void *mddi_toshiba_vsync_handler_arg;
+static uint16 mddi_toshiba_vsync_attempts;
+
+static mddi_toshiba_state_t toshiba_state = TOSHIBA_STATE_OFF;
+
+static struct msm_panel_common_pdata *mddi_toshiba_pdata;
+
+static int mddi_toshiba_lcd_on(struct platform_device *pdev);
+static int mddi_toshiba_lcd_off(struct platform_device *pdev);
+
+static void mddi_toshiba_state_transition(mddi_toshiba_state_t a,
+ mddi_toshiba_state_t b)
+{
+ if (toshiba_state != a) {
+ MDDI_MSG_ERR("toshiba state trans. (%d->%d) found %d\n", a, b,
+ toshiba_state);
+ }
+ toshiba_state = b;
+}
+
+#define GORDON_REG_IMGCTL1 0x10 /* Image interface control 1 */
+#define GORDON_REG_IMGCTL2 0x11 /* Image interface control 2 */
+#define GORDON_REG_IMGSET1 0x12 /* Image interface settings 1 */
+#define GORDON_REG_IMGSET2 0x13 /* Image interface settings 2 */
+#define GORDON_REG_IVBP1 0x14 /* DM0: Vert back porch */
+#define GORDON_REG_IHBP1 0x15 /* DM0: Horiz back porch */
+#define GORDON_REG_IVNUM1 0x16 /* DM0: Num of vert lines */
+#define GORDON_REG_IHNUM1 0x17 /* DM0: Num of pixels per line */
+#define GORDON_REG_IVBP2 0x18 /* DM1: Vert back porch */
+#define GORDON_REG_IHBP2 0x19 /* DM1: Horiz back porch */
+#define GORDON_REG_IVNUM2 0x1A /* DM1: Num of vert lines */
+#define GORDON_REG_IHNUM2 0x1B /* DM1: Num of pixels per line */
+#define GORDON_REG_LCDIFCTL1 0x30 /* LCD interface control 1 */
+#define GORDON_REG_VALTRAN 0x31 /* LCD IF ctl: VALTRAN sync flag */
+#define GORDON_REG_AVCTL 0x33
+#define GORDON_REG_LCDIFCTL2 0x34 /* LCD interface control 2 */
+#define GORDON_REG_LCDIFCTL3 0x35 /* LCD interface control 3 */
+#define GORDON_REG_LCDIFSET1 0x36 /* LCD interface settings 1 */
+#define GORDON_REG_PCCTL 0x3C
+#define GORDON_REG_TPARAM1 0x40
+#define GORDON_REG_TLCDIF1 0x41
+#define GORDON_REG_TSSPB_ST1 0x42
+#define GORDON_REG_TSSPB_ED1 0x43
+#define GORDON_REG_TSCK_ST1 0x44
+#define GORDON_REG_TSCK_WD1 0x45
+#define GORDON_REG_TGSPB_VST1 0x46
+#define GORDON_REG_TGSPB_VED1 0x47
+#define GORDON_REG_TGSPB_CH1 0x48
+#define GORDON_REG_TGCK_ST1 0x49
+#define GORDON_REG_TGCK_ED1 0x4A
+#define GORDON_REG_TPCTL_ST1 0x4B
+#define GORDON_REG_TPCTL_ED1 0x4C
+#define GORDON_REG_TPCHG_ED1 0x4D
+#define GORDON_REG_TCOM_CH1 0x4E
+#define GORDON_REG_THBP1 0x4F
+#define GORDON_REG_TPHCTL1 0x50
+#define GORDON_REG_EVPH1 0x51
+#define GORDON_REG_EVPL1 0x52
+#define GORDON_REG_EVNH1 0x53
+#define GORDON_REG_EVNL1 0x54
+#define GORDON_REG_TBIAS1 0x55
+#define GORDON_REG_TPARAM2 0x56
+#define GORDON_REG_TLCDIF2 0x57
+#define GORDON_REG_TSSPB_ST2 0x58
+#define GORDON_REG_TSSPB_ED2 0x59
+#define GORDON_REG_TSCK_ST2 0x5A
+#define GORDON_REG_TSCK_WD2 0x5B
+#define GORDON_REG_TGSPB_VST2 0x5C
+#define GORDON_REG_TGSPB_VED2 0x5D
+#define GORDON_REG_TGSPB_CH2 0x5E
+#define GORDON_REG_TGCK_ST2 0x5F
+#define GORDON_REG_TGCK_ED2 0x60
+#define GORDON_REG_TPCTL_ST2 0x61
+#define GORDON_REG_TPCTL_ED2 0x62
+#define GORDON_REG_TPCHG_ED2 0x63
+#define GORDON_REG_TCOM_CH2 0x64
+#define GORDON_REG_THBP2 0x65
+#define GORDON_REG_TPHCTL2 0x66
+#define GORDON_REG_EVPH2 0x67
+#define GORDON_REG_EVPL2 0x68
+#define GORDON_REG_EVNH2 0x69
+#define GORDON_REG_EVNL2 0x6A
+#define GORDON_REG_TBIAS2 0x6B
+#define GORDON_REG_POWCTL 0x80
+#define GORDON_REG_POWOSC1 0x81
+#define GORDON_REG_POWOSC2 0x82
+#define GORDON_REG_POWSET 0x83
+#define GORDON_REG_POWTRM1 0x85
+#define GORDON_REG_POWTRM2 0x86
+#define GORDON_REG_POWTRM3 0x87
+#define GORDON_REG_POWTRMSEL 0x88
+#define GORDON_REG_POWHIZ 0x89
+
+void serigo(uint16 reg, uint8 data)
+{
+ uint32 mddi_val = 0;
+ mddi_queue_register_read(SSIINTS, &mddi_val, TRUE, 0);
+ if (mddi_val & (1 << 8))
+ mddi_wait(1);
+ /* No De-assert of CS and send 2 bytes */
+ mddi_val = 0x90000 | ((0x00FF & reg) << 8) | data;
+ mddi_queue_register_write(SSITX, mddi_val, TRUE, 0);
+}
+
+void gordon_init(void)
+{
+ /* Image interface settings ***/
+ serigo(GORDON_REG_IMGCTL2, 0x00);
+ serigo(GORDON_REG_IMGSET1, 0x01);
+
+ /* Exchange the RGB signal for J510(Softbank mobile) */
+ serigo(GORDON_REG_IMGSET2, 0x12);
+ serigo(GORDON_REG_LCDIFSET1, 0x00);
+ mddi_wait(2);
+
+ /* Pre-charge settings */
+ serigo(GORDON_REG_PCCTL, 0x09);
+ serigo(GORDON_REG_LCDIFCTL2, 0x1B);
+ mddi_wait(1);
+}
+
+void gordon_disp_on(void)
+{
+ /*gordon_dispmode setting */
+ /*VGA settings */
+ serigo(GORDON_REG_TPARAM1, 0x30);
+ serigo(GORDON_REG_TLCDIF1, 0x00);
+ serigo(GORDON_REG_TSSPB_ST1, 0x8B);
+ serigo(GORDON_REG_TSSPB_ED1, 0x93);
+ mddi_wait(2);
+ serigo(GORDON_REG_TSCK_ST1, 0x88);
+ serigo(GORDON_REG_TSCK_WD1, 0x00);
+ serigo(GORDON_REG_TGSPB_VST1, 0x01);
+ serigo(GORDON_REG_TGSPB_VED1, 0x02);
+ mddi_wait(2);
+ serigo(GORDON_REG_TGSPB_CH1, 0x5E);
+ serigo(GORDON_REG_TGCK_ST1, 0x80);
+ serigo(GORDON_REG_TGCK_ED1, 0x3C);
+ serigo(GORDON_REG_TPCTL_ST1, 0x50);
+ mddi_wait(2);
+ serigo(GORDON_REG_TPCTL_ED1, 0x74);
+ serigo(GORDON_REG_TPCHG_ED1, 0x78);
+ serigo(GORDON_REG_TCOM_CH1, 0x50);
+ serigo(GORDON_REG_THBP1, 0x84);
+ mddi_wait(2);
+ serigo(GORDON_REG_TPHCTL1, 0x00);
+ serigo(GORDON_REG_EVPH1, 0x70);
+ serigo(GORDON_REG_EVPL1, 0x64);
+ serigo(GORDON_REG_EVNH1, 0x56);
+ mddi_wait(2);
+ serigo(GORDON_REG_EVNL1, 0x48);
+ serigo(GORDON_REG_TBIAS1, 0x88);
+ mddi_wait(2);
+ serigo(GORDON_REG_TPARAM2, 0x28);
+ serigo(GORDON_REG_TLCDIF2, 0x14);
+ serigo(GORDON_REG_TSSPB_ST2, 0x49);
+ serigo(GORDON_REG_TSSPB_ED2, 0x4B);
+ mddi_wait(2);
+ serigo(GORDON_REG_TSCK_ST2, 0x4A);
+ serigo(GORDON_REG_TSCK_WD2, 0x02);
+ serigo(GORDON_REG_TGSPB_VST2, 0x02);
+ serigo(GORDON_REG_TGSPB_VED2, 0x03);
+ mddi_wait(2);
+ serigo(GORDON_REG_TGSPB_CH2, 0x2F);
+ serigo(GORDON_REG_TGCK_ST2, 0x40);
+ serigo(GORDON_REG_TGCK_ED2, 0x1E);
+ serigo(GORDON_REG_TPCTL_ST2, 0x2C);
+ mddi_wait(2);
+ serigo(GORDON_REG_TPCTL_ED2, 0x3A);
+ serigo(GORDON_REG_TPCHG_ED2, 0x3C);
+ serigo(GORDON_REG_TCOM_CH2, 0x28);
+ serigo(GORDON_REG_THBP2, 0x4D);
+ mddi_wait(2);
+ serigo(GORDON_REG_TPHCTL2, 0x1A);
+ mddi_wait(2);
+ serigo(GORDON_REG_IVBP1, 0x02);
+ serigo(GORDON_REG_IHBP1, 0x90);
+ serigo(GORDON_REG_IVNUM1, 0xA0);
+ serigo(GORDON_REG_IHNUM1, 0x78);
+ mddi_wait(2);
+ serigo(GORDON_REG_IVBP2, 0x02);
+ serigo(GORDON_REG_IHBP2, 0x48);
+ serigo(GORDON_REG_IVNUM2, 0x50);
+ serigo(GORDON_REG_IHNUM2, 0x3C);
+ mddi_wait(2);
+ serigo(GORDON_REG_POWCTL, 0x03);
+ mddi_wait(15);
+ serigo(GORDON_REG_POWCTL, 0x07);
+ mddi_wait(15);
+ serigo(GORDON_REG_POWCTL, 0x0F);
+ mddi_wait(15);
+ serigo(GORDON_REG_AVCTL, 0x03);
+ mddi_wait(15);
+ serigo(GORDON_REG_POWCTL, 0x1F);
+ mddi_wait(15);
+ serigo(GORDON_REG_POWCTL, 0x5F);
+ mddi_wait(15);
+ serigo(GORDON_REG_POWCTL, 0x7F);
+ mddi_wait(15);
+ serigo(GORDON_REG_LCDIFCTL1, 0x02);
+ mddi_wait(15);
+ serigo(GORDON_REG_IMGCTL1, 0x00);
+ mddi_wait(15);
+ serigo(GORDON_REG_LCDIFCTL3, 0x00);
+ mddi_wait(15);
+ serigo(GORDON_REG_VALTRAN, 0x01);
+ mddi_wait(15);
+ serigo(GORDON_REG_LCDIFCTL1, 0x03);
+ serigo(GORDON_REG_LCDIFCTL1, 0x03);
+ mddi_wait(1);
+}
+
+void gordon_disp_off(void)
+{
+ serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+ serigo(GORDON_REG_VALTRAN, 0x01);
+ serigo(GORDON_REG_LCDIFCTL1, 0x02);
+ serigo(GORDON_REG_LCDIFCTL3, 0x01);
+ mddi_wait(20);
+ serigo(GORDON_REG_VALTRAN, 0x01);
+ serigo(GORDON_REG_IMGCTL1, 0x01);
+ serigo(GORDON_REG_LCDIFCTL1, 0x00);
+ mddi_wait(20);
+ serigo(GORDON_REG_POWCTL, 0x1F);
+ mddi_wait(40);
+ serigo(GORDON_REG_POWCTL, 0x07);
+ mddi_wait(40);
+ serigo(GORDON_REG_POWCTL, 0x03);
+ mddi_wait(40);
+ serigo(GORDON_REG_POWCTL, 0x00);
+ mddi_wait(40);
+}
+
+void gordon_disp_init(void)
+{
+ gordon_init();
+ mddi_wait(20);
+ gordon_disp_on();
+}
+
+static void toshiba_common_initial_setup(struct msm_fb_data_type *mfd)
+{
+ if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) {
+ write_client_reg(DPSET0 , 0x4bec0066, TRUE);
+ write_client_reg(DPSET1 , 0x00000113, TRUE);
+ write_client_reg(DPSUS , 0x00000000, TRUE);
+ write_client_reg(DPRUN , 0x00000001, TRUE);
+ mddi_wait(5);
+ write_client_reg(SYSCKENA , 0x00000001, TRUE);
+ write_client_reg(CLKENB , 0x0000a0e9, TRUE);
+
+ write_client_reg(GPIODATA , 0x03FF0000, TRUE);
+ write_client_reg(GPIODIR , 0x0000024D, TRUE);
+ write_client_reg(GPIOSEL , 0x00000173, TRUE);
+ write_client_reg(GPIOPC , 0x03C300C0, TRUE);
+ write_client_reg(WKREQ , 0x00000000, TRUE);
+ write_client_reg(GPIOIS , 0x00000000, TRUE);
+ write_client_reg(GPIOIEV , 0x00000001, TRUE);
+ write_client_reg(GPIOIC , 0x000003FF, TRUE);
+ write_client_reg(GPIODATA , 0x00040004, TRUE);
+
+ write_client_reg(GPIODATA , 0x00080008, TRUE);
+ write_client_reg(DRAMPWR , 0x00000001, TRUE);
+ write_client_reg(CLKENB , 0x0000a0eb, TRUE);
+ write_client_reg(PWMCR , 0x00000000, TRUE);
+ mddi_wait(1);
+
+ write_client_reg(SSICTL , 0x00060399, TRUE);
+ write_client_reg(SSITIME , 0x00000100, TRUE);
+ write_client_reg(CNT_DIS , 0x00000002, TRUE);
+ write_client_reg(SSICTL , 0x0006039b, TRUE);
+
+ write_client_reg(SSITX , 0x00000000, TRUE);
+ mddi_wait(7);
+ write_client_reg(SSITX , 0x00000000, TRUE);
+ mddi_wait(7);
+ write_client_reg(SSITX , 0x00000000, TRUE);
+ mddi_wait(7);
+
+ write_client_reg(SSITX , 0x000800BA, TRUE);
+ write_client_reg(SSITX , 0x00000111, TRUE);
+ write_client_reg(SSITX , 0x00080036, TRUE);
+ write_client_reg(SSITX , 0x00000100, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x0008003A, TRUE);
+ write_client_reg(SSITX , 0x00000160, TRUE);
+ write_client_reg(SSITX , 0x000800B1, TRUE);
+ write_client_reg(SSITX , 0x0000015D, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800B2, TRUE);
+ write_client_reg(SSITX , 0x00000133, TRUE);
+ write_client_reg(SSITX , 0x000800B3, TRUE);
+ write_client_reg(SSITX , 0x00000122, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800B4, TRUE);
+ write_client_reg(SSITX , 0x00000102, TRUE);
+ write_client_reg(SSITX , 0x000800B5, TRUE);
+ write_client_reg(SSITX , 0x0000011E, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800B6, TRUE);
+ write_client_reg(SSITX , 0x00000127, TRUE);
+ write_client_reg(SSITX , 0x000800B7, TRUE);
+ write_client_reg(SSITX , 0x00000103, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800B9, TRUE);
+ write_client_reg(SSITX , 0x00000124, TRUE);
+ write_client_reg(SSITX , 0x000800BD, TRUE);
+ write_client_reg(SSITX , 0x000001A1, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800BB, TRUE);
+ write_client_reg(SSITX , 0x00000100, TRUE);
+ write_client_reg(SSITX , 0x000800BF, TRUE);
+ write_client_reg(SSITX , 0x00000101, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800BE, TRUE);
+ write_client_reg(SSITX , 0x00000100, TRUE);
+ write_client_reg(SSITX , 0x000800C0, TRUE);
+ write_client_reg(SSITX , 0x00000111, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800C1, TRUE);
+ write_client_reg(SSITX , 0x00000111, TRUE);
+ write_client_reg(SSITX , 0x000800C2, TRUE);
+ write_client_reg(SSITX , 0x00000111, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800C3, TRUE);
+ write_client_reg(SSITX , 0x00080132, TRUE);
+ write_client_reg(SSITX , 0x00000132, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800C4, TRUE);
+ write_client_reg(SSITX , 0x00080132, TRUE);
+ write_client_reg(SSITX , 0x00000132, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800C5, TRUE);
+ write_client_reg(SSITX , 0x00080132, TRUE);
+ write_client_reg(SSITX , 0x00000132, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800C6, TRUE);
+ write_client_reg(SSITX , 0x00080132, TRUE);
+ write_client_reg(SSITX , 0x00000132, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800C7, TRUE);
+ write_client_reg(SSITX , 0x00080164, TRUE);
+ write_client_reg(SSITX , 0x00000145, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800C8, TRUE);
+ write_client_reg(SSITX , 0x00000144, TRUE);
+ write_client_reg(SSITX , 0x000800C9, TRUE);
+ write_client_reg(SSITX , 0x00000152, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800CA, TRUE);
+ write_client_reg(SSITX , 0x00000100, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800EC, TRUE);
+ write_client_reg(SSITX , 0x00080101, TRUE);
+ write_client_reg(SSITX , 0x000001FC, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800CF, TRUE);
+ write_client_reg(SSITX , 0x00000101, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800D0, TRUE);
+ write_client_reg(SSITX , 0x00080110, TRUE);
+ write_client_reg(SSITX , 0x00000104, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800D1, TRUE);
+ write_client_reg(SSITX , 0x00000101, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800D2, TRUE);
+ write_client_reg(SSITX , 0x00080100, TRUE);
+ write_client_reg(SSITX , 0x00000128, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800D3, TRUE);
+ write_client_reg(SSITX , 0x00080100, TRUE);
+ write_client_reg(SSITX , 0x00000128, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800D4, TRUE);
+ write_client_reg(SSITX , 0x00080126, TRUE);
+ write_client_reg(SSITX , 0x000001A4, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800D5, TRUE);
+ write_client_reg(SSITX , 0x00000120, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800EF, TRUE);
+ write_client_reg(SSITX , 0x00080132, TRUE);
+ write_client_reg(SSITX , 0x00000100, TRUE);
+ mddi_wait(1);
+
+ write_client_reg(BITMAP0 , 0x032001E0, TRUE);
+ write_client_reg(BITMAP1 , 0x032001E0, TRUE);
+ write_client_reg(BITMAP2 , 0x014000F0, TRUE);
+ write_client_reg(BITMAP3 , 0x014000F0, TRUE);
+ write_client_reg(BITMAP4 , 0x014000F0, TRUE);
+ write_client_reg(CLKENB , 0x0000A1EB, TRUE);
+ write_client_reg(PORT_ENB , 0x00000001, TRUE);
+ write_client_reg(PORT , 0x00000004, TRUE);
+ write_client_reg(PXL , 0x00000002, TRUE);
+ write_client_reg(MPLFBUF , 0x00000000, TRUE);
+ write_client_reg(HCYCLE , 0x000000FD, TRUE);
+ write_client_reg(HSW , 0x00000003, TRUE);
+ write_client_reg(HDE_START , 0x00000007, TRUE);
+ write_client_reg(HDE_SIZE , 0x000000EF, TRUE);
+ write_client_reg(VCYCLE , 0x00000325, TRUE);
+ write_client_reg(VSW , 0x00000001, TRUE);
+ write_client_reg(VDE_START , 0x00000003, TRUE);
+ write_client_reg(VDE_SIZE , 0x0000031F, TRUE);
+ write_client_reg(START , 0x00000001, TRUE);
+ mddi_wait(32);
+ write_client_reg(SSITX , 0x000800BC, TRUE);
+ write_client_reg(SSITX , 0x00000180, TRUE);
+ write_client_reg(SSITX , 0x0008003B, TRUE);
+ write_client_reg(SSITX , 0x00000100, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800B0, TRUE);
+ write_client_reg(SSITX , 0x00000116, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800B8, TRUE);
+ write_client_reg(SSITX , 0x000801FF, TRUE);
+ write_client_reg(SSITX , 0x000001F5, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x00000011, TRUE);
+ mddi_wait(5);
+ write_client_reg(SSITX , 0x00000029, TRUE);
+ return;
+ }
+
+ if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
+ write_client_reg(DPSET0, 0x4BEC0066, TRUE);
+ write_client_reg(DPSET1, 0x00000113, TRUE);
+ write_client_reg(DPSUS, 0x00000000, TRUE);
+ write_client_reg(DPRUN, 0x00000001, TRUE);
+ mddi_wait(14);
+ write_client_reg(SYSCKENA, 0x00000001, TRUE);
+ write_client_reg(CLKENB, 0x000000EF, TRUE);
+ write_client_reg(GPIO_BLOCK_BASE, 0x03FF0000, TRUE);
+ write_client_reg(GPIODIR, 0x0000024D, TRUE);
+ write_client_reg(SYSTEM_BLOCK2_BASE, 0x00000173, TRUE);
+ write_client_reg(GPIOPC, 0x03C300C0, TRUE);
+ write_client_reg(SYSTEM_BLOCK1_BASE, 0x00000000, TRUE);
+ write_client_reg(GPIOIS, 0x00000000, TRUE);
+ write_client_reg(GPIOIEV, 0x00000001, TRUE);
+ write_client_reg(GPIOIC, 0x000003FF, TRUE);
+ write_client_reg(GPIO_BLOCK_BASE, 0x00060006, TRUE);
+ write_client_reg(GPIO_BLOCK_BASE, 0x00080008, TRUE);
+ write_client_reg(GPIO_BLOCK_BASE, 0x02000200, TRUE);
+ write_client_reg(DRAMPWR, 0x00000001, TRUE);
+ write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
+ write_client_reg(PWM_BLOCK_BASE, 0x00001388, TRUE);
+ write_client_reg(PWM0OFF, 0x00001387, TRUE);
+ write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
+ write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
+ write_client_reg(PWM1OFF, 0x00001387, TRUE);
+ write_client_reg(TIMER0CTRL, 0x000000E0, TRUE);
+ write_client_reg(TIMER1CTRL, 0x000000E0, TRUE);
+ write_client_reg(PWMCR, 0x00000003, TRUE);
+ mddi_wait(1);
+ write_client_reg(SPI_BLOCK_BASE, 0x00063111, TRUE);
+ write_client_reg(SSITIME, 0x00000100, TRUE);
+ write_client_reg(SPI_BLOCK_BASE, 0x00063113, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x00000000, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x00000000, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x00000000, TRUE);
+ mddi_wait(1);
+ write_client_reg(CLKENB, 0x0000A1EF, TRUE);
+ write_client_reg(START, 0x00000000, TRUE);
+ write_client_reg(WRSTB, 0x0000003F, TRUE);
+ write_client_reg(RDSTB, 0x00000432, TRUE);
+ write_client_reg(PORT_ENB, 0x00000002, TRUE);
+ write_client_reg(VSYNIF, 0x00000000, TRUE);
+ write_client_reg(ASY_DATA, 0x80000000, TRUE);
+ write_client_reg(ASY_DATB, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(10);
+ write_client_reg(ASY_DATA, 0x80000000, TRUE);
+ write_client_reg(ASY_DATB, 0x80000000, TRUE);
+ write_client_reg(ASY_DATC, 0x80000000, TRUE);
+ write_client_reg(ASY_DATD, 0x80000000, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
+ write_client_reg(ASY_DATA, 0x80000007, TRUE);
+ write_client_reg(ASY_DATB, 0x00004005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(20);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x00000000, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+
+ write_client_reg(VSYNIF, 0x00000001, TRUE);
+ write_client_reg(PORT_ENB, 0x00000001, TRUE);
+ } else {
+ write_client_reg(DPSET0, 0x4BEC0066, TRUE);
+ write_client_reg(DPSET1, 0x00000113, TRUE);
+ write_client_reg(DPSUS, 0x00000000, TRUE);
+ write_client_reg(DPRUN, 0x00000001, TRUE);
+ mddi_wait(14);
+ write_client_reg(SYSCKENA, 0x00000001, TRUE);
+ write_client_reg(CLKENB, 0x000000EF, TRUE);
+ write_client_reg(GPIODATA, 0x03FF0000, TRUE);
+ write_client_reg(GPIODIR, 0x0000024D, TRUE);
+ write_client_reg(GPIOSEL, 0x00000173, TRUE);
+ write_client_reg(GPIOPC, 0x03C300C0, TRUE);
+ write_client_reg(WKREQ, 0x00000000, TRUE);
+ write_client_reg(GPIOIS, 0x00000000, TRUE);
+ write_client_reg(GPIOIEV, 0x00000001, TRUE);
+ write_client_reg(GPIOIC, 0x000003FF, TRUE);
+ write_client_reg(GPIODATA, 0x00060006, TRUE);
+ write_client_reg(GPIODATA, 0x00080008, TRUE);
+ write_client_reg(GPIODATA, 0x02000200, TRUE);
+
+ if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA) {
+ mddi_wait(400);
+ write_client_reg(DRAMPWR, 0x00000001, TRUE);
+
+ write_client_reg(CNT_DIS, 0x00000002, TRUE);
+ write_client_reg(BITMAP0, 0x01E00320, TRUE);
+ write_client_reg(PORT_ENB, 0x00000001, TRUE);
+ write_client_reg(PORT, 0x00000004, TRUE);
+ write_client_reg(PXL, 0x0000003A, TRUE);
+ write_client_reg(MPLFBUF, 0x00000000, TRUE);
+ write_client_reg(HCYCLE, 0x00000253, TRUE);
+ write_client_reg(HSW, 0x00000003, TRUE);
+ write_client_reg(HDE_START, 0x00000017, TRUE);
+ write_client_reg(HDE_SIZE, 0x0000018F, TRUE);
+ write_client_reg(VCYCLE, 0x000001FF, TRUE);
+ write_client_reg(VSW, 0x00000001, TRUE);
+ write_client_reg(VDE_START, 0x00000003, TRUE);
+ write_client_reg(VDE_SIZE, 0x000001DF, TRUE);
+ write_client_reg(START, 0x00000001, TRUE);
+ mddi_wait(1);
+ write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
+ write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
+ write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
+ write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
+ write_client_reg(PWM1OFF, 0x00000087, TRUE);
+ } else {
+ write_client_reg(DRAMPWR, 0x00000001, TRUE);
+ write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
+ write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
+ write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
+ write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
+ write_client_reg(PWM1OFF, 0x00001387, TRUE);
+ }
+
+ write_client_reg(TIMER0CTRL, 0x000000E0, TRUE);
+ write_client_reg(TIMER1CTRL, 0x000000E0, TRUE);
+ write_client_reg(PWMCR, 0x00000003, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSICTL, 0x00000799, TRUE);
+ write_client_reg(SSITIME, 0x00000100, TRUE);
+ write_client_reg(SSICTL, 0x0000079b, TRUE);
+ write_client_reg(SSITX, 0x00000000, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x00000000, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x00000000, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x000800BA, TRUE);
+ write_client_reg(SSITX, 0x00000111, TRUE);
+ write_client_reg(SSITX, 0x00080036, TRUE);
+ write_client_reg(SSITX, 0x00000100, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800BB, TRUE);
+ write_client_reg(SSITX, 0x00000100, TRUE);
+ write_client_reg(SSITX, 0x0008003A, TRUE);
+ write_client_reg(SSITX, 0x00000160, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800BF, TRUE);
+ write_client_reg(SSITX, 0x00000100, TRUE);
+ write_client_reg(SSITX, 0x000800B1, TRUE);
+ write_client_reg(SSITX, 0x0000015D, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800B2, TRUE);
+ write_client_reg(SSITX, 0x00000133, TRUE);
+ write_client_reg(SSITX, 0x000800B3, TRUE);
+ write_client_reg(SSITX, 0x00000122, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800B4, TRUE);
+ write_client_reg(SSITX, 0x00000102, TRUE);
+ write_client_reg(SSITX, 0x000800B5, TRUE);
+ write_client_reg(SSITX, 0x0000011F, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800B6, TRUE);
+ write_client_reg(SSITX, 0x00000128, TRUE);
+ write_client_reg(SSITX, 0x000800B7, TRUE);
+ write_client_reg(SSITX, 0x00000103, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800B9, TRUE);
+ write_client_reg(SSITX, 0x00000120, TRUE);
+ write_client_reg(SSITX, 0x000800BD, TRUE);
+ write_client_reg(SSITX, 0x00000102, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800BE, TRUE);
+ write_client_reg(SSITX, 0x00000100, TRUE);
+ write_client_reg(SSITX, 0x000800C0, TRUE);
+ write_client_reg(SSITX, 0x00000111, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800C1, TRUE);
+ write_client_reg(SSITX, 0x00000111, TRUE);
+ write_client_reg(SSITX, 0x000800C2, TRUE);
+ write_client_reg(SSITX, 0x00000111, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800C3, TRUE);
+ write_client_reg(SSITX, 0x0008010A, TRUE);
+ write_client_reg(SSITX, 0x0000010A, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800C4, TRUE);
+ write_client_reg(SSITX, 0x00080160, TRUE);
+ write_client_reg(SSITX, 0x00000160, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800C5, TRUE);
+ write_client_reg(SSITX, 0x00080160, TRUE);
+ write_client_reg(SSITX, 0x00000160, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800C6, TRUE);
+ write_client_reg(SSITX, 0x00080160, TRUE);
+ write_client_reg(SSITX, 0x00000160, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800C7, TRUE);
+ write_client_reg(SSITX, 0x00080133, TRUE);
+ write_client_reg(SSITX, 0x00000143, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800C8, TRUE);
+ write_client_reg(SSITX, 0x00000144, TRUE);
+ write_client_reg(SSITX, 0x000800C9, TRUE);
+ write_client_reg(SSITX, 0x00000133, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800CA, TRUE);
+ write_client_reg(SSITX, 0x00000100, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800EC, TRUE);
+ write_client_reg(SSITX, 0x00080102, TRUE);
+ write_client_reg(SSITX, 0x00000118, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800CF, TRUE);
+ write_client_reg(SSITX, 0x00000101, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800D0, TRUE);
+ write_client_reg(SSITX, 0x00080110, TRUE);
+ write_client_reg(SSITX, 0x00000104, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800D1, TRUE);
+ write_client_reg(SSITX, 0x00000101, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800D2, TRUE);
+ write_client_reg(SSITX, 0x00080100, TRUE);
+ write_client_reg(SSITX, 0x0000013A, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800D3, TRUE);
+ write_client_reg(SSITX, 0x00080100, TRUE);
+ write_client_reg(SSITX, 0x0000013A, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800D4, TRUE);
+ write_client_reg(SSITX, 0x00080124, TRUE);
+ write_client_reg(SSITX, 0x0000016E, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x000800D5, TRUE);
+ write_client_reg(SSITX, 0x00000124, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800ED, TRUE);
+ write_client_reg(SSITX, 0x00080101, TRUE);
+ write_client_reg(SSITX, 0x0000010A, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800D6, TRUE);
+ write_client_reg(SSITX, 0x00000101, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800D7, TRUE);
+ write_client_reg(SSITX, 0x00080110, TRUE);
+ write_client_reg(SSITX, 0x0000010A, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800D8, TRUE);
+ write_client_reg(SSITX, 0x00000101, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800D9, TRUE);
+ write_client_reg(SSITX, 0x00080100, TRUE);
+ write_client_reg(SSITX, 0x00000114, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800DE, TRUE);
+ write_client_reg(SSITX, 0x00080100, TRUE);
+ write_client_reg(SSITX, 0x00000114, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800DF, TRUE);
+ write_client_reg(SSITX, 0x00080112, TRUE);
+ write_client_reg(SSITX, 0x0000013F, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800E0, TRUE);
+ write_client_reg(SSITX, 0x0000010B, TRUE);
+ write_client_reg(SSITX, 0x000800E2, TRUE);
+ write_client_reg(SSITX, 0x00000101, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800E3, TRUE);
+ write_client_reg(SSITX, 0x00000136, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800E4, TRUE);
+ write_client_reg(SSITX, 0x00080100, TRUE);
+ write_client_reg(SSITX, 0x00000103, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800E5, TRUE);
+ write_client_reg(SSITX, 0x00080102, TRUE);
+ write_client_reg(SSITX, 0x00000104, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800E6, TRUE);
+ write_client_reg(SSITX, 0x00000103, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800E7, TRUE);
+ write_client_reg(SSITX, 0x00080104, TRUE);
+ write_client_reg(SSITX, 0x0000010A, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800E8, TRUE);
+ write_client_reg(SSITX, 0x00000104, TRUE);
+ write_client_reg(CLKENB, 0x000001EF, TRUE);
+ write_client_reg(START, 0x00000000, TRUE);
+ write_client_reg(WRSTB, 0x0000003F, TRUE);
+ write_client_reg(RDSTB, 0x00000432, TRUE);
+ write_client_reg(PORT_ENB, 0x00000002, TRUE);
+ write_client_reg(VSYNIF, 0x00000000, TRUE);
+ write_client_reg(ASY_DATA, 0x80000000, TRUE);
+ write_client_reg(ASY_DATB, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(10);
+ write_client_reg(ASY_DATA, 0x80000000, TRUE);
+ write_client_reg(ASY_DATB, 0x80000000, TRUE);
+ write_client_reg(ASY_DATC, 0x80000000, TRUE);
+ write_client_reg(ASY_DATD, 0x80000000, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
+ write_client_reg(ASY_DATA, 0x80000007, TRUE);
+ write_client_reg(ASY_DATB, 0x00004005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(20);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x00000000, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ write_client_reg(VSYNIF, 0x00000001, TRUE);
+ write_client_reg(PORT_ENB, 0x00000001, TRUE);
+ }
+
+ mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_STANDBY,
+ TOSHIBA_STATE_PRIM_SEC_READY);
+}
+
+static void toshiba_prim_start(struct msm_fb_data_type *mfd)
+{
+ if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+ return;
+
+ if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
+ write_client_reg(BITMAP1, 0x01E000F0, TRUE);
+ write_client_reg(BITMAP2, 0x01E000F0, TRUE);
+ write_client_reg(BITMAP3, 0x01E000F0, TRUE);
+ write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
+ write_client_reg(CLKENB, 0x000001EF, TRUE);
+ write_client_reg(PORT_ENB, 0x00000001, TRUE);
+ write_client_reg(PORT, 0x00000016, TRUE);
+ write_client_reg(PXL, 0x00000002, TRUE);
+ write_client_reg(MPLFBUF, 0x00000000, TRUE);
+ write_client_reg(HCYCLE, 0x00000185, TRUE);
+ write_client_reg(HSW, 0x00000018, TRUE);
+ write_client_reg(HDE_START, 0x0000004A, TRUE);
+ write_client_reg(HDE_SIZE, 0x000000EF, TRUE);
+ write_client_reg(VCYCLE, 0x0000028E, TRUE);
+ write_client_reg(VSW, 0x00000004, TRUE);
+ write_client_reg(VDE_START, 0x00000009, TRUE);
+ write_client_reg(VDE_SIZE, 0x0000027F, TRUE);
+ write_client_reg(START, 0x00000001, TRUE);
+ write_client_reg(SYSTEM_BLOCK1_BASE, 0x00000002, TRUE);
+ } else{
+
+ write_client_reg(VSYNIF, 0x00000001, TRUE);
+ write_client_reg(PORT_ENB, 0x00000001, TRUE);
+ write_client_reg(BITMAP1, 0x01E000F0, TRUE);
+ write_client_reg(BITMAP2, 0x01E000F0, TRUE);
+ write_client_reg(BITMAP3, 0x01E000F0, TRUE);
+ write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
+ write_client_reg(CLKENB, 0x000001EF, TRUE);
+ write_client_reg(PORT_ENB, 0x00000001, TRUE);
+ write_client_reg(PORT, 0x00000004, TRUE);
+ write_client_reg(PXL, 0x00000002, TRUE);
+ write_client_reg(MPLFBUF, 0x00000000, TRUE);
+
+ if (mddi_toshiba_61Hz_refresh) {
+ write_client_reg(HCYCLE, 0x000000FC, TRUE);
+ mddi_toshiba_rows_per_second = 39526;
+ mddi_toshiba_rows_per_refresh = 646;
+ mddi_toshiba_usecs_per_refresh = 16344;
+ } else {
+ write_client_reg(HCYCLE, 0x0000010b, TRUE);
+ mddi_toshiba_rows_per_second = 37313;
+ mddi_toshiba_rows_per_refresh = 646;
+ mddi_toshiba_usecs_per_refresh = 17313;
+ }
+
+ write_client_reg(HSW, 0x00000003, TRUE);
+ write_client_reg(HDE_START, 0x00000007, TRUE);
+ write_client_reg(HDE_SIZE, 0x000000EF, TRUE);
+ write_client_reg(VCYCLE, 0x00000285, TRUE);
+ write_client_reg(VSW, 0x00000001, TRUE);
+ write_client_reg(VDE_START, 0x00000003, TRUE);
+ write_client_reg(VDE_SIZE, 0x0000027F, TRUE);
+ write_client_reg(START, 0x00000001, TRUE);
+ mddi_wait(10);
+ write_client_reg(SSITX, 0x000800BC, TRUE);
+ write_client_reg(SSITX, 0x00000180, TRUE);
+ write_client_reg(SSITX, 0x0008003B, TRUE);
+ write_client_reg(SSITX, 0x00000100, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x000800B0, TRUE);
+ write_client_reg(SSITX, 0x00000116, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x000800B8, TRUE);
+ write_client_reg(SSITX, 0x000801FF, TRUE);
+ write_client_reg(SSITX, 0x000001F5, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x00000011, TRUE);
+ write_client_reg(SSITX, 0x00000029, TRUE);
+ write_client_reg(WKREQ, 0x00000000, TRUE);
+ write_client_reg(WAKEUP, 0x00000000, TRUE);
+ write_client_reg(INTMSK, 0x00000001, TRUE);
+ }
+
+ mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_READY,
+ TOSHIBA_STATE_PRIM_NORMAL_MODE);
+}
+
+static void toshiba_sec_start(struct msm_fb_data_type *mfd)
+{
+ if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+ return;
+
+ write_client_reg(VSYNIF, 0x00000000, TRUE);
+ write_client_reg(PORT_ENB, 0x00000002, TRUE);
+ write_client_reg(CLKENB, 0x000011EF, TRUE);
+ write_client_reg(BITMAP0, 0x028001E0, TRUE);
+ write_client_reg(BITMAP1, 0x00000000, TRUE);
+ write_client_reg(BITMAP2, 0x00000000, TRUE);
+ write_client_reg(BITMAP3, 0x00000000, TRUE);
+ write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
+ write_client_reg(PORT, 0x00000000, TRUE);
+ write_client_reg(PXL, 0x00000000, TRUE);
+ write_client_reg(MPLFBUF, 0x00000004, TRUE);
+ write_client_reg(HCYCLE, 0x0000006B, TRUE);
+ write_client_reg(HSW, 0x00000003, TRUE);
+ write_client_reg(HDE_START, 0x00000007, TRUE);
+ write_client_reg(HDE_SIZE, 0x00000057, TRUE);
+ write_client_reg(VCYCLE, 0x000000E6, TRUE);
+ write_client_reg(VSW, 0x00000001, TRUE);
+ write_client_reg(VDE_START, 0x00000003, TRUE);
+ write_client_reg(VDE_SIZE, 0x000000DB, TRUE);
+ write_client_reg(ASY_DATA, 0x80000001, TRUE);
+ write_client_reg(ASY_DATB, 0x0000011B, TRUE);
+ write_client_reg(ASY_DATC, 0x80000002, TRUE);
+ write_client_reg(ASY_DATD, 0x00000700, TRUE);
+ write_client_reg(ASY_DATE, 0x80000003, TRUE);
+ write_client_reg(ASY_DATF, 0x00000230, TRUE);
+ write_client_reg(ASY_DATG, 0x80000008, TRUE);
+ write_client_reg(ASY_DATH, 0x00000402, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ write_client_reg(ASY_DATA, 0x80000009, TRUE);
+ write_client_reg(ASY_DATB, 0x00000000, TRUE);
+ write_client_reg(ASY_DATC, 0x8000000B, TRUE);
+ write_client_reg(ASY_DATD, 0x00000000, TRUE);
+ write_client_reg(ASY_DATE, 0x8000000C, TRUE);
+ write_client_reg(ASY_DATF, 0x00000000, TRUE);
+ write_client_reg(ASY_DATG, 0x8000000D, TRUE);
+ write_client_reg(ASY_DATH, 0x00000409, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ write_client_reg(ASY_DATA, 0x8000000E, TRUE);
+ write_client_reg(ASY_DATB, 0x00000409, TRUE);
+ write_client_reg(ASY_DATC, 0x80000030, TRUE);
+ write_client_reg(ASY_DATD, 0x00000000, TRUE);
+ write_client_reg(ASY_DATE, 0x80000031, TRUE);
+ write_client_reg(ASY_DATF, 0x00000100, TRUE);
+ write_client_reg(ASY_DATG, 0x80000032, TRUE);
+ write_client_reg(ASY_DATH, 0x00000104, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ write_client_reg(ASY_DATA, 0x80000033, TRUE);
+ write_client_reg(ASY_DATB, 0x00000400, TRUE);
+ write_client_reg(ASY_DATC, 0x80000034, TRUE);
+ write_client_reg(ASY_DATD, 0x00000306, TRUE);
+ write_client_reg(ASY_DATE, 0x80000035, TRUE);
+ write_client_reg(ASY_DATF, 0x00000706, TRUE);
+ write_client_reg(ASY_DATG, 0x80000036, TRUE);
+ write_client_reg(ASY_DATH, 0x00000707, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ write_client_reg(ASY_DATA, 0x80000037, TRUE);
+ write_client_reg(ASY_DATB, 0x00000004, TRUE);
+ write_client_reg(ASY_DATC, 0x80000038, TRUE);
+ write_client_reg(ASY_DATD, 0x00000000, TRUE);
+ write_client_reg(ASY_DATE, 0x80000039, TRUE);
+ write_client_reg(ASY_DATF, 0x00000000, TRUE);
+ write_client_reg(ASY_DATG, 0x8000003A, TRUE);
+ write_client_reg(ASY_DATH, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ write_client_reg(ASY_DATA, 0x80000044, TRUE);
+ write_client_reg(ASY_DATB, 0x0000AF00, TRUE);
+ write_client_reg(ASY_DATC, 0x80000045, TRUE);
+ write_client_reg(ASY_DATD, 0x0000DB00, TRUE);
+ write_client_reg(ASY_DATE, 0x08000042, TRUE);
+ write_client_reg(ASY_DATF, 0x0000DB00, TRUE);
+ write_client_reg(ASY_DATG, 0x80000021, TRUE);
+ write_client_reg(ASY_DATH, 0x00000000, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ write_client_reg(PXL, 0x0000000C, TRUE);
+ write_client_reg(VSYNIF, 0x00000001, TRUE);
+ write_client_reg(ASY_DATA, 0x80000022, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000003, TRUE);
+ write_client_reg(START, 0x00000001, TRUE);
+ mddi_wait(60);
+ write_client_reg(PXL, 0x00000000, TRUE);
+ write_client_reg(VSYNIF, 0x00000000, TRUE);
+ write_client_reg(START, 0x00000000, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ write_client_reg(ASY_DATA, 0x80000050, TRUE);
+ write_client_reg(ASY_DATB, 0x00000000, TRUE);
+ write_client_reg(ASY_DATC, 0x80000051, TRUE);
+ write_client_reg(ASY_DATD, 0x00000E00, TRUE);
+ write_client_reg(ASY_DATE, 0x80000052, TRUE);
+ write_client_reg(ASY_DATF, 0x00000D01, TRUE);
+ write_client_reg(ASY_DATG, 0x80000053, TRUE);
+ write_client_reg(ASY_DATH, 0x00000000, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ write_client_reg(ASY_DATA, 0x80000058, TRUE);
+ write_client_reg(ASY_DATB, 0x00000000, TRUE);
+ write_client_reg(ASY_DATC, 0x8000005A, TRUE);
+ write_client_reg(ASY_DATD, 0x00000E01, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
+ write_client_reg(ASY_DATA, 0x80000011, TRUE);
+ write_client_reg(ASY_DATB, 0x00000812, TRUE);
+ write_client_reg(ASY_DATC, 0x80000012, TRUE);
+ write_client_reg(ASY_DATD, 0x00000003, TRUE);
+ write_client_reg(ASY_DATE, 0x80000013, TRUE);
+ write_client_reg(ASY_DATF, 0x00000909, TRUE);
+ write_client_reg(ASY_DATG, 0x80000010, TRUE);
+ write_client_reg(ASY_DATH, 0x00000040, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ mddi_wait(40);
+ write_client_reg(ASY_DATA, 0x80000010, TRUE);
+ write_client_reg(ASY_DATB, 0x00000340, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(60);
+ write_client_reg(ASY_DATA, 0x80000010, TRUE);
+ write_client_reg(ASY_DATB, 0x00003340, TRUE);
+ write_client_reg(ASY_DATC, 0x80000007, TRUE);
+ write_client_reg(ASY_DATD, 0x00004007, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
+ mddi_wait(1);
+ write_client_reg(ASY_DATA, 0x80000007, TRUE);
+ write_client_reg(ASY_DATB, 0x00004017, TRUE);
+ write_client_reg(ASY_DATC, 0x8000005B, TRUE);
+ write_client_reg(ASY_DATD, 0x00000000, TRUE);
+ write_client_reg(ASY_DATE, 0x80000059, TRUE);
+ write_client_reg(ASY_DATF, 0x00000011, TRUE);
+ write_client_reg(ASY_CMDSET, 0x0000000D, TRUE);
+ write_client_reg(ASY_CMDSET, 0x0000000C, TRUE);
+ mddi_wait(20);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ /* LTPS I/F control */
+ write_client_reg(ASY_DATB, 0x00000019, TRUE);
+ /* Direct cmd transfer enable */
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ /* Direct cmd transfer disable */
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(20);
+ /* Index setting of SUB LCDD */
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ /* LTPS I/F control */
+ write_client_reg(ASY_DATB, 0x00000079, TRUE);
+ /* Direct cmd transfer enable */
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ /* Direct cmd transfer disable */
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(20);
+ /* Index setting of SUB LCDD */
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ /* LTPS I/F control */
+ write_client_reg(ASY_DATB, 0x000003FD, TRUE);
+ /* Direct cmd transfer enable */
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ /* Direct cmd transfer disable */
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(20);
+ mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_READY,
+ TOSHIBA_STATE_SEC_NORMAL_MODE);
+}
+
+static void toshiba_prim_lcd_off(struct msm_fb_data_type *mfd)
+{
+ if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
+ gordon_disp_off();
+ } else{
+
+ /* Main panel power off (Deep standby in) */
+ write_client_reg(SSITX, 0x000800BC, TRUE);
+ write_client_reg(SSITX, 0x00000100, TRUE);
+ write_client_reg(SSITX, 0x00000028, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x000800B8, TRUE);
+ write_client_reg(SSITX, 0x00000180, TRUE);
+ write_client_reg(SSITX, 0x00000102, TRUE);
+ write_client_reg(SSITX, 0x00000010, TRUE);
+ }
+ write_client_reg(PORT, 0x00000003, TRUE);
+ write_client_reg(REGENB, 0x00000001, TRUE);
+ mddi_wait(1);
+ write_client_reg(PXL, 0x00000000, TRUE);
+ write_client_reg(START, 0x00000000, TRUE);
+ write_client_reg(REGENB, 0x00000001, TRUE);
+ mddi_wait(3);
+ if (TM_GET_PID(mfd->panel.id) != LCD_SHARP_2P4_VGA) {
+ write_client_reg(SSITX, 0x000800B0, TRUE);
+ write_client_reg(SSITX, 0x00000100, TRUE);
+ }
+ mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_NORMAL_MODE,
+ TOSHIBA_STATE_PRIM_SEC_STANDBY);
+}
+
+static void toshiba_sec_lcd_off(struct msm_fb_data_type *mfd)
+{
+ if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+ return;
+
+ write_client_reg(VSYNIF, 0x00000000, TRUE);
+ write_client_reg(PORT_ENB, 0x00000002, TRUE);
+ write_client_reg(ASY_DATA, 0x80000007, TRUE);
+ write_client_reg(ASY_DATB, 0x00004016, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x00000019, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x0000000B, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x00000002, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(4);
+ write_client_reg(ASY_DATA, 0x80000010, TRUE);
+ write_client_reg(ASY_DATB, 0x00000300, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(4);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x00000000, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000007, TRUE);
+ write_client_reg(ASY_DATB, 0x00004004, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(PORT, 0x00000000, TRUE);
+ write_client_reg(PXL, 0x00000000, TRUE);
+ write_client_reg(START, 0x00000000, TRUE);
+ write_client_reg(VSYNIF, 0x00000001, TRUE);
+ write_client_reg(PORT_ENB, 0x00000001, TRUE);
+ write_client_reg(REGENB, 0x00000001, TRUE);
+ mddi_toshiba_state_transition(TOSHIBA_STATE_SEC_NORMAL_MODE,
+ TOSHIBA_STATE_PRIM_SEC_STANDBY);
+}
+
+static void toshiba_sec_cont_update_start(struct msm_fb_data_type *mfd)
+{
+
+ if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+ return;
+
+ write_client_reg(VSYNIF, 0x00000000, TRUE);
+ write_client_reg(PORT_ENB, 0x00000002, TRUE);
+ write_client_reg(INTMASK, 0x00000001, TRUE);
+ write_client_reg(TTBUSSEL, 0x0000000B, TRUE);
+ write_client_reg(MONI, 0x00000008, TRUE);
+ write_client_reg(CLKENB, 0x000000EF, TRUE);
+ write_client_reg(CLKENB, 0x000010EF, TRUE);
+ write_client_reg(CLKENB, 0x000011EF, TRUE);
+ write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
+ write_client_reg(HCYCLE, 0x0000006B, TRUE);
+ write_client_reg(HSW, 0x00000003, TRUE);
+ write_client_reg(HDE_START, 0x00000002, TRUE);
+ write_client_reg(HDE_SIZE, 0x00000057, TRUE);
+ write_client_reg(VCYCLE, 0x000000E6, TRUE);
+ write_client_reg(VSW, 0x00000001, TRUE);
+ write_client_reg(VDE_START, 0x00000003, TRUE);
+ write_client_reg(VDE_SIZE, 0x000000DB, TRUE);
+ write_client_reg(WRSTB, 0x00000015, TRUE);
+ write_client_reg(MPLFBUF, 0x00000004, TRUE);
+ write_client_reg(ASY_DATA, 0x80000021, TRUE);
+ write_client_reg(ASY_DATB, 0x00000000, TRUE);
+ write_client_reg(ASY_DATC, 0x80000022, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000007, TRUE);
+ write_client_reg(PXL, 0x00000089, TRUE);
+ write_client_reg(VSYNIF, 0x00000001, TRUE);
+ mddi_wait(2);
+}
+
+static void toshiba_sec_cont_update_stop(struct msm_fb_data_type *mfd)
+{
+ if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+ return;
+
+ write_client_reg(PXL, 0x00000000, TRUE);
+ write_client_reg(VSYNIF, 0x00000000, TRUE);
+ write_client_reg(START, 0x00000000, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ mddi_wait(3);
+ write_client_reg(SRST, 0x00000002, TRUE);
+ mddi_wait(3);
+ write_client_reg(SRST, 0x00000003, TRUE);
+}
+
+static void toshiba_sec_backlight_on(struct msm_fb_data_type *mfd)
+{
+ if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+ return;
+
+ write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
+ write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
+ write_client_reg(PWM0OFF, 0x00000001, TRUE);
+ write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
+ write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
+ write_client_reg(PWM1OFF, 0x00001387, TRUE);
+ write_client_reg(TIMER0CTRL, 0x000000E0, TRUE);
+ write_client_reg(TIMER1CTRL, 0x000000E0, TRUE);
+ write_client_reg(PWMCR, 0x00000003, TRUE);
+}
+
+static void toshiba_sec_sleep_in(struct msm_fb_data_type *mfd)
+{
+ if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+ return;
+
+ write_client_reg(VSYNIF, 0x00000000, TRUE);
+ write_client_reg(PORT_ENB, 0x00000002, TRUE);
+ write_client_reg(ASY_DATA, 0x80000007, TRUE);
+ write_client_reg(ASY_DATB, 0x00004016, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x00000019, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x0000000B, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x00000002, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(4);
+ write_client_reg(ASY_DATA, 0x80000010, TRUE);
+ write_client_reg(ASY_DATB, 0x00000300, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(4);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x00000000, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000007, TRUE);
+ write_client_reg(ASY_DATB, 0x00004004, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(PORT, 0x00000000, TRUE);
+ write_client_reg(PXL, 0x00000000, TRUE);
+ write_client_reg(START, 0x00000000, TRUE);
+ write_client_reg(REGENB, 0x00000001, TRUE);
+ /* Sleep in sequence */
+ write_client_reg(ASY_DATA, 0x80000010, TRUE);
+ write_client_reg(ASY_DATB, 0x00000302, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+}
+
+static void toshiba_sec_sleep_out(struct msm_fb_data_type *mfd)
+{
+ if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+ return;
+
+ write_client_reg(VSYNIF, 0x00000000, TRUE);
+ write_client_reg(PORT_ENB, 0x00000002, TRUE);
+ write_client_reg(ASY_DATA, 0x80000010, TRUE);
+ write_client_reg(ASY_DATB, 0x00000300, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ /* Display ON sequence */
+ write_client_reg(ASY_DATA, 0x80000011, TRUE);
+ write_client_reg(ASY_DATB, 0x00000812, TRUE);
+ write_client_reg(ASY_DATC, 0x80000012, TRUE);
+ write_client_reg(ASY_DATD, 0x00000003, TRUE);
+ write_client_reg(ASY_DATE, 0x80000013, TRUE);
+ write_client_reg(ASY_DATF, 0x00000909, TRUE);
+ write_client_reg(ASY_DATG, 0x80000010, TRUE);
+ write_client_reg(ASY_DATH, 0x00000040, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ mddi_wait(4);
+ write_client_reg(ASY_DATA, 0x80000010, TRUE);
+ write_client_reg(ASY_DATB, 0x00000340, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(6);
+ write_client_reg(ASY_DATA, 0x80000010, TRUE);
+ write_client_reg(ASY_DATB, 0x00003340, TRUE);
+ write_client_reg(ASY_DATC, 0x80000007, TRUE);
+ write_client_reg(ASY_DATD, 0x00004007, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
+ mddi_wait(1);
+ write_client_reg(ASY_DATA, 0x80000007, TRUE);
+ write_client_reg(ASY_DATB, 0x00004017, TRUE);
+ write_client_reg(ASY_DATC, 0x8000005B, TRUE);
+ write_client_reg(ASY_DATD, 0x00000000, TRUE);
+ write_client_reg(ASY_DATE, 0x80000059, TRUE);
+ write_client_reg(ASY_DATF, 0x00000011, TRUE);
+ write_client_reg(ASY_CMDSET, 0x0000000D, TRUE);
+ write_client_reg(ASY_CMDSET, 0x0000000C, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x00000019, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x00000079, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x000003FD, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+}
+
+static void mddi_toshiba_lcd_set_backlight(struct msm_fb_data_type *mfd)
+{
+ int32 level;
+ int ret = -EPERM;
+ int max = mfd->panel_info.bl_max;
+ int min = mfd->panel_info.bl_min;
+ int i = 0;
+
+ if (mddi_toshiba_pdata && mddi_toshiba_pdata->pmic_backlight) {
+ while (i++ < 3) {
+ ret = mddi_toshiba_pdata->pmic_backlight(mfd->bl_level);
+ if (!ret)
+ return;
+ msleep(10);
+ }
+ printk(KERN_WARNING "%s: pmic_backlight Failed\n", __func__);
+ }
+
+
+ if (ret && mddi_toshiba_pdata && mddi_toshiba_pdata->backlight_level) {
+ level = mddi_toshiba_pdata->backlight_level(mfd->bl_level,
+ max, min);
+
+ if (level < 0)
+ return;
+
+ if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA)
+ write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
+ } else {
+ if (!max)
+ level = 0;
+ else
+ level = (mfd->bl_level * 4999) / max;
+ }
+
+ write_client_reg(PWM0OFF, level, TRUE);
+}
+
+static void mddi_toshiba_vsync_set_handler(msm_fb_vsync_handler_type handler, /* ISR to be executed */
+ void *arg)
+{
+ boolean error = FALSE;
+ unsigned long flags;
+
+ /* Disable interrupts */
+ spin_lock_irqsave(&mddi_host_spin_lock, flags);
+ /* INTLOCK(); */
+
+ if (mddi_toshiba_vsync_handler != NULL) {
+ error = TRUE;
+ } else {
+ /* Register the handler for this particular GROUP interrupt source */
+ mddi_toshiba_vsync_handler = handler;
+ mddi_toshiba_vsync_handler_arg = arg;
+ }
+
+ /* Restore interrupts */
+ spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+ /* MDDI_INTFREE(); */
+ if (error) {
+ MDDI_MSG_ERR("MDDI: Previous Vsync handler never called\n");
+ } else {
+ /* Enable the vsync wakeup */
+ mddi_queue_register_write(INTMSK, 0x0000, FALSE, 0);
+
+ mddi_toshiba_vsync_attempts = 1;
+ mddi_vsync_detect_enabled = TRUE;
+ }
+} /* mddi_toshiba_vsync_set_handler */
+
+static void mddi_toshiba_lcd_vsync_detected(boolean detected)
+{
+ /* static timetick_type start_time = 0; */
+ static struct timeval start_time;
+ static boolean first_time = TRUE;
+ /* uint32 mdp_cnt_val = 0; */
+ /* timetick_type elapsed_us; */
+ struct timeval now;
+ uint32 elapsed_us;
+ uint32 num_vsyncs;
+
+ if ((detected) || (mddi_toshiba_vsync_attempts > 5)) {
+ if ((detected) && (mddi_toshiba_monitor_refresh_value)) {
+ /* if (start_time != 0) */
+ if (!first_time) {
+ jiffies_to_timeval(jiffies, &now);
+ elapsed_us =
+ (now.tv_sec - start_time.tv_sec) * 1000000 +
+ now.tv_usec - start_time.tv_usec;
+ /*
+ * LCD is configured for a refresh every usecs,
+ * so to determine the number of vsyncs that
+ * have occurred since the last measurement
+ * add half that to the time difference and
+ * divide by the refresh rate.
+ */
+ num_vsyncs = (elapsed_us +
+ (mddi_toshiba_usecs_per_refresh >>
+ 1)) /
+ mddi_toshiba_usecs_per_refresh;
+ /*
+ * LCD is configured for * hsyncs (rows) per
+ * refresh cycle. Calculate new rows_per_second
+ * value based upon these new measurements.
+ * MDP can update with this new value.
+ */
+ mddi_toshiba_rows_per_second =
+ (mddi_toshiba_rows_per_refresh * 1000 *
+ num_vsyncs) / (elapsed_us / 1000);
+ }
+ /* start_time = timetick_get(); */
+ first_time = FALSE;
+ jiffies_to_timeval(jiffies, &start_time);
+ if (mddi_toshiba_report_refresh_measurements) {
+ (void)mddi_queue_register_read_int(VPOS,
+ &mddi_toshiba_curr_vpos);
+ /* mdp_cnt_val = MDP_LINE_COUNT; */
+ }
+ }
+ /* if detected = TRUE, client initiated wakeup was detected */
+ if (mddi_toshiba_vsync_handler != NULL) {
+ (*mddi_toshiba_vsync_handler)
+ (mddi_toshiba_vsync_handler_arg);
+ mddi_toshiba_vsync_handler = NULL;
+ }
+ mddi_vsync_detect_enabled = FALSE;
+ mddi_toshiba_vsync_attempts = 0;
+ /* need to disable the interrupt wakeup */
+ if (!mddi_queue_register_write_int(INTMSK, 0x0001))
+ MDDI_MSG_ERR("Vsync interrupt disable failed!\n");
+ if (!detected) {
+ /* give up after 5 failed attempts but show error */
+ MDDI_MSG_NOTICE("Vsync detection failed!\n");
+ } else if ((mddi_toshiba_monitor_refresh_value) &&
+ (mddi_toshiba_report_refresh_measurements)) {
+ MDDI_MSG_NOTICE(" Last Line Counter=%d!\n",
+ mddi_toshiba_curr_vpos);
+ /* MDDI_MSG_NOTICE(" MDP Line Counter=%d!\n",mdp_cnt_val); */
+ MDDI_MSG_NOTICE(" Lines Per Second=%d!\n",
+ mddi_toshiba_rows_per_second);
+ }
+ /* clear the interrupt */
+ if (!mddi_queue_register_write_int(INTFLG, 0x0001))
+ MDDI_MSG_ERR("Vsync interrupt clear failed!\n");
+ } else {
+ /* if detected = FALSE, we woke up from hibernation, but did not
+ * detect client initiated wakeup.
+ */
+ mddi_toshiba_vsync_attempts++;
+ }
+}
+
+static void mddi_toshiba_prim_init(struct msm_fb_data_type *mfd)
+{
+
+ switch (toshiba_state) {
+ case TOSHIBA_STATE_PRIM_SEC_READY:
+ break;
+ case TOSHIBA_STATE_OFF:
+ toshiba_state = TOSHIBA_STATE_PRIM_SEC_STANDBY;
+ toshiba_common_initial_setup(mfd);
+ break;
+ case TOSHIBA_STATE_PRIM_SEC_STANDBY:
+ toshiba_common_initial_setup(mfd);
+ break;
+ case TOSHIBA_STATE_SEC_NORMAL_MODE:
+ toshiba_sec_cont_update_stop(mfd);
+ toshiba_sec_sleep_in(mfd);
+ toshiba_sec_sleep_out(mfd);
+ toshiba_sec_lcd_off(mfd);
+ toshiba_common_initial_setup(mfd);
+ break;
+ default:
+ MDDI_MSG_ERR("mddi_toshiba_prim_init from state %d\n",
+ toshiba_state);
+ }
+
+ toshiba_prim_start(mfd);
+ if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA)
+ gordon_disp_init();
+ mddi_host_write_pix_attr_reg(0x00C3);
+}
+
+static void mddi_toshiba_sec_init(struct msm_fb_data_type *mfd)
+{
+
+ switch (toshiba_state) {
+ case TOSHIBA_STATE_PRIM_SEC_READY:
+ break;
+ case TOSHIBA_STATE_PRIM_SEC_STANDBY:
+ toshiba_common_initial_setup(mfd);
+ break;
+ case TOSHIBA_STATE_PRIM_NORMAL_MODE:
+ toshiba_prim_lcd_off(mfd);
+ toshiba_common_initial_setup(mfd);
+ break;
+ default:
+ MDDI_MSG_ERR("mddi_toshiba_sec_init from state %d\n",
+ toshiba_state);
+ }
+
+ toshiba_sec_start(mfd);
+ toshiba_sec_backlight_on(mfd);
+ toshiba_sec_cont_update_start(mfd);
+ mddi_host_write_pix_attr_reg(0x0400);
+}
+
+static void mddi_toshiba_lcd_powerdown(struct msm_fb_data_type *mfd)
+{
+ switch (toshiba_state) {
+ case TOSHIBA_STATE_PRIM_SEC_READY:
+ mddi_toshiba_prim_init(mfd);
+ mddi_toshiba_lcd_powerdown(mfd);
+ return;
+ case TOSHIBA_STATE_PRIM_SEC_STANDBY:
+ break;
+ case TOSHIBA_STATE_PRIM_NORMAL_MODE:
+ toshiba_prim_lcd_off(mfd);
+ break;
+ case TOSHIBA_STATE_SEC_NORMAL_MODE:
+ toshiba_sec_cont_update_stop(mfd);
+ toshiba_sec_sleep_in(mfd);
+ toshiba_sec_sleep_out(mfd);
+ toshiba_sec_lcd_off(mfd);
+ break;
+ default:
+ MDDI_MSG_ERR("mddi_toshiba_lcd_powerdown from state %d\n",
+ toshiba_state);
+ }
+}
+
+static int mddi_sharpgordon_firsttime = 1;
+
+static int mddi_toshiba_lcd_on(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ mfd = platform_get_drvdata(pdev);
+ if (!mfd)
+ return -ENODEV;
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ mddi_host_client_cnt_reset();
+
+ if (TM_GET_DID(mfd->panel.id) == TOSHIBA_VGA_PRIM)
+ mddi_toshiba_prim_init(mfd);
+ else
+ mddi_toshiba_sec_init(mfd);
+ if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
+ if (mddi_sharpgordon_firsttime) {
+ mddi_sharpgordon_firsttime = 0;
+ write_client_reg(REGENB, 0x00000001, TRUE);
+ }
+ }
+ return 0;
+}
+
+static int mddi_toshiba_lcd_off(struct platform_device *pdev)
+{
+ if (mddi_toshiba_vsync_handler != NULL) {
+ (*mddi_toshiba_vsync_handler)
+ (mddi_toshiba_vsync_handler_arg);
+ mddi_toshiba_vsync_handler = NULL;
+ printk(KERN_INFO "%s: clean up vsyn_handler=%x\n", __func__,
+ (int)mddi_toshiba_vsync_handler);
+ }
+
+ mddi_toshiba_lcd_powerdown(platform_get_drvdata(pdev));
+ return 0;
+}
+
+static int __devinit mddi_toshiba_lcd_probe(struct platform_device *pdev)
+{
+ if (pdev->id == 0) {
+ mddi_toshiba_pdata = pdev->dev.platform_data;
+ return 0;
+ }
+
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = mddi_toshiba_lcd_probe,
+ .driver = {
+ .name = "mddi_toshiba",
+ },
+};
+
+static struct msm_fb_panel_data toshiba_panel_data = {
+ .on = mddi_toshiba_lcd_on,
+ .off = mddi_toshiba_lcd_off,
+};
+
+static int ch_used[3];
+
+int mddi_toshiba_device_register(struct msm_panel_info *pinfo,
+ u32 channel, u32 panel)
+{
+ struct platform_device *pdev = NULL;
+ int ret;
+
+ if ((channel >= 3) || ch_used[channel])
+ return -ENODEV;
+
+ if ((channel != TOSHIBA_VGA_PRIM) &&
+ mddi_toshiba_pdata && mddi_toshiba_pdata->panel_num)
+ if (mddi_toshiba_pdata->panel_num() < 2)
+ return -ENODEV;
+
+ ch_used[channel] = TRUE;
+
+ pdev = platform_device_alloc("mddi_toshiba", (panel << 8)|channel);
+ if (!pdev)
+ return -ENOMEM;
+
+ if (channel == TOSHIBA_VGA_PRIM) {
+ toshiba_panel_data.set_backlight =
+ mddi_toshiba_lcd_set_backlight;
+
+ if (pinfo->lcd.vsync_enable) {
+ toshiba_panel_data.set_vsync_notifier =
+ mddi_toshiba_vsync_set_handler;
+ mddi_lcd.vsync_detected =
+ mddi_toshiba_lcd_vsync_detected;
+ }
+ } else {
+ toshiba_panel_data.set_backlight = NULL;
+ toshiba_panel_data.set_vsync_notifier = NULL;
+ }
+
+ toshiba_panel_data.panel_info = *pinfo;
+
+ ret = platform_device_add_data(pdev, &toshiba_panel_data,
+ sizeof(toshiba_panel_data));
+ if (ret) {
+ printk(KERN_ERR
+ "%s: platform_device_add_data failed!\n", __func__);
+ goto err_device_put;
+ }
+
+ ret = platform_device_add(pdev);
+ if (ret) {
+ printk(KERN_ERR
+ "%s: platform_device_register failed!\n", __func__);
+ goto err_device_put;
+ }
+
+ return 0;
+
+err_device_put:
+ platform_device_put(pdev);
+ return ret;
+}
+
+static int __init mddi_toshiba_lcd_init(void)
+{
+ return platform_driver_register(&this_driver);
+}
+
+module_init(mddi_toshiba_lcd_init);
diff --git a/drivers/video/msm/mddi_toshiba.h b/drivers/video/msm/mddi_toshiba.h
new file mode 100644
index 0000000..646f5e9
--- /dev/null
+++ b/drivers/video/msm/mddi_toshiba.h
@@ -0,0 +1,37 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MDDI_TOSHIBA_H
+#define MDDI_TOSHIBA_H
+
+#define TOSHIBA_VGA_PRIM 1
+#define TOSHIBA_VGA_SECD 2
+
+#define LCD_TOSHIBA_2P4_VGA 0
+#define LCD_TOSHIBA_2P4_WVGA 1
+#define LCD_TOSHIBA_2P4_WVGA_PT 2
+#define LCD_SHARP_2P4_VGA 3
+
+#define GPIO_BLOCK_BASE 0x150000
+#define SYSTEM_BLOCK2_BASE 0x170000
+
+#define GPIODIR (GPIO_BLOCK_BASE|0x04)
+#define GPIOSEL (SYSTEM_BLOCK2_BASE|0x00)
+#define GPIOPC (GPIO_BLOCK_BASE|0x28)
+#define GPIODATA (GPIO_BLOCK_BASE|0x00)
+
+#define write_client_reg(__X, __Y, __Z) {\
+ mddi_queue_register_write(__X, __Y, TRUE, 0);\
+}
+
+#endif /* MDDI_TOSHIBA_H */
diff --git a/drivers/video/msm/mddi_toshiba_vga.c b/drivers/video/msm/mddi_toshiba_vga.c
new file mode 100644
index 0000000..794edff
--- /dev/null
+++ b/drivers/video/msm/mddi_toshiba_vga.c
@@ -0,0 +1,133 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+#include "mddi_toshiba.h"
+
+static uint32 read_client_reg(uint32 addr)
+{
+ uint32 val;
+ mddi_queue_register_read(addr, &val, TRUE, 0);
+ return val;
+}
+
+static uint32 toshiba_lcd_gpio_read(void)
+{
+ uint32 val;
+
+ write_client_reg(GPIODIR, 0x0000000C, TRUE);
+ write_client_reg(GPIOSEL, 0x00000000, TRUE);
+ write_client_reg(GPIOSEL, 0x00000000, TRUE);
+ write_client_reg(GPIOPC, 0x03CF00C0, TRUE);
+ val = read_client_reg(GPIODATA) & 0x2C0;
+
+ return val;
+}
+
+static u32 mddi_toshiba_panel_detect(void)
+{
+ mddi_host_type host_idx = MDDI_HOST_PRIM;
+ uint32 lcd_gpio;
+ u32 mddi_toshiba_lcd = LCD_TOSHIBA_2P4_VGA;
+
+ /* Toshiba display requires larger drive_lo value */
+ mddi_host_reg_out(DRIVE_LO, 0x0050);
+
+ lcd_gpio = toshiba_lcd_gpio_read();
+ switch (lcd_gpio) {
+ case 0x0080:
+ mddi_toshiba_lcd = LCD_SHARP_2P4_VGA;
+ break;
+
+ case 0x00C0:
+ default:
+ mddi_toshiba_lcd = LCD_TOSHIBA_2P4_VGA;
+ break;
+ }
+
+ return mddi_toshiba_lcd;
+}
+
+static int __init mddi_toshiba_vga_init(void)
+{
+ int ret;
+ struct msm_panel_info pinfo;
+ u32 panel;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ u32 id;
+
+ ret = msm_fb_detect_client("mddi_toshiba_vga");
+ if (ret == -ENODEV)
+ return 0;
+
+ if (ret) {
+ id = mddi_get_client_id();
+ if ((id >> 16) != 0xD263)
+ return 0;
+ }
+#endif
+
+ panel = mddi_toshiba_panel_detect();
+
+ pinfo.xres = 480;
+ pinfo.yres = 640;
+ pinfo.type = MDDI_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 18;
+ pinfo.lcd.vsync_enable = TRUE;
+ pinfo.lcd.refx100 = 6118;
+ pinfo.lcd.v_back_porch = 6;
+ pinfo.lcd.v_front_porch = 0;
+ pinfo.lcd.v_pulse_width = 0;
+ pinfo.lcd.hw_vsync_mode = FALSE;
+ pinfo.lcd.vsync_notifier_period = (1 * HZ);
+ pinfo.bl_max = 99;
+ pinfo.bl_min = 1;
+ pinfo.clk_rate = 122880000;
+ pinfo.clk_min = 120000000;
+ pinfo.clk_max = 200000000;
+ pinfo.fb_num = 2;
+
+ ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM, panel);
+ if (ret) {
+ printk(KERN_ERR "%s: failed to register device!\n", __func__);
+ return ret;
+ }
+
+ pinfo.xres = 176;
+ pinfo.yres = 220;
+ MSM_FB_SINGLE_MODE_PANEL(&pinfo);
+ pinfo.type = MDDI_PANEL;
+ pinfo.pdest = DISPLAY_2;
+ pinfo.mddi.vdopkt = 0x400;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 18;
+ pinfo.clk_rate = 122880000;
+ pinfo.clk_min = 120000000;
+ pinfo.clk_max = 200000000;
+ pinfo.fb_num = 2;
+
+ ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_SECD, panel);
+ if (ret)
+ printk(KERN_WARNING
+ "%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(mddi_toshiba_vga_init);
diff --git a/drivers/video/msm/mddi_toshiba_wvga.c b/drivers/video/msm/mddi_toshiba_wvga.c
new file mode 100644
index 0000000..ad4ce46
--- /dev/null
+++ b/drivers/video/msm/mddi_toshiba_wvga.c
@@ -0,0 +1,60 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddi_toshiba.h"
+
+static int __init mddi_toshiba_wvga_init(void)
+{
+ int ret;
+ struct msm_panel_info pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ if (msm_fb_detect_client("mddi_toshiba_wvga"))
+ return 0;
+#endif
+
+ pinfo.xres = 800;
+ pinfo.yres = 480;
+ MSM_FB_SINGLE_MODE_PANEL(&pinfo);
+ pinfo.pdest = DISPLAY_2;
+ pinfo.type = MDDI_PANEL;
+ pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 18;
+ pinfo.lcd.vsync_enable = TRUE;
+ pinfo.lcd.refx100 = 6118;
+ pinfo.lcd.v_back_porch = 6;
+ pinfo.lcd.v_front_porch = 0;
+ pinfo.lcd.v_pulse_width = 0;
+ pinfo.lcd.hw_vsync_mode = FALSE;
+ pinfo.lcd.vsync_notifier_period = (1 * HZ);
+ pinfo.bl_max = 4;
+ pinfo.bl_min = 1;
+ pinfo.clk_rate = 192000000;
+ pinfo.clk_min = 190000000;
+ pinfo.clk_max = 200000000;
+ pinfo.fb_num = 2;
+
+ ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM,
+ LCD_TOSHIBA_2P4_WVGA);
+ if (ret) {
+ printk(KERN_ERR "%s: failed to register device!\n", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+module_init(mddi_toshiba_wvga_init);
diff --git a/drivers/video/msm/mddi_toshiba_wvga_pt.c b/drivers/video/msm/mddi_toshiba_wvga_pt.c
new file mode 100644
index 0000000..edf739d
--- /dev/null
+++ b/drivers/video/msm/mddi_toshiba_wvga_pt.c
@@ -0,0 +1,68 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+#include "mddi_toshiba.h"
+
+static struct msm_panel_info pinfo;
+
+static int __init mddi_toshiba_wvga_pt_init(void)
+{
+ int ret;
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ uint id;
+
+ ret = msm_fb_detect_client("mddi_toshiba_wvga_pt");
+ if (ret == -ENODEV)
+ return 0;
+
+ if (ret) {
+ id = mddi_get_client_id();
+ if (id != 0xd2638722)
+ return 0;
+ }
+#endif
+
+ pinfo.xres = 480;
+ pinfo.yres = 800;
+ MSM_FB_SINGLE_MODE_PANEL(&pinfo);
+ pinfo.type = MDDI_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 18;
+ pinfo.lcd.vsync_enable = TRUE;
+ pinfo.lcd.refx100 = 6096; /* adjust refx100 to prevent tearing */
+ pinfo.lcd.v_back_porch = 2; /* vsw=1 + vbp = 2 */
+ pinfo.lcd.v_front_porch = 3;
+ pinfo.lcd.v_pulse_width = 1;
+ pinfo.lcd.hw_vsync_mode = FALSE;
+ pinfo.lcd.vsync_notifier_period = (1 * HZ);
+ pinfo.bl_max = 15;
+ pinfo.bl_min = 1;
+ pinfo.clk_rate = 222750000;
+ pinfo.clk_min = 200000000;
+ pinfo.clk_max = 240000000;
+ pinfo.fb_num = 2;
+
+ ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM,
+ LCD_TOSHIBA_2P4_WVGA_PT);
+ if (ret)
+ printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(mddi_toshiba_wvga_pt_init);
diff --git a/drivers/video/msm/mddihost.c b/drivers/video/msm/mddihost.c
new file mode 100644
index 0000000..c6acf9f
--- /dev/null
+++ b/drivers/video/msm/mddihost.c
@@ -0,0 +1,626 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+#include <linux/clk.h>
+#include <mach/clk.h>
+
+struct semaphore mddi_host_mutex;
+
+struct clk *mddi_io_clk;
+static boolean mddi_host_powered = FALSE;
+static boolean mddi_host_initialized = FALSE;
+extern uint32 *mddi_reg_read_value_ptr;
+
+mddi_lcd_func_type mddi_lcd;
+
+extern mddi_client_capability_type mddi_client_capability_pkt;
+
+#ifdef MDDI_HOST_WINDOW_WORKAROUND
+/* Tables showing number of rows that would cause a packet length
+ * ending in 0x02, for each number of columns. These tables have
+ * been generated for MDDI packets that have 16 and 16 bits-per-pixel.
+ * This is a work-around for MDDI clients that declare a CRC error
+ * on MDDI packets where ((length & 0x00ff) == 0x02).
+ */
+static uint16 error_vals_16bpp[] = {
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 12, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 10, 0, 0, 0, 14, 0, 0, 0, 2, 0, 0, 4, 6, 12, 0,
+0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0,
+0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 11, 4, 0, 12, 0,
+0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0,
+0, 10, 0, 1, 0, 14, 0, 0, 0, 2, 0, 3, 4, 6, 12, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 12, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 10, 0, 0, 0, 14, 0, 0, 0, 2, 0, 0, 4, 6, 12, 0,
+0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0,
+0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 11, 4, 0, 12, 0,
+0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0,
+};
+
+static uint16 error_vals_18bpp[] = {
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 14,
+0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 9, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 7,
+0, 0, 0, 0, 0, 0, 1, 0, 0, 16, 0, 0, 0, 0, 0, 6,
+14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+7, 0, 0, 0, 0, 0, 0, 4, 0, 16, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
+0, 7, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 9, 0
+};
+#endif
+
+#ifdef FEATURE_MDDI_HITACHI
+extern void mddi_hitachi_window_adjust(uint16 x1,
+ uint16 x2, uint16 y1, uint16 y2);
+#endif
+
+extern void mddi_toshiba_lcd_init(void);
+
+#ifdef FEATURE_MDDI_S6D0142
+extern void mddi_s6d0142_lcd_init(void);
+extern void mddi_s6d0142_window_adjust(uint16 x1,
+ uint16 x2,
+ uint16 y1,
+ uint16 y2,
+ mddi_llist_done_cb_type done_cb);
+#endif
+
+void mddi_init(void)
+{
+ if (mddi_host_initialized)
+ return;
+
+ mddi_host_initialized = TRUE;
+
+ sema_init(&mddi_host_mutex, 1);
+
+ if (!mddi_host_powered) {
+ down(&mddi_host_mutex);
+ mddi_host_init(MDDI_HOST_PRIM);
+ mddi_host_powered = TRUE;
+ up(&mddi_host_mutex);
+ mdelay(10);
+ }
+}
+
+int mddi_host_register_read(uint32 reg_addr,
+ uint32 *reg_value_ptr, boolean wait, mddi_host_type host) {
+ mddi_linked_list_type *curr_llist_ptr;
+ mddi_register_access_packet_type *regacc_pkt_ptr;
+ uint16 curr_llist_idx;
+ int ret = 0;
+
+ if (in_interrupt())
+ MDDI_MSG_CRIT("Called from ISR context\n");
+
+ if (!mddi_host_powered) {
+ MDDI_MSG_ERR("MDDI powered down!\n");
+ mddi_init();
+ }
+
+ down(&mddi_host_mutex);
+
+ mddi_reg_read_value_ptr = reg_value_ptr;
+ curr_llist_idx = mddi_get_reg_read_llist_item(host, TRUE);
+ if (curr_llist_idx == UNASSIGNED_INDEX) {
+ up(&mddi_host_mutex);
+
+ /* need to change this to some sort of wait */
+ MDDI_MSG_ERR("Attempting to queue up more than 1 reg read\n");
+ return -EINVAL;
+ }
+
+ curr_llist_ptr = &llist_extern[host][curr_llist_idx];
+ curr_llist_ptr->link_controller_flags = 0x11;
+ curr_llist_ptr->packet_header_count = 14;
+ curr_llist_ptr->packet_data_count = 0;
+
+ curr_llist_ptr->next_packet_pointer = NULL;
+ curr_llist_ptr->packet_data_pointer = NULL;
+ curr_llist_ptr->reserved = 0;
+
+ regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
+
+ regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count;
+ regacc_pkt_ptr->packet_type = 146; /* register access packet */
+ regacc_pkt_ptr->bClient_ID = 0;
+ regacc_pkt_ptr->read_write_info = 0x8001;
+ regacc_pkt_ptr->register_address = reg_addr;
+
+ /* now adjust pointers */
+ mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, wait,
+ NULL, host);
+ /* need to check if we can write the pointer or not */
+
+ up(&mddi_host_mutex);
+
+ if (wait) {
+ int wait_ret;
+
+ mddi_linked_list_notify_type *llist_notify_ptr;
+ llist_notify_ptr = &llist_extern_notify[host][curr_llist_idx];
+ wait_ret = wait_for_completion_timeout(
+ &(llist_notify_ptr->done_comp), 5 * HZ);
+
+ if (wait_ret <= 0)
+ ret = -EBUSY;
+
+ if (wait_ret < 0)
+ printk(KERN_ERR "%s: failed to wait for completion!\n",
+ __func__);
+ else if (!wait_ret)
+ printk(KERN_ERR "%s: Timed out waiting!\n", __func__);
+
+ if (!ret && (mddi_reg_read_value_ptr == reg_value_ptr) &&
+ (*reg_value_ptr == -EBUSY)) {
+ printk(KERN_ERR "%s - failed to get data from client",
+ __func__);
+ mddi_reg_read_value_ptr = NULL;
+ ret = -EBUSY;
+ }
+ }
+
+ MDDI_MSG_DEBUG("Reg Read value=0x%x\n", *reg_value_ptr);
+
+ return ret;
+} /* mddi_host_register_read */
+
+int mddi_host_register_write(uint32 reg_addr,
+ uint32 reg_val, enum mddi_data_packet_size_type packet_size,
+ boolean wait, mddi_llist_done_cb_type done_cb, mddi_host_type host) {
+ mddi_linked_list_type *curr_llist_ptr;
+ mddi_linked_list_type *curr_llist_dma_ptr;
+ mddi_register_access_packet_type *regacc_pkt_ptr;
+ uint16 curr_llist_idx;
+ int ret = 0;
+
+ if (in_interrupt())
+ MDDI_MSG_CRIT("Called from ISR context\n");
+
+ if (!mddi_host_powered) {
+ MDDI_MSG_ERR("MDDI powered down!\n");
+ mddi_init();
+ }
+
+ down(&mddi_host_mutex);
+
+ curr_llist_idx = mddi_get_next_free_llist_item(host, TRUE);
+ curr_llist_ptr = &llist_extern[host][curr_llist_idx];
+ curr_llist_dma_ptr = &llist_dma_extern[host][curr_llist_idx];
+
+ curr_llist_ptr->link_controller_flags = 1;
+ curr_llist_ptr->packet_header_count = 14;
+ curr_llist_ptr->packet_data_count = 4;
+
+ curr_llist_ptr->next_packet_pointer = NULL;
+ curr_llist_ptr->reserved = 0;
+
+ regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
+
+ regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count +
+ (uint16)packet_size;
+ regacc_pkt_ptr->packet_type = 146; /* register access packet */
+ regacc_pkt_ptr->bClient_ID = 0;
+ regacc_pkt_ptr->read_write_info = 0x0001;
+ regacc_pkt_ptr->register_address = reg_addr;
+ regacc_pkt_ptr->register_data_list[0] = reg_val;
+
+ MDDI_MSG_DEBUG("Reg Access write reg=0x%x, value=0x%x\n",
+ regacc_pkt_ptr->register_address,
+ regacc_pkt_ptr->register_data_list[0]);
+
+ regacc_pkt_ptr = &curr_llist_dma_ptr->packet_header.register_pkt;
+ curr_llist_ptr->packet_data_pointer =
+ (void *)(®acc_pkt_ptr->register_data_list[0]);
+
+ /* now adjust pointers */
+ mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, wait,
+ done_cb, host);
+
+ up(&mddi_host_mutex);
+
+ if (wait) {
+ int wait_ret;
+
+ mddi_linked_list_notify_type *llist_notify_ptr;
+ llist_notify_ptr = &llist_extern_notify[host][curr_llist_idx];
+ wait_ret = wait_for_completion_timeout(
+ &(llist_notify_ptr->done_comp), 5 * HZ);
+
+ if (wait_ret <= 0)
+ ret = -EBUSY;
+
+ if (wait_ret < 0)
+ printk(KERN_ERR "%s: failed to wait for completion!\n",
+ __func__);
+ else if (!wait_ret)
+ printk(KERN_ERR "%s: Timed out waiting!\n", __func__);
+ }
+
+ return ret;
+} /* mddi_host_register_write */
+
+boolean mddi_host_register_read_int
+ (uint32 reg_addr, uint32 *reg_value_ptr, mddi_host_type host) {
+ mddi_linked_list_type *curr_llist_ptr;
+ mddi_register_access_packet_type *regacc_pkt_ptr;
+ uint16 curr_llist_idx;
+
+ if (!in_interrupt())
+ MDDI_MSG_CRIT("Called from TASK context\n");
+
+ if (!mddi_host_powered) {
+ MDDI_MSG_ERR("MDDI powered down!\n");
+ return FALSE;
+ }
+
+ if (down_trylock(&mddi_host_mutex) != 0)
+ return FALSE;
+
+ mddi_reg_read_value_ptr = reg_value_ptr;
+ curr_llist_idx = mddi_get_reg_read_llist_item(host, FALSE);
+ if (curr_llist_idx == UNASSIGNED_INDEX) {
+ up(&mddi_host_mutex);
+ return FALSE;
+ }
+
+ curr_llist_ptr = &llist_extern[host][curr_llist_idx];
+ curr_llist_ptr->link_controller_flags = 0x11;
+ curr_llist_ptr->packet_header_count = 14;
+ curr_llist_ptr->packet_data_count = 0;
+
+ curr_llist_ptr->next_packet_pointer = NULL;
+ curr_llist_ptr->packet_data_pointer = NULL;
+ curr_llist_ptr->reserved = 0;
+
+ regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
+
+ regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count;
+ regacc_pkt_ptr->packet_type = 146; /* register access packet */
+ regacc_pkt_ptr->bClient_ID = 0;
+ regacc_pkt_ptr->read_write_info = 0x8001;
+ regacc_pkt_ptr->register_address = reg_addr;
+
+ /* now adjust pointers */
+ mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, FALSE,
+ NULL, host);
+ /* need to check if we can write the pointer or not */
+
+ up(&mddi_host_mutex);
+
+ return TRUE;
+
+} /* mddi_host_register_read */
+
+boolean mddi_host_register_write_int
+ (uint32 reg_addr,
+ uint32 reg_val, mddi_llist_done_cb_type done_cb, mddi_host_type host) {
+ mddi_linked_list_type *curr_llist_ptr;
+ mddi_linked_list_type *curr_llist_dma_ptr;
+ mddi_register_access_packet_type *regacc_pkt_ptr;
+ uint16 curr_llist_idx;
+
+ if (!in_interrupt())
+ MDDI_MSG_CRIT("Called from TASK context\n");
+
+ if (!mddi_host_powered) {
+ MDDI_MSG_ERR("MDDI powered down!\n");
+ return FALSE;
+ }
+
+ if (down_trylock(&mddi_host_mutex) != 0)
+ return FALSE;
+
+ curr_llist_idx = mddi_get_next_free_llist_item(host, FALSE);
+ if (curr_llist_idx == UNASSIGNED_INDEX) {
+ up(&mddi_host_mutex);
+ return FALSE;
+ }
+
+ curr_llist_ptr = &llist_extern[host][curr_llist_idx];
+ curr_llist_dma_ptr = &llist_dma_extern[host][curr_llist_idx];
+
+ curr_llist_ptr->link_controller_flags = 1;
+ curr_llist_ptr->packet_header_count = 14;
+ curr_llist_ptr->packet_data_count = 4;
+
+ curr_llist_ptr->next_packet_pointer = NULL;
+ curr_llist_ptr->reserved = 0;
+
+ regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
+
+ regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count + 4;
+ regacc_pkt_ptr->packet_type = 146; /* register access packet */
+ regacc_pkt_ptr->bClient_ID = 0;
+ regacc_pkt_ptr->read_write_info = 0x0001;
+ regacc_pkt_ptr->register_address = reg_addr;
+ regacc_pkt_ptr->register_data_list[0] = reg_val;
+
+ regacc_pkt_ptr = &curr_llist_dma_ptr->packet_header.register_pkt;
+ curr_llist_ptr->packet_data_pointer =
+ (void *)(&(regacc_pkt_ptr->register_data_list[0]));
+
+ /* now adjust pointers */
+ mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, FALSE,
+ done_cb, host);
+ up(&mddi_host_mutex);
+
+ return TRUE;
+
+} /* mddi_host_register_write */
+
+void mddi_wait(uint16 time_ms)
+{
+ mdelay(time_ms);
+}
+
+void mddi_client_lcd_vsync_detected(boolean detected)
+{
+ if (mddi_lcd.vsync_detected)
+ (*mddi_lcd.vsync_detected) (detected);
+}
+
+/* extended version of function includes done callback */
+void mddi_window_adjust_ext(struct msm_fb_data_type *mfd,
+ uint16 x1,
+ uint16 x2,
+ uint16 y1,
+ uint16 y2, mddi_llist_done_cb_type done_cb)
+{
+#ifdef FEATURE_MDDI_HITACHI
+ if (mfd->panel.id == HITACHI)
+ mddi_hitachi_window_adjust(x1, x2, y1, y2);
+#elif defined(FEATURE_MDDI_S6D0142)
+ if (mfd->panel.id == MDDI_LCD_S6D0142)
+ mddi_s6d0142_window_adjust(x1, x2, y1, y2, done_cb);
+#else
+ /* Do nothing then... except avoid lint/compiler warnings */
+ (void)x1;
+ (void)x2;
+ (void)y1;
+ (void)y2;
+ (void)done_cb;
+#endif
+}
+
+void mddi_window_adjust(struct msm_fb_data_type *mfd,
+ uint16 x1, uint16 x2, uint16 y1, uint16 y2)
+{
+ mddi_window_adjust_ext(mfd, x1, x2, y1, y2, NULL);
+}
+
+#ifdef MDDI_HOST_WINDOW_WORKAROUND
+uint16 mddi_assign_pkt_height(uint16 pkt_width,
+ uint16 pkt_height, uint16 bpp)
+{
+ uint16 new_pkt_height;
+ uint16 problem_height = 0;
+
+ if (pkt_width <= 240) {
+ if (bpp == 16)
+ problem_height = error_vals_16bpp[pkt_width-1];
+ else if (bpp == 18)
+ problem_height = error_vals_18bpp[pkt_width-1];
+ else {
+ printk(KERN_ERR"Invalid bpp value");
+ return -EINVAL;
+ }
+ }
+ if (problem_height == pkt_height)
+ new_pkt_height = problem_height - 1;
+ else
+ new_pkt_height = pkt_height;
+
+ return new_pkt_height;
+}
+#endif
+
+#ifdef ENABLE_MDDI_MULTI_READ_WRITE
+int mddi_host_register_multiwrite(uint32 reg_addr,
+ uint32 *value_list_ptr,
+ uint32 value_count, boolean wait, mddi_llist_done_cb_type done_cb,
+ mddi_host_type host)
+{
+ mddi_linked_list_type *curr_llist_ptr;
+ mddi_linked_list_type *curr_llist_dma_ptr;
+ mddi_register_access_packet_type *regacc_pkt_ptr;
+ uint16 curr_llist_idx;
+ int ret = 0;
+
+ if (!value_list_ptr || !value_count ||
+ value_count > MDDI_HOST_MAX_CLIENT_REG_IN_SAME_ADDR) {
+ MDDI_MSG_ERR("\n Invalid value_list or value_count");
+ return -EINVAL;
+ }
+
+ if (in_interrupt())
+ MDDI_MSG_CRIT("Called from ISR context\n");
+
+ if (!mddi_host_powered) {
+ MDDI_MSG_ERR("MDDI powered down!\n");
+ mddi_init();
+ }
+
+ down(&mddi_host_mutex);
+
+ curr_llist_idx = mddi_get_next_free_llist_item(host, TRUE);
+ curr_llist_ptr = &llist_extern[host][curr_llist_idx];
+ curr_llist_dma_ptr = &llist_dma_extern[host][curr_llist_idx];
+
+ curr_llist_ptr->link_controller_flags = 1;
+ curr_llist_ptr->packet_header_count = 14;
+ curr_llist_ptr->packet_data_count =
+ (uint16)(value_count * 4);
+
+ curr_llist_ptr->next_packet_pointer = NULL;
+ curr_llist_ptr->reserved = 0;
+
+ regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
+
+ regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count
+ + curr_llist_ptr->packet_data_count;
+ regacc_pkt_ptr->packet_type = 146; /* register access packet */
+ regacc_pkt_ptr->bClient_ID = 0;
+ regacc_pkt_ptr->read_write_info = value_count;
+ regacc_pkt_ptr->register_address = reg_addr;
+ memcpy((void *)®acc_pkt_ptr->register_data_list[0], value_list_ptr,
+ curr_llist_ptr->packet_data_count);
+
+ regacc_pkt_ptr = &curr_llist_dma_ptr->packet_header.register_pkt;
+ curr_llist_ptr->packet_data_pointer =
+ (void *)(®acc_pkt_ptr->register_data_list[0]);
+ MDDI_MSG_DEBUG("MultiReg Access write reg=0x%x, value[0]=0x%x\n",
+ regacc_pkt_ptr->register_address,
+ regacc_pkt_ptr->register_data_list[0]);
+
+ /* now adjust pointers */
+ mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, wait,
+ done_cb, host);
+
+ up(&mddi_host_mutex);
+
+ if (wait) {
+ int wait_ret;
+
+ mddi_linked_list_notify_type *llist_notify_ptr;
+ llist_notify_ptr = &llist_extern_notify[host][curr_llist_idx];
+ wait_ret = wait_for_completion_timeout(
+ &(llist_notify_ptr->done_comp), 5 * HZ);
+
+ if (wait_ret <= 0)
+ ret = -EBUSY;
+
+ if (wait_ret < 0)
+ printk(KERN_ERR "%s: failed to wait for completion!\n",
+ __func__);
+ else if (!wait_ret)
+ printk(KERN_ERR "%s: Timed out waiting!\n", __func__);
+ }
+
+ return ret;
+}
+
+int mddi_host_register_multiread(uint32 reg_addr,
+ uint32 *value_list_ptr, uint32 value_count,
+ boolean wait, mddi_host_type host) {
+ mddi_linked_list_type *curr_llist_ptr;
+ mddi_register_access_packet_type *regacc_pkt_ptr;
+ uint16 curr_llist_idx;
+ int ret = 0;
+
+ if (!value_list_ptr || !value_count ||
+ value_count >= MDDI_HOST_MAX_CLIENT_REG_IN_SAME_ADDR) {
+ MDDI_MSG_ERR("\n Invalid value_list or value_count");
+ return -EINVAL;
+ }
+
+ if (in_interrupt())
+ MDDI_MSG_CRIT("Called from ISR context\n");
+
+ if (!mddi_host_powered) {
+ MDDI_MSG_ERR("MDDI powered down!\n");
+ mddi_init();
+ }
+
+ down(&mddi_host_mutex);
+
+ mddi_reg_read_value_ptr = value_list_ptr;
+ curr_llist_idx = mddi_get_reg_read_llist_item(host, TRUE);
+ if (curr_llist_idx == UNASSIGNED_INDEX) {
+ up(&mddi_host_mutex);
+
+ /* need to change this to some sort of wait */
+ MDDI_MSG_ERR("Attempting to queue up more than 1 reg read\n");
+ return -EINVAL;
+ }
+
+ curr_llist_ptr = &llist_extern[host][curr_llist_idx];
+ curr_llist_ptr->link_controller_flags = 0x11;
+ curr_llist_ptr->packet_header_count = 14;
+ curr_llist_ptr->packet_data_count = 0;
+
+ curr_llist_ptr->next_packet_pointer = NULL;
+ curr_llist_ptr->packet_data_pointer = NULL;
+ curr_llist_ptr->reserved = 0;
+
+ regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
+
+ regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count;
+ regacc_pkt_ptr->packet_type = 146; /* register access packet */
+ regacc_pkt_ptr->bClient_ID = 0;
+ regacc_pkt_ptr->read_write_info = 0x8000 | value_count;
+ regacc_pkt_ptr->register_address = reg_addr;
+
+ /* now adjust pointers */
+ mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, wait,
+ NULL, host);
+ /* need to check if we can write the pointer or not */
+
+ up(&mddi_host_mutex);
+
+ if (wait) {
+ int wait_ret;
+
+ mddi_linked_list_notify_type *llist_notify_ptr;
+ llist_notify_ptr = &llist_extern_notify[host][curr_llist_idx];
+ wait_ret = wait_for_completion_timeout(
+ &(llist_notify_ptr->done_comp), 5 * HZ);
+
+ if (wait_ret <= 0)
+ ret = -EBUSY;
+
+ if (wait_ret < 0)
+ printk(KERN_ERR "%s: failed to wait for completion!\n",
+ __func__);
+ else if (!wait_ret)
+ printk(KERN_ERR "%s: Timed out waiting!\n", __func__);
+
+ if (!ret && (mddi_reg_read_value_ptr == value_list_ptr) &&
+ (*value_list_ptr == -EBUSY)) {
+ printk(KERN_ERR "%s - failed to get data from client",
+ __func__);
+ mddi_reg_read_value_ptr = NULL;
+ ret = -EBUSY;
+ }
+ }
+
+ MDDI_MSG_DEBUG("MultiReg Read value[0]=0x%x\n", *value_list_ptr);
+
+ return ret;
+}
+#endif
diff --git a/drivers/video/msm/mddihost.h b/drivers/video/msm/mddihost.h
new file mode 100644
index 0000000..52bc67c
--- /dev/null
+++ b/drivers/video/msm/mddihost.h
@@ -0,0 +1,231 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MDDIHOST_H
+#define MDDIHOST_H
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+
+#include "msm_fb_panel.h"
+
+#undef FEATURE_MDDI_MC4
+#undef FEATURE_MDDI_S6D0142
+#undef FEATURE_MDDI_HITACHI
+#define FEATURE_MDDI_SHARP
+#define FEATURE_MDDI_TOSHIBA
+#undef FEATURE_MDDI_E751
+#define FEATURE_MDDI_CORONA
+#define FEATURE_MDDI_PRISM
+
+#define T_MSM7500
+
+typedef enum {
+ format_16bpp,
+ format_18bpp,
+ format_24bpp
+} mddi_video_format;
+
+typedef enum {
+ MDDI_LCD_NONE = 0,
+ MDDI_LCD_MC4,
+ MDDI_LCD_S6D0142,
+ MDDI_LCD_SHARP,
+ MDDI_LCD_E751,
+ MDDI_LCD_CORONA,
+ MDDI_LCD_HITACHI,
+ MDDI_LCD_TOSHIBA,
+ MDDI_LCD_PRISM,
+ MDDI_LCD_TP2,
+ MDDI_NUM_LCD_TYPES,
+ MDDI_LCD_DEFAULT = MDDI_LCD_TOSHIBA
+} mddi_lcd_type;
+
+typedef enum {
+ MDDI_HOST_PRIM = 0,
+ MDDI_HOST_EXT,
+ MDDI_NUM_HOST_CORES
+} mddi_host_type;
+
+typedef enum {
+ MDDI_DRIVER_RESET, /* host core registers have not been written. */
+ MDDI_DRIVER_DISABLED, /* registers written, interrupts disabled. */
+ MDDI_DRIVER_ENABLED /* registers written, interrupts enabled. */
+} mddi_host_driver_state_type;
+
+typedef enum {
+ MDDI_GPIO_INT_0 = 0,
+ MDDI_GPIO_INT_1,
+ MDDI_GPIO_INT_2,
+ MDDI_GPIO_INT_3,
+ MDDI_GPIO_INT_4,
+ MDDI_GPIO_INT_5,
+ MDDI_GPIO_INT_6,
+ MDDI_GPIO_INT_7,
+ MDDI_GPIO_INT_8,
+ MDDI_GPIO_INT_9,
+ MDDI_GPIO_INT_10,
+ MDDI_GPIO_INT_11,
+ MDDI_GPIO_INT_12,
+ MDDI_GPIO_INT_13,
+ MDDI_GPIO_INT_14,
+ MDDI_GPIO_INT_15,
+ MDDI_GPIO_NUM_INTS
+} mddi_gpio_int_type;
+
+enum mddi_data_packet_size_type {
+ MDDI_DATA_PACKET_4_BYTES = 4,
+ MDDI_DATA_PACKET_8_BYTES = 8,
+ MDDI_DATA_PACKET_12_BYTES = 12,
+ MDDI_DATA_PACKET_16_BYTES = 16,
+ MDDI_DATA_PACKET_24_BYTES = 24
+};
+
+typedef struct {
+ uint32 addr;
+ uint32 value;
+} mddi_reg_write_type;
+
+boolean mddi_vsync_set_handler(msm_fb_vsync_handler_type handler, void *arg);
+
+typedef void (*mddi_llist_done_cb_type) (void);
+
+typedef void (*mddi_rev_handler_type) (void *);
+
+boolean mddi_set_rev_handler(mddi_rev_handler_type handler, uint16 pkt_type);
+
+#define MDDI_DEFAULT_PRIM_PIX_ATTR 0xC3
+#define MDDI_DEFAULT_SECD_PIX_ATTR 0xC0
+
+typedef int gpio_int_polarity_type;
+typedef int gpio_int_handler_type;
+
+typedef struct {
+ void (*vsync_detected) (boolean);
+} mddi_lcd_func_type;
+
+extern mddi_lcd_func_type mddi_lcd;
+extern int irq_enabled;
+extern unsigned char mddi_timer_shutdown_flag;
+extern struct mutex mddi_timer_lock;
+
+void mddi_init(void);
+void mddi_powerdown(void);
+
+void mddi_host_start_ext_display(void);
+void mddi_host_stop_ext_display(void);
+
+extern spinlock_t mddi_host_spin_lock;
+#ifdef T_MSM7500
+void mddi_reset(void);
+#ifdef FEATURE_DUAL_PROC_MODEM_DISPLAY
+void mddi_host_switch_proc_control(boolean on);
+#endif
+#endif
+void mddi_host_exit_power_collapse(void);
+
+void mddi_queue_splash_screen
+ (void *buf_ptr,
+ boolean clear_area,
+ int16 src_width,
+ int16 src_starting_row,
+ int16 src_starting_column,
+ int16 num_of_rows,
+ int16 num_of_columns, int16 dst_starting_row, int16 dst_starting_column);
+
+void mddi_queue_image
+ (void *buf_ptr,
+ uint8 stereo_video,
+ boolean clear_area,
+ int16 src_width,
+ int16 src_starting_row,
+ int16 src_starting_column,
+ int16 num_of_rows,
+ int16 num_of_columns, int16 dst_starting_row, int16 dst_starting_column);
+
+int mddi_host_register_read
+ (uint32 reg_addr,
+ uint32 *reg_value_ptr, boolean wait, mddi_host_type host_idx);
+int mddi_host_register_write
+ (uint32 reg_addr, uint32 reg_val,
+ enum mddi_data_packet_size_type packet_size,
+ boolean wait, mddi_llist_done_cb_type done_cb, mddi_host_type host);
+boolean mddi_host_register_write_int
+ (uint32 reg_addr,
+ uint32 reg_val, mddi_llist_done_cb_type done_cb, mddi_host_type host);
+boolean mddi_host_register_read_int
+ (uint32 reg_addr, uint32 *reg_value_ptr, mddi_host_type host_idx);
+void mddi_queue_register_write_static
+ (uint32 reg_addr,
+ uint32 reg_val, boolean wait, mddi_llist_done_cb_type done_cb);
+void mddi_queue_static_window_adjust
+ (const mddi_reg_write_type *reg_write,
+ uint16 num_writes, mddi_llist_done_cb_type done_cb);
+
+#ifdef ENABLE_MDDI_MULTI_READ_WRITE
+int mddi_host_register_multiwrite(uint32 reg_addr,
+ uint32 *value_list_ptr, uint32 value_count,
+ boolean wait, mddi_llist_done_cb_type done_cb,
+ mddi_host_type host);
+int mddi_host_register_multiread(uint32 reg_addr,
+ uint32 *value_list_ptr, uint32 value_count,
+ boolean wait, mddi_host_type host);
+#endif
+
+#define mddi_queue_register_read(reg, val_ptr, wait, sig) \
+ mddi_host_register_read(reg, val_ptr, wait, MDDI_HOST_PRIM)
+#define mddi_queue_register_write(reg, val, wait, sig) \
+ mddi_host_register_write(reg, val, MDDI_DATA_PACKET_4_BYTES,\
+ wait, NULL, MDDI_HOST_PRIM)
+#define mddi_queue_register_write_extn(reg, val, pkt_size, wait, sig) \
+ mddi_host_register_write(reg, val, pkt_size, \
+ wait, NULL, MDDI_HOST_PRIM)
+#define mddi_queue_register_write_int(reg, val) \
+ mddi_host_register_write_int(reg, val, NULL, MDDI_HOST_PRIM)
+#define mddi_queue_register_read_int(reg, val_ptr) \
+ mddi_host_register_read_int(reg, val_ptr, MDDI_HOST_PRIM)
+#define mddi_queue_register_writes(reg_ptr, val, wait, sig) \
+ mddi_host_register_writes(reg_ptr, val, wait, sig, MDDI_HOST_PRIM)
+
+void mddi_wait(uint16 time_ms);
+void mddi_assign_max_pkt_dimensions(uint16 image_cols,
+ uint16 image_rows,
+ uint16 bpp,
+ uint16 *max_cols, uint16 * max_rows);
+#ifdef MDDI_HOST_WINDOW_WORKAROUND
+uint16 mddi_assign_pkt_height(uint16 pkt_width, uint16 pkt_height, uint16 bpp);
+#endif
+void mddi_queue_reverse_encapsulation(boolean wait);
+int mddi_client_power(unsigned int client_id);
+void mddi_disable(int lock);
+void mddi_window_adjust(struct msm_fb_data_type *mfd,
+ uint16 x1, uint16 x2, uint16 y1, uint16 y2);
+void mddi_send_fw_link_skew_cal(mddi_host_type host_idx);
+int pmdh_clk_func(int enable);
+
+#endif /* MDDIHOST_H */
diff --git a/drivers/video/msm/mddihost_e.c b/drivers/video/msm/mddihost_e.c
new file mode 100644
index 0000000..d53aa6f
--- /dev/null
+++ b/drivers/video/msm/mddihost_e.c
@@ -0,0 +1,59 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+#include <linux/clk.h>
+#include <mach/clk.h>
+
+extern struct semaphore mddi_host_mutex;
+static boolean mddi_host_ext_powered = FALSE;
+
+void mddi_host_start_ext_display(void)
+{
+ down(&mddi_host_mutex);
+
+ if (!mddi_host_ext_powered) {
+ mddi_host_init(MDDI_HOST_EXT);
+
+ mddi_host_ext_powered = TRUE;
+ }
+
+ up(&mddi_host_mutex);
+}
+
+void mddi_host_stop_ext_display(void)
+{
+ down(&mddi_host_mutex);
+
+ if (mddi_host_ext_powered) {
+ mddi_host_powerdown(MDDI_HOST_EXT);
+
+ mddi_host_ext_powered = FALSE;
+ }
+
+ up(&mddi_host_mutex);
+}
diff --git a/drivers/video/msm/mddihosti.c b/drivers/video/msm/mddihosti.c
new file mode 100644
index 0000000..4989d35
--- /dev/null
+++ b/drivers/video/msm/mddihosti.c
@@ -0,0 +1,2304 @@
+/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include "msm_fb_panel.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+#define FEATURE_MDDI_UNDERRUN_RECOVERY
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+static void mddi_read_rev_packet(byte *data_ptr);
+#endif
+
+struct timer_list mddi_host_timer;
+
+#define MDDI_DEFAULT_TIMER_LENGTH 5000 /* 5 seconds */
+uint32 mddi_rtd_frequency = 60000; /* send RTD every 60 seconds */
+uint32 mddi_client_status_frequency = 60000; /* get status pkt every 60 secs */
+
+boolean mddi_vsync_detect_enabled = FALSE;
+mddi_gpio_info_type mddi_gpio;
+
+uint32 mddi_host_core_version;
+boolean mddi_debug_log_statistics = FALSE;
+/* #define FEATURE_MDDI_HOST_ENABLE_EARLY_HIBERNATION */
+/* default to TRUE in case MDP does not vote */
+static boolean mddi_host_mdp_active_flag = TRUE;
+static uint32 mddi_log_stats_counter;
+uint32 mddi_log_stats_frequency = 4000;
+int32 mddi_client_type;
+
+#define MDDI_DEFAULT_REV_PKT_SIZE 0x20
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+static boolean mddi_rev_ptr_workaround = TRUE;
+static uint32 mddi_reg_read_retry;
+static uint32 mddi_reg_read_retry_max = 20;
+static boolean mddi_enable_reg_read_retry = TRUE;
+static boolean mddi_enable_reg_read_retry_once = FALSE;
+
+#define MDDI_MAX_REV_PKT_SIZE 0x60
+
+#define MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE 0x60
+
+#define MDDI_VIDEO_REV_PKT_SIZE 0x40
+#define MDDI_REV_BUFFER_SIZE MDDI_MAX_REV_PKT_SIZE
+static byte rev_packet_data[MDDI_MAX_REV_PKT_SIZE];
+#endif /* FEATURE_MDDI_DISABLE_REVERSE */
+/* leave these variables so graphics will compile */
+
+#define MDDI_MAX_REV_DATA_SIZE 128
+/*lint -d__align(x) */
+boolean mddi_debug_clear_rev_data = TRUE;
+
+uint32 *mddi_reg_read_value_ptr;
+
+mddi_client_capability_type mddi_client_capability_pkt;
+static boolean mddi_client_capability_request = FALSE;
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+
+#define MAX_MDDI_REV_HANDLERS 2
+#define INVALID_PKT_TYPE 0xFFFF
+
+typedef struct {
+ mddi_rev_handler_type handler; /* ISR to be executed */
+ uint16 pkt_type;
+} mddi_rev_pkt_handler_type;
+static mddi_rev_pkt_handler_type mddi_rev_pkt_handler[MAX_MDDI_REV_HANDLERS] =
+ { {NULL, INVALID_PKT_TYPE}, {NULL, INVALID_PKT_TYPE} };
+
+static boolean mddi_rev_encap_user_request = FALSE;
+static mddi_linked_list_notify_type mddi_rev_user;
+
+spinlock_t mddi_host_spin_lock;
+extern uint32 mdp_in_processing;
+#endif
+
+typedef enum {
+ MDDI_REV_IDLE
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ , MDDI_REV_REG_READ_ISSUED,
+ MDDI_REV_REG_READ_SENT,
+ MDDI_REV_ENCAP_ISSUED,
+ MDDI_REV_STATUS_REQ_ISSUED,
+ MDDI_REV_CLIENT_CAP_ISSUED
+#endif
+} mddi_rev_link_state_type;
+
+typedef enum {
+ MDDI_LINK_DISABLED,
+ MDDI_LINK_HIBERNATING,
+ MDDI_LINK_ACTIVATING,
+ MDDI_LINK_ACTIVE
+} mddi_host_link_state_type;
+
+typedef struct {
+ uint32 count;
+ uint32 in_count;
+ uint32 disp_req_count;
+ uint32 state_change_count;
+ uint32 ll_done_count;
+ uint32 rev_avail_count;
+ uint32 error_count;
+ uint32 rev_encap_count;
+ uint32 llist_ptr_write_1;
+ uint32 llist_ptr_write_2;
+} mddi_host_int_type;
+
+typedef struct {
+ uint32 fwd_crc_count;
+ uint32 rev_crc_count;
+ uint32 pri_underflow;
+ uint32 sec_underflow;
+ uint32 rev_overflow;
+ uint32 pri_overwrite;
+ uint32 sec_overwrite;
+ uint32 rev_overwrite;
+ uint32 dma_failure;
+ uint32 rtd_failure;
+ uint32 reg_read_failure;
+#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY
+ uint32 pri_underrun_detected;
+#endif
+} mddi_host_stat_type;
+
+typedef struct {
+ uint32 rtd_cnt;
+ uint32 rev_enc_cnt;
+ uint32 vid_cnt;
+ uint32 reg_acc_cnt;
+ uint32 cli_stat_cnt;
+ uint32 cli_cap_cnt;
+ uint32 reg_read_cnt;
+ uint32 link_active_cnt;
+ uint32 link_hibernate_cnt;
+ uint32 vsync_response_cnt;
+ uint32 fwd_crc_cnt;
+ uint32 rev_crc_cnt;
+} mddi_log_params_struct_type;
+
+typedef struct {
+ uint32 rtd_value;
+ uint32 rtd_counter;
+ uint32 client_status_cnt;
+ boolean rev_ptr_written;
+ uint8 *rev_ptr_start;
+ uint8 *rev_ptr_curr;
+ uint32 mddi_rev_ptr_write_val;
+ dma_addr_t rev_data_dma_addr;
+ uint16 rev_pkt_size;
+ mddi_rev_link_state_type rev_state;
+ mddi_host_link_state_type link_state;
+ mddi_host_driver_state_type driver_state;
+ boolean disable_hibernation;
+ uint32 saved_int_reg;
+ uint32 saved_int_en;
+ mddi_linked_list_type *llist_ptr;
+ dma_addr_t llist_dma_addr;
+ mddi_linked_list_type *llist_dma_ptr;
+ uint32 *rev_data_buf;
+ struct completion mddi_llist_avail_comp;
+ boolean mddi_waiting_for_llist_avail;
+ mddi_host_int_type int_type;
+ mddi_host_stat_type stats;
+ mddi_log_params_struct_type log_parms;
+ mddi_llist_info_type llist_info;
+ mddi_linked_list_notify_type llist_notify[MDDI_MAX_NUM_LLIST_ITEMS];
+} mddi_host_cntl_type;
+
+static mddi_host_type mddi_curr_host = MDDI_HOST_PRIM;
+static mddi_host_cntl_type mhctl[MDDI_NUM_HOST_CORES];
+mddi_linked_list_type *llist_extern[MDDI_NUM_HOST_CORES];
+mddi_linked_list_type *llist_dma_extern[MDDI_NUM_HOST_CORES];
+mddi_linked_list_notify_type *llist_extern_notify[MDDI_NUM_HOST_CORES];
+static mddi_log_params_struct_type prev_parms[MDDI_NUM_HOST_CORES];
+
+extern uint32 mdp_total_vdopkts;
+
+static boolean mddi_host_io_clock_on = FALSE;
+static boolean mddi_host_hclk_on = FALSE;
+
+int int_mddi_pri_flag = FALSE;
+int int_mddi_ext_flag = FALSE;
+
+static void mddi_report_errors(uint32 int_reg)
+{
+ mddi_host_type host_idx = mddi_curr_host;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ if (int_reg & MDDI_INT_PRI_UNDERFLOW) {
+ pmhctl->stats.pri_underflow++;
+ MDDI_MSG_ERR("!!! MDDI Primary Underflow !!!\n");
+ }
+ if (int_reg & MDDI_INT_SEC_UNDERFLOW) {
+ pmhctl->stats.sec_underflow++;
+ MDDI_MSG_ERR("!!! MDDI Secondary Underflow !!!\n");
+ }
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ if (int_reg & MDDI_INT_REV_OVERFLOW) {
+ pmhctl->stats.rev_overflow++;
+ MDDI_MSG_ERR("!!! MDDI Reverse Overflow !!!\n");
+ pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+ mddi_host_reg_out(REV_PTR, pmhctl->mddi_rev_ptr_write_val);
+
+ }
+ if (int_reg & MDDI_INT_CRC_ERROR)
+ MDDI_MSG_ERR("!!! MDDI Reverse CRC Error !!!\n");
+#endif
+ if (int_reg & MDDI_INT_PRI_OVERWRITE) {
+ pmhctl->stats.pri_overwrite++;
+ MDDI_MSG_ERR("!!! MDDI Primary Overwrite !!!\n");
+ }
+ if (int_reg & MDDI_INT_SEC_OVERWRITE) {
+ pmhctl->stats.sec_overwrite++;
+ MDDI_MSG_ERR("!!! MDDI Secondary Overwrite !!!\n");
+ }
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ if (int_reg & MDDI_INT_REV_OVERWRITE) {
+ pmhctl->stats.rev_overwrite++;
+ /* This will show up normally and is not a problem */
+ MDDI_MSG_DEBUG("MDDI Reverse Overwrite!\n");
+ }
+ if (int_reg & MDDI_INT_RTD_FAILURE) {
+ mddi_host_reg_outm(INTEN, MDDI_INT_RTD_FAILURE, 0);
+ pmhctl->stats.rtd_failure++;
+ MDDI_MSG_ERR("!!! MDDI RTD Failure !!!\n");
+ }
+#endif
+ if (int_reg & MDDI_INT_DMA_FAILURE) {
+ pmhctl->stats.dma_failure++;
+ MDDI_MSG_ERR("!!! MDDI DMA Abort !!!\n");
+ }
+}
+
+static void mddi_host_enable_io_clock(void)
+{
+ if (!MDDI_HOST_IS_IO_CLOCK_ON)
+ MDDI_HOST_ENABLE_IO_CLOCK;
+}
+
+static void mddi_host_enable_hclk(void)
+{
+
+ if (!MDDI_HOST_IS_HCLK_ON)
+ MDDI_HOST_ENABLE_HCLK;
+}
+
+static void mddi_host_disable_io_clock(void)
+{
+#ifndef FEATURE_MDDI_HOST_IO_CLOCK_CONTROL_DISABLE
+ if (MDDI_HOST_IS_IO_CLOCK_ON)
+ MDDI_HOST_DISABLE_IO_CLOCK;
+#endif
+}
+
+static void mddi_host_disable_hclk(void)
+{
+#ifndef FEATURE_MDDI_HOST_HCLK_CONTROL_DISABLE
+ if (MDDI_HOST_IS_HCLK_ON)
+ MDDI_HOST_DISABLE_HCLK;
+#endif
+}
+
+static void mddi_vote_to_sleep(mddi_host_type host_idx, boolean sleep)
+{
+ uint16 vote_mask;
+
+ if (host_idx == MDDI_HOST_PRIM)
+ vote_mask = 0x01;
+ else
+ vote_mask = 0x02;
+}
+
+static void mddi_report_state_change(uint32 int_reg)
+{
+ mddi_host_type host_idx = mddi_curr_host;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ if ((pmhctl->saved_int_reg & MDDI_INT_IN_HIBERNATION) &&
+ (pmhctl->saved_int_reg & MDDI_INT_LINK_ACTIVE)) {
+ /* recover from condition where the io_clock was turned off by the
+ clock driver during a transition to hibernation. The io_clock
+ disable is to prevent MDP/MDDI underruns when changing ARM
+ clock speeds. In the process of halting the ARM, the hclk
+ divider needs to be set to 1. When it is set to 1, there is
+ a small time (usecs) when hclk is off or slow, and this can
+ cause an underrun. To prevent the underrun, clock driver turns
+ off the MDDI io_clock before making the change. */
+ mddi_host_reg_out(CMD, MDDI_CMD_POWERUP);
+ }
+
+ if (int_reg & MDDI_INT_LINK_ACTIVE) {
+ pmhctl->link_state = MDDI_LINK_ACTIVE;
+ pmhctl->log_parms.link_active_cnt++;
+ pmhctl->rtd_value = mddi_host_reg_in(RTD_VAL);
+ MDDI_MSG_DEBUG("!!! MDDI Active RTD:0x%x!!!\n",
+ pmhctl->rtd_value);
+ /* now interrupt on hibernation */
+ mddi_host_reg_outm(INTEN,
+ (MDDI_INT_IN_HIBERNATION |
+ MDDI_INT_LINK_ACTIVE),
+ MDDI_INT_IN_HIBERNATION);
+
+#ifdef DEBUG_MDDIHOSTI
+ /* if gpio interrupt is enabled, start polling at fastest
+ * registered rate
+ */
+ if (mddi_gpio.polling_enabled) {
+ timer_reg(&mddi_gpio_poll_timer,
+ mddi_gpio_poll_timer_cb, 0, mddi_gpio.polling_interval, 0);
+ }
+#endif
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ if (mddi_rev_ptr_workaround) {
+ /* HW CR: need to reset reverse register stuff */
+ pmhctl->rev_ptr_written = FALSE;
+ pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+ }
+#endif
+ /* vote on sleep */
+ mddi_vote_to_sleep(host_idx, FALSE);
+
+ if (host_idx == MDDI_HOST_PRIM) {
+ if (mddi_vsync_detect_enabled) {
+ /*
+ * Indicate to client specific code that vsync
+ * was enabled, but we did not detect a client
+ * intiated wakeup. The client specific
+ * handler can either reassert vsync detection,
+ * or treat this as a valid vsync.
+ */
+ mddi_client_lcd_vsync_detected(FALSE);
+ pmhctl->log_parms.vsync_response_cnt++;
+ }
+ }
+ }
+ if (int_reg & MDDI_INT_IN_HIBERNATION) {
+ pmhctl->link_state = MDDI_LINK_HIBERNATING;
+ pmhctl->log_parms.link_hibernate_cnt++;
+ MDDI_MSG_DEBUG("!!! MDDI Hibernating !!!\n");
+
+ if (mddi_client_type == 2) {
+ mddi_host_reg_out(PAD_CTL, 0x402a850f);
+ mddi_host_reg_out(PAD_CAL, 0x10220020);
+ mddi_host_reg_out(TA1_LEN, 0x0010);
+ mddi_host_reg_out(TA2_LEN, 0x0040);
+ }
+ /* now interrupt on link_active */
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+ mddi_host_reg_outm(INTEN,
+ (MDDI_INT_MDDI_IN |
+ MDDI_INT_IN_HIBERNATION |
+ MDDI_INT_LINK_ACTIVE),
+ MDDI_INT_LINK_ACTIVE);
+#else
+ mddi_host_reg_outm(INTEN,
+ (MDDI_INT_MDDI_IN |
+ MDDI_INT_IN_HIBERNATION |
+ MDDI_INT_LINK_ACTIVE),
+ (MDDI_INT_MDDI_IN | MDDI_INT_LINK_ACTIVE));
+
+ pmhctl->rtd_counter = mddi_rtd_frequency;
+
+ if (pmhctl->rev_state != MDDI_REV_IDLE) {
+ /* a rev_encap will not wake up the link, so we do that here */
+ pmhctl->link_state = MDDI_LINK_ACTIVATING;
+ mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
+ }
+#endif
+
+ if (pmhctl->disable_hibernation) {
+ mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
+ mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
+ pmhctl->link_state = MDDI_LINK_ACTIVATING;
+ }
+#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY
+ if ((pmhctl->llist_info.transmitting_start_idx !=
+ UNASSIGNED_INDEX)
+ &&
+ ((pmhctl->
+ saved_int_reg & (MDDI_INT_PRI_LINK_LIST_DONE |
+ MDDI_INT_PRI_PTR_READ)) ==
+ MDDI_INT_PRI_PTR_READ)) {
+ mddi_linked_list_type *llist_dma;
+ llist_dma = pmhctl->llist_dma_ptr;
+ /*
+ * All indications are that we have not received a
+ * linked list done interrupt, due to an underrun
+ * condition. Recovery attempt is to send again.
+ */
+ dma_coherent_pre_ops();
+ /* Write to primary pointer register again */
+ mddi_host_reg_out(PRI_PTR,
+ &llist_dma[pmhctl->llist_info.
+ transmitting_start_idx]);
+ pmhctl->stats.pri_underrun_detected++;
+ }
+#endif
+
+ /* vote on sleep */
+ if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
+ mddi_vote_to_sleep(host_idx, TRUE);
+ }
+
+#ifdef DEBUG_MDDIHOSTI
+ /* need to stop polling timer */
+ if (mddi_gpio.polling_enabled) {
+ (void) timer_clr(&mddi_gpio_poll_timer, T_NONE);
+ }
+#endif
+ }
+}
+
+void mddi_host_timer_service(unsigned long data)
+{
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ unsigned long flags;
+#endif
+ mddi_host_type host_idx;
+ mddi_host_cntl_type *pmhctl;
+
+ unsigned long time_ms = MDDI_DEFAULT_TIMER_LENGTH;
+ init_timer(&mddi_host_timer);
+ for (host_idx = MDDI_HOST_PRIM; host_idx < MDDI_NUM_HOST_CORES;
+ host_idx++) {
+ pmhctl = &(mhctl[host_idx]);
+ mddi_log_stats_counter += (uint32) time_ms;
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ pmhctl->rtd_counter += (uint32) time_ms;
+ pmhctl->client_status_cnt += (uint32) time_ms;
+
+ if (host_idx == MDDI_HOST_PRIM) {
+ if (pmhctl->client_status_cnt >=
+ mddi_client_status_frequency) {
+ if ((pmhctl->link_state ==
+ MDDI_LINK_HIBERNATING)
+ && (pmhctl->client_status_cnt >
+ mddi_client_status_frequency)) {
+ /*
+ * special case where we are hibernating
+ * and mddi_host_isr is not firing, so
+ * kick the link so that the status can
+ * be retrieved
+ */
+
+ /* need to wake up link before issuing
+ * rev encap command
+ */
+ MDDI_MSG_INFO("wake up link!\n");
+ spin_lock_irqsave(&mddi_host_spin_lock,
+ flags);
+ mddi_host_enable_hclk();
+ mddi_host_enable_io_clock();
+ pmhctl->link_state =
+ MDDI_LINK_ACTIVATING;
+ mddi_host_reg_out(CMD,
+ MDDI_CMD_LINK_ACTIVE);
+ spin_unlock_irqrestore
+ (&mddi_host_spin_lock, flags);
+ } else
+ if ((pmhctl->link_state == MDDI_LINK_ACTIVE)
+ && pmhctl->disable_hibernation) {
+ /*
+ * special case where we have disabled
+ * hibernation and mddi_host_isr
+ * is not firing, so enable interrupt
+ * for no pkts pending, which will
+ * generate an interrupt
+ */
+ MDDI_MSG_INFO("kick isr!\n");
+ spin_lock_irqsave(&mddi_host_spin_lock,
+ flags);
+ mddi_host_enable_hclk();
+ mddi_host_reg_outm(INTEN,
+ MDDI_INT_NO_CMD_PKTS_PEND,
+ MDDI_INT_NO_CMD_PKTS_PEND);
+ spin_unlock_irqrestore
+ (&mddi_host_spin_lock, flags);
+ }
+ }
+ }
+#endif /* #ifndef FEATURE_MDDI_DISABLE_REVERSE */
+ }
+
+ /* Check if logging is turned on */
+ for (host_idx = MDDI_HOST_PRIM; host_idx < MDDI_NUM_HOST_CORES;
+ host_idx++) {
+ mddi_log_params_struct_type *prev_ptr = &(prev_parms[host_idx]);
+ pmhctl = &(mhctl[host_idx]);
+
+ if (mddi_debug_log_statistics) {
+
+ /* get video pkt count from MDP, since MDDI sw cannot know this */
+ pmhctl->log_parms.vid_cnt = mdp_total_vdopkts;
+
+ if (mddi_log_stats_counter >= mddi_log_stats_frequency) {
+ /* mddi_log_stats_counter = 0; */
+ if (mddi_debug_log_statistics) {
+ MDDI_MSG_NOTICE
+ ("MDDI Statistics since last report:\n");
+ MDDI_MSG_NOTICE(" Packets sent:\n");
+ MDDI_MSG_NOTICE
+ (" %d RTD packet(s)\n",
+ pmhctl->log_parms.rtd_cnt -
+ prev_ptr->rtd_cnt);
+ if (prev_ptr->rtd_cnt !=
+ pmhctl->log_parms.rtd_cnt) {
+ unsigned long flags;
+ spin_lock_irqsave
+ (&mddi_host_spin_lock,
+ flags);
+ mddi_host_enable_hclk();
+ pmhctl->rtd_value =
+ mddi_host_reg_in(RTD_VAL);
+ spin_unlock_irqrestore
+ (&mddi_host_spin_lock,
+ flags);
+ MDDI_MSG_NOTICE
+ (" RTD value=%d\n",
+ pmhctl->rtd_value);
+ }
+ MDDI_MSG_NOTICE
+ (" %d VIDEO packets\n",
+ pmhctl->log_parms.vid_cnt -
+ prev_ptr->vid_cnt);
+ MDDI_MSG_NOTICE
+ (" %d Register Access packets\n",
+ pmhctl->log_parms.reg_acc_cnt -
+ prev_ptr->reg_acc_cnt);
+ MDDI_MSG_NOTICE
+ (" %d Reverse Encapsulation packet(s)\n",
+ pmhctl->log_parms.rev_enc_cnt -
+ prev_ptr->rev_enc_cnt);
+ if (prev_ptr->rev_enc_cnt !=
+ pmhctl->log_parms.rev_enc_cnt) {
+ /* report # of reverse CRC errors */
+ MDDI_MSG_NOTICE
+ (" %d reverse CRC errors detected\n",
+ pmhctl->log_parms.
+ rev_crc_cnt -
+ prev_ptr->rev_crc_cnt);
+ }
+ MDDI_MSG_NOTICE
+ (" Packets received:\n");
+ MDDI_MSG_NOTICE
+ (" %d Client Status packets",
+ pmhctl->log_parms.cli_stat_cnt -
+ prev_ptr->cli_stat_cnt);
+ if (prev_ptr->cli_stat_cnt !=
+ pmhctl->log_parms.cli_stat_cnt) {
+ MDDI_MSG_NOTICE
+ (" %d forward CRC errors reported\n",
+ pmhctl->log_parms.
+ fwd_crc_cnt -
+ prev_ptr->fwd_crc_cnt);
+ }
+ MDDI_MSG_NOTICE
+ (" %d Register Access Read packets\n",
+ pmhctl->log_parms.reg_read_cnt -
+ prev_ptr->reg_read_cnt);
+
+ if (pmhctl->link_state ==
+ MDDI_LINK_ACTIVE) {
+ MDDI_MSG_NOTICE
+ (" Current Link Status: Active\n");
+ } else
+ if ((pmhctl->link_state ==
+ MDDI_LINK_HIBERNATING)
+ || (pmhctl->link_state ==
+ MDDI_LINK_ACTIVATING)) {
+ MDDI_MSG_NOTICE
+ (" Current Link Status: Hibernation\n");
+ } else {
+ MDDI_MSG_NOTICE
+ (" Current Link Status: Inactive\n");
+ }
+ MDDI_MSG_NOTICE
+ (" Active state entered %d times\n",
+ pmhctl->log_parms.link_active_cnt -
+ prev_ptr->link_active_cnt);
+ MDDI_MSG_NOTICE
+ (" Hibernation state entered %d times\n",
+ pmhctl->log_parms.
+ link_hibernate_cnt -
+ prev_ptr->link_hibernate_cnt);
+ }
+ }
+ prev_parms[host_idx] = pmhctl->log_parms;
+ }
+ }
+ if (mddi_log_stats_counter >= mddi_log_stats_frequency)
+ mddi_log_stats_counter = 0;
+
+ mutex_lock(&mddi_timer_lock);
+ if (!mddi_timer_shutdown_flag) {
+ mddi_host_timer.function = mddi_host_timer_service;
+ mddi_host_timer.data = 0;
+ mddi_host_timer.expires = jiffies + ((time_ms * HZ) / 1000);
+ add_timer(&mddi_host_timer);
+ }
+ mutex_unlock(&mddi_timer_lock);
+
+ return;
+} /* mddi_host_timer_cb */
+
+static void mddi_process_link_list_done(void)
+{
+ mddi_host_type host_idx = mddi_curr_host;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ /* normal forward linked list packet(s) were sent */
+ if (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) {
+ MDDI_MSG_ERR("**** getting LL done, but no list ****\n");
+ } else {
+ uint16 idx;
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ if (pmhctl->rev_state == MDDI_REV_REG_READ_ISSUED) {
+ /* special case where a register read packet was sent */
+ pmhctl->rev_state = MDDI_REV_REG_READ_SENT;
+ if (pmhctl->llist_info.reg_read_idx == UNASSIGNED_INDEX) {
+ MDDI_MSG_ERR
+ ("**** getting LL done, but no list ****\n");
+ }
+ }
+#endif
+ for (idx = pmhctl->llist_info.transmitting_start_idx;;) {
+ uint16 next_idx = pmhctl->llist_notify[idx].next_idx;
+ /* with reg read we don't release the waiting tcb until after
+ * the reverse encapsulation has completed.
+ */
+ if (idx != pmhctl->llist_info.reg_read_idx) {
+ /* notify task that may be waiting on this completion */
+ if (pmhctl->llist_notify[idx].waiting) {
+ complete(&
+ (pmhctl->llist_notify[idx].
+ done_comp));
+ }
+ if (pmhctl->llist_notify[idx].done_cb != NULL) {
+ (*(pmhctl->llist_notify[idx].done_cb))
+ ();
+ }
+
+ pmhctl->llist_notify[idx].in_use = FALSE;
+ pmhctl->llist_notify[idx].waiting = FALSE;
+ pmhctl->llist_notify[idx].done_cb = NULL;
+ if (idx < MDDI_NUM_DYNAMIC_LLIST_ITEMS) {
+ /* static LLIST items are configured only once */
+ pmhctl->llist_notify[idx].next_idx =
+ UNASSIGNED_INDEX;
+ }
+ /*
+ * currently, all linked list packets are
+ * register access, so we can increment the
+ * counter for that packet type here.
+ */
+ pmhctl->log_parms.reg_acc_cnt++;
+ }
+ if (idx == pmhctl->llist_info.transmitting_end_idx)
+ break;
+ idx = next_idx;
+ if (idx == UNASSIGNED_INDEX)
+ MDDI_MSG_CRIT("MDDI linked list corruption!\n");
+ }
+
+ pmhctl->llist_info.transmitting_start_idx = UNASSIGNED_INDEX;
+ pmhctl->llist_info.transmitting_end_idx = UNASSIGNED_INDEX;
+
+ if (pmhctl->mddi_waiting_for_llist_avail) {
+ if (!
+ (pmhctl->
+ llist_notify[pmhctl->llist_info.next_free_idx].
+ in_use)) {
+ pmhctl->mddi_waiting_for_llist_avail = FALSE;
+ complete(&(pmhctl->mddi_llist_avail_comp));
+ }
+ }
+ }
+
+ /* Turn off MDDI_INT_PRI_LINK_LIST_DONE interrupt */
+ mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE, 0);
+
+}
+
+static void mddi_queue_forward_linked_list(void)
+{
+ uint16 first_pkt_index;
+ mddi_linked_list_type *llist_dma;
+ mddi_host_type host_idx = mddi_curr_host;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+ llist_dma = pmhctl->llist_dma_ptr;
+
+ first_pkt_index = UNASSIGNED_INDEX;
+
+ if (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) {
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ if (pmhctl->llist_info.reg_read_waiting) {
+ if (pmhctl->rev_state == MDDI_REV_IDLE) {
+ /*
+ * we have a register read to send and
+ * can send it now
+ */
+ pmhctl->rev_state = MDDI_REV_REG_READ_ISSUED;
+ mddi_reg_read_retry = 0;
+ first_pkt_index =
+ pmhctl->llist_info.waiting_start_idx;
+ pmhctl->llist_info.reg_read_waiting = FALSE;
+ }
+ } else
+#endif
+ {
+ /*
+ * not register read to worry about, go ahead and write
+ * anything that may be on the waiting list.
+ */
+ first_pkt_index = pmhctl->llist_info.waiting_start_idx;
+ }
+ }
+
+ if (first_pkt_index != UNASSIGNED_INDEX) {
+ pmhctl->llist_info.transmitting_start_idx =
+ pmhctl->llist_info.waiting_start_idx;
+ pmhctl->llist_info.transmitting_end_idx =
+ pmhctl->llist_info.waiting_end_idx;
+ pmhctl->llist_info.waiting_start_idx = UNASSIGNED_INDEX;
+ pmhctl->llist_info.waiting_end_idx = UNASSIGNED_INDEX;
+
+ /* write to the primary pointer register */
+ MDDI_MSG_DEBUG("MDDI writing primary ptr with idx=%d\n",
+ first_pkt_index);
+
+ pmhctl->int_type.llist_ptr_write_2++;
+
+ dma_coherent_pre_ops();
+ mddi_host_reg_out(PRI_PTR, &llist_dma[first_pkt_index]);
+
+ /* enable interrupt when complete */
+ mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE,
+ MDDI_INT_PRI_LINK_LIST_DONE);
+
+ }
+
+}
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+static void mddi_read_rev_packet(byte *data_ptr)
+{
+ uint16 i, length;
+ mddi_host_type host_idx = mddi_curr_host;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ uint8 *rev_ptr_overflow =
+ (pmhctl->rev_ptr_start + MDDI_REV_BUFFER_SIZE);
+
+ /* first determine the length and handle invalid lengths */
+ length = *pmhctl->rev_ptr_curr++;
+ if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
+ pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+ length |= ((*pmhctl->rev_ptr_curr++) << 8);
+ if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
+ pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+ if (length > (pmhctl->rev_pkt_size - 2)) {
+ MDDI_MSG_ERR("Invalid rev pkt length %d\n", length);
+ /* rev_pkt_size should always be <= rev_ptr_size so limit to packet size */
+ length = pmhctl->rev_pkt_size - 2;
+ }
+
+ /* If the data pointer is NULL, just increment the pmhctl->rev_ptr_curr.
+ * Loop around if necessary. Don't bother reading the data.
+ */
+ if (data_ptr == NULL) {
+ pmhctl->rev_ptr_curr += length;
+ if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
+ pmhctl->rev_ptr_curr -= MDDI_REV_BUFFER_SIZE;
+ return;
+ }
+
+ data_ptr[0] = length & 0x0ff;
+ data_ptr[1] = length >> 8;
+ data_ptr += 2;
+ /* copy the data to data_ptr byte-at-a-time */
+ for (i = 0; (i < length) && (pmhctl->rev_ptr_curr < rev_ptr_overflow);
+ i++)
+ *data_ptr++ = *pmhctl->rev_ptr_curr++;
+ if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
+ pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+ for (; (i < length) && (pmhctl->rev_ptr_curr < rev_ptr_overflow); i++)
+ *data_ptr++ = *pmhctl->rev_ptr_curr++;
+}
+
+static void mddi_process_rev_packets(void)
+{
+ uint32 rev_packet_count;
+ word i;
+ uint32 crc_errors;
+ boolean mddi_reg_read_successful = FALSE;
+ mddi_host_type host_idx = mddi_curr_host;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ pmhctl->log_parms.rev_enc_cnt++;
+ if ((pmhctl->rev_state != MDDI_REV_ENCAP_ISSUED) &&
+ (pmhctl->rev_state != MDDI_REV_STATUS_REQ_ISSUED) &&
+ (pmhctl->rev_state != MDDI_REV_CLIENT_CAP_ISSUED)) {
+ MDDI_MSG_ERR("Wrong state %d for reverse int\n",
+ pmhctl->rev_state);
+ }
+ /* Turn off MDDI_INT_REV_AVAIL interrupt */
+ mddi_host_reg_outm(INTEN, MDDI_INT_REV_DATA_AVAIL, 0);
+
+ /* Clear rev data avail int */
+ mddi_host_reg_out(INT, MDDI_INT_REV_DATA_AVAIL);
+
+ /* Get Number of packets */
+ rev_packet_count = mddi_host_reg_in(REV_PKT_CNT);
+
+#ifndef T_MSM7500
+ /* Clear out rev packet counter */
+ mddi_host_reg_out(REV_PKT_CNT, 0x0000);
+#endif
+
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
+ if ((pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED) &&
+ (rev_packet_count > 0) &&
+ (mddi_host_core_version == 0x28 ||
+ mddi_host_core_version == 0x30)) {
+
+ uint32 int_reg;
+ uint32 max_count = 0;
+
+ mddi_host_reg_out(REV_PTR, pmhctl->mddi_rev_ptr_write_val);
+ int_reg = mddi_host_reg_in(INT);
+ while ((int_reg & 0x100000) == 0) {
+ udelay(3);
+ int_reg = mddi_host_reg_in(INT);
+ if (++max_count > 100)
+ break;
+ }
+ }
+#endif
+
+ /* Get CRC error count */
+ crc_errors = mddi_host_reg_in(REV_CRC_ERR);
+ if (crc_errors != 0) {
+ pmhctl->log_parms.rev_crc_cnt += crc_errors;
+ pmhctl->stats.rev_crc_count += crc_errors;
+ MDDI_MSG_ERR("!!! MDDI %d Reverse CRC Error(s) !!!\n",
+ crc_errors);
+#ifndef T_MSM7500
+ /* Clear CRC error count */
+ mddi_host_reg_out(REV_CRC_ERR, 0x0000);
+#endif
+ /* also issue an RTD to attempt recovery */
+ pmhctl->rtd_counter = mddi_rtd_frequency;
+ }
+
+ pmhctl->rtd_value = mddi_host_reg_in(RTD_VAL);
+
+ MDDI_MSG_DEBUG("MDDI rev pkt cnt=%d, ptr=0x%x, RTD:0x%x\n",
+ rev_packet_count,
+ pmhctl->rev_ptr_curr - pmhctl->rev_ptr_start,
+ pmhctl->rtd_value);
+
+ if (rev_packet_count >= 1) {
+ mddi_invalidate_cache_lines((uint32 *) pmhctl->rev_ptr_start,
+ MDDI_REV_BUFFER_SIZE);
+ } else {
+ MDDI_MSG_ERR("Reverse pkt sent, no data rxd\n");
+ if (mddi_reg_read_value_ptr)
+ *mddi_reg_read_value_ptr = -EBUSY;
+ }
+ /* order the reads */
+ dma_coherent_post_ops();
+ for (i = 0; i < rev_packet_count; i++) {
+ mddi_rev_packet_type *rev_pkt_ptr;
+
+ mddi_read_rev_packet(rev_packet_data);
+
+ rev_pkt_ptr = (mddi_rev_packet_type *) rev_packet_data;
+
+ if (rev_pkt_ptr->packet_length > pmhctl->rev_pkt_size) {
+ MDDI_MSG_ERR("!!!invalid packet size: %d\n",
+ rev_pkt_ptr->packet_length);
+ }
+
+ MDDI_MSG_DEBUG("MDDI rev pkt 0x%x size 0x%x\n",
+ rev_pkt_ptr->packet_type,
+ rev_pkt_ptr->packet_length);
+
+ /* Do whatever you want to do with the data based on the packet type */
+ switch (rev_pkt_ptr->packet_type) {
+ case 66: /* Client Capability */
+ {
+ mddi_client_capability_type
+ *client_capability_pkt_ptr;
+
+ client_capability_pkt_ptr =
+ (mddi_client_capability_type *)
+ rev_packet_data;
+ MDDI_MSG_NOTICE
+ ("Client Capability: Week=%d, Year=%d\n",
+ client_capability_pkt_ptr->
+ Week_of_Manufacture,
+ client_capability_pkt_ptr->
+ Year_of_Manufacture);
+ memcpy((void *)&mddi_client_capability_pkt,
+ (void *)rev_packet_data,
+ sizeof(mddi_client_capability_type));
+ pmhctl->log_parms.cli_cap_cnt++;
+ }
+ break;
+
+ case 70: /* Display Status */
+ {
+ mddi_client_status_type *client_status_pkt_ptr;
+
+ client_status_pkt_ptr =
+ (mddi_client_status_type *) rev_packet_data;
+ if ((client_status_pkt_ptr->crc_error_count !=
+ 0)
+ || (client_status_pkt_ptr->
+ reverse_link_request != 0)) {
+ MDDI_MSG_ERR
+ ("Client Status: RevReq=%d, CrcErr=%d\n",
+ client_status_pkt_ptr->
+ reverse_link_request,
+ client_status_pkt_ptr->
+ crc_error_count);
+ } else {
+ MDDI_MSG_DEBUG
+ ("Client Status: RevReq=%d, CrcErr=%d\n",
+ client_status_pkt_ptr->
+ reverse_link_request,
+ client_status_pkt_ptr->
+ crc_error_count);
+ }
+ pmhctl->log_parms.fwd_crc_cnt +=
+ client_status_pkt_ptr->crc_error_count;
+ pmhctl->stats.fwd_crc_count +=
+ client_status_pkt_ptr->crc_error_count;
+ pmhctl->log_parms.cli_stat_cnt++;
+ }
+ break;
+
+ case 146: /* register access packet */
+ {
+ mddi_register_access_packet_type
+ * regacc_pkt_ptr;
+ uint32 data_count;
+
+ regacc_pkt_ptr =
+ (mddi_register_access_packet_type *)
+ rev_packet_data;
+
+ /* Bits[0:13] - read data count */
+ data_count = regacc_pkt_ptr->read_write_info
+ & 0x3FFF;
+ MDDI_MSG_DEBUG("\n MDDI rev read: 0x%x",
+ regacc_pkt_ptr->read_write_info);
+ MDDI_MSG_DEBUG("Reg Acc parse reg=0x%x,"
+ "value=0x%x\n", regacc_pkt_ptr->
+ register_address, regacc_pkt_ptr->
+ register_data_list[0]);
+
+ /* Copy register value to location passed in */
+ if (mddi_reg_read_value_ptr) {
+#if defined(T_MSM6280) && !defined(T_MSM7200)
+ /* only least significant 16 bits are valid with 6280 */
+ *mddi_reg_read_value_ptr =
+ regacc_pkt_ptr->
+ register_data_list[0] & 0x0000ffff;
+ mddi_reg_read_successful = TRUE;
+ mddi_reg_read_value_ptr = NULL;
+#else
+ if (data_count && data_count <=
+ MDDI_HOST_MAX_CLIENT_REG_IN_SAME_ADDR) {
+ memcpy(mddi_reg_read_value_ptr,
+ (void *)®acc_pkt_ptr->
+ register_data_list[0],
+ data_count * 4);
+ mddi_reg_read_successful = TRUE;
+ mddi_reg_read_value_ptr = NULL;
+ }
+#endif
+ }
+
+#ifdef DEBUG_MDDIHOSTI
+ if ((mddi_gpio.polling_enabled) &&
+ (regacc_pkt_ptr->register_address ==
+ mddi_gpio.polling_reg)) {
+ /*
+ * ToDo: need to call Linux GPIO call
+ * here...
+ */
+ mddi_client_lcd_gpio_poll(
+ regacc_pkt_ptr->register_data_list[0]);
+ }
+#endif
+ pmhctl->log_parms.reg_read_cnt++;
+ }
+ break;
+
+ case INVALID_PKT_TYPE: /* 0xFFFF */
+ MDDI_MSG_ERR("!!!INVALID_PKT_TYPE rcvd\n");
+ break;
+
+ default: /* any other packet */
+ {
+ uint16 hdlr;
+
+ for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS;
+ hdlr++) {
+ if (mddi_rev_pkt_handler[hdlr].
+ handler == NULL)
+ continue;
+ if (mddi_rev_pkt_handler[hdlr].
+ pkt_type ==
+ rev_pkt_ptr->packet_type) {
+ (*(mddi_rev_pkt_handler[hdlr].
+ handler)) (rev_pkt_ptr);
+ /* pmhctl->rev_state = MDDI_REV_IDLE; */
+ break;
+ }
+ }
+ if (hdlr >= MAX_MDDI_REV_HANDLERS)
+ MDDI_MSG_ERR("MDDI unknown rev pkt\n");
+ }
+ break;
+ }
+ }
+ if ((pmhctl->rev_ptr_curr + pmhctl->rev_pkt_size) >=
+ (pmhctl->rev_ptr_start + MDDI_REV_BUFFER_SIZE)) {
+ pmhctl->rev_ptr_written = FALSE;
+ }
+
+ if (pmhctl->rev_state == MDDI_REV_ENCAP_ISSUED) {
+ pmhctl->rev_state = MDDI_REV_IDLE;
+ if (mddi_rev_user.waiting) {
+ mddi_rev_user.waiting = FALSE;
+ complete(&(mddi_rev_user.done_comp));
+ } else if (pmhctl->llist_info.reg_read_idx == UNASSIGNED_INDEX) {
+ MDDI_MSG_ERR
+ ("Reverse Encap state, but no reg read in progress\n");
+ } else {
+ if ((!mddi_reg_read_successful) &&
+ (mddi_reg_read_retry < mddi_reg_read_retry_max) &&
+ (mddi_enable_reg_read_retry)) {
+ /*
+ * There is a race condition that can happen
+ * where the reverse encapsulation message is
+ * sent out by the MDDI host before the register
+ * read packet is sent. As a work-around for
+ * that problem we issue the reverse
+ * encapsulation one more time before giving up.
+ */
+ if (mddi_enable_reg_read_retry_once)
+ mddi_reg_read_retry =
+ mddi_reg_read_retry_max;
+ else
+ mddi_reg_read_retry++;
+ pmhctl->rev_state = MDDI_REV_REG_READ_SENT;
+ pmhctl->stats.reg_read_failure++;
+ } else {
+ uint16 reg_read_idx =
+ pmhctl->llist_info.reg_read_idx;
+
+ mddi_reg_read_retry = 0;
+ if (pmhctl->llist_notify[reg_read_idx].waiting) {
+ complete(&
+ (pmhctl->
+ llist_notify[reg_read_idx].
+ done_comp));
+ }
+ pmhctl->llist_info.reg_read_idx =
+ UNASSIGNED_INDEX;
+ if (pmhctl->llist_notify[reg_read_idx].
+ done_cb != NULL) {
+ (*
+ (pmhctl->llist_notify[reg_read_idx].
+ done_cb)) ();
+ }
+ pmhctl->llist_notify[reg_read_idx].next_idx =
+ UNASSIGNED_INDEX;
+ pmhctl->llist_notify[reg_read_idx].in_use =
+ FALSE;
+ pmhctl->llist_notify[reg_read_idx].waiting =
+ FALSE;
+ pmhctl->llist_notify[reg_read_idx].done_cb =
+ NULL;
+ if (!mddi_reg_read_successful)
+ pmhctl->stats.reg_read_failure++;
+ }
+ }
+ } else if (pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED) {
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
+ if (mddi_host_core_version == 0x28 ||
+ mddi_host_core_version == 0x30) {
+ mddi_host_reg_out(FIFO_ALLOC, 0x00);
+ pmhctl->rev_ptr_written = TRUE;
+ mddi_host_reg_out(REV_PTR,
+ pmhctl->mddi_rev_ptr_write_val);
+ pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+ mddi_host_reg_out(CMD, 0xC00);
+ }
+#endif
+
+ if (mddi_rev_user.waiting) {
+ mddi_rev_user.waiting = FALSE;
+ complete(&(mddi_rev_user.done_comp));
+ }
+ pmhctl->rev_state = MDDI_REV_IDLE;
+ } else {
+ pmhctl->rev_state = MDDI_REV_IDLE;
+ }
+
+ /* pmhctl->rev_state = MDDI_REV_IDLE; */
+
+ /* Re-enable interrupt */
+ mddi_host_reg_outm(INTEN, MDDI_INT_REV_DATA_AVAIL,
+ MDDI_INT_REV_DATA_AVAIL);
+
+}
+
+static void mddi_issue_reverse_encapsulation(void)
+{
+ mddi_host_type host_idx = mddi_curr_host;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+ /* Only issue a reverse encapsulation packet if:
+ * 1) another reverse is not in progress (MDDI_REV_IDLE).
+ * 2) a register read has been sent (MDDI_REV_REG_READ_SENT).
+ * 3) forward is not in progress, because of a hw bug in client that
+ * causes forward crc errors on packet immediately after rev encap.
+ */
+ if (((pmhctl->rev_state == MDDI_REV_IDLE) ||
+ (pmhctl->rev_state == MDDI_REV_REG_READ_SENT)) &&
+ (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) &&
+ (!mdp_in_processing)) {
+ uint32 mddi_command = MDDI_CMD_SEND_REV_ENCAP;
+
+ if ((pmhctl->rev_state == MDDI_REV_REG_READ_SENT) ||
+ (mddi_rev_encap_user_request == TRUE)) {
+ mddi_host_enable_io_clock();
+ if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
+ /* need to wake up link before issuing rev encap command */
+ MDDI_MSG_DEBUG("wake up link!\n");
+ pmhctl->link_state = MDDI_LINK_ACTIVATING;
+ mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
+ } else {
+ if (pmhctl->rtd_counter >= mddi_rtd_frequency) {
+ MDDI_MSG_DEBUG
+ ("mddi sending RTD command!\n");
+ mddi_host_reg_out(CMD,
+ MDDI_CMD_SEND_RTD);
+ pmhctl->rtd_counter = 0;
+ pmhctl->log_parms.rtd_cnt++;
+ }
+ if (pmhctl->rev_state != MDDI_REV_REG_READ_SENT) {
+ /* this is generic reverse request by user, so
+ * reset the waiting flag. */
+ mddi_rev_encap_user_request = FALSE;
+ }
+ /* link is active so send reverse encap to get register read results */
+ pmhctl->rev_state = MDDI_REV_ENCAP_ISSUED;
+ mddi_command = MDDI_CMD_SEND_REV_ENCAP;
+ MDDI_MSG_DEBUG("sending rev encap!\n");
+ }
+ } else
+ if ((pmhctl->client_status_cnt >=
+ mddi_client_status_frequency)
+ || mddi_client_capability_request) {
+ mddi_host_enable_io_clock();
+ if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
+ /* only wake up the link if it client status is overdue */
+ if ((pmhctl->client_status_cnt >=
+ (mddi_client_status_frequency * 2))
+ || mddi_client_capability_request) {
+ /* need to wake up link before issuing rev encap command */
+ MDDI_MSG_DEBUG("wake up link!\n");
+ pmhctl->link_state =
+ MDDI_LINK_ACTIVATING;
+ mddi_host_reg_out(CMD,
+ MDDI_CMD_LINK_ACTIVE);
+ }
+ } else {
+ if (pmhctl->rtd_counter >= mddi_rtd_frequency) {
+ MDDI_MSG_DEBUG
+ ("mddi sending RTD command!\n");
+ mddi_host_reg_out(CMD,
+ MDDI_CMD_SEND_RTD);
+ pmhctl->rtd_counter = 0;
+ pmhctl->log_parms.rtd_cnt++;
+ }
+ /* periodically get client status */
+ MDDI_MSG_DEBUG
+ ("mddi sending rev enc! (get status)\n");
+ if (mddi_client_capability_request) {
+ pmhctl->rev_state =
+ MDDI_REV_CLIENT_CAP_ISSUED;
+ mddi_command = MDDI_CMD_GET_CLIENT_CAP;
+ mddi_client_capability_request = FALSE;
+ } else {
+ pmhctl->rev_state =
+ MDDI_REV_STATUS_REQ_ISSUED;
+ pmhctl->client_status_cnt = 0;
+ mddi_command =
+ MDDI_CMD_GET_CLIENT_STATUS;
+ }
+ }
+ }
+ if ((pmhctl->rev_state == MDDI_REV_ENCAP_ISSUED) ||
+ (pmhctl->rev_state == MDDI_REV_STATUS_REQ_ISSUED) ||
+ (pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED)) {
+ pmhctl->int_type.rev_encap_count++;
+#if defined(T_MSM6280) && !defined(T_MSM7200)
+ mddi_rev_pointer_written = TRUE;
+ mddi_host_reg_out(REV_PTR, mddi_rev_ptr_write_val);
+ mddi_rev_ptr_curr = mddi_rev_ptr_start;
+ /* force new rev ptr command */
+ mddi_host_reg_out(CMD, 0xC00);
+#else
+ if (!pmhctl->rev_ptr_written) {
+ MDDI_MSG_DEBUG("writing reverse pointer!\n");
+ pmhctl->rev_ptr_written = TRUE;
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
+ if ((pmhctl->rev_state ==
+ MDDI_REV_CLIENT_CAP_ISSUED) &&
+ (mddi_host_core_version == 0x28 ||
+ mddi_host_core_version == 0x30)) {
+ pmhctl->rev_ptr_written = FALSE;
+ mddi_host_reg_out(FIFO_ALLOC, 0x02);
+ } else
+ mddi_host_reg_out(REV_PTR,
+ pmhctl->
+ mddi_rev_ptr_write_val);
+#else
+ mddi_host_reg_out(REV_PTR,
+ pmhctl->
+ mddi_rev_ptr_write_val);
+#endif
+ }
+#endif
+ if (mddi_debug_clear_rev_data) {
+ uint16 i;
+ for (i = 0; i < MDDI_MAX_REV_DATA_SIZE / 4; i++)
+ pmhctl->rev_data_buf[i] = 0xdddddddd;
+ /* clean cache */
+ mddi_flush_cache_lines(pmhctl->rev_data_buf,
+ MDDI_MAX_REV_DATA_SIZE);
+ }
+
+ /* send reverse encapsulation to get needed data */
+ mddi_host_reg_out(CMD, mddi_command);
+ }
+ }
+
+}
+
+static void mddi_process_client_initiated_wakeup(void)
+{
+ mddi_host_type host_idx = mddi_curr_host;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ /* Disable MDDI_INT Interrupt, we detect client initiated wakeup one
+ * time for each entry into hibernation */
+ mddi_host_reg_outm(INTEN, MDDI_INT_MDDI_IN, 0);
+
+ if (host_idx == MDDI_HOST_PRIM) {
+ if (mddi_vsync_detect_enabled) {
+ mddi_host_enable_io_clock();
+#ifndef MDDI_HOST_DISP_LISTEN
+ /* issue command to bring up link */
+ /* need to do this to clear the vsync condition */
+ if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
+ pmhctl->link_state = MDDI_LINK_ACTIVATING;
+ mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
+ }
+#endif
+ /*
+ * Indicate to client specific code that vsync was
+ * enabled, and we did not detect a client initiated
+ * wakeup. The client specific handler can clear the
+ * condition if necessary to prevent subsequent
+ * client initiated wakeups.
+ */
+ mddi_client_lcd_vsync_detected(TRUE);
+ pmhctl->log_parms.vsync_response_cnt++;
+ MDDI_MSG_NOTICE("MDDI_INT_IN condition\n");
+
+ }
+ }
+
+ if (mddi_gpio.polling_enabled) {
+ mddi_host_enable_io_clock();
+ /* check interrupt status now */
+ (void)mddi_queue_register_read_int(mddi_gpio.polling_reg,
+ &mddi_gpio.polling_val);
+ }
+}
+#endif /* FEATURE_MDDI_DISABLE_REVERSE */
+
+static void mddi_host_isr(void)
+{
+ uint32 int_reg, int_en;
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ uint32 status_reg;
+#endif
+ mddi_host_type host_idx = mddi_curr_host;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ if (!MDDI_HOST_IS_HCLK_ON) {
+ MDDI_HOST_ENABLE_HCLK;
+ }
+ int_reg = mddi_host_reg_in(INT);
+ int_en = mddi_host_reg_in(INTEN);
+ pmhctl->saved_int_reg = int_reg;
+ pmhctl->saved_int_en = int_en;
+ int_reg = int_reg & int_en;
+ pmhctl->int_type.count++;
+
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ status_reg = mddi_host_reg_in(STAT);
+
+ if ((int_reg & MDDI_INT_MDDI_IN) ||
+ ((int_en & MDDI_INT_MDDI_IN) &&
+ ((int_reg == 0) || (status_reg & MDDI_STAT_CLIENT_WAKEUP_REQ)))) {
+ /*
+ * The MDDI_IN condition will clear itself, and so it is
+ * possible that MDDI_IN was the reason for the isr firing,
+ * even though the interrupt register does not have the
+ * MDDI_IN bit set. To check if this was the case we need to
+ * look at the status register bit that signifies a client
+ * initiated wakeup. If the status register bit is set, as well
+ * as the MDDI_IN interrupt enabled, then we treat this as a
+ * client initiated wakeup.
+ */
+ if (int_reg & MDDI_INT_MDDI_IN)
+ pmhctl->int_type.in_count++;
+ mddi_process_client_initiated_wakeup();
+ }
+#endif
+
+ if (int_reg & MDDI_INT_LINK_STATE_CHANGES) {
+ pmhctl->int_type.state_change_count++;
+ mddi_report_state_change(int_reg);
+ }
+
+ if (int_reg & MDDI_INT_PRI_LINK_LIST_DONE) {
+ pmhctl->int_type.ll_done_count++;
+ mddi_process_link_list_done();
+ }
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ if (int_reg & MDDI_INT_REV_DATA_AVAIL) {
+ pmhctl->int_type.rev_avail_count++;
+ mddi_process_rev_packets();
+ }
+#endif
+
+ if (int_reg & MDDI_INT_ERROR_CONDITIONS) {
+ pmhctl->int_type.error_count++;
+ mddi_report_errors(int_reg);
+
+ mddi_host_reg_out(INT, int_reg & MDDI_INT_ERROR_CONDITIONS);
+ }
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ mddi_issue_reverse_encapsulation();
+
+ if ((pmhctl->rev_state != MDDI_REV_ENCAP_ISSUED) &&
+ (pmhctl->rev_state != MDDI_REV_STATUS_REQ_ISSUED))
+#endif
+ /* don't want simultaneous reverse and forward with Eagle */
+ mddi_queue_forward_linked_list();
+
+ if (int_reg & MDDI_INT_NO_CMD_PKTS_PEND) {
+ /* this interrupt is used to kick the isr when hibernation is disabled */
+ mddi_host_reg_outm(INTEN, MDDI_INT_NO_CMD_PKTS_PEND, 0);
+ }
+
+ if ((!mddi_host_mdp_active_flag) &&
+ (!mddi_vsync_detect_enabled) &&
+ (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) &&
+ (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) &&
+ (pmhctl->rev_state == MDDI_REV_IDLE)) {
+ if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
+ mddi_host_disable_io_clock();
+ mddi_host_disable_hclk();
+ }
+#ifdef FEATURE_MDDI_HOST_ENABLE_EARLY_HIBERNATION
+ else if ((pmhctl->link_state == MDDI_LINK_ACTIVE) &&
+ (!pmhctl->disable_hibernation)) {
+ mddi_host_reg_out(CMD, MDDI_CMD_POWERDOWN);
+ }
+#endif
+ }
+}
+
+static void mddi_host_isr_primary(void)
+{
+ mddi_curr_host = MDDI_HOST_PRIM;
+ mddi_host_isr();
+}
+
+irqreturn_t mddi_pmdh_isr_proxy(int irq, void *ptr)
+{
+ mddi_host_isr_primary();
+ return IRQ_HANDLED;
+}
+
+static void mddi_host_isr_external(void)
+{
+ mddi_curr_host = MDDI_HOST_EXT;
+ mddi_host_isr();
+ mddi_curr_host = MDDI_HOST_PRIM;
+}
+
+irqreturn_t mddi_emdh_isr_proxy(int irq, void *ptr)
+{
+ mddi_host_isr_external();
+ return IRQ_HANDLED;
+}
+
+static void mddi_host_initialize_registers(mddi_host_type host_idx)
+{
+ uint32 pad_reg_val;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ if (pmhctl->driver_state == MDDI_DRIVER_ENABLED)
+ return;
+
+ /* turn on HCLK to MDDI host core */
+ mddi_host_enable_hclk();
+
+ /* MDDI Reset command */
+ mddi_host_reg_out(CMD, MDDI_CMD_RESET);
+
+ /* Version register (= 0x01) */
+ mddi_host_reg_out(VERSION, 0x0001);
+
+ /* Bytes per subframe register */
+ mddi_host_reg_out(BPS, MDDI_HOST_BYTES_PER_SUBFRAME);
+
+ /* Subframes per media frames register (= 0x03) */
+ mddi_host_reg_out(SPM, 0x0003);
+
+ /* Turn Around 1 register (= 0x05) */
+ mddi_host_reg_out(TA1_LEN, 0x0005);
+
+ /* Turn Around 2 register (= 0x0C) */
+ mddi_host_reg_out(TA2_LEN, MDDI_HOST_TA2_LEN);
+
+ /* Drive hi register (= 0x96) */
+ mddi_host_reg_out(DRIVE_HI, 0x0096);
+
+ /* Drive lo register (= 0x32) */
+ mddi_host_reg_out(DRIVE_LO, 0x0032);
+
+ /* Display wakeup count register (= 0x3c) */
+ mddi_host_reg_out(DISP_WAKE, 0x003c);
+
+ /* Reverse Rate Divisor register (= 0x2) */
+ mddi_host_reg_out(REV_RATE_DIV, MDDI_HOST_REV_RATE_DIV);
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ /* Reverse Pointer Size */
+ mddi_host_reg_out(REV_SIZE, MDDI_REV_BUFFER_SIZE);
+
+ /* Rev Encap Size */
+ mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size);
+#endif
+
+ /* Periodic Rev Encap */
+ /* don't send periodically */
+ mddi_host_reg_out(CMD, MDDI_CMD_PERIODIC_REV_ENCAP);
+
+ pad_reg_val = mddi_host_reg_in(PAD_CTL);
+ if (pad_reg_val == 0) {
+ /* If we are turning on band gap, need to wait 5us before turning
+ * on the rest of the PAD */
+ mddi_host_reg_out(PAD_CTL, 0x08000);
+ udelay(5);
+ }
+#ifdef T_MSM7200
+ /* Recommendation from PAD hw team */
+ mddi_host_reg_out(PAD_CTL, 0xa850a);
+#else
+ /* Recommendation from PAD hw team */
+ mddi_host_reg_out(PAD_CTL, 0xa850f);
+#endif
+
+ pad_reg_val = 0x00220020;
+
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
+ mddi_host_reg_out(PAD_IO_CTL, 0x00320000);
+ mddi_host_reg_out(PAD_CAL, pad_reg_val);
+#endif
+
+ mddi_host_core_version = mddi_host_reg_inm(CORE_VER, 0xffff);
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ if (mddi_host_core_version >= 8)
+ mddi_rev_ptr_workaround = FALSE;
+ pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+#endif
+
+ if ((mddi_host_core_version > 8) && (mddi_host_core_version < 0x19))
+ mddi_host_reg_out(TEST, 0x2);
+
+ /* Need an even number for counts */
+ mddi_host_reg_out(DRIVER_START_CNT, 0x60006);
+
+#ifndef T_MSM7500
+ /* Setup defaults for MDP related register */
+ mddi_host_reg_out(MDP_VID_FMT_DES, 0x5666);
+ mddi_host_reg_out(MDP_VID_PIX_ATTR, 0x00C3);
+ mddi_host_reg_out(MDP_VID_CLIENTID, 0);
+#endif
+
+ /* automatically hibernate after 1 empty subframe */
+ if (pmhctl->disable_hibernation)
+ mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
+ else
+ mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
+
+ /* Bring up link if display (client) requests it */
+#ifdef MDDI_HOST_DISP_LISTEN
+ mddi_host_reg_out(CMD, MDDI_CMD_DISP_LISTEN);
+#else
+ mddi_host_reg_out(CMD, MDDI_CMD_DISP_IGNORE);
+#endif
+
+}
+
+void mddi_host_configure_interrupts(mddi_host_type host_idx, boolean enable)
+{
+ unsigned long flags;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ spin_lock_irqsave(&mddi_host_spin_lock, flags);
+
+ /* turn on HCLK to MDDI host core if it has been disabled */
+ mddi_host_enable_hclk();
+ /* Clear MDDI Interrupt enable reg */
+ mddi_host_reg_out(INTEN, 0);
+
+ spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+ if (enable) {
+ pmhctl->driver_state = MDDI_DRIVER_ENABLED;
+
+ if (host_idx == MDDI_HOST_PRIM) {
+ if (request_irq
+ (INT_MDDI_PRI, mddi_pmdh_isr_proxy, IRQF_DISABLED,
+ "PMDH", 0) != 0)
+ printk(KERN_ERR
+ "a mddi: unable to request_irq\n");
+ else {
+ int_mddi_pri_flag = TRUE;
+ irq_enabled = 1;
+ }
+ } else {
+ if (request_irq
+ (INT_MDDI_EXT, mddi_emdh_isr_proxy, IRQF_DISABLED,
+ "EMDH", 0) != 0)
+ printk(KERN_ERR
+ "b mddi: unable to request_irq\n");
+ else
+ int_mddi_ext_flag = TRUE;
+ }
+
+ /* Set MDDI Interrupt enable reg -- Enable Reverse data avail */
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+ mddi_host_reg_out(INTEN,
+ MDDI_INT_ERROR_CONDITIONS |
+ MDDI_INT_LINK_STATE_CHANGES);
+#else
+ /* Reverse Pointer register */
+ pmhctl->rev_ptr_written = FALSE;
+
+ mddi_host_reg_out(INTEN,
+ MDDI_INT_REV_DATA_AVAIL |
+ MDDI_INT_ERROR_CONDITIONS |
+ MDDI_INT_LINK_STATE_CHANGES);
+ pmhctl->rtd_counter = mddi_rtd_frequency;
+ pmhctl->client_status_cnt = 0;
+#endif
+ } else {
+ if (pmhctl->driver_state == MDDI_DRIVER_ENABLED)
+ pmhctl->driver_state = MDDI_DRIVER_DISABLED;
+ }
+
+}
+
+/*
+ * mddi_host_client_cnt_reset:
+ * reset client_status_cnt to 0 to make sure host does not
+ * send RTD cmd to client right after resume before mddi
+ * client be powered up. this fix "MDDI RTD Failure" problem
+ */
+void mddi_host_client_cnt_reset(void)
+{
+ unsigned long flags;
+ mddi_host_cntl_type *pmhctl;
+
+ pmhctl = &(mhctl[MDDI_HOST_PRIM]);
+ spin_lock_irqsave(&mddi_host_spin_lock, flags);
+ pmhctl->client_status_cnt = 0;
+ spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+}
+
+static void mddi_host_powerup(mddi_host_type host_idx)
+{
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ if (pmhctl->link_state != MDDI_LINK_DISABLED)
+ return;
+
+ /* enable IO_CLK and hclk to MDDI host core */
+ mddi_host_enable_io_clock();
+
+ mddi_host_initialize_registers(host_idx);
+ mddi_host_configure_interrupts(host_idx, TRUE);
+
+ pmhctl->link_state = MDDI_LINK_ACTIVATING;
+
+ /* Link activate command */
+ mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
+
+#ifdef CLKRGM_MDDI_IO_CLOCK_IN_MHZ
+ MDDI_MSG_NOTICE("MDDI Host: Activating Link %d Mbps\n",
+ CLKRGM_MDDI_IO_CLOCK_IN_MHZ * 2);
+#else
+ MDDI_MSG_NOTICE("MDDI Host: Activating Link\n");
+#endif
+
+ /* Initialize the timer */
+ if (host_idx == MDDI_HOST_PRIM)
+ mddi_host_timer_service(0);
+}
+
+void mddi_send_fw_link_skew_cal(mddi_host_type host_idx)
+{
+ mddi_host_reg_out(CMD, MDDI_CMD_FW_LINK_SKEW_CAL);
+ MDDI_MSG_DEBUG("%s: Skew Calibration done!!\n", __func__);
+}
+
+
+void mddi_host_init(mddi_host_type host_idx)
+/* Write out the MDDI configuration registers */
+{
+ static boolean initialized = FALSE;
+ mddi_host_cntl_type *pmhctl;
+
+ if (host_idx >= MDDI_NUM_HOST_CORES) {
+ MDDI_MSG_ERR("Invalid host core index\n");
+ return;
+ }
+
+ if (!initialized) {
+ uint16 idx;
+ mddi_host_type host;
+
+ for (host = MDDI_HOST_PRIM; host < MDDI_NUM_HOST_CORES; host++) {
+ pmhctl = &(mhctl[host]);
+ initialized = TRUE;
+
+ pmhctl->llist_ptr =
+ dma_alloc_coherent(NULL, MDDI_LLIST_POOL_SIZE,
+ &(pmhctl->llist_dma_addr),
+ GFP_KERNEL);
+ pmhctl->llist_dma_ptr =
+ (mddi_linked_list_type *) (void *)pmhctl->
+ llist_dma_addr;
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+ pmhctl->rev_data_buf = NULL;
+ if (pmhctl->llist_ptr == NULL)
+#else
+ mddi_rev_user.waiting = FALSE;
+ init_completion(&(mddi_rev_user.done_comp));
+ pmhctl->rev_data_buf =
+ dma_alloc_coherent(NULL, MDDI_MAX_REV_DATA_SIZE,
+ &(pmhctl->rev_data_dma_addr),
+ GFP_KERNEL);
+ if ((pmhctl->llist_ptr == NULL)
+ || (pmhctl->rev_data_buf == NULL))
+#endif
+ {
+ MDDI_MSG_CRIT
+ ("unable to alloc non-cached memory\n");
+ }
+ llist_extern[host] = pmhctl->llist_ptr;
+ llist_dma_extern[host] = pmhctl->llist_dma_ptr;
+ llist_extern_notify[host] = pmhctl->llist_notify;
+
+ for (idx = 0; idx < UNASSIGNED_INDEX; idx++) {
+ init_completion(&
+ (pmhctl->llist_notify[idx].
+ done_comp));
+ }
+ init_completion(&(pmhctl->mddi_llist_avail_comp));
+ spin_lock_init(&mddi_host_spin_lock);
+ pmhctl->mddi_waiting_for_llist_avail = FALSE;
+ pmhctl->mddi_rev_ptr_write_val =
+ (uint32) (void *)(pmhctl->rev_data_dma_addr);
+ pmhctl->rev_ptr_start = (void *)pmhctl->rev_data_buf;
+
+ pmhctl->rev_pkt_size = MDDI_DEFAULT_REV_PKT_SIZE;
+ pmhctl->rev_state = MDDI_REV_IDLE;
+#ifdef IMAGE_MODEM_PROC
+ /* assume hibernation state is last state from APPS proc, so that
+ * we don't reinitialize the host core */
+ pmhctl->link_state = MDDI_LINK_HIBERNATING;
+#else
+ pmhctl->link_state = MDDI_LINK_DISABLED;
+#endif
+ pmhctl->driver_state = MDDI_DRIVER_DISABLED;
+ pmhctl->disable_hibernation = FALSE;
+
+ /* initialize llist variables */
+ pmhctl->llist_info.transmitting_start_idx =
+ UNASSIGNED_INDEX;
+ pmhctl->llist_info.transmitting_end_idx =
+ UNASSIGNED_INDEX;
+ pmhctl->llist_info.waiting_start_idx = UNASSIGNED_INDEX;
+ pmhctl->llist_info.waiting_end_idx = UNASSIGNED_INDEX;
+ pmhctl->llist_info.reg_read_idx = UNASSIGNED_INDEX;
+ pmhctl->llist_info.next_free_idx =
+ MDDI_FIRST_DYNAMIC_LLIST_IDX;
+ pmhctl->llist_info.reg_read_waiting = FALSE;
+
+ mddi_vsync_detect_enabled = FALSE;
+ mddi_gpio.polling_enabled = FALSE;
+
+ pmhctl->int_type.count = 0;
+ pmhctl->int_type.in_count = 0;
+ pmhctl->int_type.disp_req_count = 0;
+ pmhctl->int_type.state_change_count = 0;
+ pmhctl->int_type.ll_done_count = 0;
+ pmhctl->int_type.rev_avail_count = 0;
+ pmhctl->int_type.error_count = 0;
+ pmhctl->int_type.rev_encap_count = 0;
+ pmhctl->int_type.llist_ptr_write_1 = 0;
+ pmhctl->int_type.llist_ptr_write_2 = 0;
+
+ pmhctl->stats.fwd_crc_count = 0;
+ pmhctl->stats.rev_crc_count = 0;
+ pmhctl->stats.pri_underflow = 0;
+ pmhctl->stats.sec_underflow = 0;
+ pmhctl->stats.rev_overflow = 0;
+ pmhctl->stats.pri_overwrite = 0;
+ pmhctl->stats.sec_overwrite = 0;
+ pmhctl->stats.rev_overwrite = 0;
+ pmhctl->stats.dma_failure = 0;
+ pmhctl->stats.rtd_failure = 0;
+ pmhctl->stats.reg_read_failure = 0;
+#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY
+ pmhctl->stats.pri_underrun_detected = 0;
+#endif
+
+ pmhctl->log_parms.rtd_cnt = 0;
+ pmhctl->log_parms.rev_enc_cnt = 0;
+ pmhctl->log_parms.vid_cnt = 0;
+ pmhctl->log_parms.reg_acc_cnt = 0;
+ pmhctl->log_parms.cli_stat_cnt = 0;
+ pmhctl->log_parms.cli_cap_cnt = 0;
+ pmhctl->log_parms.reg_read_cnt = 0;
+ pmhctl->log_parms.link_active_cnt = 0;
+ pmhctl->log_parms.link_hibernate_cnt = 0;
+ pmhctl->log_parms.fwd_crc_cnt = 0;
+ pmhctl->log_parms.rev_crc_cnt = 0;
+ pmhctl->log_parms.vsync_response_cnt = 0;
+
+ prev_parms[host_idx] = pmhctl->log_parms;
+ mddi_client_capability_pkt.packet_length = 0;
+ }
+
+#ifndef T_MSM7500
+ /* tell clock driver we are user of this PLL */
+ MDDI_HOST_ENABLE_IO_CLOCK;
+#endif
+ }
+
+ mddi_host_powerup(host_idx);
+ pmhctl = &(mhctl[host_idx]);
+}
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+static uint32 mddi_client_id;
+
+uint32 mddi_get_client_id(void)
+{
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ mddi_host_type host_idx = MDDI_HOST_PRIM;
+ static boolean client_detection_try = FALSE;
+ mddi_host_cntl_type *pmhctl;
+ unsigned long flags;
+ uint16 saved_rev_pkt_size;
+ int ret;
+
+ if (!client_detection_try) {
+ /* Toshiba display requires larger drive_lo value */
+ mddi_host_reg_out(DRIVE_LO, 0x0050);
+
+ pmhctl = &(mhctl[MDDI_HOST_PRIM]);
+
+ saved_rev_pkt_size = pmhctl->rev_pkt_size;
+
+ /* Increase Rev Encap Size */
+ pmhctl->rev_pkt_size = MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE;
+ mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size);
+
+ /* disable hibernation temporarily */
+ if (!pmhctl->disable_hibernation)
+ mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
+
+ mddi_rev_user.waiting = TRUE;
+ INIT_COMPLETION(mddi_rev_user.done_comp);
+
+ spin_lock_irqsave(&mddi_host_spin_lock, flags);
+
+ /* turn on clock(s), if they have been disabled */
+ mddi_host_enable_hclk();
+ mddi_host_enable_io_clock();
+
+ mddi_client_capability_request = TRUE;
+
+ if (pmhctl->rev_state == MDDI_REV_IDLE) {
+ /* attempt to send the reverse encapsulation now */
+ mddi_issue_reverse_encapsulation();
+ }
+ spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+ wait_for_completion_killable(&(mddi_rev_user.done_comp));
+
+ /* Set Rev Encap Size back to its original value */
+ pmhctl->rev_pkt_size = saved_rev_pkt_size;
+ mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size);
+
+ /* reenable auto-hibernate */
+ if (!pmhctl->disable_hibernation)
+ mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
+
+ mddi_host_reg_out(DRIVE_LO, 0x0032);
+ client_detection_try = TRUE;
+
+ mddi_client_id = (mddi_client_capability_pkt.Mfr_Name<<16) |
+ mddi_client_capability_pkt.Product_Code;
+
+ if (!mddi_client_id)
+ mddi_disable(1);
+
+ ret = mddi_client_power(mddi_client_id);
+ if (ret < 0)
+ MDDI_MSG_ERR("mddi_client_power return %d", ret);
+ }
+
+#if 0
+ switch (mddi_client_capability_pkt.Mfr_Name) {
+ case 0x4474:
+ if ((mddi_client_capability_pkt.Product_Code != 0x8960) &&
+ (target == DISPLAY_1)) {
+ ret = PRISM_WVGA;
+ }
+ break;
+
+ case 0xD263:
+ if (target == DISPLAY_1)
+ ret = TOSHIBA_VGA_PRIM;
+ else if (target == DISPLAY_2)
+ ret = TOSHIBA_QCIF_SECD;
+ break;
+
+ case 0:
+ if (mddi_client_capability_pkt.Product_Code == 0x8835) {
+ if (target == DISPLAY_1)
+ ret = SHARP_QVGA_PRIM;
+ else if (target == DISPLAY_2)
+ ret = SHARP_128x128_SECD;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if ((!client_detection_try) && (ret != TOSHIBA_VGA_PRIM)
+ && (ret != TOSHIBA_QCIF_SECD)) {
+ /* Not a Toshiba display, so change drive_lo back to default value */
+ mddi_host_reg_out(DRIVE_LO, 0x0032);
+ }
+#endif
+
+#endif
+
+ return mddi_client_id;
+}
+#endif
+
+void mddi_host_powerdown(mddi_host_type host_idx)
+{
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ if (host_idx >= MDDI_NUM_HOST_CORES) {
+ MDDI_MSG_ERR("Invalid host core index\n");
+ return;
+ }
+
+ if (pmhctl->driver_state == MDDI_DRIVER_RESET) {
+ return;
+ }
+
+ if (host_idx == MDDI_HOST_PRIM) {
+ /* disable timer */
+ del_timer(&mddi_host_timer);
+ }
+
+ mddi_host_configure_interrupts(host_idx, FALSE);
+
+ /* turn on HCLK to MDDI host core if it has been disabled */
+ mddi_host_enable_hclk();
+
+ /* MDDI Reset command */
+ mddi_host_reg_out(CMD, MDDI_CMD_RESET);
+
+ /* Pad Control Register */
+ mddi_host_reg_out(PAD_CTL, 0x0);
+
+ /* disable IO_CLK and hclk to MDDI host core */
+ mddi_host_disable_io_clock();
+ mddi_host_disable_hclk();
+
+ pmhctl->link_state = MDDI_LINK_DISABLED;
+ pmhctl->driver_state = MDDI_DRIVER_RESET;
+
+ MDDI_MSG_NOTICE("MDDI Host: Disabling Link\n");
+
+}
+
+uint16 mddi_get_next_free_llist_item(mddi_host_type host_idx, boolean wait)
+{
+ unsigned long flags;
+ uint16 ret_idx;
+ boolean forced_wait = FALSE;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ ret_idx = pmhctl->llist_info.next_free_idx;
+
+ pmhctl->llist_info.next_free_idx++;
+ if (pmhctl->llist_info.next_free_idx >= MDDI_NUM_DYNAMIC_LLIST_ITEMS)
+ pmhctl->llist_info.next_free_idx = MDDI_FIRST_DYNAMIC_LLIST_IDX;
+ spin_lock_irqsave(&mddi_host_spin_lock, flags);
+ if (pmhctl->llist_notify[ret_idx].in_use) {
+ if (!wait) {
+ pmhctl->llist_info.next_free_idx = ret_idx;
+ ret_idx = UNASSIGNED_INDEX;
+ } else {
+ forced_wait = TRUE;
+ INIT_COMPLETION(pmhctl->mddi_llist_avail_comp);
+ }
+ }
+ spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+ if (forced_wait) {
+ wait_for_completion_killable(&
+ (pmhctl->
+ mddi_llist_avail_comp));
+ MDDI_MSG_ERR("task waiting on mddi llist item\n");
+ }
+
+ if (ret_idx != UNASSIGNED_INDEX) {
+ pmhctl->llist_notify[ret_idx].waiting = FALSE;
+ pmhctl->llist_notify[ret_idx].done_cb = NULL;
+ pmhctl->llist_notify[ret_idx].in_use = TRUE;
+ pmhctl->llist_notify[ret_idx].next_idx = UNASSIGNED_INDEX;
+ }
+
+ return ret_idx;
+}
+
+uint16 mddi_get_reg_read_llist_item(mddi_host_type host_idx, boolean wait)
+{
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+ MDDI_MSG_CRIT("No reverse link available\n");
+ (void)wait;
+ return FALSE;
+#else
+ unsigned long flags;
+ uint16 ret_idx;
+ boolean error = FALSE;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ spin_lock_irqsave(&mddi_host_spin_lock, flags);
+ if (pmhctl->llist_info.reg_read_idx != UNASSIGNED_INDEX) {
+ /* need to block here or is this an error condition? */
+ error = TRUE;
+ ret_idx = UNASSIGNED_INDEX;
+ }
+ spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+ if (!error) {
+ ret_idx = pmhctl->llist_info.reg_read_idx =
+ mddi_get_next_free_llist_item(host_idx, wait);
+ /* clear the reg_read_waiting flag */
+ pmhctl->llist_info.reg_read_waiting = FALSE;
+ }
+
+ if (error)
+ MDDI_MSG_ERR("***** Reg read still in progress! ****\n");
+ return ret_idx;
+#endif
+
+}
+
+void mddi_queue_forward_packets(uint16 first_llist_idx,
+ uint16 last_llist_idx,
+ boolean wait,
+ mddi_llist_done_cb_type llist_done_cb,
+ mddi_host_type host_idx)
+{
+ unsigned long flags;
+ mddi_linked_list_type *llist;
+ mddi_linked_list_type *llist_dma;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ if ((first_llist_idx >= UNASSIGNED_INDEX) ||
+ (last_llist_idx >= UNASSIGNED_INDEX)) {
+ MDDI_MSG_ERR("MDDI queueing invalid linked list\n");
+ return;
+ }
+
+ if (pmhctl->link_state == MDDI_LINK_DISABLED)
+ MDDI_MSG_CRIT("MDDI host powered down!\n");
+
+ llist = pmhctl->llist_ptr;
+ llist_dma = pmhctl->llist_dma_ptr;
+
+ /* clean cache so MDDI host can read data */
+ memory_barrier();
+
+ pmhctl->llist_notify[last_llist_idx].waiting = wait;
+ if (wait)
+ INIT_COMPLETION(pmhctl->llist_notify[last_llist_idx].done_comp);
+ pmhctl->llist_notify[last_llist_idx].done_cb = llist_done_cb;
+
+ spin_lock_irqsave(&mddi_host_spin_lock, flags);
+
+ if ((pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) &&
+ (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) &&
+ (pmhctl->rev_state == MDDI_REV_IDLE)) {
+ /* no packets are currently transmitting */
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ if (first_llist_idx == pmhctl->llist_info.reg_read_idx) {
+ /* This is the special case where the packet is a register read. */
+ pmhctl->rev_state = MDDI_REV_REG_READ_ISSUED;
+ mddi_reg_read_retry = 0;
+ /* mddi_rev_reg_read_attempt = 1; */
+ }
+#endif
+ /* assign transmitting index values */
+ pmhctl->llist_info.transmitting_start_idx = first_llist_idx;
+ pmhctl->llist_info.transmitting_end_idx = last_llist_idx;
+
+ /* turn on clock(s), if they have been disabled */
+ mddi_host_enable_hclk();
+ mddi_host_enable_io_clock();
+ pmhctl->int_type.llist_ptr_write_1++;
+ /* Write to primary pointer register */
+ dma_coherent_pre_ops();
+ mddi_host_reg_out(PRI_PTR, &llist_dma[first_llist_idx]);
+
+ /* enable interrupt when complete */
+ mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE,
+ MDDI_INT_PRI_LINK_LIST_DONE);
+
+ } else if (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) {
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ if (first_llist_idx == pmhctl->llist_info.reg_read_idx) {
+ /*
+ * we have a register read to send but need to wait
+ * for current reverse activity to end or there are
+ * packets currently transmitting
+ */
+ /* mddi_rev_reg_read_attempt = 0; */
+ pmhctl->llist_info.reg_read_waiting = TRUE;
+ }
+#endif
+
+ /* assign waiting index values */
+ pmhctl->llist_info.waiting_start_idx = first_llist_idx;
+ pmhctl->llist_info.waiting_end_idx = last_llist_idx;
+ } else {
+ uint16 prev_end_idx = pmhctl->llist_info.waiting_end_idx;
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ if (first_llist_idx == pmhctl->llist_info.reg_read_idx) {
+ /*
+ * we have a register read to send but need to wait
+ * for current reverse activity to end or there are
+ * packets currently transmitting
+ */
+ /* mddi_rev_reg_read_attempt = 0; */
+ pmhctl->llist_info.reg_read_waiting = TRUE;
+ }
+#endif
+
+ llist = pmhctl->llist_ptr;
+
+ /* clear end flag in previous last packet */
+ llist[prev_end_idx].link_controller_flags = 0;
+ pmhctl->llist_notify[prev_end_idx].next_idx = first_llist_idx;
+
+ /* set the next_packet_pointer of the previous last packet */
+ llist[prev_end_idx].next_packet_pointer =
+ (void *)(&llist_dma[first_llist_idx]);
+
+ /* clean cache so MDDI host can read data */
+ memory_barrier();
+
+ /* assign new waiting last index value */
+ pmhctl->llist_info.waiting_end_idx = last_llist_idx;
+ }
+
+ spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+}
+
+void mddi_host_write_pix_attr_reg(uint32 value)
+{
+ (void)value;
+}
+
+void mddi_queue_reverse_encapsulation(boolean wait)
+{
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+ MDDI_MSG_CRIT("No reverse link available\n");
+ (void)wait;
+#else
+ unsigned long flags;
+ boolean error = FALSE;
+ mddi_host_type host_idx = MDDI_HOST_PRIM;
+ mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]);
+
+ spin_lock_irqsave(&mddi_host_spin_lock, flags);
+
+ /* turn on clock(s), if they have been disabled */
+ mddi_host_enable_hclk();
+ mddi_host_enable_io_clock();
+
+ if (wait) {
+ if (!mddi_rev_user.waiting) {
+ mddi_rev_user.waiting = TRUE;
+ INIT_COMPLETION(mddi_rev_user.done_comp);
+ } else
+ error = TRUE;
+ }
+ mddi_rev_encap_user_request = TRUE;
+
+ if (pmhctl->rev_state == MDDI_REV_IDLE) {
+ /* attempt to send the reverse encapsulation now */
+ mddi_host_type orig_host_idx = mddi_curr_host;
+ mddi_curr_host = host_idx;
+ mddi_issue_reverse_encapsulation();
+ mddi_curr_host = orig_host_idx;
+ }
+ spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+ if (error) {
+ MDDI_MSG_ERR("Reverse Encap request already in progress\n");
+ } else if (wait)
+ wait_for_completion_killable(&(mddi_rev_user.done_comp));
+#endif
+}
+
+/* ISR to be executed */
+boolean mddi_set_rev_handler(mddi_rev_handler_type handler, uint16 pkt_type)
+{
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+ MDDI_MSG_CRIT("No reverse link available\n");
+ (void)handler;
+ (void)pkt_type;
+ return (FALSE);
+#else
+ unsigned long flags;
+ uint16 hdlr;
+ boolean handler_set = FALSE;
+ boolean overwrite = FALSE;
+ mddi_host_type host_idx = MDDI_HOST_PRIM;
+ mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]);
+
+ /* Disable interrupts */
+ spin_lock_irqsave(&mddi_host_spin_lock, flags);
+
+ for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; hdlr++) {
+ if (mddi_rev_pkt_handler[hdlr].pkt_type == pkt_type) {
+ mddi_rev_pkt_handler[hdlr].handler = handler;
+ if (handler == NULL) {
+ /* clearing handler from table */
+ mddi_rev_pkt_handler[hdlr].pkt_type =
+ INVALID_PKT_TYPE;
+ handler_set = TRUE;
+ if (pkt_type == 0x10) { /* video stream packet */
+ /* ensure HCLK on to MDDI host core before register write */
+ mddi_host_enable_hclk();
+ /* No longer getting video, so reset rev encap size to default */
+ pmhctl->rev_pkt_size =
+ MDDI_DEFAULT_REV_PKT_SIZE;
+ mddi_host_reg_out(REV_ENCAP_SZ,
+ pmhctl->rev_pkt_size);
+ }
+ } else {
+ /* already a handler for this packet */
+ overwrite = TRUE;
+ }
+ break;
+ }
+ }
+ if ((hdlr >= MAX_MDDI_REV_HANDLERS) && (handler != NULL)) {
+ /* assigning new handler */
+ for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; hdlr++) {
+ if (mddi_rev_pkt_handler[hdlr].pkt_type ==
+ INVALID_PKT_TYPE) {
+ if ((pkt_type == 0x10) && /* video stream packet */
+ (pmhctl->rev_pkt_size <
+ MDDI_VIDEO_REV_PKT_SIZE)) {
+ /* ensure HCLK on to MDDI host core before register write */
+ mddi_host_enable_hclk();
+ /* Increase Rev Encap Size */
+ pmhctl->rev_pkt_size =
+ MDDI_VIDEO_REV_PKT_SIZE;
+ mddi_host_reg_out(REV_ENCAP_SZ,
+ pmhctl->rev_pkt_size);
+ }
+ mddi_rev_pkt_handler[hdlr].handler = handler;
+ mddi_rev_pkt_handler[hdlr].pkt_type = pkt_type;
+ handler_set = TRUE;
+ break;
+ }
+ }
+ }
+
+ /* Restore interrupts */
+ spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+ if (overwrite)
+ MDDI_MSG_ERR("Overwriting previous rev packet handler\n");
+
+ return handler_set;
+
+#endif
+} /* mddi_set_rev_handler */
+
+void mddi_host_disable_hibernation(boolean disable)
+{
+ mddi_host_type host_idx = MDDI_HOST_PRIM;
+ mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]);
+
+ if (disable) {
+ pmhctl->disable_hibernation = TRUE;
+ /* hibernation will be turned off by isr next time it is entered */
+ } else {
+ if (pmhctl->disable_hibernation) {
+ unsigned long flags;
+ spin_lock_irqsave(&mddi_host_spin_lock, flags);
+ if (!MDDI_HOST_IS_HCLK_ON)
+ MDDI_HOST_ENABLE_HCLK;
+ mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
+ spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+ pmhctl->disable_hibernation = FALSE;
+ }
+ }
+}
+
+void mddi_mhctl_remove(mddi_host_type host_idx)
+{
+ mddi_host_cntl_type *pmhctl;
+
+ pmhctl = &(mhctl[host_idx]);
+
+ dma_free_coherent(NULL, MDDI_LLIST_POOL_SIZE, (void *)pmhctl->llist_ptr,
+ pmhctl->llist_dma_addr);
+
+ dma_free_coherent(NULL, MDDI_MAX_REV_DATA_SIZE,
+ (void *)pmhctl->rev_data_buf,
+ pmhctl->rev_data_dma_addr);
+}
diff --git a/drivers/video/msm/mddihosti.h b/drivers/video/msm/mddihosti.h
new file mode 100644
index 0000000..166d15c
--- /dev/null
+++ b/drivers/video/msm/mddihosti.h
@@ -0,0 +1,552 @@
+/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MDDIHOSTI_H
+#define MDDIHOSTI_H
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include <linux/clk.h>
+
+/* Register offsets in MDDI, applies to both msm_pmdh_base and
+ * (u32)msm_emdh_base. */
+#define MDDI_CMD 0x0000
+#define MDDI_VERSION 0x0004
+#define MDDI_PRI_PTR 0x0008
+#define MDDI_BPS 0x0010
+#define MDDI_SPM 0x0014
+#define MDDI_INT 0x0018
+#define MDDI_INTEN 0x001c
+#define MDDI_REV_PTR 0x0020
+#define MDDI_REV_SIZE 0x0024
+#define MDDI_STAT 0x0028
+#define MDDI_REV_RATE_DIV 0x002c
+#define MDDI_REV_CRC_ERR 0x0030
+#define MDDI_TA1_LEN 0x0034
+#define MDDI_TA2_LEN 0x0038
+#define MDDI_TEST 0x0040
+#define MDDI_REV_PKT_CNT 0x0044
+#define MDDI_DRIVE_HI 0x0048
+#define MDDI_DRIVE_LO 0x004c
+#define MDDI_DISP_WAKE 0x0050
+#define MDDI_REV_ENCAP_SZ 0x0054
+#define MDDI_RTD_VAL 0x0058
+#define MDDI_PAD_CTL 0x0068
+#define MDDI_DRIVER_START_CNT 0x006c
+#define MDDI_CORE_VER 0x008c
+#define MDDI_FIFO_ALLOC 0x0090
+#define MDDI_PAD_IO_CTL 0x00a0
+#define MDDI_PAD_CAL 0x00a4
+
+#ifdef ENABLE_MDDI_MULTI_READ_WRITE
+#define MDDI_HOST_MAX_CLIENT_REG_IN_SAME_ADDR 128
+#else
+#define MDDI_HOST_MAX_CLIENT_REG_IN_SAME_ADDR 1
+#endif
+
+extern int32 mddi_client_type;
+extern u32 mddi_msg_level;
+
+/* No longer need to write to clear these registers */
+#define xxxx_mddi_host_reg_outm(reg, mask, val) \
+do { \
+ if (host_idx == MDDI_HOST_PRIM) \
+ mddi_host_reg_outm_pmdh(reg, mask, val); \
+ else \
+ mddi_host_reg_outm_emdh(reg, mask, val); \
+} while (0)
+
+#define mddi_host_reg_outm(reg, mask, val) \
+do { \
+ unsigned long __addr; \
+ if (host_idx == MDDI_HOST_PRIM) \
+ __addr = (u32)msm_pmdh_base + MDDI_##reg; \
+ else \
+ __addr = (u32)msm_emdh_base + MDDI_##reg; \
+ writel((readl(__addr) & ~(mask)) | ((val) & (mask)), __addr); \
+} while (0)
+
+#define xxxx_mddi_host_reg_out(reg, val) \
+do { \
+ if (host_idx == MDDI_HOST_PRIM) \
+ mddi_host_reg_out_pmdh(reg, val); \
+ else \
+ mddi_host_reg_out_emdh(reg, val); \
+ } while (0)
+
+#define mddi_host_reg_out(reg, val) \
+do { \
+ if (host_idx == MDDI_HOST_PRIM) \
+ writel(val, (u32)msm_pmdh_base + MDDI_##reg); \
+ else \
+ writel(val, (u32)msm_emdh_base + MDDI_##reg); \
+} while (0)
+
+#define xxxx_mddi_host_reg_in(reg) \
+ ((host_idx) ? \
+ mddi_host_reg_in_emdh(reg) : mddi_host_reg_in_pmdh(reg));
+
+#define mddi_host_reg_in(reg) \
+((host_idx) ? \
+ readl((u32)msm_emdh_base + MDDI_##reg) : \
+ readl((u32)msm_pmdh_base + MDDI_##reg)) \
+
+#define xxxx_mddi_host_reg_inm(reg, mask) \
+ ((host_idx) ? \
+ mddi_host_reg_inm_emdh(reg, mask) : \
+ mddi_host_reg_inm_pmdh(reg, mask);)
+
+#define mddi_host_reg_inm(reg, mask) \
+((host_idx) ? \
+ readl((u32)msm_emdh_base + MDDI_##reg) & (mask) : \
+ readl((u32)msm_pmdh_base + MDDI_##reg) & (mask)) \
+
+/* Using non-cacheable pmem, so do nothing */
+#define mddi_invalidate_cache_lines(addr_start, num_bytes)
+/*
+ * Using non-cacheable pmem, so do nothing with cache
+ * but, ensure write goes out to memory
+ */
+#define mddi_flush_cache_lines(addr_start, num_bytes) \
+ (void) addr_start; \
+ (void) num_bytes; \
+ memory_barrier()
+
+/* Since this translates to Remote Procedure Calls to check on clock status
+* just use a local variable to keep track of io_clock */
+#define MDDI_HOST_IS_IO_CLOCK_ON mddi_host_io_clock_on
+#define MDDI_HOST_ENABLE_IO_CLOCK
+#define MDDI_HOST_DISABLE_IO_CLOCK
+#define MDDI_HOST_IS_HCLK_ON mddi_host_hclk_on
+#define MDDI_HOST_ENABLE_HCLK
+#define MDDI_HOST_DISABLE_HCLK
+#define FEATURE_MDDI_HOST_IO_CLOCK_CONTROL_DISABLE
+#define FEATURE_MDDI_HOST_HCLK_CONTROL_DISABLE
+
+#define TRAMP_MDDI_HOST_ISR TRAMP_MDDI_PRI_ISR
+#define TRAMP_MDDI_HOST_EXT_ISR TRAMP_MDDI_EXT_ISR
+#define MDP_LINE_COUNT_BMSK 0x3ff
+#define MDP_SYNC_STATUS 0x000c
+#define MDP_LINE_COUNT \
+(readl(msm_mdp_base + MDP_SYNC_STATUS) & MDP_LINE_COUNT_BMSK)
+
+/* MDP sends 256 pixel packets, so lower value hibernates more without
+* significantly increasing latency of waiting for next subframe */
+#define MDDI_HOST_BYTES_PER_SUBFRAME 0x3C00
+
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
+#define MDDI_HOST_TA2_LEN 0x001a
+#define MDDI_HOST_REV_RATE_DIV 0x0004
+#else
+#define MDDI_HOST_TA2_LEN 0x000c
+#define MDDI_HOST_REV_RATE_DIV 0x0002
+#endif
+
+#define MDDI_MSG_EMERG(msg, ...) \
+ if (mddi_msg_level > 0) \
+ printk(KERN_EMERG msg, ## __VA_ARGS__);
+#define MDDI_MSG_ALERT(msg, ...) \
+ if (mddi_msg_level > 1) \
+ printk(KERN_ALERT msg, ## __VA_ARGS__);
+#define MDDI_MSG_CRIT(msg, ...) \
+ if (mddi_msg_level > 2) \
+ printk(KERN_CRIT msg, ## __VA_ARGS__);
+#define MDDI_MSG_ERR(msg, ...) \
+ if (mddi_msg_level > 3) \
+ printk(KERN_ERR msg, ## __VA_ARGS__);
+#define MDDI_MSG_WARNING(msg, ...) \
+ if (mddi_msg_level > 4) \
+ printk(KERN_WARNING msg, ## __VA_ARGS__);
+#define MDDI_MSG_NOTICE(msg, ...) \
+ if (mddi_msg_level > 5) \
+ printk(KERN_NOTICE msg, ## __VA_ARGS__);
+#define MDDI_MSG_INFO(msg, ...) \
+ if (mddi_msg_level > 6) \
+ printk(KERN_INFO msg, ## __VA_ARGS__);
+#define MDDI_MSG_DEBUG(msg, ...) \
+ if (mddi_msg_level > 7) \
+ printk(KERN_DEBUG msg, ## __VA_ARGS__);
+
+#define GCC_PACKED __attribute__((packed))
+typedef struct GCC_PACKED {
+ uint16 packet_length;
+ /* total # of bytes in the packet not including
+ the packet_length field. */
+
+ uint16 packet_type;
+ /* A Packet Type of 70 identifies the packet as
+ a Client status Packet. */
+
+ uint16 bClient_ID;
+ /* This field is reserved for future use and shall
+ be set to zero. */
+
+} mddi_rev_packet_type;
+
+typedef struct GCC_PACKED {
+ uint16 packet_length;
+ /* total # of bytes in the packet not including
+ the packet_length field. */
+
+ uint16 packet_type;
+ /* A Packet Type of 70 identifies the packet as
+ a Client status Packet. */
+
+ uint16 bClient_ID;
+ /* This field is reserved for future use and shall
+ be set to zero. */
+
+ uint16 reverse_link_request;
+ /* 16 bit unsigned integer with number of bytes client
+ needs in the * reverse encapsulation message
+ to transmit data. */
+
+ uint8 crc_error_count;
+ uint8 capability_change;
+ uint16 graphics_busy_flags;
+
+ uint16 parameter_CRC;
+ /* 16-bit CRC of all the bytes in the packet
+ including Packet Length. */
+
+} mddi_client_status_type;
+
+typedef struct GCC_PACKED {
+ uint16 packet_length;
+ /* total # of bytes in the packet not including
+ the packet_length field. */
+
+ uint16 packet_type;
+ /* A Packet Type of 66 identifies the packet as
+ a Client Capability Packet. */
+
+ uint16 bClient_ID;
+ /* This field is reserved for future use and
+ shall be set to zero. */
+
+ uint16 Protocol_Version;
+ uint16 Minimum_Protocol_Version;
+ uint16 Data_Rate_Capability;
+ uint8 Interface_Type_Capability;
+ uint8 Number_of_Alt_Displays;
+ uint16 PostCal_Data_Rate;
+ uint16 Bitmap_Width;
+ uint16 Bitmap_Height;
+ uint16 Display_Window_Width;
+ uint16 Display_Window_Height;
+ uint32 Color_Map_Size;
+ uint16 Color_Map_RGB_Width;
+ uint16 RGB_Capability;
+ uint8 Monochrome_Capability;
+ uint8 Reserved_1;
+ uint16 Y_Cb_Cr_Capability;
+ uint16 Bayer_Capability;
+ uint16 Alpha_Cursor_Image_Planes;
+ uint32 Client_Feature_Capability_Indicators;
+ uint8 Maximum_Video_Frame_Rate_Capability;
+ uint8 Minimum_Video_Frame_Rate_Capability;
+ uint16 Minimum_Sub_frame_Rate;
+ uint16 Audio_Buffer_Depth;
+ uint16 Audio_Channel_Capability;
+ uint16 Audio_Sample_Rate_Capability;
+ uint8 Audio_Sample_Resolution;
+ uint8 Mic_Audio_Sample_Resolution;
+ uint16 Mic_Sample_Rate_Capability;
+ uint8 Keyboard_Data_Format;
+ uint8 pointing_device_data_format;
+ uint16 content_protection_type;
+ uint16 Mfr_Name;
+ uint16 Product_Code;
+ uint16 Reserved_3;
+ uint32 Serial_Number;
+ uint8 Week_of_Manufacture;
+ uint8 Year_of_Manufacture;
+
+ uint16 parameter_CRC;
+ /* 16-bit CRC of all the bytes in the packet including Packet Length. */
+
+} mddi_client_capability_type;
+
+typedef struct GCC_PACKED {
+ uint16 packet_length;
+ /* total # of bytes in the packet not including the packet_length field. */
+
+ uint16 packet_type;
+ /* A Packet Type of 16 identifies the packet as a Video Stream Packet. */
+
+ uint16 bClient_ID;
+ /* This field is reserved for future use and shall be set to zero. */
+
+ uint16 video_data_format_descriptor;
+ /* format of each pixel in the Pixel Data in the present stream in the
+ * present packet.
+ * If bits [15:13] = 000 monochrome
+ * If bits [15:13] = 001 color pixels (palette).
+ * If bits [15:13] = 010 color pixels in raw RGB
+ * If bits [15:13] = 011 data in 4:2:2 Y Cb Cr format
+ * If bits [15:13] = 100 Bayer pixels
+ */
+
+ uint16 pixel_data_attributes;
+ /* interpreted as follows:
+ * Bits [1:0] = 11 pixel data is displayed to both eyes
+ * Bits [1:0] = 10 pixel data is routed to the left eye only.
+ * Bits [1:0] = 01 pixel data is routed to the right eye only.
+ * Bits [1:0] = 00 pixel data is routed to the alternate display.
+ * Bit 2 is 0 Pixel Data is in the standard progressive format.
+ * Bit 2 is 1 Pixel Data is in interlace format.
+ * Bit 3 is 0 Pixel Data is in the standard progressive format.
+ * Bit 3 is 1 Pixel Data is in alternate pixel format.
+ * Bit 4 is 0 Pixel Data is to or from the display frame buffer.
+ * Bit 4 is 1 Pixel Data is to or from the camera.
+ * Bit 5 is 0 pixel data contains the next consecutive row of pixels.
+ * Bit 5 is 1 X Left Edge, Y Top Edge, X Right Edge, Y Bottom Edge,
+ * X Start, and Y Start parameters are not defined and
+ * shall be ignored by the client.
+ * Bits [7:6] = 01 Pixel data is written to the offline image buffer.
+ * Bits [7:6] = 00 Pixel data is written to the buffer to refresh display.
+ * Bits [7:6] = 11 Pixel data is written to all image buffers.
+ * Bits [7:6] = 10 Invalid. Reserved for future use.
+ * Bits 8 through 11 alternate display number.
+ * Bits 12 through 14 are reserved for future use and shall be set to zero.
+ * Bit 15 is 1 the row of pixels is the last row of pixels in a frame.
+ */
+
+ uint16 x_left_edge;
+ uint16 y_top_edge;
+ /* X,Y coordinate of the top left edge of the screen window */
+
+ uint16 x_right_edge;
+ uint16 y_bottom_edge;
+ /* X,Y coordinate of the bottom right edge of the window being updated. */
+
+ uint16 x_start;
+ uint16 y_start;
+ /* (X Start, Y Start) is the first pixel in the Pixel Data field below. */
+
+ uint16 pixel_count;
+ /* number of pixels in the Pixel Data field below. */
+
+ uint16 parameter_CRC;
+ /* 16-bit CRC of all bytes from the Packet Length to the Pixel Count. */
+
+ uint16 reserved;
+ /* 16-bit variable to make structure align on 4 byte boundary */
+
+} mddi_video_stream_packet_type;
+
+typedef struct GCC_PACKED {
+ uint16 packet_length;
+ /* total # of bytes in the packet not including the packet_length field. */
+
+ uint16 packet_type;
+ /* A Packet Type of 146 identifies the packet as a Register Access Packet. */
+
+ uint16 bClient_ID;
+ /* This field is reserved for future use and shall be set to zero. */
+
+ uint16 read_write_info;
+ /* Bits 13:0 a 14-bit unsigned integer that specifies the number of
+ * 32-bit Register Data List items to be transferred in the
+ * Register Data List field.
+ * Bits[15:14] = 00 Write to register(s);
+ * Bits[15:14] = 10 Read from register(s);
+ * Bits[15:14] = 11 Response to a Read.
+ * Bits[15:14] = 01 this value is reserved for future use. */
+
+ uint32 register_address;
+ /* the register address that is to be written to or read from. */
+
+ uint16 parameter_CRC;
+ /* 16-bit CRC of all bytes from the Packet Length to the Register Address. */
+
+ uint32 register_data_list[MDDI_HOST_MAX_CLIENT_REG_IN_SAME_ADDR];
+ /* list of 4-byte register data values for/from client registers */
+ /* For multi-read/write, 512(128 * 4) bytes of data available */
+
+} mddi_register_access_packet_type;
+
+typedef union GCC_PACKED {
+ mddi_video_stream_packet_type video_pkt;
+ mddi_register_access_packet_type register_pkt;
+#ifdef ENABLE_MDDI_MULTI_READ_WRITE
+ /* add 1008 byte pad to ensure 1024 byte llist struct, that can be
+ * manipulated easily with cache */
+ uint32 alignment_pad[252]; /* 1008 bytes */
+#else
+ /* add 48 byte pad to ensure 64 byte llist struct, that can be
+ * manipulated easily with cache */
+ uint32 alignment_pad[12]; /* 48 bytes */
+#endif
+} mddi_packet_header_type;
+
+typedef struct GCC_PACKED mddi_host_llist_struct {
+ uint16 link_controller_flags;
+ uint16 packet_header_count;
+ uint16 packet_data_count;
+ void *packet_data_pointer;
+ struct mddi_host_llist_struct *next_packet_pointer;
+ uint16 reserved;
+ mddi_packet_header_type packet_header;
+} mddi_linked_list_type;
+
+typedef struct {
+ struct completion done_comp;
+ mddi_llist_done_cb_type done_cb;
+ uint16 next_idx;
+ boolean waiting;
+ boolean in_use;
+} mddi_linked_list_notify_type;
+
+#ifdef ENABLE_MDDI_MULTI_READ_WRITE
+#define MDDI_LLIST_POOL_SIZE 0x10000
+#else
+#define MDDI_LLIST_POOL_SIZE 0x1000
+#endif
+#define MDDI_MAX_NUM_LLIST_ITEMS (MDDI_LLIST_POOL_SIZE / \
+ sizeof(mddi_linked_list_type))
+#define UNASSIGNED_INDEX MDDI_MAX_NUM_LLIST_ITEMS
+#define MDDI_FIRST_DYNAMIC_LLIST_IDX 0
+
+/* Static llist items can be used for applications that frequently send
+ * the same set of packets using the linked list interface. */
+/* Here we configure for 6 static linked list items:
+ * The 1st is used for a the adaptive backlight setting.
+ * and the remaining 5 are used for sending window adjustments for
+ * MDDI clients that need windowing info sent separate from video
+ * packets. */
+#define MDDI_NUM_STATIC_ABL_ITEMS 1
+#define MDDI_NUM_STATIC_WINDOW_ITEMS 5
+#define MDDI_NUM_STATIC_LLIST_ITEMS (MDDI_NUM_STATIC_ABL_ITEMS + \
+ MDDI_NUM_STATIC_WINDOW_ITEMS)
+#define MDDI_NUM_DYNAMIC_LLIST_ITEMS (MDDI_MAX_NUM_LLIST_ITEMS - \
+ MDDI_NUM_STATIC_LLIST_ITEMS)
+
+#define MDDI_FIRST_STATIC_LLIST_IDX MDDI_NUM_DYNAMIC_LLIST_ITEMS
+#define MDDI_FIRST_STATIC_ABL_IDX MDDI_FIRST_STATIC_LLIST_IDX
+#define MDDI_FIRST_STATIC_WINDOW_IDX (MDDI_FIRST_STATIC_LLIST_IDX + \
+ MDDI_NUM_STATIC_ABL_ITEMS)
+
+/* GPIO registers */
+#define VSYNC_WAKEUP_REG 0x80
+#define GPIO_REG 0x81
+#define GPIO_OUTPUT_REG 0x82
+#define GPIO_INTERRUPT_REG 0x83
+#define GPIO_INTERRUPT_ENABLE_REG 0x84
+#define GPIO_POLARITY_REG 0x85
+
+/* Interrupt Bits */
+#define MDDI_INT_PRI_PTR_READ 0x0001
+#define MDDI_INT_SEC_PTR_READ 0x0002
+#define MDDI_INT_REV_DATA_AVAIL 0x0004
+#define MDDI_INT_DISP_REQ 0x0008
+#define MDDI_INT_PRI_UNDERFLOW 0x0010
+#define MDDI_INT_SEC_UNDERFLOW 0x0020
+#define MDDI_INT_REV_OVERFLOW 0x0040
+#define MDDI_INT_CRC_ERROR 0x0080
+#define MDDI_INT_MDDI_IN 0x0100
+#define MDDI_INT_PRI_OVERWRITE 0x0200
+#define MDDI_INT_SEC_OVERWRITE 0x0400
+#define MDDI_INT_REV_OVERWRITE 0x0800
+#define MDDI_INT_DMA_FAILURE 0x1000
+#define MDDI_INT_LINK_ACTIVE 0x2000
+#define MDDI_INT_IN_HIBERNATION 0x4000
+#define MDDI_INT_PRI_LINK_LIST_DONE 0x8000
+#define MDDI_INT_SEC_LINK_LIST_DONE 0x10000
+#define MDDI_INT_NO_CMD_PKTS_PEND 0x20000
+#define MDDI_INT_RTD_FAILURE 0x40000
+
+#define MDDI_INT_ERROR_CONDITIONS ( \
+ MDDI_INT_PRI_UNDERFLOW | MDDI_INT_SEC_UNDERFLOW | \
+ MDDI_INT_REV_OVERFLOW | MDDI_INT_CRC_ERROR | \
+ MDDI_INT_PRI_OVERWRITE | MDDI_INT_SEC_OVERWRITE | \
+ MDDI_INT_RTD_FAILURE | \
+ MDDI_INT_REV_OVERWRITE | MDDI_INT_DMA_FAILURE)
+
+#define MDDI_INT_LINK_STATE_CHANGES ( \
+ MDDI_INT_LINK_ACTIVE | MDDI_INT_IN_HIBERNATION)
+
+/* Status Bits */
+#define MDDI_STAT_LINK_ACTIVE 0x0001
+#define MDDI_STAT_NEW_REV_PTR 0x0002
+#define MDDI_STAT_NEW_PRI_PTR 0x0004
+#define MDDI_STAT_NEW_SEC_PTR 0x0008
+#define MDDI_STAT_IN_HIBERNATION 0x0010
+#define MDDI_STAT_PRI_LINK_LIST_DONE 0x0020
+#define MDDI_STAT_SEC_LINK_LIST_DONE 0x0040
+#define MDDI_STAT_PENDING_TIMING_PKT 0x0080
+#define MDDI_STAT_PENDING_REV_ENCAP 0x0100
+#define MDDI_STAT_PENDING_POWERDOWN 0x0200
+#define MDDI_STAT_RTD_MEAS_FAIL 0x0800
+#define MDDI_STAT_CLIENT_WAKEUP_REQ 0x1000
+
+/* Command Bits */
+#define MDDI_CMD_POWERDOWN 0x0100
+#define MDDI_CMD_POWERUP 0x0200
+#define MDDI_CMD_HIBERNATE 0x0300
+#define MDDI_CMD_RESET 0x0400
+#define MDDI_CMD_DISP_IGNORE 0x0501
+#define MDDI_CMD_DISP_LISTEN 0x0500
+#define MDDI_CMD_SEND_REV_ENCAP 0x0600
+#define MDDI_CMD_GET_CLIENT_CAP 0x0601
+#define MDDI_CMD_GET_CLIENT_STATUS 0x0602
+#define MDDI_CMD_SEND_RTD 0x0700
+#define MDDI_CMD_LINK_ACTIVE 0x0900
+#define MDDI_CMD_PERIODIC_REV_ENCAP 0x0A00
+#define MDDI_CMD_FW_LINK_SKEW_CAL 0x0D00
+
+extern void mddi_host_init(mddi_host_type host);
+extern void mddi_host_powerdown(mddi_host_type host);
+extern uint16 mddi_get_next_free_llist_item(mddi_host_type host, boolean wait);
+extern uint16 mddi_get_reg_read_llist_item(mddi_host_type host, boolean wait);
+extern void mddi_queue_forward_packets(uint16 first_llist_idx,
+ uint16 last_llist_idx,
+ boolean wait,
+ mddi_llist_done_cb_type llist_done_cb,
+ mddi_host_type host);
+
+extern void mddi_host_write_pix_attr_reg(uint32 value);
+extern void mddi_client_lcd_gpio_poll(uint32 poll_reg_val);
+extern void mddi_client_lcd_vsync_detected(boolean detected);
+extern void mddi_host_disable_hibernation(boolean disable);
+
+extern mddi_linked_list_type *llist_extern[];
+extern mddi_linked_list_type *llist_dma_extern[];
+extern mddi_linked_list_notify_type *llist_extern_notify[];
+extern struct timer_list mddi_host_timer;
+
+typedef struct {
+ uint16 transmitting_start_idx;
+ uint16 transmitting_end_idx;
+ uint16 waiting_start_idx;
+ uint16 waiting_end_idx;
+ uint16 reg_read_idx;
+ uint16 next_free_idx;
+ boolean reg_read_waiting;
+} mddi_llist_info_type;
+
+extern mddi_llist_info_type mddi_llist;
+
+#define MDDI_GPIO_DEFAULT_POLLING_INTERVAL 200
+typedef struct {
+ uint32 polling_reg;
+ uint32 polling_val;
+ uint32 polling_interval;
+ boolean polling_enabled;
+} mddi_gpio_info_type;
+
+uint32 mddi_get_client_id(void);
+void mddi_mhctl_remove(mddi_host_type host_idx);
+void mddi_host_timer_service(unsigned long data);
+void mddi_host_client_cnt_reset(void);
+#endif /* MDDIHOSTI_H */
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index c3636d5..8df57ae 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -2,7 +2,7 @@
*
* MSM MDP Interface (used by framebuffer core)
*
- * Copyright (C) 2007 QUALCOMM Incorporated
+ * Copyright (c) 2007-2011, Code Aurora Forum. All rights reserved.
* Copyright (C) 2007 Google Incorporated
*
* This software is licensed under the terms of the GNU General Public
@@ -15,507 +15,1659 @@
* GNU General Public License for more details.
*/
+#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/fb.h>
-#include <linux/msm_mdp.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
#include <linux/interrupt.h>
-#include <linux/wait.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
#include <linux/clk.h>
-#include <linux/file.h>
-#include <linux/major.h>
-#include <linux/slab.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
-#include <mach/msm_iomap.h>
-#include <mach/msm_fb.h>
-#include <linux/platform_device.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <mach/clk.h>
+#include "mdp.h"
+#include "msm_fb.h"
+#ifdef CONFIG_FB_MSM_MDP40
+#include "mdp4.h"
+#endif
+#include "mipi_dsi.h"
-#include "mdp_hw.h"
+uint32 mdp4_extn_disp;
-struct class *mdp_class;
+static struct clk *mdp_clk;
+static struct clk *mdp_pclk;
+static struct clk *mdp_axi_clk;
+static struct clk *mdp_lut_clk;
+int mdp_rev;
-#define MDP_CMD_DEBUG_ACCESS_BASE (0x10000)
+struct regulator *footswitch;
-static uint16_t mdp_default_ccs[] = {
- 0x254, 0x000, 0x331, 0x254, 0xF38, 0xE61, 0x254, 0x409, 0x000,
- 0x010, 0x080, 0x080
-};
+struct completion mdp_ppp_comp;
+struct semaphore mdp_ppp_mutex;
+struct semaphore mdp_pipe_ctrl_mutex;
-static DECLARE_WAIT_QUEUE_HEAD(mdp_dma2_waitqueue);
-static DECLARE_WAIT_QUEUE_HEAD(mdp_ppp_waitqueue);
-static struct msmfb_callback *dma_callback;
-static struct clk *clk;
-static unsigned int mdp_irq_mask;
-static DEFINE_SPINLOCK(mdp_lock);
-DEFINE_MUTEX(mdp_mutex);
+unsigned long mdp_timer_duration = (HZ/20); /* 50 msecond */
-static int enable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
+boolean mdp_ppp_waiting = FALSE;
+uint32 mdp_tv_underflow_cnt;
+uint32 mdp_lcdc_underflow_cnt;
+
+boolean mdp_current_clk_on = FALSE;
+boolean mdp_is_in_isr = FALSE;
+
+/*
+ * legacy mdp_in_processing is only for DMA2-MDDI
+ * this applies to DMA2 block only
+ */
+uint32 mdp_in_processing = FALSE;
+
+#ifdef CONFIG_FB_MSM_MDP40
+uint32 mdp_intr_mask = MDP4_ANY_INTR_MASK;
+#else
+uint32 mdp_intr_mask = MDP_ANY_INTR_MASK;
+#endif
+
+MDP_BLOCK_TYPE mdp_debug[MDP_MAX_BLOCK];
+
+atomic_t mdp_block_power_cnt[MDP_MAX_BLOCK];
+
+spinlock_t mdp_spin_lock;
+struct workqueue_struct *mdp_dma_wq; /*mdp dma wq */
+struct workqueue_struct *mdp_vsync_wq; /*mdp vsync wq */
+
+static struct workqueue_struct *mdp_pipe_ctrl_wq; /* mdp mdp pipe ctrl wq */
+static struct delayed_work mdp_pipe_ctrl_worker;
+
+static boolean mdp_suspended = FALSE;
+DEFINE_MUTEX(mdp_suspend_mutex);
+
+#ifdef CONFIG_FB_MSM_MDP40
+struct mdp_dma_data dma2_data;
+struct mdp_dma_data dma_s_data;
+struct mdp_dma_data dma_e_data;
+ulong mdp4_display_intf;
+#else
+static struct mdp_dma_data dma2_data;
+static struct mdp_dma_data dma_s_data;
+#ifndef CONFIG_FB_MSM_MDP303
+static struct mdp_dma_data dma_e_data;
+#endif
+#endif
+static struct mdp_dma_data dma3_data;
+
+extern ktime_t mdp_dma2_last_update_time;
+
+extern uint32 mdp_dma2_update_time_in_usec;
+extern int mdp_lcd_rd_cnt_offset_slow;
+extern int mdp_lcd_rd_cnt_offset_fast;
+extern int mdp_usec_diff_threshold;
+
+#ifdef CONFIG_FB_MSM_LCDC
+extern int first_pixel_start_x;
+extern int first_pixel_start_y;
+#endif
+
+#ifdef MSM_FB_ENABLE_DBGFS
+struct dentry *mdp_dir;
+#endif
+
+#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
+static int mdp_suspend(struct platform_device *pdev, pm_message_t state);
+#else
+#define mdp_suspend NULL
+#endif
+
+struct timeval mdp_dma2_timeval;
+struct timeval mdp_ppp_timeval;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static struct early_suspend early_suspend;
+#endif
+
+static u32 mdp_irq;
+
+static uint32 mdp_prim_panel_type = NO_PANEL;
+#ifndef CONFIG_FB_MSM_MDP22
+DEFINE_MUTEX(mdp_lut_push_sem);
+static int mdp_lut_i;
+static int mdp_lut_hw_update(struct fb_cmap *cmap)
{
- unsigned long irq_flags;
- int ret = 0;
+ int i;
+ u16 *c[3];
+ u16 r, g, b;
- BUG_ON(!mask);
+ c[0] = cmap->green;
+ c[1] = cmap->blue;
+ c[2] = cmap->red;
- spin_lock_irqsave(&mdp_lock, irq_flags);
- /* if the mask bits are already set return an error, this interrupt
- * is already enabled */
- if (mdp_irq_mask & mask) {
- printk(KERN_ERR "mdp irq already on already on %x %x\n",
- mdp_irq_mask, mask);
- ret = -1;
- }
- /* if the mdp irq is not already enabled enable it */
- if (!mdp_irq_mask) {
- if (clk)
- clk_enable(clk);
- enable_irq(mdp->irq);
+ for (i = 0; i < cmap->len; i++) {
+ if (copy_from_user(&r, cmap->red++, sizeof(r)) ||
+ copy_from_user(&g, cmap->green++, sizeof(g)) ||
+ copy_from_user(&b, cmap->blue++, sizeof(b)))
+ return -EFAULT;
+
+#ifdef CONFIG_FB_MSM_MDP40
+ MDP_OUTP(MDP_BASE + 0x94800 +
+#else
+ MDP_OUTP(MDP_BASE + 0x93800 +
+#endif
+ (0x400*mdp_lut_i) + cmap->start*4 + i*4,
+ ((g & 0xff) |
+ ((b & 0xff) << 8) |
+ ((r & 0xff) << 16)));
}
- /* update the irq mask to reflect the fact that the interrupt is
- * enabled */
- mdp_irq_mask |= mask;
- spin_unlock_irqrestore(&mdp_lock, irq_flags);
- return ret;
+ return 0;
}
-static int locked_disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
+static int mdp_lut_push;
+static int mdp_lut_push_i;
+static int mdp_lut_update_nonlcdc(struct fb_info *info, struct fb_cmap *cmap)
{
- /* this interrupt is already disabled! */
- if (!(mdp_irq_mask & mask)) {
- printk(KERN_ERR "mdp irq already off %x %x\n",
- mdp_irq_mask, mask);
- return -1;
+ int ret;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ ret = mdp_lut_hw_update(cmap);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ if (ret)
+ return ret;
+
+ mutex_lock(&mdp_lut_push_sem);
+ mdp_lut_push = 1;
+ mdp_lut_push_i = mdp_lut_i;
+ mutex_unlock(&mdp_lut_push_sem);
+
+ mdp_lut_i = (mdp_lut_i + 1)%2;
+
+ return 0;
+}
+
+static int mdp_lut_update_lcdc(struct fb_info *info, struct fb_cmap *cmap)
+{
+ int ret;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ ret = mdp_lut_hw_update(cmap);
+
+ if (ret) {
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ return ret;
}
- /* update the irq mask to reflect the fact that the interrupt is
- * disabled */
- mdp_irq_mask &= ~(mask);
- /* if no one is waiting on the interrupt, disable it */
- if (!mdp_irq_mask) {
- disable_irq_nosync(mdp->irq);
- if (clk)
- clk_disable(clk);
+
+ MDP_OUTP(MDP_BASE + 0x90070, (mdp_lut_i << 10) | 0x17);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ mdp_lut_i = (mdp_lut_i + 1)%2;
+
+ return 0;
+}
+
+static void mdp_lut_enable(void)
+{
+ if (mdp_lut_push) {
+ mutex_lock(&mdp_lut_push_sem);
+ mdp_lut_push = 0;
+ MDP_OUTP(MDP_BASE + 0x90070,
+ (mdp_lut_push_i << 10) | 0x17);
+ mutex_unlock(&mdp_lut_push_sem);
+ }
+}
+
+#define MDP_HIST_MAX_BIN 32
+static __u32 mdp_hist_r[MDP_HIST_MAX_BIN];
+static __u32 mdp_hist_g[MDP_HIST_MAX_BIN];
+static __u32 mdp_hist_b[MDP_HIST_MAX_BIN];
+
+#ifdef CONFIG_FB_MSM_MDP40
+struct mdp_histogram mdp_hist;
+struct completion mdp_hist_comp;
+boolean mdp_is_hist_start = FALSE;
+#else
+static struct mdp_histogram mdp_hist;
+static struct completion mdp_hist_comp;
+static boolean mdp_is_hist_start = FALSE;
+#endif
+static DEFINE_MUTEX(mdp_hist_mutex);
+
+int mdp_histogram_ctrl(boolean en)
+{
+ unsigned long flag;
+ boolean hist_start;
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ hist_start = mdp_is_hist_start;
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+ if (hist_start == TRUE) {
+ if (en == TRUE) {
+ mdp_enable_irq(MDP_HISTOGRAM_TERM);
+ mdp_hist.frame_cnt = 1;
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+#ifdef CONFIG_FB_MSM_MDP40
+ MDP_OUTP(MDP_BASE + 0x95010, 1);
+ MDP_OUTP(MDP_BASE + 0x9501c, INTR_HIST_DONE);
+ MDP_OUTP(MDP_BASE + 0x95004, 1);
+ MDP_OUTP(MDP_BASE + 0x95000, 1);
+#else
+ MDP_OUTP(MDP_BASE + 0x94004, 1);
+ MDP_OUTP(MDP_BASE + 0x94000, 1);
+#endif
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF,
+ FALSE);
+ } else
+ mdp_disable_irq(MDP_HISTOGRAM_TERM);
}
return 0;
}
-static int disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
+int mdp_start_histogram(struct fb_info *info)
{
- unsigned long irq_flags;
- int ret;
+ unsigned long flag;
- spin_lock_irqsave(&mdp_lock, irq_flags);
- ret = locked_disable_mdp_irq(mdp, mask);
- spin_unlock_irqrestore(&mdp_lock, irq_flags);
+ int ret = 0;
+ mutex_lock(&mdp_hist_mutex);
+ if (mdp_is_hist_start == TRUE) {
+ printk(KERN_ERR "%s histogram already started\n", __func__);
+ ret = -EPERM;
+ goto mdp_hist_start_err;
+ }
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_is_hist_start = TRUE;
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ mdp_enable_irq(MDP_HISTOGRAM_TERM);
+ mdp_hist.frame_cnt = 1;
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+#ifdef CONFIG_FB_MSM_MDP40
+ MDP_OUTP(MDP_BASE + 0x95004, 1);
+ MDP_OUTP(MDP_BASE + 0x95000, 1);
+#else
+ MDP_OUTP(MDP_BASE + 0x94004, 1);
+ MDP_OUTP(MDP_BASE + 0x94000, 1);
+#endif
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+mdp_hist_start_err:
+ mutex_unlock(&mdp_hist_mutex);
+ return ret;
+
+}
+int mdp_stop_histogram(struct fb_info *info)
+{
+ unsigned long flag;
+ int ret = 0;
+ mutex_lock(&mdp_hist_mutex);
+ if (!mdp_is_hist_start) {
+ printk(KERN_ERR "%s histogram already stopped\n", __func__);
+ ret = -EPERM;
+ goto mdp_hist_stop_err;
+ }
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_is_hist_start = FALSE;
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ /* disable the irq for histogram since we handled it
+ when the control reaches here */
+ mdp_disable_irq(MDP_HISTOGRAM_TERM);
+
+mdp_hist_stop_err:
+ mutex_unlock(&mdp_hist_mutex);
return ret;
}
-static irqreturn_t mdp_isr(int irq, void *data)
+static int mdp_do_histogram(struct fb_info *info, struct mdp_histogram *hist)
{
- uint32_t status;
- unsigned long irq_flags;
- struct mdp_info *mdp = data;
+ int ret = 0;
- spin_lock_irqsave(&mdp_lock, irq_flags);
+ if (!hist->frame_cnt || (hist->bin_cnt == 0) ||
+ (hist->bin_cnt > MDP_HIST_MAX_BIN))
+ return -EINVAL;
+ mutex_lock(&mdp_hist_mutex);
+ if (!mdp_is_hist_start) {
+ printk(KERN_ERR "%s histogram not started\n", __func__);
+ mutex_unlock(&mdp_hist_mutex);
+ return -EPERM;
+ }
+ mutex_unlock(&mdp_hist_mutex);
- status = mdp_readl(mdp, MDP_INTR_STATUS);
- mdp_writel(mdp, status, MDP_INTR_CLEAR);
+ INIT_COMPLETION(mdp_hist_comp);
- status &= mdp_irq_mask;
- if (status & DL0_DMA2_TERM_DONE) {
- if (dma_callback) {
- dma_callback->func(dma_callback);
- dma_callback = NULL;
- }
- wake_up(&mdp_dma2_waitqueue);
+ mdp_hist.bin_cnt = hist->bin_cnt;
+ mdp_hist.frame_cnt = hist->frame_cnt;
+ mdp_hist.r = (hist->r) ? mdp_hist_r : 0;
+ mdp_hist.g = (hist->g) ? mdp_hist_g : 0;
+ mdp_hist.b = (hist->b) ? mdp_hist_b : 0;
+
+ wait_for_completion_killable(&mdp_hist_comp);
+
+ if (hist->r) {
+ ret = copy_to_user(hist->r, mdp_hist.r, hist->bin_cnt*4);
+ if (ret)
+ goto hist_err;
+ }
+ if (hist->g) {
+ ret = copy_to_user(hist->g, mdp_hist.g, hist->bin_cnt*4);
+ if (ret)
+ goto hist_err;
+ }
+ if (hist->b) {
+ ret = copy_to_user(hist->b, mdp_hist.b, hist->bin_cnt*4);
+ if (ret)
+ goto hist_err;
+ }
+ return 0;
+
+hist_err:
+ printk(KERN_ERR "%s: invalid hist buffer\n", __func__);
+ return ret;
+}
+#endif
+
+/* Returns < 0 on error, 0 on timeout, or > 0 on successful wait */
+
+int mdp_ppp_pipe_wait(void)
+{
+ int ret = 1;
+
+ /* wait 5 seconds for the operation to complete before declaring
+ the MDP hung */
+
+ if (mdp_ppp_waiting == TRUE) {
+ ret = wait_for_completion_interruptible_timeout(&mdp_ppp_comp,
+ 5 * HZ);
+
+ if (!ret)
+ printk(KERN_ERR "%s: Timed out waiting for the MDP.\n",
+ __func__);
}
- if (status & DL0_ROI_DONE)
- wake_up(&mdp_ppp_waitqueue);
+ return ret;
+}
- if (status)
- locked_disable_mdp_irq(mdp, status);
+static DEFINE_SPINLOCK(mdp_lock);
+static int mdp_irq_mask;
+static int mdp_irq_enabled;
+/*
+ * mdp_enable_irq: can not be called from isr
+ */
+void mdp_enable_irq(uint32 term)
+{
+ unsigned long irq_flags;
+
+ spin_lock_irqsave(&mdp_lock, irq_flags);
+ if (mdp_irq_mask & term) {
+ printk(KERN_ERR "%s: MDP IRQ term-0x%x is already set, mask=%x irq=%d\n",
+ __func__, term, mdp_irq_mask, mdp_irq_enabled);
+ } else {
+ mdp_irq_mask |= term;
+ if (mdp_irq_mask && !mdp_irq_enabled) {
+ mdp_irq_enabled = 1;
+ enable_irq(mdp_irq);
+ }
+ }
spin_unlock_irqrestore(&mdp_lock, irq_flags);
+}
+
+/*
+ * mdp_disable_irq: can not be called from isr
+ */
+void mdp_disable_irq(uint32 term)
+{
+ unsigned long irq_flags;
+
+ spin_lock_irqsave(&mdp_lock, irq_flags);
+ if (!(mdp_irq_mask & term)) {
+ printk(KERN_ERR "%s: MDP IRQ term-0x%x is NOT set, mask=%x irq=%d\n",
+ __func__, term, mdp_irq_mask, mdp_irq_enabled);
+ } else {
+ mdp_irq_mask &= ~term;
+ if (!mdp_irq_mask && mdp_irq_enabled) {
+ mdp_irq_enabled = 0;
+ disable_irq(mdp_irq);
+ }
+ }
+ spin_unlock_irqrestore(&mdp_lock, irq_flags);
+}
+
+void mdp_disable_irq_nosync(uint32 term)
+{
+ spin_lock(&mdp_lock);
+ if (!(mdp_irq_mask & term)) {
+ printk(KERN_ERR "%s: MDP IRQ term-0x%x is NOT set, mask=%x irq=%d\n",
+ __func__, term, mdp_irq_mask, mdp_irq_enabled);
+ } else {
+ mdp_irq_mask &= ~term;
+ if (!mdp_irq_mask && mdp_irq_enabled) {
+ mdp_irq_enabled = 0;
+ disable_irq_nosync(mdp_irq);
+ }
+ }
+ spin_unlock(&mdp_lock);
+}
+
+void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd)
+{
+ /* complete all the writes before starting */
+ wmb();
+
+ /* kick off PPP engine */
+ if (term == MDP_PPP_TERM) {
+ if (mdp_debug[MDP_PPP_BLOCK])
+ jiffies_to_timeval(jiffies, &mdp_ppp_timeval);
+
+ /* let's turn on PPP block */
+ mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ mdp_enable_irq(term);
+ INIT_COMPLETION(mdp_ppp_comp);
+ mdp_ppp_waiting = TRUE;
+ outpdw(MDP_BASE + 0x30, 0x1000);
+ wait_for_completion_killable(&mdp_ppp_comp);
+ mdp_disable_irq(term);
+
+ if (mdp_debug[MDP_PPP_BLOCK]) {
+ struct timeval now;
+
+ jiffies_to_timeval(jiffies, &now);
+ mdp_ppp_timeval.tv_usec =
+ now.tv_usec - mdp_ppp_timeval.tv_usec;
+ MSM_FB_DEBUG("MDP-PPP: %d\n",
+ (int)mdp_ppp_timeval.tv_usec);
+ }
+ } else if (term == MDP_DMA2_TERM) {
+ if (mdp_debug[MDP_DMA2_BLOCK]) {
+ MSM_FB_DEBUG("MDP-DMA2: %d\n",
+ (int)mdp_dma2_timeval.tv_usec);
+ jiffies_to_timeval(jiffies, &mdp_dma2_timeval);
+ }
+ /* DMA update timestamp */
+ mdp_dma2_last_update_time = ktime_get_real();
+ /* let's turn on DMA2 block */
+#if 0
+ mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+#endif
+#ifdef CONFIG_FB_MSM_MDP22
+ outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x0044, 0x0);/* start DMA */
+#else
+ mdp_lut_enable();
+
+#ifdef CONFIG_FB_MSM_MDP40
+ outpdw(MDP_BASE + 0x000c, 0x0); /* start DMA */
+#else
+ outpdw(MDP_BASE + 0x0044, 0x0); /* start DMA */
+
+#ifdef CONFIG_FB_MSM_MDP303
+
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+ mipi_dsi_cmd_mdp_sw_trigger();
+#endif
+
+#endif
+
+#endif
+#endif
+#ifdef CONFIG_FB_MSM_MDP40
+ } else if (term == MDP_DMA_S_TERM) {
+ mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ outpdw(MDP_BASE + 0x0010, 0x0); /* start DMA */
+ } else if (term == MDP_DMA_E_TERM) {
+ mdp_pipe_ctrl(MDP_DMA_E_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ outpdw(MDP_BASE + 0x0014, 0x0); /* start DMA */
+ } else if (term == MDP_OVERLAY0_TERM) {
+ mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ mdp_lut_enable();
+ outpdw(MDP_BASE + 0x0004, 0);
+ } else if (term == MDP_OVERLAY1_TERM) {
+ mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ mdp_lut_enable();
+ outpdw(MDP_BASE + 0x0008, 0);
+ }
+#else
+ } else if (term == MDP_DMA_S_TERM) {
+ mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ outpdw(MDP_BASE + 0x0048, 0x0); /* start DMA */
+ } else if (term == MDP_DMA_E_TERM) {
+ mdp_pipe_ctrl(MDP_DMA_E_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ outpdw(MDP_BASE + 0x004C, 0x0);
+ }
+#endif
+}
+static int mdp_clk_rate;
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+
+static void mdp_pipe_ctrl_workqueue_handler(struct work_struct *work)
+{
+ mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
+ boolean isr)
+{
+ boolean mdp_all_blocks_off = TRUE;
+ int i;
+ unsigned long flag;
+ struct msm_fb_panel_data *pdata;
+
+ /*
+ * It is assumed that if isr = TRUE then start = OFF
+ * if start = ON when isr = TRUE it could happen that the usercontext
+ * could turn off the clocks while the interrupt is updating the
+ * power to ON
+ */
+ WARN_ON(isr == TRUE && state == MDP_BLOCK_POWER_ON);
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ if (MDP_BLOCK_POWER_ON == state) {
+ atomic_inc(&mdp_block_power_cnt[block]);
+
+ if (MDP_DMA2_BLOCK == block)
+ mdp_in_processing = TRUE;
+ } else {
+ atomic_dec(&mdp_block_power_cnt[block]);
+
+ if (atomic_read(&mdp_block_power_cnt[block]) < 0) {
+ /*
+ * Master has to serve a request to power off MDP always
+ * It also has a timer to power off. So, in case of
+ * timer expires first and DMA2 finishes later,
+ * master has to power off two times
+ * There shouldn't be multiple power-off request for
+ * other blocks
+ */
+ if (block != MDP_MASTER_BLOCK) {
+ MSM_FB_INFO("mdp_block_power_cnt[block=%d] \
+ multiple power-off request\n", block);
+ }
+ atomic_set(&mdp_block_power_cnt[block], 0);
+ }
+
+ if (MDP_DMA2_BLOCK == block)
+ mdp_in_processing = FALSE;
+ }
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+ /*
+ * If it's in isr, we send our request to workqueue.
+ * Otherwise, processing happens in the current context
+ */
+ if (isr) {
+ if (mdp_current_clk_on) {
+ /* checking all blocks power state */
+ for (i = 0; i < MDP_MAX_BLOCK; i++) {
+ if (atomic_read(&mdp_block_power_cnt[i]) > 0) {
+ mdp_all_blocks_off = FALSE;
+ break;
+ }
+ }
+
+ if (mdp_all_blocks_off) {
+ /* send workqueue to turn off mdp power */
+ queue_delayed_work(mdp_pipe_ctrl_wq,
+ &mdp_pipe_ctrl_worker,
+ mdp_timer_duration);
+ }
+ }
+ } else {
+ down(&mdp_pipe_ctrl_mutex);
+ /* checking all blocks power state */
+ for (i = 0; i < MDP_MAX_BLOCK; i++) {
+ if (atomic_read(&mdp_block_power_cnt[i]) > 0) {
+ mdp_all_blocks_off = FALSE;
+ break;
+ }
+ }
+
+ /*
+ * find out whether a delayable work item is currently
+ * pending
+ */
+
+ if (delayed_work_pending(&mdp_pipe_ctrl_worker)) {
+ /*
+ * try to cancel the current work if it fails to
+ * stop (which means del_timer can't delete it
+ * from the list, it's about to expire and run),
+ * we have to let it run. queue_delayed_work won't
+ * accept the next job which is same as
+ * queue_delayed_work(mdp_timer_duration = 0)
+ */
+ cancel_delayed_work(&mdp_pipe_ctrl_worker);
+ }
+
+ if ((mdp_all_blocks_off) && (mdp_current_clk_on)) {
+ mutex_lock(&mdp_suspend_mutex);
+ if (block == MDP_MASTER_BLOCK || mdp_suspended) {
+ mdp_current_clk_on = FALSE;
+ mb();
+ /* turn off MDP clks */
+ mdp_vsync_clk_disable();
+ for (i = 0; i < pdev_list_cnt; i++) {
+ pdata = (struct msm_fb_panel_data *)
+ pdev_list[i]->dev.platform_data;
+ if (pdata && pdata->clk_func)
+ pdata->clk_func(0);
+ }
+ if (mdp_clk != NULL) {
+ mdp_clk_rate = clk_get_rate(mdp_clk);
+ clk_disable(mdp_clk);
+ if (mdp_hw_revision <=
+ MDP4_REVISION_V2_1 &&
+ mdp_clk_rate > 122880000) {
+ clk_set_rate(mdp_clk,
+ 122880000);
+ }
+ MSM_FB_DEBUG("MDP CLK OFF\n");
+ }
+ if (mdp_pclk != NULL) {
+ clk_disable(mdp_pclk);
+ MSM_FB_DEBUG("MDP PCLK OFF\n");
+ }
+ if (mdp_axi_clk != NULL)
+ clk_disable(mdp_axi_clk);
+ if (mdp_lut_clk != NULL)
+ clk_disable(mdp_lut_clk);
+ } else {
+ /* send workqueue to turn off mdp power */
+ queue_delayed_work(mdp_pipe_ctrl_wq,
+ &mdp_pipe_ctrl_worker,
+ mdp_timer_duration);
+ }
+ mutex_unlock(&mdp_suspend_mutex);
+ } else if ((!mdp_all_blocks_off) && (!mdp_current_clk_on)) {
+ mdp_current_clk_on = TRUE;
+ /* turn on MDP clks */
+ for (i = 0; i < pdev_list_cnt; i++) {
+ pdata = (struct msm_fb_panel_data *)
+ pdev_list[i]->dev.platform_data;
+ if (pdata && pdata->clk_func)
+ pdata->clk_func(1);
+ }
+ if (mdp_clk != NULL) {
+ if (mdp_hw_revision <=
+ MDP4_REVISION_V2_1 &&
+ mdp_clk_rate > 122880000) {
+ clk_set_rate(mdp_clk,
+ mdp_clk_rate);
+ }
+ clk_enable(mdp_clk);
+ MSM_FB_DEBUG("MDP CLK ON\n");
+ }
+ if (mdp_pclk != NULL) {
+ clk_enable(mdp_pclk);
+ MSM_FB_DEBUG("MDP PCLK ON\n");
+ }
+ if (mdp_axi_clk != NULL)
+ clk_enable(mdp_axi_clk);
+ if (mdp_lut_clk != NULL)
+ clk_enable(mdp_lut_clk);
+ mdp_vsync_clk_enable();
+ }
+ up(&mdp_pipe_ctrl_mutex);
+ }
+}
+
+#ifndef CONFIG_FB_MSM_MDP40
+irqreturn_t mdp_isr(int irq, void *ptr)
+{
+ uint32 mdp_interrupt = 0;
+ struct mdp_dma_data *dma;
+
+ mdp_is_in_isr = TRUE;
+ do {
+ mdp_interrupt = inp32(MDP_INTR_STATUS);
+ outp32(MDP_INTR_CLEAR, mdp_interrupt);
+
+ mdp_interrupt &= mdp_intr_mask;
+
+ if (mdp_interrupt & TV_ENC_UNDERRUN) {
+ mdp_interrupt &= ~(TV_ENC_UNDERRUN);
+ mdp_tv_underflow_cnt++;
+ }
+
+ if (!mdp_interrupt)
+ break;
+
+ /* DMA3 TV-Out Start */
+ if (mdp_interrupt & TV_OUT_DMA3_START) {
+ /* let's disable TV out interrupt */
+ mdp_intr_mask &= ~TV_OUT_DMA3_START;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+
+ dma = &dma3_data;
+ if (dma->waiting) {
+ dma->waiting = FALSE;
+ complete(&dma->comp);
+ }
+ }
+#ifndef CONFIG_FB_MSM_MDP22
+ if (mdp_interrupt & MDP_HIST_DONE) {
+ outp32(MDP_BASE + 0x94018, 0x3);
+ outp32(MDP_INTR_CLEAR, MDP_HIST_DONE);
+ if (mdp_hist.r)
+ memcpy(mdp_hist.r, MDP_BASE + 0x94100,
+ mdp_hist.bin_cnt*4);
+ if (mdp_hist.g)
+ memcpy(mdp_hist.g, MDP_BASE + 0x94200,
+ mdp_hist.bin_cnt*4);
+ if (mdp_hist.b)
+ memcpy(mdp_hist.b, MDP_BASE + 0x94300,
+ mdp_hist.bin_cnt*4);
+ complete(&mdp_hist_comp);
+ if (mdp_is_hist_start == TRUE) {
+ MDP_OUTP(MDP_BASE + 0x94004,
+ mdp_hist.frame_cnt);
+ MDP_OUTP(MDP_BASE + 0x94000, 1);
+ }
+ }
+
+ /* LCDC UnderFlow */
+ if (mdp_interrupt & LCDC_UNDERFLOW) {
+ mdp_lcdc_underflow_cnt++;
+ /*when underflow happens HW resets all the histogram
+ registers that were set before so restore them back
+ to normal.*/
+ MDP_OUTP(MDP_BASE + 0x94010, 1);
+ MDP_OUTP(MDP_BASE + 0x9401c, 2);
+ if (mdp_is_hist_start == TRUE) {
+ MDP_OUTP(MDP_BASE + 0x94004,
+ mdp_hist.frame_cnt);
+ MDP_OUTP(MDP_BASE + 0x94000, 1);
+ }
+ }
+ /* LCDC Frame Start */
+ if (mdp_interrupt & LCDC_FRAME_START) {
+ /* let's disable LCDC interrupt */
+ mdp_intr_mask &= ~LCDC_FRAME_START;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+
+ dma = &dma2_data;
+ if (dma->waiting) {
+ dma->waiting = FALSE;
+ complete(&dma->comp);
+ }
+ }
+
+ /* DMA2 LCD-Out Complete */
+ if (mdp_interrupt & MDP_DMA_S_DONE) {
+ dma = &dma_s_data;
+ dma->busy = FALSE;
+ mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_OFF,
+ TRUE);
+ complete(&dma->comp);
+ }
+ /* DMA_E LCD-Out Complete */
+ if (mdp_interrupt & MDP_DMA_E_DONE) {
+ dma = &dma_s_data;
+ dma->busy = FALSE;
+ mdp_pipe_ctrl(MDP_DMA_E_BLOCK, MDP_BLOCK_POWER_OFF,
+ TRUE);
+ complete(&dma->comp);
+ }
+
+#endif
+
+ /* DMA2 LCD-Out Complete */
+ if (mdp_interrupt & MDP_DMA_P_DONE) {
+ struct timeval now;
+
+ mdp_dma2_last_update_time = ktime_sub(ktime_get_real(),
+ mdp_dma2_last_update_time);
+ if (mdp_debug[MDP_DMA2_BLOCK]) {
+ jiffies_to_timeval(jiffies, &now);
+ mdp_dma2_timeval.tv_usec =
+ now.tv_usec - mdp_dma2_timeval.tv_usec;
+ }
+#ifndef CONFIG_FB_MSM_MDP303
+ dma = &dma2_data;
+ dma->busy = FALSE;
+ mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF,
+ TRUE);
+ complete(&dma->comp);
+#else
+ if (mdp_prim_panel_type == MIPI_CMD_PANEL) {
+ dma = &dma2_data;
+ dma->busy = FALSE;
+ mdp_pipe_ctrl(MDP_DMA2_BLOCK,
+ MDP_BLOCK_POWER_OFF, TRUE);
+ complete(&dma->comp);
+ }
+#endif
+ }
+ /* PPP Complete */
+ if (mdp_interrupt & MDP_PPP_DONE) {
+#ifdef CONFIG_FB_MSM_MDP31
+ MDP_OUTP(MDP_BASE + 0x00100, 0xFFFF);
+#endif
+ mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+ if (mdp_ppp_waiting) {
+ mdp_ppp_waiting = FALSE;
+ complete(&mdp_ppp_comp);
+ }
+ }
+ } while (1);
+
+ mdp_is_in_isr = FALSE;
+
return IRQ_HANDLED;
}
+#endif
-static uint32_t mdp_check_mask(uint32_t mask)
+static void mdp_drv_init(void)
{
- uint32_t ret;
- unsigned long irq_flags;
+ int i;
- spin_lock_irqsave(&mdp_lock, irq_flags);
- ret = mdp_irq_mask & mask;
- spin_unlock_irqrestore(&mdp_lock, irq_flags);
- return ret;
-}
-
-static int mdp_wait(struct mdp_info *mdp, uint32_t mask, wait_queue_head_t *wq)
-{
- int ret = 0;
- unsigned long irq_flags;
-
- wait_event_timeout(*wq, !mdp_check_mask(mask), HZ);
-
- spin_lock_irqsave(&mdp_lock, irq_flags);
- if (mdp_irq_mask & mask) {
- locked_disable_mdp_irq(mdp, mask);
- printk(KERN_WARNING "timeout waiting for mdp to complete %x\n",
- mask);
- ret = -ETIMEDOUT;
- }
- spin_unlock_irqrestore(&mdp_lock, irq_flags);
-
- return ret;
-}
-
-void mdp_dma_wait(struct mdp_device *mdp_dev)
-{
-#define MDP_MAX_TIMEOUTS 20
- static int timeout_count;
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
-
- if (mdp_wait(mdp, DL0_DMA2_TERM_DONE, &mdp_dma2_waitqueue) == -ETIMEDOUT)
- timeout_count++;
- else
- timeout_count = 0;
-
- if (timeout_count > MDP_MAX_TIMEOUTS) {
- printk(KERN_ERR "mdp: dma failed %d times, somethings wrong!\n",
- MDP_MAX_TIMEOUTS);
- BUG();
- }
-}
-
-static int mdp_ppp_wait(struct mdp_info *mdp)
-{
- return mdp_wait(mdp, DL0_ROI_DONE, &mdp_ppp_waitqueue);
-}
-
-void mdp_dma_to_mddi(struct mdp_info *mdp, uint32_t addr, uint32_t stride,
- uint32_t width, uint32_t height, uint32_t x, uint32_t y,
- struct msmfb_callback *callback)
-{
- uint32_t dma2_cfg;
- uint16_t ld_param = 0; /* 0=PRIM, 1=SECD, 2=EXT */
-
- if (enable_mdp_irq(mdp, DL0_DMA2_TERM_DONE)) {
- printk(KERN_ERR "mdp_dma_to_mddi: busy\n");
- return;
+ for (i = 0; i < MDP_MAX_BLOCK; i++) {
+ mdp_debug[i] = 0;
}
- dma_callback = callback;
+ /* initialize spin lock and workqueue */
+ spin_lock_init(&mdp_spin_lock);
+ mdp_dma_wq = create_singlethread_workqueue("mdp_dma_wq");
+ mdp_vsync_wq = create_singlethread_workqueue("mdp_vsync_wq");
+ mdp_pipe_ctrl_wq = create_singlethread_workqueue("mdp_pipe_ctrl_wq");
+ INIT_DELAYED_WORK(&mdp_pipe_ctrl_worker,
+ mdp_pipe_ctrl_workqueue_handler);
- dma2_cfg = DMA_PACK_TIGHT |
- DMA_PACK_ALIGN_LSB |
- DMA_PACK_PATTERN_RGB |
- DMA_OUT_SEL_AHB |
- DMA_IBUF_NONCONTIGUOUS;
+ /* initialize semaphore */
+ init_completion(&mdp_ppp_comp);
+ sema_init(&mdp_ppp_mutex, 1);
+ sema_init(&mdp_pipe_ctrl_mutex, 1);
- dma2_cfg |= DMA_IBUF_FORMAT_RGB565;
+ dma2_data.busy = FALSE;
+ dma2_data.dmap_busy = FALSE;
+ dma2_data.waiting = FALSE;
+ init_completion(&dma2_data.comp);
+ init_completion(&dma2_data.dmap_comp);
+ sema_init(&dma2_data.mutex, 1);
+ mutex_init(&dma2_data.ov_mutex);
- dma2_cfg |= DMA_OUT_SEL_MDDI;
+ dma3_data.busy = FALSE;
+ dma3_data.waiting = FALSE;
+ init_completion(&dma3_data.comp);
+ sema_init(&dma3_data.mutex, 1);
- dma2_cfg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
+ dma_s_data.busy = FALSE;
+ dma_s_data.waiting = FALSE;
+ init_completion(&dma_s_data.comp);
+ sema_init(&dma_s_data.mutex, 1);
- dma2_cfg |= DMA_DITHER_EN;
+#ifndef CONFIG_FB_MSM_MDP303
+ dma_e_data.busy = FALSE;
+ dma_e_data.waiting = FALSE;
+ init_completion(&dma_e_data.comp);
+ mutex_init(&dma_e_data.ov_mutex);
+#endif
- /* setup size, address, and stride */
- mdp_writel(mdp, (height << 16) | (width),
- MDP_CMD_DEBUG_ACCESS_BASE + 0x0184);
- mdp_writel(mdp, addr, MDP_CMD_DEBUG_ACCESS_BASE + 0x0188);
- mdp_writel(mdp, stride, MDP_CMD_DEBUG_ACCESS_BASE + 0x018C);
+#ifndef CONFIG_FB_MSM_MDP22
+ init_completion(&mdp_hist_comp);
+#endif
- /* 666 18BPP */
- dma2_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
-
- /* set y & x offset and MDDI transaction parameters */
- mdp_writel(mdp, (y << 16) | (x), MDP_CMD_DEBUG_ACCESS_BASE + 0x0194);
- mdp_writel(mdp, ld_param, MDP_CMD_DEBUG_ACCESS_BASE + 0x01a0);
- mdp_writel(mdp, (MDDI_VDO_PACKET_DESC << 16) | MDDI_VDO_PACKET_PRIM,
- MDP_CMD_DEBUG_ACCESS_BASE + 0x01a4);
-
- mdp_writel(mdp, dma2_cfg, MDP_CMD_DEBUG_ACCESS_BASE + 0x0180);
-
- /* start DMA2 */
- mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0044);
-}
-
-void mdp_dma(struct mdp_device *mdp_dev, uint32_t addr, uint32_t stride,
- uint32_t width, uint32_t height, uint32_t x, uint32_t y,
- struct msmfb_callback *callback, int interface)
-{
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
-
- if (interface == MSM_MDDI_PMDH_INTERFACE) {
- mdp_dma_to_mddi(mdp, addr, stride, width, height, x, y,
- callback);
- }
-}
-
-int get_img(struct mdp_img *img, struct fb_info *info,
- unsigned long *start, unsigned long *len,
- struct file **filep)
-{
- int put_needed, ret = 0;
- struct file *file;
-
- file = fget_light(img->memory_id, &put_needed);
- if (file == NULL)
- return -1;
-
- if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
- *start = info->fix.smem_start;
- *len = info->fix.smem_len;
- } else
- ret = -1;
- fput_light(file, put_needed);
-
- return ret;
-}
-
-void put_img(struct file *src_file, struct file *dst_file)
-{
-}
-
-int mdp_blit(struct mdp_device *mdp_dev, struct fb_info *fb,
- struct mdp_blit_req *req)
-{
- int ret;
- unsigned long src_start = 0, src_len = 0, dst_start = 0, dst_len = 0;
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
- struct file *src_file = 0, *dst_file = 0;
-
- /* WORKAROUND FOR HARDWARE BUG IN BG TILE FETCH */
- if (unlikely(req->src_rect.h == 0 ||
- req->src_rect.w == 0)) {
- printk(KERN_ERR "mpd_ppp: src img of zero size!\n");
- return -EINVAL;
- }
- if (unlikely(req->dst_rect.h == 0 ||
- req->dst_rect.w == 0))
- return -EINVAL;
-
- /* do this first so that if this fails, the caller can always
- * safely call put_img */
- if (unlikely(get_img(&req->src, fb, &src_start, &src_len, &src_file))) {
- printk(KERN_ERR "mpd_ppp: could not retrieve src image from "
- "memory\n");
- return -EINVAL;
+ /* initializing mdp power block counter to 0 */
+ for (i = 0; i < MDP_MAX_BLOCK; i++) {
+ atomic_set(&mdp_block_power_cnt[i], 0);
}
- if (unlikely(get_img(&req->dst, fb, &dst_start, &dst_len, &dst_file))) {
- printk(KERN_ERR "mpd_ppp: could not retrieve dst image from "
- "memory\n");
- return -EINVAL;
- }
- mutex_lock(&mdp_mutex);
+#ifdef MSM_FB_ENABLE_DBGFS
+ {
+ struct dentry *root;
+ char sub_name[] = "mdp";
- /* transp_masking unimplemented */
- req->transp_mask = MDP_TRANSP_NOP;
- if (unlikely((req->transp_mask != MDP_TRANSP_NOP ||
- req->alpha != MDP_ALPHA_NOP ||
- HAS_ALPHA(req->src.format)) &&
- (req->flags & MDP_ROT_90 &&
- req->dst_rect.w <= 16 && req->dst_rect.h >= 16))) {
- int i;
- unsigned int tiles = req->dst_rect.h / 16;
- unsigned int remainder = req->dst_rect.h % 16;
- req->src_rect.w = 16*req->src_rect.w / req->dst_rect.h;
- req->dst_rect.h = 16;
- for (i = 0; i < tiles; i++) {
- enable_mdp_irq(mdp, DL0_ROI_DONE);
- ret = mdp_ppp_blit(mdp, req, src_file, src_start,
- src_len, dst_file, dst_start,
- dst_len);
- if (ret)
- goto err_bad_blit;
- ret = mdp_ppp_wait(mdp);
- if (ret)
- goto err_wait_failed;
- req->dst_rect.y += 16;
- req->src_rect.x += req->src_rect.w;
+ root = msm_fb_get_debugfs_root();
+ if (root != NULL) {
+ mdp_dir = debugfs_create_dir(sub_name, root);
+
+ if (mdp_dir) {
+ msm_fb_debugfs_file_create(mdp_dir,
+ "dma2_update_time_in_usec",
+ (u32 *) &mdp_dma2_update_time_in_usec);
+ msm_fb_debugfs_file_create(mdp_dir,
+ "vs_rdcnt_slow",
+ (u32 *) &mdp_lcd_rd_cnt_offset_slow);
+ msm_fb_debugfs_file_create(mdp_dir,
+ "vs_rdcnt_fast",
+ (u32 *) &mdp_lcd_rd_cnt_offset_fast);
+ msm_fb_debugfs_file_create(mdp_dir,
+ "mdp_usec_diff_threshold",
+ (u32 *) &mdp_usec_diff_threshold);
+ msm_fb_debugfs_file_create(mdp_dir,
+ "mdp_current_clk_on",
+ (u32 *) &mdp_current_clk_on);
+#ifdef CONFIG_FB_MSM_LCDC
+ msm_fb_debugfs_file_create(mdp_dir,
+ "lcdc_start_x",
+ (u32 *) &first_pixel_start_x);
+ msm_fb_debugfs_file_create(mdp_dir,
+ "lcdc_start_y",
+ (u32 *) &first_pixel_start_y);
+#endif
+ }
}
- if (!remainder)
- goto end;
- req->src_rect.w = remainder*req->src_rect.w / req->dst_rect.h;
- req->dst_rect.h = remainder;
}
- enable_mdp_irq(mdp, DL0_ROI_DONE);
- ret = mdp_ppp_blit(mdp, req, src_file, src_start, src_len, dst_file,
- dst_start,
- dst_len);
- if (ret)
- goto err_bad_blit;
- ret = mdp_ppp_wait(mdp);
- if (ret)
- goto err_wait_failed;
-end:
- put_img(src_file, dst_file);
- mutex_unlock(&mdp_mutex);
+#endif
+}
+
+static int mdp_probe(struct platform_device *pdev);
+static int mdp_remove(struct platform_device *pdev);
+
+static int mdp_runtime_suspend(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: suspending...\n");
return 0;
-err_bad_blit:
- disable_mdp_irq(mdp, DL0_ROI_DONE);
-err_wait_failed:
- put_img(src_file, dst_file);
- mutex_unlock(&mdp_mutex);
- return ret;
}
-void mdp_set_grp_disp(struct mdp_device *mdp_dev, unsigned disp_id)
+static int mdp_runtime_resume(struct device *dev)
{
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
-
- disp_id &= 0xf;
- mdp_writel(mdp, disp_id, MDP_FULL_BYPASS_WORD43);
-}
-
-int register_mdp_client(struct class_interface *cint)
-{
- if (!mdp_class) {
- pr_err("mdp: no mdp_class when registering mdp client\n");
- return -ENODEV;
- }
- cint->class = mdp_class;
- return class_interface_register(cint);
-}
-
-#include "mdp_csc_table.h"
-#include "mdp_scale_tables.h"
-
-int mdp_probe(struct platform_device *pdev)
-{
- struct resource *resource;
- int ret;
- int n;
- struct mdp_info *mdp;
-
- resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!resource) {
- pr_err("mdp: can not get mdp mem resource!\n");
- return -ENOMEM;
- }
-
- mdp = kzalloc(sizeof(struct mdp_info), GFP_KERNEL);
- if (!mdp)
- return -ENOMEM;
-
- mdp->irq = platform_get_irq(pdev, 0);
- if (mdp->irq < 0) {
- pr_err("mdp: can not get mdp irq\n");
- ret = mdp->irq;
- goto error_get_irq;
- }
-
- mdp->base = ioremap(resource->start,
- resource->end - resource->start);
- if (mdp->base == 0) {
- printk(KERN_ERR "msmfb: cannot allocate mdp regs!\n");
- ret = -ENOMEM;
- goto error_ioremap;
- }
-
- mdp->mdp_dev.dma = mdp_dma;
- mdp->mdp_dev.dma_wait = mdp_dma_wait;
- mdp->mdp_dev.blit = mdp_blit;
- mdp->mdp_dev.set_grp_disp = mdp_set_grp_disp;
-
- clk = clk_get(&pdev->dev, "mdp_clk");
- if (IS_ERR(clk)) {
- printk(KERN_INFO "mdp: failed to get mdp clk");
- return PTR_ERR(clk);
- }
-
- ret = request_irq(mdp->irq, mdp_isr, IRQF_DISABLED, "msm_mdp", mdp);
- if (ret)
- goto error_request_irq;
- disable_irq(mdp->irq);
- mdp_irq_mask = 0;
-
- /* debug interface write access */
- mdp_writel(mdp, 1, 0x60);
-
- mdp_writel(mdp, MDP_ANY_INTR_MASK, MDP_INTR_ENABLE);
- mdp_writel(mdp, 1, MDP_EBI2_PORTMAP_MODE);
-
- mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8);
- mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc);
-
- for (n = 0; n < ARRAY_SIZE(csc_table); n++)
- mdp_writel(mdp, csc_table[n].val, csc_table[n].reg);
-
- /* clear up unused fg/main registers */
- /* comp.plane 2&3 ystride */
- mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0120);
-
- /* unpacked pattern */
- mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x012c);
- mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0130);
- mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0134);
- mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0158);
- mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x015c);
- mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0160);
- mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0170);
- mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0174);
- mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x017c);
-
- /* comp.plane 2 & 3 */
- mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0114);
- mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0118);
-
- /* clear unused bg registers */
- mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8);
- mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0);
- mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc);
- mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0);
- mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4);
-
- for (n = 0; n < ARRAY_SIZE(mdp_upscale_table); n++)
- mdp_writel(mdp, mdp_upscale_table[n].val,
- mdp_upscale_table[n].reg);
-
- for (n = 0; n < 9; n++)
- mdp_writel(mdp, mdp_default_ccs[n], 0x40440 + 4 * n);
- mdp_writel(mdp, mdp_default_ccs[9], 0x40500 + 4 * 0);
- mdp_writel(mdp, mdp_default_ccs[10], 0x40500 + 4 * 0);
- mdp_writel(mdp, mdp_default_ccs[11], 0x40500 + 4 * 0);
-
- /* register mdp device */
- mdp->mdp_dev.dev.parent = &pdev->dev;
- mdp->mdp_dev.dev.class = mdp_class;
- dev_set_name(&mdp->mdp_dev.dev, "mdp%d", pdev->id);
-
- /* if you can remove the platform device you'd have to implement
- * this:
- mdp_dev.release = mdp_class; */
-
- ret = device_register(&mdp->mdp_dev.dev);
- if (ret)
- goto error_device_register;
+ dev_dbg(dev, "pm_runtime: resuming...\n");
return 0;
-
-error_device_register:
- free_irq(mdp->irq, mdp);
-error_request_irq:
- iounmap(mdp->base);
-error_get_irq:
-error_ioremap:
- kfree(mdp);
- return ret;
}
-static struct platform_driver msm_mdp_driver = {
- .probe = mdp_probe,
- .driver = {.name = "msm_mdp"},
+static struct dev_pm_ops mdp_dev_pm_ops = {
+ .runtime_suspend = mdp_runtime_suspend,
+ .runtime_resume = mdp_runtime_resume,
};
-static int __init mdp_init(void)
+
+static struct platform_driver mdp_driver = {
+ .probe = mdp_probe,
+ .remove = mdp_remove,
+#ifndef CONFIG_HAS_EARLYSUSPEND
+ .suspend = mdp_suspend,
+ .resume = NULL,
+#endif
+ .shutdown = NULL,
+ .driver = {
+ /*
+ * Driver name must match the device name added in
+ * platform.c.
+ */
+ .name = "mdp",
+ .pm = &mdp_dev_pm_ops,
+ },
+};
+
+static int mdp_off(struct platform_device *pdev)
{
- mdp_class = class_create(THIS_MODULE, "msm_mdp");
- if (IS_ERR(mdp_class)) {
- printk(KERN_ERR "Error creating mdp class\n");
- return PTR_ERR(mdp_class);
- }
- return platform_driver_register(&msm_mdp_driver);
+ int ret = 0;
+ mdp_histogram_ctrl(FALSE);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ ret = panel_next_off(pdev);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ return ret;
}
-subsys_initcall(mdp_init);
+static int mdp_on(struct platform_device *pdev)
+{
+ int ret = 0;
+#ifdef CONFIG_FB_MSM_MDP40
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ if (is_mdp4_hw_reset()) {
+ mdp4_hw_init();
+ outpdw(MDP_BASE + 0x0038, mdp4_display_intf);
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+#endif
+ mdp_histogram_ctrl(TRUE);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ ret = panel_next_on(pdev);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ return ret;
+}
+
+static int mdp_resource_initialized;
+static struct msm_panel_common_pdata *mdp_pdata;
+
+uint32 mdp_hw_revision;
+
+/*
+ * mdp_hw_revision:
+ * 0 == V1
+ * 1 == V2
+ * 2 == V2.1
+ *
+ */
+void mdp_hw_version(void)
+{
+ char *cp;
+ uint32 *hp;
+
+ if (mdp_pdata == NULL)
+ return;
+
+ mdp_hw_revision = MDP4_REVISION_NONE;
+ if (mdp_pdata->hw_revision_addr == 0)
+ return;
+
+ /* tlmmgpio2 shadow */
+ cp = (char *)ioremap(mdp_pdata->hw_revision_addr, 0x16);
+
+ if (cp == NULL)
+ return;
+
+ hp = (uint32 *)cp; /* HW_REVISION_NUMBER */
+ mdp_hw_revision = *hp;
+ iounmap(cp);
+
+ mdp_hw_revision >>= 28; /* bit 31:28 */
+ mdp_hw_revision &= 0x0f;
+
+ MSM_FB_DEBUG("%s: mdp_hw_revision=%x\n",
+ __func__, mdp_hw_revision);
+}
+
+#ifdef CONFIG_FB_MSM_MDP40
+static void configure_mdp_core_clk_table(uint32 min_clk_rate)
+{
+ uint8 count;
+ uint32 current_rate;
+ if (mdp_clk && mdp_pdata
+ && mdp_pdata->mdp_core_clk_table) {
+ if (clk_set_min_rate(mdp_clk,
+ min_clk_rate) < 0)
+ printk(KERN_ERR "%s: clk_set_min_rate failed\n",
+ __func__);
+ else {
+ count = 0;
+ current_rate = clk_get_rate(mdp_clk);
+ while (count < mdp_pdata->num_mdp_clk) {
+ if (mdp_pdata->mdp_core_clk_table[count]
+ < current_rate) {
+ mdp_pdata->
+ mdp_core_clk_table[count] =
+ current_rate;
+ }
+ count++;
+ }
+ }
+ }
+}
+#endif
+
+#ifdef CONFIG_MSM_BUS_SCALING
+static uint32_t mdp_bus_scale_handle;
+int mdp_bus_scale_update_request(uint32_t index)
+{
+ if (!mdp_pdata && (!mdp_pdata->mdp_bus_scale_table
+ || index > (mdp_pdata->mdp_bus_scale_table->num_usecases - 1))) {
+ printk(KERN_ERR "%s invalid table or index\n", __func__);
+ return -EINVAL;
+ }
+ if (mdp_bus_scale_handle < 1) {
+ printk(KERN_ERR "%s invalid bus handle\n", __func__);
+ return -EINVAL;
+ }
+ return msm_bus_scale_client_update_request(mdp_bus_scale_handle,
+ index);
+}
+#endif
+DEFINE_MUTEX(mdp_clk_lock);
+int mdp_set_core_clk(uint16 perf_level)
+{
+ int ret = -EINVAL;
+ if (mdp_clk && mdp_pdata
+ && mdp_pdata->mdp_core_clk_table) {
+ if (perf_level > mdp_pdata->num_mdp_clk)
+ printk(KERN_ERR "%s invalid perf level\n", __func__);
+ else {
+ mutex_lock(&mdp_clk_lock);
+ if (mdp4_extn_disp)
+ perf_level = 1;
+ ret = clk_set_rate(mdp_clk,
+ mdp_pdata->
+ mdp_core_clk_table[mdp_pdata->num_mdp_clk
+ - perf_level]);
+ mutex_unlock(&mdp_clk_lock);
+ if (ret) {
+ printk(KERN_ERR "%s unable to set mdp_core_clk rate\n",
+ __func__);
+ }
+ }
+ }
+ return ret;
+}
+
+unsigned long mdp_get_core_clk(void)
+{
+ unsigned long clk_rate = 0;
+ if (mdp_clk) {
+ mutex_lock(&mdp_clk_lock);
+ clk_rate = clk_get_rate(mdp_clk);
+ mutex_unlock(&mdp_clk_lock);
+ }
+
+ return clk_rate;
+}
+
+unsigned long mdp_perf_level2clk_rate(uint32 perf_level)
+{
+ unsigned long clk_rate = 0;
+
+ if (mdp_pdata && mdp_pdata->mdp_core_clk_table) {
+ if (perf_level > mdp_pdata->num_mdp_clk) {
+ printk(KERN_ERR "%s invalid perf level\n", __func__);
+ clk_rate = mdp_get_core_clk();
+ } else {
+ if (mdp4_extn_disp)
+ perf_level = 1;
+ clk_rate = mdp_pdata->
+ mdp_core_clk_table[mdp_pdata->num_mdp_clk
+ - perf_level];
+ }
+ } else
+ clk_rate = mdp_get_core_clk();
+
+ return clk_rate;
+}
+
+static int mdp_irq_clk_setup(void)
+{
+ int ret;
+
+#ifdef CONFIG_FB_MSM_MDP40
+ ret = request_irq(mdp_irq, mdp4_isr, IRQF_DISABLED, "MDP", 0);
+#else
+ ret = request_irq(mdp_irq, mdp_isr, IRQF_DISABLED, "MDP", 0);
+#endif
+ if (ret) {
+ printk(KERN_ERR "mdp request_irq() failed!\n");
+ return ret;
+ }
+ disable_irq(mdp_irq);
+
+ footswitch = regulator_get(NULL, "fs_mdp");
+ if (IS_ERR(footswitch))
+ footswitch = NULL;
+ else
+ regulator_enable(footswitch);
+
+ mdp_clk = clk_get(NULL, "mdp_clk");
+ if (IS_ERR(mdp_clk)) {
+ ret = PTR_ERR(mdp_clk);
+ printk(KERN_ERR "can't get mdp_clk error:%d!\n", ret);
+ free_irq(mdp_irq, 0);
+ return ret;
+ }
+
+ mdp_pclk = clk_get(NULL, "mdp_pclk");
+ if (IS_ERR(mdp_pclk))
+ mdp_pclk = NULL;
+
+ if (mdp_rev == MDP_REV_42) {
+ mdp_axi_clk = clk_get(NULL, "mdp_axi_clk");
+ if (IS_ERR(mdp_axi_clk)) {
+ ret = PTR_ERR(mdp_axi_clk);
+ clk_put(mdp_clk);
+ pr_err("can't get mdp_axi_clk error:%d!\n", ret);
+ return ret;
+ }
+
+ mdp_lut_clk = clk_get(NULL, "lut_mdp");
+ if (IS_ERR(mdp_lut_clk)) {
+ ret = PTR_ERR(mdp_lut_clk);
+ pr_err("can't get mdp_clk error:%d!\n", ret);
+ clk_put(mdp_clk);
+ clk_put(mdp_axi_clk);
+ free_irq(mdp_irq, 0);
+ return ret;
+ }
+ } else {
+ mdp_axi_clk = NULL;
+ mdp_lut_clk = NULL;
+ }
+
+#ifdef CONFIG_FB_MSM_MDP40
+ /*
+ * mdp_clk should greater than mdp_pclk always
+ */
+ if (mdp_pdata && mdp_pdata->mdp_core_clk_rate) {
+ mutex_lock(&mdp_clk_lock);
+ clk_set_rate(mdp_clk, mdp_pdata->mdp_core_clk_rate);
+ if (mdp_lut_clk != NULL)
+ clk_set_rate(mdp_lut_clk, mdp_pdata->mdp_core_clk_rate);
+ mutex_unlock(&mdp_clk_lock);
+ }
+ MSM_FB_DEBUG("mdp_clk: mdp_clk=%d\n", (int)clk_get_rate(mdp_clk));
+#endif
+ return 0;
+}
+
+static int mdp_probe(struct platform_device *pdev)
+{
+ struct platform_device *msm_fb_dev = NULL;
+ struct msm_fb_data_type *mfd;
+ struct msm_fb_panel_data *pdata = NULL;
+ int rc;
+ resource_size_t size ;
+#ifdef CONFIG_FB_MSM_MDP40
+ int intf, if_no;
+#else
+ unsigned long flag;
+#endif
+#if defined(CONFIG_FB_MSM_MIPI_DSI) && defined(CONFIG_FB_MSM_MDP40)
+ struct mipi_panel_info *mipi;
+#endif
+
+ if ((pdev->id == 0) && (pdev->num_resources > 0)) {
+ mdp_pdata = pdev->dev.platform_data;
+
+ size = resource_size(&pdev->resource[0]);
+ msm_mdp_base = ioremap(pdev->resource[0].start, size);
+
+ MSM_FB_DEBUG("MDP HW Base phy_Address = 0x%x virt = 0x%x\n",
+ (int)pdev->resource[0].start, (int)msm_mdp_base);
+
+ if (unlikely(!msm_mdp_base))
+ return -ENOMEM;
+
+ mdp_irq = platform_get_irq(pdev, 0);
+ if (mdp_irq < 0) {
+ pr_err("mdp: can not get mdp irq\n");
+ return -ENOMEM;
+ }
+
+ mdp_rev = mdp_pdata->mdp_rev;
+ rc = mdp_irq_clk_setup();
+
+ if (rc)
+ return rc;
+
+ mdp_hw_version();
+
+ /* initializing mdp hw */
+#ifdef CONFIG_FB_MSM_MDP40
+ mdp4_hw_init();
+ mdp4_fetch_cfg(clk_get_rate(mdp_clk));
+#else
+ mdp_hw_init();
+#endif
+
+#ifdef CONFIG_FB_MSM_OVERLAY
+ mdp_hw_cursor_init();
+#endif
+
+ mdp_resource_initialized = 1;
+ return 0;
+ }
+
+ if (!mdp_resource_initialized)
+ return -EPERM;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+ return -ENOMEM;
+
+ msm_fb_dev = platform_device_alloc("msm_fb", pdev->id);
+ if (!msm_fb_dev)
+ return -ENOMEM;
+
+ /* link to the latest pdev */
+ mfd->pdev = msm_fb_dev;
+
+ /* add panel data */
+ if (platform_device_add_data
+ (msm_fb_dev, pdev->dev.platform_data,
+ sizeof(struct msm_fb_panel_data))) {
+ printk(KERN_ERR "mdp_probe: platform_device_add_data failed!\n");
+ rc = -ENOMEM;
+ goto mdp_probe_err;
+ }
+ /* data chain */
+ pdata = msm_fb_dev->dev.platform_data;
+ pdata->on = mdp_on;
+ pdata->off = mdp_off;
+ pdata->next = pdev;
+
+ mdp_prim_panel_type = mfd->panel.type;
+ switch (mfd->panel.type) {
+ case EXT_MDDI_PANEL:
+ case MDDI_PANEL:
+ case EBI2_PANEL:
+ INIT_WORK(&mfd->dma_update_worker,
+ mdp_lcd_update_workqueue_handler);
+ INIT_WORK(&mfd->vsync_resync_worker,
+ mdp_vsync_resync_workqueue_handler);
+ mfd->hw_refresh = FALSE;
+
+ if (mfd->panel.type == EXT_MDDI_PANEL) {
+ /* 15 fps -> 66 msec */
+ mfd->refresh_timer_duration = (66 * HZ / 1000);
+ } else {
+ /* 24 fps -> 42 msec */
+ mfd->refresh_timer_duration = (42 * HZ / 1000);
+ }
+
+#ifdef CONFIG_FB_MSM_MDP22
+ mfd->dma_fnc = mdp_dma2_update;
+ mfd->dma = &dma2_data;
+#else
+ if (mfd->panel_info.pdest == DISPLAY_1) {
+#if defined(CONFIG_FB_MSM_OVERLAY) && defined(CONFIG_FB_MSM_MDDI)
+ mfd->dma_fnc = mdp4_mddi_overlay;
+ mfd->cursor_update = mdp4_mddi_overlay_cursor;
+#else
+ mfd->dma_fnc = mdp_dma2_update;
+#endif
+ mfd->dma = &dma2_data;
+ mfd->lut_update = mdp_lut_update_nonlcdc;
+ mfd->do_histogram = mdp_do_histogram;
+ } else {
+ mfd->dma_fnc = mdp_dma_s_update;
+ mfd->dma = &dma_s_data;
+ }
+#endif
+ if (mdp_pdata)
+ mfd->vsync_gpio = mdp_pdata->gpio;
+ else
+ mfd->vsync_gpio = -1;
+
+#ifdef CONFIG_FB_MSM_MDP40
+ if (mfd->panel.type == EBI2_PANEL)
+ intf = EBI2_INTF;
+ else
+ intf = MDDI_INTF;
+
+ if (mfd->panel_info.pdest == DISPLAY_1)
+ if_no = PRIMARY_INTF_SEL;
+ else
+ if_no = SECONDARY_INTF_SEL;
+
+ mdp4_display_intf_sel(if_no, intf);
+#endif
+ mdp_config_vsync(mfd);
+ break;
+
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+ case MIPI_VIDEO_PANEL:
+#ifndef CONFIG_FB_MSM_MDP303
+ pdata->on = mdp4_dsi_video_on;
+ pdata->off = mdp4_dsi_video_off;
+ mfd->hw_refresh = TRUE;
+ mfd->dma_fnc = mdp4_dsi_video_overlay;
+ if (mfd->panel_info.pdest == DISPLAY_1) {
+ if_no = PRIMARY_INTF_SEL;
+ mfd->dma = &dma2_data;
+ } else {
+ if_no = EXTERNAL_INTF_SEL;
+ mfd->dma = &dma_e_data;
+ }
+ mdp4_display_intf_sel(if_no, DSI_VIDEO_INTF);
+#else
+ pdata->on = mdp_dsi_video_on;
+ pdata->off = mdp_dsi_video_off;
+ mfd->hw_refresh = TRUE;
+ mfd->dma_fnc = mdp_dsi_video_update;
+ mfd->do_histogram = mdp_do_histogram;
+ if (mfd->panel_info.pdest == DISPLAY_1)
+ mfd->dma = &dma2_data;
+ else {
+ printk(KERN_ERR "Invalid Selection of destination panel\n");
+ rc = -ENODEV;
+ goto mdp_probe_err;
+ }
+
+#endif
+ break;
+
+ case MIPI_CMD_PANEL:
+#ifndef CONFIG_FB_MSM_MDP303
+ mfd->dma_fnc = mdp4_dsi_cmd_overlay;
+#ifdef CONFIG_FB_MSM_MDP40
+ mipi = &mfd->panel_info.mipi;
+ configure_mdp_core_clk_table((mipi->dsi_pclk_rate) * 3 / 2);
+#endif
+ if (mfd->panel_info.pdest == DISPLAY_1) {
+ if_no = PRIMARY_INTF_SEL;
+ mfd->dma = &dma2_data;
+ } else {
+ if_no = SECONDARY_INTF_SEL;
+ mfd->dma = &dma_s_data;
+ }
+ mdp4_display_intf_sel(if_no, DSI_CMD_INTF);
+#else
+ mfd->dma_fnc = mdp_dma2_update;
+ mfd->do_histogram = mdp_do_histogram;
+ if (mfd->panel_info.pdest == DISPLAY_1)
+ mfd->dma = &dma2_data;
+ else {
+ printk(KERN_ERR "Invalid Selection of destination panel\n");
+ rc = -ENODEV;
+ goto mdp_probe_err;
+ }
+#endif
+ mdp_config_vsync(mfd);
+ break;
+#endif
+
+#ifdef CONFIG_FB_MSM_DTV
+ case DTV_PANEL:
+ pdata->on = mdp4_dtv_on;
+ pdata->off = mdp4_dtv_off;
+ mfd->hw_refresh = TRUE;
+ mfd->cursor_update = mdp_hw_cursor_update;
+ mfd->dma_fnc = mdp4_dtv_overlay;
+ mfd->dma = &dma_e_data;
+ mdp4_display_intf_sel(EXTERNAL_INTF_SEL, DTV_INTF);
+ break;
+#endif
+ case HDMI_PANEL:
+ case LCDC_PANEL:
+ pdata->on = mdp_lcdc_on;
+ pdata->off = mdp_lcdc_off;
+ mfd->hw_refresh = TRUE;
+#if defined(CONFIG_FB_MSM_OVERLAY) && defined(CONFIG_FB_MSM_MDP40)
+ mfd->cursor_update = mdp_hw_cursor_sync_update;
+#else
+ mfd->cursor_update = mdp_hw_cursor_update;
+#endif
+#ifndef CONFIG_FB_MSM_MDP22
+ mfd->lut_update = mdp_lut_update_lcdc;
+ mfd->do_histogram = mdp_do_histogram;
+#endif
+#ifdef CONFIG_FB_MSM_OVERLAY
+ mfd->dma_fnc = mdp4_lcdc_overlay;
+#else
+ mfd->dma_fnc = mdp_lcdc_update;
+#endif
+
+#ifdef CONFIG_FB_MSM_MDP40
+ configure_mdp_core_clk_table((mfd->panel_info.clk_rate)
+ * 23 / 20);
+ if (mfd->panel.type == HDMI_PANEL) {
+ mfd->dma = &dma_e_data;
+ mdp4_display_intf_sel(EXTERNAL_INTF_SEL, LCDC_RGB_INTF);
+ } else {
+ mfd->dma = &dma2_data;
+ mdp4_display_intf_sel(PRIMARY_INTF_SEL, LCDC_RGB_INTF);
+ }
+#else
+ mfd->dma = &dma2_data;
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_intr_mask &= ~MDP_DMA_P_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+#endif
+ break;
+
+ case TV_PANEL:
+#if defined(CONFIG_FB_MSM_OVERLAY) && defined(CONFIG_FB_MSM_TVOUT)
+ pdata->on = mdp4_atv_on;
+ pdata->off = mdp4_atv_off;
+ mfd->dma_fnc = mdp4_atv_overlay;
+ mfd->dma = &dma_e_data;
+ mdp4_display_intf_sel(EXTERNAL_INTF_SEL, TV_INTF);
+#else
+ pdata->on = mdp_dma3_on;
+ pdata->off = mdp_dma3_off;
+ mfd->hw_refresh = TRUE;
+ mfd->dma_fnc = mdp_dma3_update;
+ mfd->dma = &dma3_data;
+#endif
+ break;
+
+ default:
+ printk(KERN_ERR "mdp_probe: unknown device type!\n");
+ rc = -ENODEV;
+ goto mdp_probe_err;
+ }
+#ifdef CONFIG_FB_MSM_MDP40
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ mdp4_display_intf = inpdw(MDP_BASE + 0x0038);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+#endif
+
+#ifdef CONFIG_MSM_BUS_SCALING
+ if (!mdp_bus_scale_handle && mdp_pdata &&
+ mdp_pdata->mdp_bus_scale_table) {
+ mdp_bus_scale_handle =
+ msm_bus_scale_register_client(
+ mdp_pdata->mdp_bus_scale_table);
+ if (!mdp_bus_scale_handle) {
+ printk(KERN_ERR "%s not able to get bus scale\n",
+ __func__);
+ return -ENOMEM;
+ }
+ }
+#endif
+ /* set driver data */
+ platform_set_drvdata(msm_fb_dev, mfd);
+
+ rc = platform_device_add(msm_fb_dev);
+ if (rc) {
+ goto mdp_probe_err;
+ }
+
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+ pdev_list[pdev_list_cnt++] = pdev;
+ mdp4_extn_disp = 0;
+ return 0;
+
+ mdp_probe_err:
+ platform_device_put(msm_fb_dev);
+#ifdef CONFIG_MSM_BUS_SCALING
+ if (mdp_pdata && mdp_pdata->mdp_bus_scale_table &&
+ mdp_bus_scale_handle > 0)
+ msm_bus_scale_unregister_client(mdp_bus_scale_handle);
+#endif
+ return rc;
+}
+
+#ifdef CONFIG_PM
+static void mdp_suspend_sub(void)
+{
+ /* cancel pipe ctrl worker */
+ cancel_delayed_work(&mdp_pipe_ctrl_worker);
+
+ /* for workder can't be cancelled... */
+ flush_workqueue(mdp_pipe_ctrl_wq);
+
+ /* let's wait for PPP completion */
+ while (atomic_read(&mdp_block_power_cnt[MDP_PPP_BLOCK]) > 0)
+ cpu_relax();
+
+ /* try to power down */
+ mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ mutex_lock(&mdp_suspend_mutex);
+ mdp_suspended = TRUE;
+ mutex_unlock(&mdp_suspend_mutex);
+}
+#endif
+
+#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
+static int mdp_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ if (pdev->id == 0) {
+ mdp_suspend_sub();
+ if (mdp_current_clk_on) {
+ printk(KERN_WARNING"MDP suspend failed\n");
+ return -EBUSY;
+ }
+ }
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mdp_early_suspend(struct early_suspend *h)
+{
+ mdp_suspend_sub();
+}
+
+static void mdp_early_resume(struct early_suspend *h)
+{
+ mutex_lock(&mdp_suspend_mutex);
+ mdp_suspended = FALSE;
+ mutex_unlock(&mdp_suspend_mutex);
+}
+#endif
+
+static int mdp_remove(struct platform_device *pdev)
+{
+ if (footswitch != NULL)
+ regulator_put(footswitch);
+ iounmap(msm_mdp_base);
+ pm_runtime_disable(&pdev->dev);
+#ifdef CONFIG_MSM_BUS_SCALING
+ if (mdp_pdata && mdp_pdata->mdp_bus_scale_table &&
+ mdp_bus_scale_handle > 0)
+ msm_bus_scale_unregister_client(mdp_bus_scale_handle);
+#endif
+ return 0;
+}
+
+static int mdp_register_driver(void)
+{
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1;
+ early_suspend.suspend = mdp_early_suspend;
+ early_suspend.resume = mdp_early_resume;
+ register_early_suspend(&early_suspend);
+#endif
+
+ return platform_driver_register(&mdp_driver);
+}
+
+static int __init mdp_driver_init(void)
+{
+ int ret;
+
+ mdp_drv_init();
+
+ ret = mdp_register_driver();
+ if (ret) {
+ printk(KERN_ERR "mdp_register_driver() failed!\n");
+ return ret;
+ }
+
+#if defined(CONFIG_DEBUG_FS)
+ mdp_debugfs_init();
+#endif
+
+ return 0;
+
+}
+
+module_init(mdp_driver_init);
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
new file mode 100644
index 0000000..165502c
--- /dev/null
+++ b/drivers/video/msm/mdp.h
@@ -0,0 +1,727 @@
+/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MDP_H
+#define MDP_H
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/hrtimer.h>
+#include <linux/msm_mdp.h>
+
+#include <mach/hardware.h>
+
+#ifdef CONFIG_MSM_BUS_SCALING
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+#endif
+
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+#include "msm_fb_panel.h"
+
+extern uint32 mdp_hw_revision;
+extern ulong mdp4_display_intf;
+extern spinlock_t mdp_spin_lock;
+extern int mdp_rev;
+
+#define MDP4_REVISION_V1 0
+#define MDP4_REVISION_V2 1
+#define MDP4_REVISION_V2_1 2
+#define MDP4_REVISION_NONE 0xffffffff
+
+#ifdef BIT
+#undef BIT
+#endif
+
+#define BIT(x) (1<<(x))
+
+#define MDPOP_NOP 0
+#define MDPOP_LR BIT(0) /* left to right flip */
+#define MDPOP_UD BIT(1) /* up and down flip */
+#define MDPOP_ROT90 BIT(2) /* rotate image to 90 degree */
+#define MDPOP_ROT180 (MDPOP_UD|MDPOP_LR)
+#define MDPOP_ROT270 (MDPOP_ROT90|MDPOP_UD|MDPOP_LR)
+#define MDPOP_ASCALE BIT(7)
+#define MDPOP_ALPHAB BIT(8) /* enable alpha blending */
+#define MDPOP_TRANSP BIT(9) /* enable transparency */
+#define MDPOP_DITHER BIT(10) /* enable dither */
+#define MDPOP_SHARPENING BIT(11) /* enable sharpening */
+#define MDPOP_BLUR BIT(12) /* enable blur */
+#define MDPOP_FG_PM_ALPHA BIT(13)
+
+struct mdp_table_entry {
+ uint32_t reg;
+ uint32_t val;
+};
+
+extern struct mdp_ccs mdp_ccs_yuv2rgb ;
+extern struct mdp_ccs mdp_ccs_rgb2yuv ;
+
+/*
+ * MDP Image Structure
+ */
+typedef struct mdpImg_ {
+ uint32 imgType; /* Image type */
+ uint32 *bmy_addr; /* bitmap or y addr */
+ uint32 *cbcr_addr; /* cbcr addr */
+ uint32 width; /* image width */
+ uint32 mdpOp; /* image opertion (rotation,flip up/down, alpha/tp) */
+ uint32 tpVal; /* transparency color */
+ uint32 alpha; /* alpha percentage 0%(0x0) ~ 100%(0x100) */
+ int sp_value; /* sharpening strength */
+} MDPIMG;
+
+#define MDP_OUTP(addr, data) outpdw((addr), (data))
+
+#define MDP_BASE msm_mdp_base
+
+typedef enum {
+ MDP_BC_SCALE_POINT2_POINT4,
+ MDP_BC_SCALE_POINT4_POINT6,
+ MDP_BC_SCALE_POINT6_POINT8,
+ MDP_BC_SCALE_POINT8_1,
+ MDP_BC_SCALE_UP,
+ MDP_PR_SCALE_POINT2_POINT4,
+ MDP_PR_SCALE_POINT4_POINT6,
+ MDP_PR_SCALE_POINT6_POINT8,
+ MDP_PR_SCALE_POINT8_1,
+ MDP_PR_SCALE_UP,
+ MDP_SCALE_BLUR,
+ MDP_INIT_SCALE
+} MDP_SCALE_MODE;
+
+typedef enum {
+ MDP_BLOCK_POWER_OFF,
+ MDP_BLOCK_POWER_ON
+} MDP_BLOCK_POWER_STATE;
+
+typedef enum {
+ MDP_CMD_BLOCK,
+ MDP_OVERLAY0_BLOCK,
+ MDP_MASTER_BLOCK,
+ MDP_PPP_BLOCK,
+ MDP_DMA2_BLOCK,
+ MDP_DMA3_BLOCK,
+ MDP_DMA_S_BLOCK,
+ MDP_DMA_E_BLOCK,
+ MDP_OVERLAY1_BLOCK,
+ MDP_MAX_BLOCK
+} MDP_BLOCK_TYPE;
+
+/* Let's keep Q Factor power of 2 for optimization */
+#define MDP_SCALE_Q_FACTOR 512
+
+#ifdef CONFIG_FB_MSM_MDP31
+#define MDP_MAX_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*8)
+#define MDP_MIN_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/8)
+#define MDP_MAX_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*8)
+#define MDP_MIN_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/8)
+#else
+#define MDP_MAX_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*4)
+#define MDP_MIN_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/4)
+#define MDP_MAX_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*4)
+#define MDP_MIN_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/4)
+#endif
+
+/* SHIM Q Factor */
+#define PHI_Q_FACTOR 29
+#define PQF_PLUS_5 (PHI_Q_FACTOR + 5) /* due to 32 phases */
+#define PQF_PLUS_4 (PHI_Q_FACTOR + 4)
+#define PQF_PLUS_2 (PHI_Q_FACTOR + 2) /* to get 4.0 */
+#define PQF_MINUS_2 (PHI_Q_FACTOR - 2) /* to get 0.25 */
+#define PQF_PLUS_5_PLUS_2 (PQF_PLUS_5 + 2)
+#define PQF_PLUS_5_MINUS_2 (PQF_PLUS_5 - 2)
+
+#define MDP_CONVTP(tpVal) (((tpVal&0xF800)<<8)|((tpVal&0x7E0)<<5)|((tpVal&0x1F)<<3))
+
+#define MDPOP_ROTATION (MDPOP_ROT90|MDPOP_LR|MDPOP_UD)
+#define MDP_CHKBIT(val, bit) ((bit) == ((val) & (bit)))
+
+/* overlay interface API defines */
+typedef enum {
+ MORE_IBUF,
+ FINAL_IBUF,
+ COMPLETE_IBUF
+} MDP_IBUF_STATE;
+
+struct mdp_dirty_region {
+ __u32 xoffset; /* source origin in the x-axis */
+ __u32 yoffset; /* source origin in the y-axis */
+ __u32 width; /* number of pixels in the x-axis */
+ __u32 height; /* number of pixels in the y-axis */
+};
+
+/*
+ * MDP extended data types
+ */
+typedef struct mdp_roi_s {
+ uint32 x;
+ uint32 y;
+ uint32 width;
+ uint32 height;
+ int32 lcd_x;
+ int32 lcd_y;
+ uint32 dst_width;
+ uint32 dst_height;
+} MDP_ROI;
+
+typedef struct mdp_ibuf_s {
+ uint8 *buf;
+ uint32 bpp;
+ uint32 ibuf_type;
+ uint32 ibuf_width;
+ uint32 ibuf_height;
+
+ MDP_ROI roi;
+ MDPIMG mdpImg;
+
+ int32 dma_x;
+ int32 dma_y;
+ uint32 dma_w;
+ uint32 dma_h;
+
+ uint32 vsync_enable;
+} MDPIBUF;
+
+struct mdp_dma_data {
+ boolean busy;
+ boolean dmap_busy;
+ boolean waiting;
+ struct mutex ov_mutex;
+ struct semaphore mutex;
+ struct completion comp;
+ struct completion dmap_comp;
+};
+
+#define MDP_CMD_DEBUG_ACCESS_BASE (MDP_BASE+0x10000)
+
+#define MDP_DMA2_TERM 0x1
+#define MDP_DMA3_TERM 0x2
+#define MDP_PPP_TERM 0x4
+#define MDP_DMA_S_TERM 0x8
+#define MDP_DMA_E_TERM 0x10
+#ifdef CONFIG_FB_MSM_MDP40
+#define MDP_OVERLAY0_TERM 0x20
+#define MDP_OVERLAY1_TERM 0x40
+#endif
+#define MDP_HISTOGRAM_TERM 0x80
+
+#define ACTIVE_START_X_EN BIT(31)
+#define ACTIVE_START_Y_EN BIT(31)
+#define ACTIVE_HIGH 0
+#define ACTIVE_LOW 1
+#define MDP_DMA_S_DONE BIT(2)
+#define MDP_DMA_E_DONE BIT(3)
+#define LCDC_FRAME_START BIT(15)
+#define LCDC_UNDERFLOW BIT(16)
+
+#ifdef CONFIG_FB_MSM_MDP22
+#define MDP_DMA_P_DONE BIT(2)
+#else
+#define MDP_DMA_P_DONE BIT(14)
+#endif
+
+#define MDP_PPP_DONE BIT(0)
+#define TV_OUT_DMA3_DONE BIT(6)
+#define TV_ENC_UNDERRUN BIT(7)
+#define TV_OUT_DMA3_START BIT(13)
+#define MDP_HIST_DONE BIT(20)
+
+#ifdef CONFIG_FB_MSM_MDP22
+#define MDP_ANY_INTR_MASK (MDP_PPP_DONE| \
+ MDP_DMA_P_DONE| \
+ TV_ENC_UNDERRUN)
+#else
+#define MDP_ANY_INTR_MASK (MDP_PPP_DONE| \
+ MDP_DMA_P_DONE| \
+ MDP_DMA_S_DONE| \
+ MDP_DMA_E_DONE| \
+ LCDC_UNDERFLOW| \
+ MDP_HIST_DONE| \
+ TV_ENC_UNDERRUN)
+#endif
+
+#define MDP_TOP_LUMA 16
+#define MDP_TOP_CHROMA 0
+#define MDP_BOTTOM_LUMA 19
+#define MDP_BOTTOM_CHROMA 3
+#define MDP_LEFT_LUMA 22
+#define MDP_LEFT_CHROMA 6
+#define MDP_RIGHT_LUMA 25
+#define MDP_RIGHT_CHROMA 9
+
+#define CLR_G 0x0
+#define CLR_B 0x1
+#define CLR_R 0x2
+#define CLR_ALPHA 0x3
+
+#define CLR_Y CLR_G
+#define CLR_CB CLR_B
+#define CLR_CR CLR_R
+
+/* from lsb to msb */
+#define MDP_GET_PACK_PATTERN(a,x,y,z,bit) (((a)<<(bit*3))|((x)<<(bit*2))|((y)<<bit)|(z))
+
+/*
+ * 0x0000 0x0004 0x0008 MDP sync config
+ */
+#ifdef CONFIG_FB_MSM_MDP22
+#define MDP_SYNCFG_HGT_LOC 22
+#define MDP_SYNCFG_VSYNC_EXT_EN BIT(21)
+#define MDP_SYNCFG_VSYNC_INT_EN BIT(20)
+#else
+#define MDP_SYNCFG_HGT_LOC 21
+#define MDP_SYNCFG_VSYNC_EXT_EN BIT(20)
+#define MDP_SYNCFG_VSYNC_INT_EN BIT(19)
+#define MDP_HW_VSYNC
+#endif
+
+/*
+ * 0x0018 MDP VSYNC THREASH
+ */
+#define MDP_PRIM_BELOW_LOC 0
+#define MDP_PRIM_ABOVE_LOC 8
+
+/*
+ * MDP_PRIMARY_VSYNC_OUT_CTRL
+ * 0x0080,84,88 internal vsync pulse config
+ */
+#define VSYNC_PULSE_EN BIT(31)
+#define VSYNC_PULSE_INV BIT(30)
+
+/*
+ * 0x008c MDP VSYNC CONTROL
+ */
+#define DISP0_VSYNC_MAP_VSYNC0 0
+#define DISP0_VSYNC_MAP_VSYNC1 BIT(0)
+#define DISP0_VSYNC_MAP_VSYNC2 BIT(0)|BIT(1)
+
+#define DISP1_VSYNC_MAP_VSYNC0 0
+#define DISP1_VSYNC_MAP_VSYNC1 BIT(2)
+#define DISP1_VSYNC_MAP_VSYNC2 BIT(2)|BIT(3)
+
+#define PRIMARY_LCD_SYNC_EN BIT(4)
+#define PRIMARY_LCD_SYNC_DISABLE 0
+
+#define SECONDARY_LCD_SYNC_EN BIT(5)
+#define SECONDARY_LCD_SYNC_DISABLE 0
+
+#define EXTERNAL_LCD_SYNC_EN BIT(6)
+#define EXTERNAL_LCD_SYNC_DISABLE 0
+
+/*
+ * 0x101f0 MDP VSYNC Threshold
+ */
+#define VSYNC_THRESHOLD_ABOVE_LOC 0
+#define VSYNC_THRESHOLD_BELOW_LOC 16
+#define VSYNC_ANTI_TEAR_EN BIT(31)
+
+/*
+ * 0x10004 command config
+ */
+#define MDP_CMD_DBGBUS_EN BIT(0)
+
+/*
+ * 0x10124 or 0x101d4PPP source config
+ */
+#define PPP_SRC_C0G_8BITS (BIT(1)|BIT(0))
+#define PPP_SRC_C1B_8BITS (BIT(3)|BIT(2))
+#define PPP_SRC_C2R_8BITS (BIT(5)|BIT(4))
+#define PPP_SRC_C3A_8BITS (BIT(7)|BIT(6))
+
+#define PPP_SRC_C0G_6BITS BIT(1)
+#define PPP_SRC_C1B_6BITS BIT(3)
+#define PPP_SRC_C2R_6BITS BIT(5)
+
+#define PPP_SRC_C0G_5BITS BIT(0)
+#define PPP_SRC_C1B_5BITS BIT(2)
+#define PPP_SRC_C2R_5BITS BIT(4)
+
+#define PPP_SRC_C3_ALPHA_EN BIT(8)
+
+#define PPP_SRC_BPP_INTERLVD_1BYTES 0
+#define PPP_SRC_BPP_INTERLVD_2BYTES BIT(9)
+#define PPP_SRC_BPP_INTERLVD_3BYTES BIT(10)
+#define PPP_SRC_BPP_INTERLVD_4BYTES (BIT(10)|BIT(9))
+
+#define PPP_SRC_BPP_ROI_ODD_X BIT(11)
+#define PPP_SRC_BPP_ROI_ODD_Y BIT(12)
+#define PPP_SRC_INTERLVD_2COMPONENTS BIT(13)
+#define PPP_SRC_INTERLVD_3COMPONENTS BIT(14)
+#define PPP_SRC_INTERLVD_4COMPONENTS (BIT(14)|BIT(13))
+
+/*
+ * RGB666 unpack format
+ * TIGHT means R6+G6+B6 together
+ * LOOSE means R6+2 +G6+2+ B6+2 (with MSB)
+ * or 2+R6 +2+G6 +2+B6 (with LSB)
+ */
+#define PPP_SRC_UNPACK_TIGHT BIT(17)
+#define PPP_SRC_UNPACK_LOOSE 0
+#define PPP_SRC_UNPACK_ALIGN_LSB 0
+#define PPP_SRC_UNPACK_ALIGN_MSB BIT(18)
+
+#define PPP_SRC_FETCH_PLANES_INTERLVD 0
+#define PPP_SRC_FETCH_PLANES_PSEUDOPLNR BIT(20)
+
+#define PPP_SRC_WMV9_MODE BIT(21) /* window media version 9 */
+
+/*
+ * 0x10138 PPP operation config
+ */
+#define PPP_OP_SCALE_X_ON BIT(0)
+#define PPP_OP_SCALE_Y_ON BIT(1)
+
+#define PPP_OP_CONVERT_RGB2YCBCR 0
+#define PPP_OP_CONVERT_YCBCR2RGB BIT(2)
+#define PPP_OP_CONVERT_ON BIT(3)
+
+#define PPP_OP_CONVERT_MATRIX_PRIMARY 0
+#define PPP_OP_CONVERT_MATRIX_SECONDARY BIT(4)
+
+#define PPP_OP_LUT_C0_ON BIT(5)
+#define PPP_OP_LUT_C1_ON BIT(6)
+#define PPP_OP_LUT_C2_ON BIT(7)
+
+/* rotate or blend enable */
+#define PPP_OP_ROT_ON BIT(8)
+
+#define PPP_OP_ROT_90 BIT(9)
+#define PPP_OP_FLIP_LR BIT(10)
+#define PPP_OP_FLIP_UD BIT(11)
+
+#define PPP_OP_BLEND_ON BIT(12)
+
+#define PPP_OP_BLEND_SRCPIXEL_ALPHA 0
+#define PPP_OP_BLEND_DSTPIXEL_ALPHA BIT(13)
+#define PPP_OP_BLEND_CONSTANT_ALPHA BIT(14)
+#define PPP_OP_BLEND_SRCPIXEL_TRANSP (BIT(13)|BIT(14))
+
+#define PPP_OP_BLEND_ALPHA_BLEND_NORMAL 0
+#define PPP_OP_BLEND_ALPHA_BLEND_REVERSE BIT(15)
+
+#define PPP_OP_DITHER_EN BIT(16)
+
+#define PPP_OP_COLOR_SPACE_RGB 0
+#define PPP_OP_COLOR_SPACE_YCBCR BIT(17)
+
+#define PPP_OP_SRC_CHROMA_RGB 0
+#define PPP_OP_SRC_CHROMA_H2V1 BIT(18)
+#define PPP_OP_SRC_CHROMA_H1V2 BIT(19)
+#define PPP_OP_SRC_CHROMA_420 (BIT(18)|BIT(19))
+#define PPP_OP_SRC_CHROMA_COSITE 0
+#define PPP_OP_SRC_CHROMA_OFFSITE BIT(20)
+
+#define PPP_OP_DST_CHROMA_RGB 0
+#define PPP_OP_DST_CHROMA_H2V1 BIT(21)
+#define PPP_OP_DST_CHROMA_H1V2 BIT(22)
+#define PPP_OP_DST_CHROMA_420 (BIT(21)|BIT(22))
+#define PPP_OP_DST_CHROMA_COSITE 0
+#define PPP_OP_DST_CHROMA_OFFSITE BIT(23)
+
+#define PPP_BLEND_CALPHA_TRNASP BIT(24)
+
+#define PPP_OP_BG_CHROMA_RGB 0
+#define PPP_OP_BG_CHROMA_H2V1 BIT(25)
+#define PPP_OP_BG_CHROMA_H1V2 BIT(26)
+#define PPP_OP_BG_CHROMA_420 BIT(25)|BIT(26)
+#define PPP_OP_BG_CHROMA_SITE_COSITE 0
+#define PPP_OP_BG_CHROMA_SITE_OFFSITE BIT(27)
+#define PPP_OP_DEINT_EN BIT(28)
+
+#define PPP_BLEND_BG_USE_ALPHA_SEL (1 << 0)
+#define PPP_BLEND_BG_ALPHA_REVERSE (1 << 3)
+#define PPP_BLEND_BG_SRCPIXEL_ALPHA (0 << 1)
+#define PPP_BLEND_BG_DSTPIXEL_ALPHA (1 << 1)
+#define PPP_BLEND_BG_CONSTANT_ALPHA (2 << 1)
+#define PPP_BLEND_BG_CONST_ALPHA_VAL(x) ((x) << 24)
+
+#define PPP_OP_DST_RGB 0
+#define PPP_OP_DST_YCBCR BIT(30)
+/*
+ * 0x10150 PPP destination config
+ */
+#define PPP_DST_C0G_8BIT (BIT(0)|BIT(1))
+#define PPP_DST_C1B_8BIT (BIT(3)|BIT(2))
+#define PPP_DST_C2R_8BIT (BIT(5)|BIT(4))
+#define PPP_DST_C3A_8BIT (BIT(7)|BIT(6))
+
+#define PPP_DST_C0G_6BIT BIT(1)
+#define PPP_DST_C1B_6BIT BIT(3)
+#define PPP_DST_C2R_6BIT BIT(5)
+
+#define PPP_DST_C0G_5BIT BIT(0)
+#define PPP_DST_C1B_5BIT BIT(2)
+#define PPP_DST_C2R_5BIT BIT(4)
+
+#define PPP_DST_C3A_8BIT (BIT(7)|BIT(6))
+#define PPP_DST_C3ALPHA_EN BIT(8)
+
+#define PPP_DST_PACKET_CNT_INTERLVD_2ELEM BIT(9)
+#define PPP_DST_PACKET_CNT_INTERLVD_3ELEM BIT(10)
+#define PPP_DST_PACKET_CNT_INTERLVD_4ELEM (BIT(10)|BIT(9))
+#define PPP_DST_PACKET_CNT_INTERLVD_6ELEM (BIT(11)|BIT(9))
+
+#define PPP_DST_PACK_LOOSE 0
+#define PPP_DST_PACK_TIGHT BIT(13)
+#define PPP_DST_PACK_ALIGN_LSB 0
+#define PPP_DST_PACK_ALIGN_MSB BIT(14)
+
+#define PPP_DST_OUT_SEL_AXI 0
+#define PPP_DST_OUT_SEL_MDDI BIT(15)
+
+#define PPP_DST_BPP_2BYTES BIT(16)
+#define PPP_DST_BPP_3BYTES BIT(17)
+#define PPP_DST_BPP_4BYTES (BIT(17)|BIT(16))
+
+#define PPP_DST_PLANE_INTERLVD 0
+#define PPP_DST_PLANE_PLANAR BIT(18)
+#define PPP_DST_PLANE_PSEUDOPLN BIT(19)
+
+#define PPP_DST_TO_TV BIT(20)
+
+#define PPP_DST_MDDI_PRIMARY 0
+#define PPP_DST_MDDI_SECONDARY BIT(21)
+#define PPP_DST_MDDI_EXTERNAL BIT(22)
+
+/*
+ * 0x10180 DMA config
+ */
+#define DMA_DSTC0G_8BITS (BIT(1)|BIT(0))
+#define DMA_DSTC1B_8BITS (BIT(3)|BIT(2))
+#define DMA_DSTC2R_8BITS (BIT(5)|BIT(4))
+
+#define DMA_DSTC0G_6BITS BIT(1)
+#define DMA_DSTC1B_6BITS BIT(3)
+#define DMA_DSTC2R_6BITS BIT(5)
+
+#define DMA_DSTC0G_5BITS BIT(0)
+#define DMA_DSTC1B_5BITS BIT(2)
+#define DMA_DSTC2R_5BITS BIT(4)
+
+#define DMA_PACK_TIGHT BIT(6)
+#define DMA_PACK_LOOSE 0
+#define DMA_PACK_ALIGN_LSB 0
+/*
+ * use DMA_PACK_ALIGN_MSB if the upper 6 bits from 8 bits output
+ * from LCDC block maps into 6 pins out to the panel
+ */
+#define DMA_PACK_ALIGN_MSB BIT(7)
+#define DMA_PACK_PATTERN_RGB \
+ (MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 2)<<8)
+#define DMA_PACK_PATTERN_BGR \
+ (MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 2)<<8)
+#define DMA_OUT_SEL_AHB 0
+#define DMA_OUT_SEL_LCDC BIT(20)
+#define DMA_IBUF_FORMAT_RGB888 0
+#define DMA_IBUF_FORMAT_xRGB8888_OR_ARGB8888 BIT(26)
+
+#ifdef CONFIG_FB_MSM_MDP303
+#define DMA_OUT_SEL_DSI_CMD BIT(19)
+#define DMA_OUT_SEL_DSI_VIDEO (3 << 19)
+#endif
+
+#ifdef CONFIG_FB_MSM_MDP22
+#define DMA_OUT_SEL_MDDI BIT(14)
+#define DMA_AHBM_LCD_SEL_PRIMARY 0
+#define DMA_AHBM_LCD_SEL_SECONDARY BIT(15)
+#define DMA_IBUF_C3ALPHA_EN BIT(16)
+#define DMA_DITHER_EN BIT(17)
+#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0
+#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY BIT(18)
+#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL BIT(19)
+#define DMA_IBUF_FORMAT_RGB565 BIT(20)
+#define DMA_IBUF_FORMAT_RGB888_OR_ARGB8888 0
+#define DMA_IBUF_NONCONTIGUOUS BIT(21)
+#else
+#define DMA_OUT_SEL_MDDI BIT(19)
+#define DMA_AHBM_LCD_SEL_PRIMARY 0
+#define DMA_AHBM_LCD_SEL_SECONDARY 0
+#define DMA_IBUF_C3ALPHA_EN 0
+#define DMA_BUF_FORMAT_RGB565 BIT(25)
+#define DMA_DITHER_EN BIT(24) /* dma_p */
+#define DMA_DEFLKR_EN BIT(24) /* dma_e */
+#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0
+#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY 0
+#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL 0
+#define DMA_IBUF_FORMAT_RGB565 BIT(25)
+#define DMA_IBUF_NONCONTIGUOUS 0
+#endif
+
+/*
+ * MDDI Register
+ */
+#define MDDI_VDO_PACKET_DESC_16 0x5565
+#define MDDI_VDO_PACKET_DESC 0x5666 /* 18 bits */
+#define MDDI_VDO_PACKET_DESC_24 0x5888
+
+#ifdef CONFIG_FB_MSM_MDP40
+#define MDP_INTR_ENABLE (msm_mdp_base + 0x0050)
+#define MDP_INTR_STATUS (msm_mdp_base + 0x0054)
+#define MDP_INTR_CLEAR (msm_mdp_base + 0x0058)
+#define MDP_EBI2_LCD0 (msm_mdp_base + 0x0060)
+#define MDP_EBI2_LCD1 (msm_mdp_base + 0x0064)
+#define MDP_EBI2_PORTMAP_MODE (msm_mdp_base + 0x0070)
+
+#define MDP_DMA_P_HIST_INTR_STATUS (msm_mdp_base + 0x95014)
+#define MDP_DMA_P_HIST_INTR_CLEAR (msm_mdp_base + 0x95018)
+#define MDP_DMA_P_HIST_INTR_ENABLE (msm_mdp_base + 0x9501C)
+#else
+#define MDP_INTR_ENABLE (msm_mdp_base + 0x0020)
+#define MDP_INTR_STATUS (msm_mdp_base + 0x0024)
+#define MDP_INTR_CLEAR (msm_mdp_base + 0x0028)
+#define MDP_EBI2_LCD0 (msm_mdp_base + 0x003c)
+#define MDP_EBI2_LCD1 (msm_mdp_base + 0x0040)
+#define MDP_EBI2_PORTMAP_MODE (msm_mdp_base + 0x005c)
+#endif
+
+#define MDP_FULL_BYPASS_WORD43 (msm_mdp_base + 0x101ac)
+
+#define MDP_CSC_PFMVn(n) (msm_mdp_base + 0x40400 + 4 * (n))
+#define MDP_CSC_PRMVn(n) (msm_mdp_base + 0x40440 + 4 * (n))
+#define MDP_CSC_PRE_BV1n(n) (msm_mdp_base + 0x40500 + 4 * (n))
+#define MDP_CSC_PRE_BV2n(n) (msm_mdp_base + 0x40540 + 4 * (n))
+#define MDP_CSC_POST_BV1n(n) (msm_mdp_base + 0x40580 + 4 * (n))
+#define MDP_CSC_POST_BV2n(n) (msm_mdp_base + 0x405c0 + 4 * (n))
+
+#ifdef CONFIG_FB_MSM_MDP31
+#define MDP_CSC_PRE_LV1n(n) (msm_mdp_base + 0x40600 + 4 * (n))
+#define MDP_CSC_PRE_LV2n(n) (msm_mdp_base + 0x40640 + 4 * (n))
+#define MDP_CSC_POST_LV1n(n) (msm_mdp_base + 0x40680 + 4 * (n))
+#define MDP_CSC_POST_LV2n(n) (msm_mdp_base + 0x406c0 + 4 * (n))
+#define MDP_PPP_SCALE_COEFF_LSBn(n) (msm_mdp_base + 0x50400 + 8 * (n))
+#define MDP_PPP_SCALE_COEFF_MSBn(n) (msm_mdp_base + 0x50404 + 8 * (n))
+
+#define SCALE_D0_SET 0
+#define SCALE_D1_SET BIT(0)
+#define SCALE_D2_SET BIT(1)
+#define SCALE_U1_SET (BIT(0)|BIT(1))
+
+#else
+#define MDP_CSC_PRE_LV1n(n) (msm_mdp_base + 0x40580 + 4 * (n))
+#endif
+
+#define MDP_CURSOR_WIDTH 64
+#define MDP_CURSOR_HEIGHT 64
+#define MDP_CURSOR_SIZE (MDP_CURSOR_WIDTH*MDP_CURSOR_WIDTH*4)
+
+#define MDP_DMA_P_LUT_C0_EN BIT(0)
+#define MDP_DMA_P_LUT_C1_EN BIT(1)
+#define MDP_DMA_P_LUT_C2_EN BIT(2)
+#define MDP_DMA_P_LUT_POST BIT(4)
+
+void mdp_hw_init(void);
+int mdp_ppp_pipe_wait(void);
+void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd);
+void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
+ boolean isr);
+void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty,
+ boolean sync);
+void mdp_dma_pan_update(struct fb_info *info);
+void mdp_refresh_screen(unsigned long data);
+int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req);
+void mdp_lcd_update_workqueue_handler(struct work_struct *work);
+void mdp_vsync_resync_workqueue_handler(struct work_struct *work);
+void mdp_dma2_update(struct msm_fb_data_type *mfd);
+void mdp_config_vsync(struct msm_fb_data_type *);
+uint32 mdp_get_lcd_line_counter(struct msm_fb_data_type *mfd);
+enum hrtimer_restart mdp_dma2_vsync_hrtimer_handler(struct hrtimer *ht);
+void mdp_set_scale(MDPIBUF *iBuf,
+ uint32 dst_roi_width,
+ uint32 dst_roi_height,
+ boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr);
+void mdp_init_scale_table(void);
+void mdp_adjust_start_addr(uint8 **src0,
+ uint8 **src1,
+ int v_slice,
+ int h_slice,
+ int x,
+ int y,
+ uint32 width,
+ uint32 height, int bpp, MDPIBUF *iBuf, int layer);
+void mdp_set_blend_attr(MDPIBUF *iBuf,
+ uint32 *alpha,
+ uint32 *tpVal,
+ uint32 perPixelAlpha, uint32 *pppop_reg_ptr);
+
+int mdp_dma3_on(struct platform_device *pdev);
+int mdp_dma3_off(struct platform_device *pdev);
+void mdp_dma3_update(struct msm_fb_data_type *mfd);
+
+int mdp_lcdc_on(struct platform_device *pdev);
+int mdp_lcdc_off(struct platform_device *pdev);
+void mdp_lcdc_update(struct msm_fb_data_type *mfd);
+
+#ifdef CONFIG_FB_MSM_MDP303
+int mdp_dsi_video_on(struct platform_device *pdev);
+int mdp_dsi_video_off(struct platform_device *pdev);
+void mdp_dsi_video_update(struct msm_fb_data_type *mfd);
+void mdp3_dsi_cmd_dma_busy_wait(struct msm_fb_data_type *mfd);
+#endif
+
+int mdp_hw_cursor_update(struct fb_info *info, struct fb_cursor *cursor);
+int mdp_hw_cursor_sync_update(struct fb_info *info, struct fb_cursor *cursor);
+void mdp_enable_irq(uint32 term);
+void mdp_disable_irq(uint32 term);
+void mdp_disable_irq_nosync(uint32 term);
+int mdp_get_bytes_per_pixel(uint32_t format,
+ struct msm_fb_data_type *mfd);
+int mdp_set_core_clk(uint16 perf_level);
+unsigned long mdp_get_core_clk(void);
+unsigned long mdp_perf_level2clk_rate(uint32 perf_level);
+
+#ifdef CONFIG_MSM_BUS_SCALING
+int mdp_bus_scale_update_request(uint32_t index);
+#endif
+
+#ifdef MDP_HW_VSYNC
+void mdp_hw_vsync_clk_enable(struct msm_fb_data_type *mfd);
+void mdp_hw_vsync_clk_disable(struct msm_fb_data_type *mfd);
+void mdp_vsync_clk_disable(void);
+void mdp_vsync_clk_enable(void);
+#endif
+
+#ifdef CONFIG_DEBUG_FS
+int mdp_debugfs_init(void);
+#endif
+
+void mdp_dma_s_update(struct msm_fb_data_type *mfd);
+int mdp_start_histogram(struct fb_info *info);
+int mdp_stop_histogram(struct fb_info *info);
+int mdp_histogram_ctrl(boolean en);
+
+#ifdef CONFIG_FB_MSM_MDP303
+static inline void mdp4_dsi_cmd_dma_busy_wait(struct msm_fb_data_type *mfd)
+{
+ /* empty */
+}
+
+static inline void mdp4_dsi_blt_dmap_busy_wait(struct msm_fb_data_type *mfd)
+{
+ /* empty */
+}
+static inline void mdp4_overlay_dsi_state_set(int state)
+{
+ /* empty */
+}
+#endif
+
+#endif /* MDP_H */
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
new file mode 100644
index 0000000..d6cf2d3
--- /dev/null
+++ b/drivers/video/msm/mdp4.h
@@ -0,0 +1,565 @@
+/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MDP4_H
+#define MDP4_H
+
+extern struct mdp_dma_data dma2_data;
+extern struct mdp_dma_data dma_s_data;
+extern struct mdp_dma_data dma_e_data;
+extern struct mdp_histogram mdp_hist;
+extern struct completion mdp_hist_comp;
+extern boolean mdp_is_hist_start;
+extern boolean mdp_is_in_isr;
+extern uint32 mdp_intr_mask;
+extern spinlock_t mdp_spin_lock;
+extern struct mdp4_statistic mdp4_stat;
+extern uint32 mdp4_extn_disp;
+
+#define MDP4_OVERLAYPROC0_BASE 0x10000
+#define MDP4_OVERLAYPROC1_BASE 0x18000
+
+#define MDP4_VIDEO_BASE 0x20000
+#define MDP4_VIDEO_OFF 0x10000
+
+#define MDP4_RGB_BASE 0x40000
+#define MDP4_RGB_OFF 0x10000
+
+enum mdp4_overlay_status {
+ MDP4_OVERLAY_TYPE_UNSET,
+ MDP4_OVERLAY_TYPE_SET,
+ MDP4_OVERLAY_TYPE_MAX
+};
+
+typedef int (*cmd_fxn_t)(struct platform_device *pdev);
+
+enum { /* display */
+ PRIMARY_INTF_SEL,
+ SECONDARY_INTF_SEL,
+ EXTERNAL_INTF_SEL
+};
+
+enum {
+ LCDC_RGB_INTF, /* 0 */
+ DTV_INTF = LCDC_RGB_INTF, /* 0 */
+ MDDI_LCDC_INTF, /* 1 */
+ MDDI_INTF, /* 2 */
+ EBI2_INTF, /* 3 */
+ TV_INTF = EBI2_INTF, /* 3 */
+ DSI_VIDEO_INTF,
+ DSI_CMD_INTF
+};
+
+enum {
+ MDDI_PRIMARY_SET,
+ MDDI_SECONDARY_SET,
+ MDDI_EXTERNAL_SET
+};
+
+enum {
+ EBI2_LCD0,
+ EBI2_LCD1
+};
+
+#define MDP4_3D_NONE 0
+#define MDP4_3D_SIDE_BY_SIDE 1
+#define MDP4_3D_TOP_DOWN 2
+
+#define MDP4_PANEL_MDDI BIT(0)
+#define MDP4_PANEL_LCDC BIT(1)
+#define MDP4_PANEL_DTV BIT(2)
+#define MDP4_PANEL_ATV BIT(3)
+#define MDP4_PANEL_DSI_VIDEO BIT(4)
+#define MDP4_PANEL_DSI_CMD BIT(5)
+
+enum {
+ OVERLAY_MODE_NONE,
+ OVERLAY_MODE_BLT
+};
+
+enum {
+ OVERLAY_REFRESH_ON_DEMAND,
+ OVERLAY_REFRESH_VSYNC,
+ OVERLAY_REFRESH_VSYNC_HALF,
+ OVERLAY_REFRESH_VSYNC_QUARTER
+};
+
+enum {
+ OVERLAY_FRAMEBUF,
+ OVERLAY_DIRECTOUT
+};
+
+/* system interrupts */
+#define INTR_OVERLAY0_DONE BIT(0)
+#define INTR_OVERLAY1_DONE BIT(1)
+#define INTR_DMA_S_DONE BIT(2)
+#define INTR_DMA_E_DONE BIT(3)
+#define INTR_DMA_P_DONE BIT(4)
+#define INTR_VG1_HISTOGRAM BIT(5)
+#define INTR_VG2_HISTOGRAM BIT(6)
+#define INTR_PRIMARY_VSYNC BIT(7)
+#define INTR_PRIMARY_INTF_UDERRUN BIT(8)
+#define INTR_EXTERNAL_VSYNC BIT(9)
+#define INTR_EXTERNAL_INTF_UDERRUN BIT(10)
+#define INTR_PRIMARY_READ_PTR BIT(11)
+#define INTR_DMA_P_HISTOGRAM BIT(17)
+
+/* histogram interrupts */
+#define INTR_HIST_DONE BIT(1)
+#define INTR_HIST_RESET_SEQ_DONE BIT(0)
+
+
+#ifdef CONFIG_FB_MSM_OVERLAY
+#define MDP4_ANY_INTR_MASK (INTR_OVERLAY0_DONE|INTR_DMA_S_DONE | \
+ INTR_DMA_P_HISTOGRAM)
+#else
+#define MDP4_ANY_INTR_MASK (INTR_DMA_P_DONE| \
+ INTR_DMA_P_HISTOGRAM)
+#endif
+
+enum {
+ OVERLAY_PIPE_RGB1,
+ OVERLAY_PIPE_RGB2,
+ OVERLAY_PIPE_VG1, /* video/graphic */
+ OVERLAY_PIPE_VG2,
+ OVERLAY_PIPE_MAX
+};
+
+/* 2 VG pipes can be shared by RGB and VIDEO */
+#define MDP4_MAX_PIPE (OVERLAY_PIPE_MAX + 2)
+
+#define OVERLAY_TYPE_RGB 0x01
+#define OVERLAY_TYPE_VIDEO 0x02
+
+enum {
+ MDP4_MIXER0,
+ MDP4_MIXER1,
+ MDP4_MIXER_MAX
+};
+
+#define MDP4_MAX_MIXER 2
+
+enum {
+ OVERLAY_PLANE_INTERLEAVED,
+ OVERLAY_PLANE_PLANAR,
+ OVERLAY_PLANE_PSEUDO_PLANAR
+};
+
+enum {
+ MDP4_MIXER_STAGE_UNUNSED, /* pipe not used */
+ MDP4_MIXER_STAGE_BASE,
+ MDP4_MIXER_STAGE0, /* zorder 0 */
+ MDP4_MIXER_STAGE1, /* zorder 1 */
+ MDP4_MIXER_STAGE2 /* zorder 2 */
+};
+
+#define MDP4_MAX_STAGE 4
+
+enum {
+ MDP4_FRAME_FORMAT_LINEAR,
+ MDP4_FRAME_FORMAT_ARGB_TILE,
+ MDP4_FRAME_FORMAT_VIDEO_SUPERTILE
+};
+
+enum {
+ MDP4_CHROMA_RGB,
+ MDP4_CHROMA_H2V1,
+ MDP4_CHROMA_H1V2,
+ MDP4_CHROMA_420
+};
+
+#define MDP4_BLEND_BG_TRANSP_EN BIT(9)
+#define MDP4_BLEND_FG_TRANSP_EN BIT(8)
+#define MDP4_BLEND_BG_MOD_ALPHA BIT(7)
+#define MDP4_BLEND_BG_INV_ALPHA BIT(6)
+#define MDP4_BLEND_BG_ALPHA_FG_CONST (0 << 4)
+#define MDP4_BLEND_BG_ALPHA_BG_CONST (1 << 4)
+#define MDP4_BLEND_BG_ALPHA_FG_PIXEL (2 << 4)
+#define MDP4_BLEND_BG_ALPHA_BG_PIXEL (3 << 4)
+#define MDP4_BLEND_FG_MOD_ALPHA BIT(3)
+#define MDP4_BLEND_FG_INV_ALPHA BIT(2)
+#define MDP4_BLEND_FG_ALPHA_FG_CONST (0 << 0)
+#define MDP4_BLEND_FG_ALPHA_BG_CONST (1 << 0)
+#define MDP4_BLEND_FG_ALPHA_FG_PIXEL (2 << 0)
+#define MDP4_BLEND_FG_ALPHA_BG_PIXEL (3 << 0)
+
+#define MDP4_FORMAT_SOLID_FILL BIT(22)
+#define MDP4_FORMAT_UNPACK_ALIGN_MSB BIT(18)
+#define MDP4_FORMAT_UNPACK_TIGHT BIT(17)
+#define MDP4_FORMAT_90_ROTATED BIT(12)
+#define MDP4_FORMAT_ALPHA_ENABLE BIT(8)
+
+#define MDP4_OP_DEINT_ODD_REF BIT(19)
+#define MDP4_OP_DEINT_EN BIT(18)
+#define MDP4_OP_IGC_LUT_EN BIT(16)
+#define MDP4_OP_DITHER_EN BIT(15)
+#define MDP4_OP_FLIP_UD BIT(14)
+#define MDP4_OP_FLIP_LR BIT(13)
+#define MDP4_OP_CSC_EN BIT(11)
+#define MDP4_OP_SRC_DATA_YCBCR BIT(9)
+#define MDP4_OP_SCALEY_FIR (0 << 4)
+#define MDP4_OP_SCALEY_MN_PHASE (1 << 4)
+#define MDP4_OP_SCALEY_PIXEL_RPT (2 << 4)
+#define MDP4_OP_SCALEX_FIR (0 << 2)
+#define MDP4_OP_SCALEX_MN_PHASE (1 << 2)
+#define MDP4_OP_SCALEX_PIXEL_RPT (2 << 2)
+#define MDP4_OP_SCALEY_EN BIT(1)
+#define MDP4_OP_SCALEX_EN BIT(0)
+
+#define MDP4_PIPE_PER_MIXER 2
+
+#define MDP4_MAX_PLANE 4
+
+
+struct mdp4_overlay_pipe {
+ uint32 pipe_used;
+ uint32 pipe_type; /* rgb, video/graphic */
+ uint32 pipe_num;
+ uint32 pipe_ndx;
+ uint32 pipe_share;
+ uint32 mixer_num; /* which mixer used */
+ uint32 mixer_stage; /* which stage of mixer used */
+ uint32 src_format;
+ uint32 src_width; /* source img width */
+ uint32 src_height; /* source img height */
+ uint32 is_3d;
+ uint32 src_width_3d; /* source img width */
+ uint32 src_height_3d; /* source img height */
+ uint32 src_w; /* roi */
+ uint32 src_h; /* roi */
+ uint32 src_x; /* roi */
+ uint32 src_y; /* roi */
+ uint32 dst_w; /* roi */
+ uint32 dst_h; /* roi */
+ uint32 dst_x; /* roi */
+ uint32 dst_y; /* roi */
+ uint32 flags;
+ uint32 op_mode;
+ uint32 transp;
+ uint32 blend_op;
+ uint32 phasex_step;
+ uint32 phasey_step;
+ uint32 alpha;
+ uint32 is_fg; /* control alpha & color key */
+ uint32 srcp0_addr; /* interleave, luma */
+ uint32 srcp0_ystride;
+ uint32 srcp1_addr; /* pseudoplanar, chroma plane */
+ uint32 srcp1_ystride;
+ uint32 srcp2_addr; /* planar color 2*/
+ uint32 srcp2_ystride;
+ uint32 srcp3_addr; /* alpha/color 3 */
+ uint32 srcp3_ystride;
+ uint32 fetch_plane;
+ uint32 frame_format; /* video */
+ uint32 chroma_site; /* video */
+ uint32 chroma_sample; /* video */
+ uint32 solid_fill;
+ uint32 vc1_reduce; /* video */
+ uint32 unpack_align_msb;/* 0 to LSB, 1 to MSB */
+ uint32 unpack_tight;/* 0 for loose, 1 for tight */
+ uint32 unpack_count;/* 0 = 1 component, 1 = 2 component ... */
+ uint32 rotated_90; /* has been rotated 90 degree */
+ uint32 bpp; /* byte per pixel */
+ uint32 alpha_enable;/* source has alpha */
+ /*
+ * number of bits for source component,
+ * 0 = 1 bit, 1 = 2 bits, 2 = 6 bits, 3 = 8 bits
+ */
+ uint32 a_bit; /* component 3, alpha */
+ uint32 r_bit; /* component 2, R_Cr */
+ uint32 b_bit; /* component 1, B_Cb */
+ uint32 g_bit; /* component 0, G_lumz */
+ /*
+ * unpack pattern
+ * A = C3, R = C2, B = C1, G = C0
+ */
+ uint32 element3; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
+ uint32 element2; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
+ uint32 element1; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
+ uint32 element0; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
+ struct completion comp;
+ ulong blt_addr; /* blt mode addr */
+ ulong blt_base;
+ ulong blt_offset;
+ uint32 blt_cnt;
+ uint32 ov_cnt;
+ uint32 dmap_cnt;
+ uint32 blt_end;
+ uint32 luma_align_size;
+ struct completion dmas_comp;
+ struct mdp_overlay req_data;
+};
+
+#define MDP4_MAX_SHARE 2
+
+struct mdp4_pipe_desc {
+ int share;
+ int ref_cnt;
+ int ndx_list[MDP4_MAX_SHARE];
+ struct mdp4_overlay_pipe *player;
+};
+
+struct mdp4_statistic {
+ ulong intr_tot;
+ ulong intr_dma_p;
+ ulong intr_dma_s;
+ ulong intr_dma_e;
+ ulong intr_overlay0;
+ ulong intr_overlay1;
+ ulong intr_underrun_p; /* Primary interface */
+ ulong intr_underrun_e; /* external interface */
+ ulong intr_dsi;
+ ulong kickoff_mddi;
+ ulong kickoff_lcdc;
+ ulong kickoff_dtv;
+ ulong kickoff_atv;
+ ulong kickoff_dsi;
+ ulong writeback; /* blt */
+ ulong overlay_set[MDP4_MIXER_MAX];
+ ulong overlay_unset[MDP4_MIXER_MAX];
+ ulong overlay_play[MDP4_MIXER_MAX];
+ ulong pipe[MDP4_MAX_PIPE];
+ ulong dsi_clkoff;
+ ulong err_mixer;
+ ulong err_zorder;
+ ulong err_size;
+ ulong err_scale;
+ ulong err_format;
+};
+
+#ifdef CONFIG_FB_MSM_OVERLAY_WRITEBACK
+static inline int mdp4_overlay_writeback_setup(struct fb_info *fbi,
+ struct mdp4_overlay_pipe *pipe, uint8 *buf, int bpp)
+{
+ int off;
+
+ pipe->blt_base = (ulong) buf;
+ off = ALIGN(fbi->var.xres, 32) * fbi->var.yres * bpp * 2;
+ off += (1920 * 1080 * 2 * 1); /* hdmi */
+ pipe->blt_base += off;
+
+ pr_info("%s: base=%x offset=%x\n",
+ __func__, (int) pipe->blt_base, (int)off);
+
+ return off;
+
+}
+#else
+static inline int mdp4_overlay_writeback_setup(struct fb_info *fbi,
+ struct mdp4_overlay_pipe *pipe, uint8 *buf, int bpp)
+{
+ return 0;
+}
+#endif
+
+void mdp4_sw_reset(unsigned long bits);
+void mdp4_display_intf_sel(int output, unsigned long intf);
+void mdp4_overlay_cfg(int layer, int blt_mode, int refresh, int direct_out);
+void mdp4_ebi2_lcd_setup(int lcd, unsigned long base, int ystride);
+void mdp4_mddi_setup(int which, unsigned long id);
+unsigned long mdp4_display_status(void);
+void mdp4_enable_clk_irq(void);
+void mdp4_disable_clk_irq(void);
+void mdp4_dma_p_update(struct msm_fb_data_type *mfd);
+void mdp4_dma_s_update(struct msm_fb_data_type *mfd);
+void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
+ boolean isr);
+void mdp4_pipe_kickoff(uint32 pipe, struct msm_fb_data_type *mfd);
+int mdp4_lcdc_on(struct platform_device *pdev);
+int mdp4_lcdc_off(struct platform_device *pdev);
+void mdp4_lcdc_update(struct msm_fb_data_type *mfd);
+void mdp4_intr_clear_set(ulong clear, ulong set);
+void mdp4_dma_p_cfg(void);
+unsigned is_mdp4_hw_reset(void);
+void mdp4_hw_init(void);
+void mdp4_isr_read(int);
+void mdp4_clear_lcdc(void);
+void mdp4_mixer_blend_init(int mixer_num);
+void mdp4_vg_qseed_init(int vg_num);
+void mdp4_vg_csc_mv_setup(int vp_num);
+void mdp4_vg_csc_pre_bv_setup(int vp_num);
+void mdp4_vg_csc_post_bv_setup(int vp_num);
+void mdp4_vg_csc_pre_lv_setup(int vp_num);
+void mdp4_vg_csc_post_lv_setup(int vp_num);
+void mdp4_mixer1_csc_mv_setup(void);
+void mdp4_mixer1_csc_pre_bv_setup(void);
+void mdp4_mixer1_csc_post_bv_setup(void);
+void mdp4_mixer1_csc_pre_lv_setup(void);
+void mdp4_mixer1_csc_post_lv_setup(void);
+irqreturn_t mdp4_isr(int irq, void *ptr);
+void mdp4_overlay_format_to_pipe(uint32 format, struct mdp4_overlay_pipe *pipe);
+uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe);
+uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe);
+uint32 mdp4_overlay_op_mode(struct mdp4_overlay_pipe *pipe);
+void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd);
+void mdp4_overlay_dtv_ov_done_push(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe);
+void mdp4_overlay_dtv_vsync_push(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe);
+void mdp4_dtv_overlay(struct msm_fb_data_type *mfd);
+int mdp4_dtv_on(struct platform_device *pdev);
+int mdp4_dtv_off(struct platform_device *pdev);
+void mdp4_atv_overlay(struct msm_fb_data_type *mfd);
+int mdp4_atv_on(struct platform_device *pdev);
+int mdp4_atv_off(struct platform_device *pdev);
+void mdp4_dsi_video_fxn_register(cmd_fxn_t fxn);
+void mdp4_dsi_video_overlay(struct msm_fb_data_type *mfd);
+int mdp4_dsi_video_on(struct platform_device *pdev);
+int mdp4_dsi_video_off(struct platform_device *pdev);
+void mdp4_overlay0_done_dsi_video(void);
+void mdp4_overlay0_done_dsi_cmd(struct mdp_dma_data *dma);
+void mdp4_dsi_cmd_overlay(struct msm_fb_data_type *mfd);
+void mdp4_overlay_dsi_state_set(int state);
+void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe);
+void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all);
+void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe);
+struct mdp4_overlay_pipe *mdp4_overlay_stage_pipe(int mixer, int stage);
+void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe);
+void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe);
+int mdp4_mixer_stage_can_run(struct mdp4_overlay_pipe *pipe);
+void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe);
+void mdp4_mddi_overlay(struct msm_fb_data_type *mfd);
+int mdp4_overlay_format2type(uint32 format);
+int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe);
+int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req);
+int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req);
+int mdp4_overlay_unset(struct fb_info *info, int ndx);
+int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
+ struct file **pp_src_file, struct file **pp_src_plane1_file,
+ struct file **pp_src_plane2_file);
+struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(int ptype, int mixer,
+ int req_share);
+void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe);
+void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc);
+void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe);
+void mdp4_overlay_dmae_cfg(struct msm_fb_data_type *mfd, int atv);
+void mdp4_overlay_dmae_xy(struct mdp4_overlay_pipe *pipe);
+int mdp4_overlay_pipe_staged(int mixer);
+void mdp4_lcdc_primary_vsyn(void);
+void mdp4_overlay0_done_lcdc(void);
+void mdp4_overlay0_done_mddi(struct mdp_dma_data *dma);
+void mdp4_dma_s_done_mddi(void);
+void mdp4_dma_p_done_mddi(void);
+void mdp4_dma_p_done_dsi(struct mdp_dma_data *dma);
+void mdp4_overlay1_done_dtv(void);
+void mdp4_overlay1_done_atv(void);
+void mdp4_primary_vsync_lcdc(void);
+void mdp4_external_vsync_dtv(void);
+void mdp4_mddi_overlay_restore(void);
+void mdp4_overlay_lcdc_wait4vsync(struct msm_fb_data_type *mfd);
+void mdp4_overlay_lcdc_vsync_push(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe);
+void mdp4_mddi_overlay_dmas_restore(void);
+void mdp4_mddi_dma_busy_wait(struct msm_fb_data_type *mfd);
+void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe);
+void mdp4_rgb_igc_lut_setup(int num);
+void mdp4_vg_igc_lut_setup(int num);
+void mdp4_mixer_gc_lut_setup(int mixer_num);
+void mdp4_fetch_cfg(uint32 clk);
+uint32 mdp4_rgb_igc_lut_cvt(uint32 ndx);
+void mdp4_vg_qseed_init(int);
+int mdp4_overlay_blt(struct fb_info *info, struct msmfb_overlay_blt *req);
+int mdp4_overlay_blt_offset(struct fb_info *info,
+ struct msmfb_overlay_blt *req);
+
+int mdp4_dsi_overlay_blt_start(struct msm_fb_data_type *mfd);
+int mdp4_dsi_overlay_blt_stop(struct msm_fb_data_type *mfd);
+
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+void mdp4_dsi_overlay_blt(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req);
+int mdp4_dsi_overlay_blt_offset(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req);
+
+void mdp4_dsi_video_overlay_blt(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req);
+int mdp4_dsi_video_overlay_blt_offset(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req);
+
+#ifdef CONFIG_FB_MSM_MDP40
+static inline void mdp3_dsi_cmd_dma_busy_wait(struct msm_fb_data_type *mfd)
+{
+ /* empty */
+}
+#endif
+#else
+static inline void mdp4_dsi_overlay_blt(
+ struct msm_fb_data_type *mfd, struct msmfb_overlay_blt *req)
+{
+}
+static inline int mdp4_dsi_overlay_blt_offset(
+ struct msm_fb_data_type *mfd, struct msmfb_overlay_blt *req)
+{
+ return -ENODEV;
+}
+static inline void mdp4_dsi_video_overlay_blt(
+ struct msm_fb_data_type *mfd, struct msmfb_overlay_blt *req)
+{
+}
+static inline int mdp4_dsi_video_overlay_blt_offset(
+ struct msm_fb_data_type *mfd, struct msmfb_overlay_blt *req)
+{
+ return -ENODEV;
+}
+#endif
+
+void mdp4_lcdc_overlay_blt(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req);
+int mdp4_lcdc_overlay_blt_offset(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req);
+
+int mdp4_mddi_overlay_blt_offset(int *off);
+void mdp4_mddi_overlay_blt(ulong addr);
+void mdp4_overlay_panel_mode(int mixer_num, uint32 mode);
+int mdp4_overlay_mixer_play(int mixer_num);
+uint32 mdp4_overlay_panel_list(void);
+void mdp4_lcdc_overlay_kickoff(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe);
+
+void mdp4_mddi_kickoff_video(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe);
+
+void mdp4_mddi_read_ptr_intr(void);
+
+void mdp4_dsi_cmd_dma_busy_check(void);
+void mdp4_dsi_cmd_dma_busy_wait(struct msm_fb_data_type *mfd);
+void mdp4_dsi_blt_dmap_busy_wait(struct msm_fb_data_type *mfd);
+void mdp4_dsi_cmd_kickoff_ui(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe);
+void mdp4_dsi_cmd_kickoff_video(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe);
+void mdp4_dsi_cmd_overlay_kickoff(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe);
+void mdp4_dsi_cmd_overlay_restore(void);
+
+void mdp4_overlay_panel_3d(int mixer_num, uint32 panel_3d);
+int mdp4_overlay_3d(struct fb_info *info, struct msmfb_overlay_3d *req);
+void mdp4_dsi_cmd_3d(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_3d *r3d);
+
+void mdp_dmap_vsync_set(int enable);
+int mdp_dmap_vsync_get(void);
+void mdp_hw_cursor_done(void);
+void mdp_hw_cursor_init(void);
+int mdp4_mddi_overlay_cursor(struct fb_info *info, struct fb_cursor *cursor);
+int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req);
+void mdp4_overlay_resource_release(void);
+void mdp4_overlay_dsi_video_wait4vsync(struct msm_fb_data_type *mfd);
+void mdp4_overlay_dsi_video_vsync_push(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe);
+void mdp4_primary_vsync_dsi_video(void);
+uint32_t mdp4_ss_table_value(int8_t param, int8_t index);
+void mdp4_overlay_status_write(enum mdp4_overlay_status type, bool val);
+bool mdp4_overlay_status_read(enum mdp4_overlay_status type);
+#endif /* MDP_H */
diff --git a/drivers/video/msm/mdp4_dtv.c b/drivers/video/msm/mdp4_dtv.c
new file mode 100644
index 0000000..b039da8
--- /dev/null
+++ b/drivers/video/msm/mdp4_dtv.c
@@ -0,0 +1,329 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/msm_reqs.h>
+#include <linux/pm_runtime.h>
+#include <mach/clk.h>
+
+#include "msm_fb.h"
+#include "mdp4.h"
+
+static int dtv_probe(struct platform_device *pdev);
+static int dtv_remove(struct platform_device *pdev);
+
+static int dtv_off(struct platform_device *pdev);
+static int dtv_on(struct platform_device *pdev);
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+
+static struct clk *tv_src_clk;
+static struct clk *hdmi_clk;
+static struct clk *mdp_tv_clk;
+
+
+static int mdp4_dtv_runtime_suspend(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: suspending...\n");
+ return 0;
+}
+
+static int mdp4_dtv_runtime_resume(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: resuming...\n");
+ return 0;
+}
+
+static const struct dev_pm_ops mdp4_dtv_dev_pm_ops = {
+ .runtime_suspend = mdp4_dtv_runtime_suspend,
+ .runtime_resume = mdp4_dtv_runtime_resume,
+};
+
+static struct platform_driver dtv_driver = {
+ .probe = dtv_probe,
+ .remove = dtv_remove,
+ .suspend = NULL,
+ .resume = NULL,
+ .shutdown = NULL,
+ .driver = {
+ .name = "dtv",
+ .pm = &mdp4_dtv_dev_pm_ops,
+ },
+};
+
+static struct lcdc_platform_data *dtv_pdata;
+#ifdef CONFIG_MSM_BUS_SCALING
+static uint32_t dtv_bus_scale_handle;
+#else
+static struct clk *ebi1_clk;
+#endif
+
+static int dtv_off(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ ret = panel_next_off(pdev);
+
+ pr_info("%s\n", __func__);
+
+ clk_disable(hdmi_clk);
+ if (mdp_tv_clk)
+ clk_disable(mdp_tv_clk);
+
+ if (dtv_pdata && dtv_pdata->lcdc_power_save)
+ dtv_pdata->lcdc_power_save(0);
+
+ if (dtv_pdata && dtv_pdata->lcdc_gpio_config)
+ ret = dtv_pdata->lcdc_gpio_config(0);
+#ifdef CONFIG_MSM_BUS_SCALING
+ if (dtv_bus_scale_handle > 0)
+ msm_bus_scale_client_update_request(dtv_bus_scale_handle,
+ 0);
+#else
+ if (ebi1_clk)
+ clk_disable(ebi1_clk);
+#endif
+ mdp4_extn_disp = 0;
+ return ret;
+}
+
+static int dtv_on(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct msm_fb_data_type *mfd;
+ unsigned long panel_pixclock_freq , pm_qos_rate;
+
+ mfd = platform_get_drvdata(pdev);
+ panel_pixclock_freq = mfd->fbi->var.pixclock;
+
+#ifdef CONFIG_MSM_NPA_SYSTEM_BUS
+ pm_qos_rate = MSM_AXI_FLOW_MDP_DTV_720P_2BPP;
+#else
+ if (panel_pixclock_freq > 58000000)
+ /* pm_qos_rate should be in Khz */
+ pm_qos_rate = panel_pixclock_freq / 1000 ;
+ else
+ pm_qos_rate = 58000;
+#endif
+ mdp_set_core_clk(1);
+ mdp4_extn_disp = 1;
+#ifdef CONFIG_MSM_BUS_SCALING
+ if (dtv_bus_scale_handle > 0)
+ msm_bus_scale_client_update_request(dtv_bus_scale_handle,
+ 1);
+#else
+ if (ebi1_clk) {
+ clk_set_rate(ebi1_clk, pm_qos_rate * 1000);
+ clk_enable(ebi1_clk);
+ }
+#endif
+ mfd = platform_get_drvdata(pdev);
+
+ ret = clk_set_rate(tv_src_clk, mfd->fbi->var.pixclock);
+ if (ret) {
+ pr_info("%s: clk_set_rate(%d) failed\n", __func__,
+ mfd->fbi->var.pixclock);
+ if (mfd->fbi->var.pixclock == 27030000)
+ mfd->fbi->var.pixclock = 27000000;
+ ret = clk_set_rate(tv_src_clk, mfd->fbi->var.pixclock);
+ }
+ pr_info("%s: tv_src_clk=%dkHz, pm_qos_rate=%ldkHz, [%d]\n", __func__,
+ mfd->fbi->var.pixclock/1000, pm_qos_rate, ret);
+
+ clk_enable(hdmi_clk);
+ clk_reset(hdmi_clk, CLK_RESET_ASSERT);
+ udelay(20);
+ clk_reset(hdmi_clk, CLK_RESET_DEASSERT);
+
+ if (mdp_tv_clk)
+ clk_enable(mdp_tv_clk);
+
+ if (dtv_pdata && dtv_pdata->lcdc_power_save)
+ dtv_pdata->lcdc_power_save(1);
+ if (dtv_pdata && dtv_pdata->lcdc_gpio_config)
+ ret = dtv_pdata->lcdc_gpio_config(1);
+
+ ret = panel_next_on(pdev);
+ return ret;
+}
+
+static int dtv_probe(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct fb_info *fbi;
+ struct platform_device *mdp_dev = NULL;
+ struct msm_fb_panel_data *pdata = NULL;
+ int rc;
+
+ if (pdev->id == 0) {
+ dtv_pdata = pdev->dev.platform_data;
+ return 0;
+ }
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+ return -ENOMEM;
+
+ mdp_dev = platform_device_alloc("mdp", pdev->id);
+ if (!mdp_dev)
+ return -ENOMEM;
+
+ /*
+ * link to the latest pdev
+ */
+ mfd->pdev = mdp_dev;
+ mfd->dest = DISPLAY_LCDC;
+
+ /*
+ * alloc panel device data
+ */
+ if (platform_device_add_data
+ (mdp_dev, pdev->dev.platform_data,
+ sizeof(struct msm_fb_panel_data))) {
+ pr_err("dtv_probe: platform_device_add_data failed!\n");
+ platform_device_put(mdp_dev);
+ return -ENOMEM;
+ }
+ /*
+ * data chain
+ */
+ pdata = (struct msm_fb_panel_data *)mdp_dev->dev.platform_data;
+ pdata->on = dtv_on;
+ pdata->off = dtv_off;
+ pdata->next = pdev;
+
+ /*
+ * get/set panel specific fb info
+ */
+ mfd->panel_info = pdata->panel_info;
+ mfd->fb_imgType = MDP_RGB_565;
+
+ fbi = mfd->fbi;
+ fbi->var.pixclock = mfd->panel_info.clk_rate;
+ fbi->var.left_margin = mfd->panel_info.lcdc.h_back_porch;
+ fbi->var.right_margin = mfd->panel_info.lcdc.h_front_porch;
+ fbi->var.upper_margin = mfd->panel_info.lcdc.v_back_porch;
+ fbi->var.lower_margin = mfd->panel_info.lcdc.v_front_porch;
+ fbi->var.hsync_len = mfd->panel_info.lcdc.h_pulse_width;
+ fbi->var.vsync_len = mfd->panel_info.lcdc.v_pulse_width;
+
+#ifdef CONFIG_MSM_BUS_SCALING
+ if (!dtv_bus_scale_handle && dtv_pdata &&
+ dtv_pdata->bus_scale_table) {
+ dtv_bus_scale_handle =
+ msm_bus_scale_register_client(
+ dtv_pdata->bus_scale_table);
+ if (!dtv_bus_scale_handle) {
+ pr_err("%s not able to get bus scale\n",
+ __func__);
+ }
+ }
+#else
+ ebi1_clk = clk_get(NULL, "ebi1_dtv_clk");
+ if (IS_ERR(ebi1_clk)) {
+ ebi1_clk = NULL;
+ pr_warning("%s: Couldn't get ebi1 clock\n", __func__);
+ }
+#endif
+ /*
+ * set driver data
+ */
+ platform_set_drvdata(mdp_dev, mfd);
+
+ /*
+ * register in mdp driver
+ */
+ rc = platform_device_add(mdp_dev);
+ if (rc)
+ goto dtv_probe_err;
+
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+ pdev_list[pdev_list_cnt++] = pdev;
+ return 0;
+
+dtv_probe_err:
+#ifdef CONFIG_MSM_BUS_SCALING
+ if (dtv_pdata && dtv_pdata->bus_scale_table &&
+ dtv_bus_scale_handle > 0)
+ msm_bus_scale_unregister_client(dtv_bus_scale_handle);
+#endif
+ platform_device_put(mdp_dev);
+ return rc;
+}
+
+static int dtv_remove(struct platform_device *pdev)
+{
+#ifdef CONFIG_MSM_BUS_SCALING
+ if (dtv_pdata && dtv_pdata->bus_scale_table &&
+ dtv_bus_scale_handle > 0)
+ msm_bus_scale_unregister_client(dtv_bus_scale_handle);
+#else
+ if (ebi1_clk)
+ clk_put(ebi1_clk);
+#endif
+ pm_runtime_disable(&pdev->dev);
+ return 0;
+}
+
+static int dtv_register_driver(void)
+{
+ return platform_driver_register(&dtv_driver);
+}
+
+static int __init dtv_driver_init(void)
+{
+ tv_src_clk = clk_get(NULL, "tv_src_clk");
+ if (IS_ERR(tv_src_clk)) {
+ pr_err("error: can't get tv_src_clk!\n");
+ return IS_ERR(tv_src_clk);
+ }
+
+ hdmi_clk = clk_get(NULL, "hdmi_clk");
+ if (IS_ERR(hdmi_clk)) {
+ pr_err("error: can't get hdmi_clk!\n");
+ return IS_ERR(hdmi_clk);
+ }
+
+ mdp_tv_clk = clk_get(NULL, "mdp_tv_clk");
+ if (IS_ERR(mdp_tv_clk))
+ mdp_tv_clk = NULL;
+
+ return dtv_register_driver();
+}
+
+module_init(dtv_driver_init);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
new file mode 100644
index 0000000..cc3bd1b
--- /dev/null
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -0,0 +1,2290 @@
+/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/clk.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/fb.h>
+#include <linux/msm_mdp.h>
+#include <linux/file.h>
+#include <linux/android_pmem.h>
+#include <linux/major.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/mutex.h>
+#include <linux/msm_kgsl.h>
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+#define VERSION_KEY_MASK 0xFFFFFF00
+
+struct mdp4_overlay_ctrl {
+ struct mdp4_pipe_desc ov_pipe[OVERLAY_PIPE_MAX];/* 4 */
+ struct mdp4_overlay_pipe plist[MDP4_MAX_PIPE]; /* 4 + 2 */
+ struct mdp4_overlay_pipe *stage[MDP4_MAX_MIXER][MDP4_MAX_STAGE + 2];
+ uint32 panel_3d;
+ uint32 panel_mode;
+ uint32 mixer0_played;
+ uint32 mixer1_played;
+} mdp4_overlay_db = {
+ .ov_pipe = {
+ {
+ .share = 0, /* RGB 1 */
+ },
+ {
+ .share = 0, /* RGB 2 */
+ },
+ {
+ .share = 1, /* VG 1 */
+ },
+ {
+ .share = 1, /* VG 2 */
+ },
+ },
+ .plist = {
+ {
+ .pipe_type = OVERLAY_TYPE_RGB,
+ .pipe_num = OVERLAY_PIPE_RGB1,
+ .pipe_ndx = 1,
+ },
+ {
+ .pipe_type = OVERLAY_TYPE_RGB,
+ .pipe_num = OVERLAY_PIPE_RGB2,
+ .pipe_ndx = 2,
+ },
+ {
+ .pipe_type = OVERLAY_TYPE_RGB, /* shared */
+ .pipe_num = OVERLAY_PIPE_VG1,
+ .pipe_ndx = 3,
+ },
+ {
+ .pipe_type = OVERLAY_TYPE_RGB, /* shared */
+ .pipe_num = OVERLAY_PIPE_VG2,
+ .pipe_ndx = 4,
+ },
+ {
+ .pipe_type = OVERLAY_TYPE_VIDEO, /* shared */
+ .pipe_num = OVERLAY_PIPE_VG1,
+ .pipe_ndx = 5,
+ },
+ {
+ .pipe_type = OVERLAY_TYPE_VIDEO, /* shared */
+ .pipe_num = OVERLAY_PIPE_VG2,
+ .pipe_ndx = 6,
+ },
+ },
+};
+
+static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db;
+static uint32 perf_level;
+static uint32 mdp4_del_res_rel;
+/* static array with index 0 for unset status and 1 for set status */
+static bool overlay_status[MDP4_OVERLAY_TYPE_MAX];
+
+void mdp4_overlay_status_write(enum mdp4_overlay_status type, bool val)
+{
+ overlay_status[type] = val;
+}
+
+bool mdp4_overlay_status_read(enum mdp4_overlay_status type)
+{
+ return overlay_status[type];
+}
+
+int mdp4_overlay_mixer_play(int mixer_num)
+{
+ if (mixer_num == MDP4_MIXER1)
+ return ctrl->mixer1_played;
+ else
+ return ctrl->mixer0_played;
+}
+
+void mdp4_overlay_panel_3d(int mixer_num, uint32 panel_3d)
+{
+ ctrl->panel_3d = panel_3d;
+}
+
+void mdp4_overlay_panel_mode(int mixer_num, uint32 mode)
+{
+ ctrl->panel_mode |= mode;
+}
+
+uint32 mdp4_overlay_panel_list(void)
+{
+ return ctrl->panel_mode;
+}
+
+void mdp4_overlay_dmae_cfg(struct msm_fb_data_type *mfd, int atv)
+{
+ uint32 dmae_cfg_reg;
+
+ if (atv)
+ dmae_cfg_reg = DMA_DEFLKR_EN;
+ else
+ dmae_cfg_reg = 0;
+
+ if (mfd->fb_imgType == MDP_BGR_565)
+ dmae_cfg_reg |= DMA_PACK_PATTERN_BGR;
+ else
+ dmae_cfg_reg |= DMA_PACK_PATTERN_RGB;
+
+
+ if (mfd->panel_info.bpp == 18) {
+ dmae_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */
+ DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+ } else if (mfd->panel_info.bpp == 16) {
+ dmae_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */
+ DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
+ } else {
+ dmae_cfg_reg |= DMA_DSTC0G_8BITS | /* 888 16BPP */
+ DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
+ }
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ /* dma2 config register */
+ MDP_OUTP(MDP_BASE + 0xb0000, dmae_cfg_reg);
+ if (atv) {
+ MDP_OUTP(MDP_BASE + 0xb0070, 0xeb0010);
+ MDP_OUTP(MDP_BASE + 0xb0074, 0xf00010);
+ MDP_OUTP(MDP_BASE + 0xb0078, 0xf00010);
+ MDP_OUTP(MDP_BASE + 0xb3000, 0x80);
+ MDP_OUTP(MDP_BASE + 0xb3010, 0x1800040);
+ MDP_OUTP(MDP_BASE + 0xb3014, 0x1000080);
+ MDP_OUTP(MDP_BASE + 0xb4004, 0x67686970);
+ } else {
+ MDP_OUTP(MDP_BASE + 0xb0070, 0xff0000);
+ MDP_OUTP(MDP_BASE + 0xb0074, 0xff0000);
+ MDP_OUTP(MDP_BASE + 0xb0078, 0xff0000);
+ }
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void unfill_black_screen(void)
+{
+ uint32 temp_src_format;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ /*
+ * VG2 Constant Color
+ */
+ temp_src_format = inpdw(MDP_BASE + 0x30050);
+ MDP_OUTP(MDP_BASE + 0x30050, temp_src_format&(~BIT(22)));
+ /*
+ * MDP_OVERLAY_REG_FLUSH
+ */
+ MDP_OUTP(MDP_BASE + 0x18000, BIT(3));
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void fill_black_screen(void)
+{
+ /*Black color*/
+ uint32 color = 0x00000000;
+ uint32 temp_src_format;
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ /*
+ * VG2 Constant Color
+ */
+ MDP_OUTP(MDP_BASE + 0x31008, color);
+ /*
+ * MDP_VG2_SRC_FORMAT
+ */
+ temp_src_format = inpdw(MDP_BASE + 0x30050);
+ MDP_OUTP(MDP_BASE + 0x30050, temp_src_format | BIT(22));
+ /*
+ * MDP_OVERLAY_REG_FLUSH
+ */
+ MDP_OUTP(MDP_BASE + 0x18000, BIT(3));
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_overlay_dmae_xy(struct mdp4_overlay_pipe *pipe)
+{
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ /* dma_p source */
+ MDP_OUTP(MDP_BASE + 0xb0004,
+ (pipe->src_height << 16 | pipe->src_width));
+ MDP_OUTP(MDP_BASE + 0xb0008, pipe->srcp0_addr);
+ MDP_OUTP(MDP_BASE + 0xb000c, pipe->srcp0_ystride);
+
+ /* dma_p dest */
+ MDP_OUTP(MDP_BASE + 0xb0010, (pipe->dst_y << 16 | pipe->dst_x));
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc)
+{
+ uint32 dma2_cfg_reg;
+
+ dma2_cfg_reg = DMA_DITHER_EN;
+#ifdef BLT_RGB565
+ /* RGB888 is 0 */
+ dma2_cfg_reg |= DMA_BUF_FORMAT_RGB565; /* blt only */
+#endif
+
+ if (mfd->fb_imgType == MDP_BGR_565)
+ dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
+ else
+ dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
+
+
+ if (mfd->panel_info.bpp == 18) {
+ dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */
+ DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+ } else if (mfd->panel_info.bpp == 16) {
+ dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */
+ DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
+ } else {
+ dma2_cfg_reg |= DMA_DSTC0G_8BITS | /* 888 16BPP */
+ DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
+ }
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+#ifndef CONFIG_FB_MSM_LCDC_CHIMEI_WXGA_PANEL
+ if (lcdc)
+ dma2_cfg_reg |= DMA_PACK_ALIGN_MSB;
+#endif
+
+ /* dma2 config register */
+ MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+/*
+ * mdp4_overlay_dmap_xy: called form baselayer only
+ */
+void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 off, bpp;
+
+ if (mdp_is_in_isr == FALSE)
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ /* dma_p source */
+ MDP_OUTP(MDP_BASE + 0x90004,
+ (pipe->src_height << 16 | pipe->src_width));
+ if (pipe->blt_addr) {
+#ifdef BLT_RGB565
+ bpp = 2; /* overlay ouput is RGB565 */
+#else
+ bpp = 3; /* overlay ouput is RGB888 */
+#endif
+ off = 0;
+ if (pipe->dmap_cnt & 0x01)
+ off = pipe->src_height * pipe->src_width * bpp;
+ MDP_OUTP(MDP_BASE + 0x90008, pipe->blt_addr + off);
+ /* RGB888, output of overlay blending */
+ MDP_OUTP(MDP_BASE + 0x9000c, pipe->src_width * bpp);
+ } else {
+ MDP_OUTP(MDP_BASE + 0x90008, pipe->srcp0_addr);
+ MDP_OUTP(MDP_BASE + 0x9000c, pipe->srcp0_ystride);
+ }
+
+ /* dma_p dest */
+ MDP_OUTP(MDP_BASE + 0x90010, (pipe->dst_y << 16 | pipe->dst_x));
+
+ if (mdp_is_in_isr == FALSE)
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+#define MDP4_VG_PHASE_STEP_DEFAULT 0x20000000
+#define MDP4_VG_PHASE_STEP_SHIFT 29
+
+static int mdp4_leading_0(uint32 num)
+{
+ uint32 bit = 0x80000000;
+ int i;
+
+ for (i = 0; i < 32; i++) {
+ if (bit & num)
+ return i;
+ bit >>= 1;
+ }
+
+ return i;
+}
+
+static uint32 mdp4_scale_phase_step(int f_num, uint32 src, uint32 dst)
+{
+ uint32 val;
+ int n;
+
+ n = mdp4_leading_0(src);
+ if (n > f_num)
+ n = f_num;
+ val = src << n; /* maximum to reduce lose of resolution */
+ val /= dst;
+ if (n < f_num) {
+ n = f_num - n;
+ val <<= n;
+ }
+
+ return val;
+}
+
+static void mdp4_scale_setup(struct mdp4_overlay_pipe *pipe)
+{
+ int ptype;
+
+ pipe->phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
+ pipe->phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
+ ptype = mdp4_overlay_format2type(pipe->src_format);
+
+ if (pipe->dst_h && pipe->src_h != pipe->dst_h) {
+ if (pipe->dst_h > pipe->src_h * 8) /* too much */
+ return;
+ pipe->op_mode |= MDP4_OP_SCALEY_EN;
+
+ if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {
+ if (pipe->dst_h <= (pipe->src_h / 4))
+ pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE;
+ else
+ pipe->op_mode |= MDP4_OP_SCALEY_FIR;
+ }
+
+ pipe->phasey_step = mdp4_scale_phase_step(29,
+ pipe->src_h, pipe->dst_h);
+ }
+
+ if (pipe->dst_w && pipe->src_w != pipe->dst_w) {
+ if (pipe->dst_w > pipe->src_w * 8) /* too much */
+ return;
+ pipe->op_mode |= MDP4_OP_SCALEX_EN;
+
+ if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {
+ if (pipe->dst_w <= (pipe->src_w / 4))
+ pipe->op_mode |= MDP4_OP_SCALEX_MN_PHASE;
+ else
+ pipe->op_mode |= MDP4_OP_SCALEX_FIR;
+ }
+
+ pipe->phasex_step = mdp4_scale_phase_step(29,
+ pipe->src_w, pipe->dst_w);
+ }
+}
+
+void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe)
+{
+ char *rgb_base;
+ uint32 src_size, src_xy, dst_size, dst_xy;
+ uint32 format, pattern;
+
+ rgb_base = MDP_BASE + MDP4_RGB_BASE;
+ rgb_base += (MDP4_RGB_OFF * pipe->pipe_num);
+
+ src_size = ((pipe->src_h << 16) | pipe->src_w);
+ src_xy = ((pipe->src_y << 16) | pipe->src_x);
+ dst_size = ((pipe->dst_h << 16) | pipe->dst_w);
+ dst_xy = ((pipe->dst_y << 16) | pipe->dst_x);
+
+ format = mdp4_overlay_format(pipe);
+ pattern = mdp4_overlay_unpack_pattern(pipe);
+
+#ifdef MDP4_IGC_LUT_ENABLE
+ pipe->op_mode |= MDP4_OP_IGC_LUT_EN;
+#endif
+
+ mdp4_scale_setup(pipe);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ outpdw(rgb_base + 0x0000, src_size); /* MDP_RGB_SRC_SIZE */
+ outpdw(rgb_base + 0x0004, src_xy); /* MDP_RGB_SRC_XY */
+ outpdw(rgb_base + 0x0008, dst_size); /* MDP_RGB_DST_SIZE */
+ outpdw(rgb_base + 0x000c, dst_xy); /* MDP_RGB_DST_XY */
+
+ outpdw(rgb_base + 0x0010, pipe->srcp0_addr);
+ outpdw(rgb_base + 0x0040, pipe->srcp0_ystride);
+
+ outpdw(rgb_base + 0x0050, format);/* MDP_RGB_SRC_FORMAT */
+ outpdw(rgb_base + 0x0054, pattern);/* MDP_RGB_SRC_UNPACK_PATTERN */
+ outpdw(rgb_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */
+ outpdw(rgb_base + 0x005c, pipe->phasex_step);
+ outpdw(rgb_base + 0x0060, pipe->phasey_step);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ mdp4_stat.pipe[pipe->pipe_num]++;
+}
+
+void mdp4_overlay_vg_setup(struct mdp4_overlay_pipe *pipe)
+{
+ char *vg_base;
+ uint32 frame_size, src_size, src_xy, dst_size, dst_xy;
+ uint32 format, pattern;
+ int pnum;
+
+ pnum = pipe->pipe_num - OVERLAY_PIPE_VG1; /* start from 0 */
+ vg_base = MDP_BASE + MDP4_VIDEO_BASE;
+ vg_base += (MDP4_VIDEO_OFF * pnum);
+
+ frame_size = ((pipe->src_height << 16) | pipe->src_width);
+ src_size = ((pipe->src_h << 16) | pipe->src_w);
+ src_xy = ((pipe->src_y << 16) | pipe->src_x);
+ dst_size = ((pipe->dst_h << 16) | pipe->dst_w);
+ dst_xy = ((pipe->dst_y << 16) | pipe->dst_x);
+
+ format = mdp4_overlay_format(pipe);
+ pattern = mdp4_overlay_unpack_pattern(pipe);
+
+ /* not RGB use VG pipe, pure VG pipe */
+ if (pipe->pipe_type != OVERLAY_TYPE_RGB)
+#ifdef MDP4_IGC_LUT_ENABLE
+ pipe->op_mode |= (MDP4_OP_CSC_EN | MDP4_OP_SRC_DATA_YCBCR |
+ MDP4_OP_IGC_LUT_EN);
+#else
+ pipe->op_mode |= (MDP4_OP_CSC_EN | MDP4_OP_SRC_DATA_YCBCR);
+#endif
+
+ mdp4_scale_setup(pipe);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ outpdw(vg_base + 0x0000, src_size); /* MDP_RGB_SRC_SIZE */
+ outpdw(vg_base + 0x0004, src_xy); /* MDP_RGB_SRC_XY */
+ outpdw(vg_base + 0x0008, dst_size); /* MDP_RGB_DST_SIZE */
+ outpdw(vg_base + 0x000c, dst_xy); /* MDP_RGB_DST_XY */
+ outpdw(vg_base + 0x0048, frame_size); /* TILE frame size */
+
+ /* luma component plane */
+ outpdw(vg_base + 0x0010, pipe->srcp0_addr);
+
+ /* chroma component plane or planar color 1 */
+ outpdw(vg_base + 0x0014, pipe->srcp1_addr);
+
+ /* planar color 2 */
+ outpdw(vg_base + 0x0018, pipe->srcp2_addr);
+
+ outpdw(vg_base + 0x0040,
+ pipe->srcp1_ystride << 16 | pipe->srcp0_ystride);
+
+ outpdw(vg_base + 0x0044,
+ pipe->srcp3_ystride << 16 | pipe->srcp2_ystride);
+
+ outpdw(vg_base + 0x0050, format); /* MDP_RGB_SRC_FORMAT */
+ outpdw(vg_base + 0x0054, pattern); /* MDP_RGB_SRC_UNPACK_PATTERN */
+ outpdw(vg_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */
+ outpdw(vg_base + 0x005c, pipe->phasex_step);
+ outpdw(vg_base + 0x0060, pipe->phasey_step);
+
+ if (pipe->op_mode & MDP4_OP_DITHER_EN) {
+ outpdw(vg_base + 0x0068,
+ pipe->r_bit << 4 | pipe->b_bit << 2 | pipe->g_bit);
+ }
+
+ if (pipe->flags & MDP_SHARPENING) {
+ outpdw(vg_base + 0x8200,
+ mdp4_ss_table_value(pipe->req_data.dpp.sharp_strength,
+ 0));
+ outpdw(vg_base + 0x8204,
+ mdp4_ss_table_value(pipe->req_data.dpp.sharp_strength,
+ 1));
+ }
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ mdp4_stat.pipe[pipe->pipe_num]++;
+}
+
+int mdp4_overlay_format2type(uint32 format)
+{
+ switch (format) {
+ case MDP_RGB_565:
+ case MDP_RGB_888:
+ case MDP_BGR_565:
+ case MDP_XRGB_8888:
+ case MDP_ARGB_8888:
+ case MDP_RGBA_8888:
+ case MDP_BGRA_8888:
+ case MDP_RGBX_8888:
+ return OVERLAY_TYPE_RGB;
+ case MDP_YCRYCB_H2V1:
+ case MDP_Y_CRCB_H2V1:
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V2:
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CBCR_H2V2_TILE:
+ case MDP_Y_CRCB_H2V2_TILE:
+ case MDP_Y_CR_CB_H2V2:
+ case MDP_Y_CB_CR_H2V2:
+ case MDP_Y_CRCB_H1V1:
+ case MDP_Y_CBCR_H1V1:
+ return OVERLAY_TYPE_VIDEO;
+ default:
+ mdp4_stat.err_format++;
+ return -ERANGE;
+ }
+
+}
+
+#define C3_ALPHA 3 /* alpha */
+#define C2_R_Cr 2 /* R/Cr */
+#define C1_B_Cb 1 /* B/Cb */
+#define C0_G_Y 0 /* G/luma */
+#define YUV_444_MAX_WIDTH 1280 /* Max width for YUV 444*/
+
+int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe)
+{
+ switch (pipe->src_format) {
+ case MDP_RGB_565:
+ pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+ pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+ pipe->a_bit = 0;
+ pipe->r_bit = 1; /* R, 5 bits */
+ pipe->b_bit = 1; /* B, 5 bits */
+ pipe->g_bit = 2; /* G, 6 bits */
+ pipe->alpha_enable = 0;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 2;
+ pipe->element2 = C2_R_Cr; /* R */
+ pipe->element1 = C0_G_Y; /* G */
+ pipe->element0 = C1_B_Cb; /* B */
+ pipe->bpp = 2; /* 2 bpp */
+ break;
+ case MDP_RGB_888:
+ pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+ pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+ pipe->a_bit = 0;
+ pipe->r_bit = 3; /* R, 8 bits */
+ pipe->b_bit = 3; /* B, 8 bits */
+ pipe->g_bit = 3; /* G, 8 bits */
+ pipe->alpha_enable = 0;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 2;
+ pipe->element2 = C2_R_Cr; /* R */
+ pipe->element1 = C0_G_Y; /* G */
+ pipe->element0 = C1_B_Cb; /* B */
+ pipe->bpp = 3; /* 3 bpp */
+ break;
+ case MDP_BGR_565:
+ pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+ pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+ pipe->a_bit = 0;
+ pipe->r_bit = 1; /* R, 5 bits */
+ pipe->b_bit = 1; /* B, 5 bits */
+ pipe->g_bit = 2; /* G, 6 bits */
+ pipe->alpha_enable = 0;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 2;
+ pipe->element2 = C1_B_Cb; /* B */
+ pipe->element1 = C0_G_Y; /* G */
+ pipe->element0 = C2_R_Cr; /* R */
+ pipe->bpp = 2; /* 2 bpp */
+ break;
+ case MDP_XRGB_8888:
+ pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+ pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+ pipe->a_bit = 3; /* alpha, 4 bits */
+ pipe->r_bit = 3; /* R, 8 bits */
+ pipe->b_bit = 3; /* B, 8 bits */
+ pipe->g_bit = 3; /* G, 8 bits */
+ pipe->alpha_enable = 0;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 3;
+ pipe->element3 = C3_ALPHA; /* alpha */
+ pipe->element2 = C2_R_Cr; /* R */
+ pipe->element1 = C0_G_Y; /* G */
+ pipe->element0 = C1_B_Cb; /* B */
+ pipe->bpp = 4; /* 4 bpp */
+ break;
+ case MDP_ARGB_8888:
+ pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+ pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+ pipe->a_bit = 3; /* alpha, 4 bits */
+ pipe->r_bit = 3; /* R, 8 bits */
+ pipe->b_bit = 3; /* B, 8 bits */
+ pipe->g_bit = 3; /* G, 8 bits */
+ pipe->alpha_enable = 1;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 3;
+ pipe->element3 = C3_ALPHA; /* alpha */
+ pipe->element2 = C2_R_Cr; /* R */
+ pipe->element1 = C0_G_Y; /* G */
+ pipe->element0 = C1_B_Cb; /* B */
+ pipe->bpp = 4; /* 4 bpp */
+ break;
+ case MDP_RGBA_8888:
+ pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+ pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+ pipe->a_bit = 3; /* alpha, 4 bits */
+ pipe->r_bit = 3; /* R, 8 bits */
+ pipe->b_bit = 3; /* B, 8 bits */
+ pipe->g_bit = 3; /* G, 8 bits */
+ pipe->alpha_enable = 1;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 3;
+ pipe->element3 = C3_ALPHA; /* alpha */
+ pipe->element2 = C1_B_Cb; /* B */
+ pipe->element1 = C0_G_Y; /* G */
+ pipe->element0 = C2_R_Cr; /* R */
+ pipe->bpp = 4; /* 4 bpp */
+ break;
+ case MDP_RGBX_8888:
+ pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+ pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+ pipe->a_bit = 3;
+ pipe->r_bit = 3; /* R, 8 bits */
+ pipe->b_bit = 3; /* B, 8 bits */
+ pipe->g_bit = 3; /* G, 8 bits */
+ pipe->alpha_enable = 0;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 3;
+ pipe->element3 = C3_ALPHA; /* alpha */
+ pipe->element2 = C1_B_Cb; /* B */
+ pipe->element1 = C0_G_Y; /* G */
+ pipe->element0 = C2_R_Cr; /* R */
+ pipe->bpp = 4; /* 4 bpp */
+ break;
+ case MDP_BGRA_8888:
+ pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+ pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+ pipe->a_bit = 3; /* alpha, 4 bits */
+ pipe->r_bit = 3; /* R, 8 bits */
+ pipe->b_bit = 3; /* B, 8 bits */
+ pipe->g_bit = 3; /* G, 8 bits */
+ pipe->alpha_enable = 1;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 3;
+ pipe->element3 = C3_ALPHA; /* alpha */
+ pipe->element2 = C2_R_Cr; /* R */
+ pipe->element1 = C0_G_Y; /* G */
+ pipe->element0 = C1_B_Cb; /* B */
+ pipe->bpp = 4; /* 4 bpp */
+ break;
+ case MDP_YCRYCB_H2V1:
+ pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+ pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+ pipe->a_bit = 0; /* alpha, 4 bits */
+ pipe->r_bit = 3; /* R, 8 bits */
+ pipe->b_bit = 3; /* B, 8 bits */
+ pipe->g_bit = 3; /* G, 8 bits */
+ pipe->alpha_enable = 0;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 3;
+ pipe->element3 = C0_G_Y; /* G */
+ pipe->element2 = C2_R_Cr; /* R */
+ pipe->element1 = C0_G_Y; /* G */
+ pipe->element0 = C1_B_Cb; /* B */
+ pipe->bpp = 2; /* 2 bpp */
+ pipe->chroma_sample = MDP4_CHROMA_H2V1;
+ break;
+ case MDP_Y_CRCB_H2V1:
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V2:
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H1V1:
+ case MDP_Y_CBCR_H1V1:
+ pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+ pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR;
+ pipe->a_bit = 0;
+ pipe->r_bit = 3; /* R, 8 bits */
+ pipe->b_bit = 3; /* B, 8 bits */
+ pipe->g_bit = 3; /* G, 8 bits */
+ pipe->alpha_enable = 0;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 1; /* 2 */
+ pipe->element3 = C0_G_Y; /* not used */
+ pipe->element2 = C0_G_Y; /* not used */
+ if (pipe->src_format == MDP_Y_CRCB_H2V1) {
+ pipe->element1 = C2_R_Cr; /* R */
+ pipe->element0 = C1_B_Cb; /* B */
+ pipe->chroma_sample = MDP4_CHROMA_H2V1;
+ } else if (pipe->src_format == MDP_Y_CRCB_H1V1) {
+ pipe->element1 = C2_R_Cr; /* R */
+ pipe->element0 = C1_B_Cb; /* B */
+ if (pipe->src_width > YUV_444_MAX_WIDTH)
+ pipe->chroma_sample = MDP4_CHROMA_H1V2;
+ else
+ pipe->chroma_sample = MDP4_CHROMA_RGB;
+ } else if (pipe->src_format == MDP_Y_CBCR_H2V1) {
+ pipe->element1 = C1_B_Cb; /* B */
+ pipe->element0 = C2_R_Cr; /* R */
+ pipe->chroma_sample = MDP4_CHROMA_H2V1;
+ } else if (pipe->src_format == MDP_Y_CBCR_H1V1) {
+ pipe->element1 = C1_B_Cb; /* B */
+ pipe->element0 = C2_R_Cr; /* R */
+ if (pipe->src_width > YUV_444_MAX_WIDTH)
+ pipe->chroma_sample = MDP4_CHROMA_H1V2;
+ else
+ pipe->chroma_sample = MDP4_CHROMA_RGB;
+ } else if (pipe->src_format == MDP_Y_CRCB_H2V2) {
+ pipe->element1 = C2_R_Cr; /* R */
+ pipe->element0 = C1_B_Cb; /* B */
+ pipe->chroma_sample = MDP4_CHROMA_420;
+ } else if (pipe->src_format == MDP_Y_CBCR_H2V2) {
+ pipe->element1 = C1_B_Cb; /* B */
+ pipe->element0 = C2_R_Cr; /* R */
+ pipe->chroma_sample = MDP4_CHROMA_420;
+ }
+ pipe->bpp = 2; /* 2 bpp */
+ break;
+ case MDP_Y_CBCR_H2V2_TILE:
+ case MDP_Y_CRCB_H2V2_TILE:
+ pipe->frame_format = MDP4_FRAME_FORMAT_VIDEO_SUPERTILE;
+ pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR;
+ pipe->a_bit = 0;
+ pipe->r_bit = 3; /* R, 8 bits */
+ pipe->b_bit = 3; /* B, 8 bits */
+ pipe->g_bit = 3; /* G, 8 bits */
+ pipe->alpha_enable = 0;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 1; /* 2 */
+ pipe->element3 = C0_G_Y; /* not used */
+ pipe->element2 = C0_G_Y; /* not used */
+ if (pipe->src_format == MDP_Y_CRCB_H2V2_TILE) {
+ pipe->element1 = C2_R_Cr; /* R */
+ pipe->element0 = C1_B_Cb; /* B */
+ pipe->chroma_sample = MDP4_CHROMA_420;
+ } else if (pipe->src_format == MDP_Y_CBCR_H2V2_TILE) {
+ pipe->element1 = C1_B_Cb; /* B */
+ pipe->element0 = C2_R_Cr; /* R */
+ pipe->chroma_sample = MDP4_CHROMA_420;
+ }
+ pipe->bpp = 2; /* 2 bpp */
+ break;
+ case MDP_Y_CR_CB_H2V2:
+ case MDP_Y_CB_CR_H2V2:
+ pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+ pipe->fetch_plane = OVERLAY_PLANE_PLANAR;
+ pipe->a_bit = 0;
+ pipe->r_bit = 3; /* R, 8 bits */
+ pipe->b_bit = 3; /* B, 8 bits */
+ pipe->g_bit = 3; /* G, 8 bits */
+ pipe->alpha_enable = 0;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 1; /* 2 */
+ pipe->element3 = C0_G_Y; /* not used */
+ pipe->element2 = C0_G_Y; /* not used */
+ if (pipe->src_format == MDP_Y_CR_CB_H2V2) {
+ pipe->element1 = C2_R_Cr; /* R */
+ pipe->element0 = C1_B_Cb; /* B */
+ pipe->chroma_sample = MDP4_CHROMA_420;
+ } else if (pipe->src_format == MDP_Y_CB_CR_H2V2) {
+ pipe->element1 = C1_B_Cb; /* B */
+ pipe->element0 = C2_R_Cr; /* R */
+ pipe->chroma_sample = MDP4_CHROMA_420;
+ }
+ pipe->bpp = 2; /* 2 bpp */
+ break;
+ default:
+ /* not likely */
+ mdp4_stat.err_format++;
+ return -ERANGE;
+ }
+
+ return 0;
+}
+
+/*
+ * color_key_convert: output with 12 bits color key
+ */
+static uint32 color_key_convert(int start, int num, uint32 color)
+{
+ uint32 data;
+
+ data = (color >> start) & ((1 << num) - 1);
+
+ /* convert to 8 bits */
+ if (num == 5)
+ data = ((data << 3) | (data >> 2));
+ else if (num == 6)
+ data = ((data << 2) | (data >> 4));
+
+ /* convert 8 bits to 12 bits */
+ data = (data << 4) | (data >> 4);
+
+ return data;
+}
+
+void transp_color_key(int format, uint32 transp,
+ uint32 *c0, uint32 *c1, uint32 *c2)
+{
+ int b_start, g_start, r_start;
+ int b_num, g_num, r_num;
+
+ switch (format) {
+ case MDP_RGB_565:
+ b_start = 0;
+ g_start = 5;
+ r_start = 11;
+ r_num = 5;
+ g_num = 6;
+ b_num = 5;
+ break;
+ case MDP_RGB_888:
+ case MDP_XRGB_8888:
+ case MDP_ARGB_8888:
+ case MDP_BGRA_8888:
+ b_start = 0;
+ g_start = 8;
+ r_start = 16;
+ r_num = 8;
+ g_num = 8;
+ b_num = 8;
+ break;
+ case MDP_RGBA_8888:
+ case MDP_RGBX_8888:
+ b_start = 16;
+ g_start = 8;
+ r_start = 0;
+ r_num = 8;
+ g_num = 8;
+ b_num = 8;
+ break;
+ case MDP_BGR_565:
+ b_start = 11;
+ g_start = 5;
+ r_start = 0;
+ r_num = 5;
+ g_num = 6;
+ b_num = 5;
+ break;
+ case MDP_Y_CB_CR_H2V2:
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CBCR_H2V1:
+ b_start = 8;
+ g_start = 16;
+ r_start = 0;
+ r_num = 8;
+ g_num = 8;
+ b_num = 8;
+ break;
+ case MDP_Y_CR_CB_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ case MDP_Y_CRCB_H2V1:
+ case MDP_Y_CRCB_H1V1:
+ case MDP_Y_CBCR_H1V1:
+ b_start = 0;
+ g_start = 16;
+ r_start = 8;
+ r_num = 8;
+ g_num = 8;
+ b_num = 8;
+ break;
+ default:
+ b_start = 0;
+ g_start = 8;
+ r_start = 16;
+ r_num = 8;
+ g_num = 8;
+ b_num = 8;
+ break;
+ }
+
+ *c0 = color_key_convert(g_start, g_num, transp);
+ *c1 = color_key_convert(b_start, b_num, transp);
+ *c2 = color_key_convert(r_start, r_num, transp);
+}
+
+uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 format;
+
+ format = 0;
+
+ if (pipe->solid_fill)
+ format |= MDP4_FORMAT_SOLID_FILL;
+
+ if (pipe->unpack_align_msb)
+ format |= MDP4_FORMAT_UNPACK_ALIGN_MSB;
+
+ if (pipe->unpack_tight)
+ format |= MDP4_FORMAT_UNPACK_TIGHT;
+
+ if (pipe->alpha_enable)
+ format |= MDP4_FORMAT_ALPHA_ENABLE;
+
+ if (pipe->flags & MDP_SOURCE_ROTATED_90)
+ format |= MDP4_FORMAT_90_ROTATED;
+ format |= (pipe->unpack_count << 13);
+ format |= ((pipe->bpp - 1) << 9);
+ format |= (pipe->a_bit << 6);
+ format |= (pipe->r_bit << 4);
+ format |= (pipe->b_bit << 2);
+ format |= pipe->g_bit;
+
+ format |= (pipe->frame_format << 29);
+
+ if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR ||
+ pipe->fetch_plane == OVERLAY_PLANE_PLANAR) {
+ /* video/graphic */
+ format |= (pipe->fetch_plane << 19);
+ format |= (pipe->chroma_site << 28);
+ format |= (pipe->chroma_sample << 26);
+ }
+
+ return format;
+}
+
+uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe)
+{
+ return (pipe->element3 << 24) | (pipe->element2 << 16) |
+ (pipe->element1 << 8) | pipe->element0;
+}
+
+/*
+ * mdp4_overlayproc_cfg: only be called from base layer
+ */
+void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 data, intf;
+ char *overlay_base;
+
+ intf = 0;
+ if (pipe->mixer_num == MDP4_MIXER1) {
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
+ intf = inpdw(MDP_BASE + 0x0038); /* MDP_DISP_INTF_SEL */
+ intf >>= 4;
+ intf &= 0x03;
+ } else
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+
+ if (mdp_is_in_isr == FALSE)
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ /*
+ * BLT only siupport at primary display
+ */
+ if (pipe->mixer_num == MDP4_MIXER0 && pipe->blt_addr) {
+ int off, bpp;
+#ifdef BLT_RGB565
+ bpp = 2; /* overlay ouput is RGB565 */
+#else
+ bpp = 3; /* overlay ouput is RGB888 */
+#endif
+ data = pipe->src_height;
+ data <<= 16;
+ data |= pipe->src_width;
+ outpdw(overlay_base + 0x0008, data); /* ROI, height + width */
+ if (ctrl->panel_mode & MDP4_PANEL_LCDC ||
+ ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
+ outpdw(overlay_base + 0x000c, pipe->blt_addr);
+ outpdw(overlay_base + 0x0010, pipe->src_width * bpp);
+ off = pipe->src_height * pipe->src_width * bpp;
+ outpdw(overlay_base + 0x001c, pipe->blt_addr + off);
+ /* LCDC - FRAME BUFFER + vsync rate */
+ outpdw(overlay_base + 0x0004, 0x02);
+ } else { /* MDDI */
+ off = 0;
+ if (pipe->ov_cnt & 0x01)
+ off = pipe->src_height * pipe->src_width * bpp;
+
+ outpdw(overlay_base + 0x000c, pipe->blt_addr + off);
+ /* overlay ouput is RGB888 */
+ outpdw(overlay_base + 0x0010, pipe->src_width * bpp);
+ outpdw(overlay_base + 0x001c, pipe->blt_addr + off);
+ /* MDDI - BLT + on demand */
+ outpdw(overlay_base + 0x0004, 0x08);
+ }
+#ifdef BLT_RGB565
+ outpdw(overlay_base + 0x0014, 0x1); /* RGB565 */
+#else
+ outpdw(overlay_base + 0x0014, 0x0); /* RGB888 */
+#endif
+ } else {
+ data = pipe->src_height;
+ data <<= 16;
+ data |= pipe->src_width;
+ outpdw(overlay_base + 0x0008, data); /* ROI, height + width */
+ outpdw(overlay_base + 0x000c, pipe->srcp0_addr);
+ outpdw(overlay_base + 0x0010, pipe->srcp0_ystride);
+ outpdw(overlay_base + 0x0004, 0x01); /* directout */
+ }
+
+ if (pipe->mixer_num == MDP4_MIXER1) {
+ if (intf == TV_INTF) {
+ outpdw(overlay_base + 0x0014, 0x02); /* yuv422 */
+ /* overlay1 CSC config */
+ outpdw(overlay_base + 0x0200, 0x05); /* rgb->yuv */
+ }
+ }
+
+#ifdef MDP4_IGC_LUT_ENABLE
+ outpdw(overlay_base + 0x0014, 0x4); /* GC_LUT_EN, 888 */
+#endif
+
+ if (mdp_is_in_isr == FALSE)
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+int mdp4_overlay_pipe_staged(int mixer)
+{
+ uint32 data, mask, i;
+ int p1, p2;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ data = inpdw(MDP_BASE + 0x10100);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ p1 = 0;
+ p2 = 0;
+ for (i = 0; i < 8; i++) {
+ mask = data & 0x0f;
+ if (mask) {
+ if (mask <= 4)
+ p1++;
+ else
+ p2++;
+ }
+ data >>= 4;
+ }
+
+ if (mixer)
+ return p2;
+ else
+ return p1;
+}
+
+void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 data, mask, snum, stage, mixer, pnum;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ stage = pipe->mixer_stage;
+ mixer = pipe->mixer_num;
+ pnum = pipe->pipe_num;
+
+ /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1 */
+ data = inpdw(MDP_BASE + 0x10100);
+
+ if (mixer == MDP4_MIXER1)
+ stage += 8;
+
+ if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {/* VG1 and VG2 */
+ pnum -= OVERLAY_PIPE_VG1; /* start from 0 */
+ snum = 0;
+ snum += (4 * pnum);
+ } else {
+ snum = 8;
+ snum += (4 * pnum); /* RGB1 and RGB2 */
+ }
+
+ mask = 0x0f;
+ mask <<= snum;
+ stage <<= snum;
+ data &= ~mask; /* clear old bits */
+
+ data |= stage;
+
+ outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */
+
+ data = inpdw(MDP_BASE + 0x10100);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = pipe; /* keep it */
+}
+
+void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 data, mask, snum, stage, mixer, pnum;
+
+ stage = pipe->mixer_stage;
+ mixer = pipe->mixer_num;
+ pnum = pipe->pipe_num;
+
+ if (pipe != ctrl->stage[mixer][stage]) /* not runing */
+ return;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1 */
+ data = inpdw(MDP_BASE + 0x10100);
+
+ if (mixer == MDP4_MIXER1)
+ stage += 8;
+
+ if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {/* VG1 and VG2 */
+ pnum -= OVERLAY_PIPE_VG1; /* start from 0 */
+ snum = 0;
+ snum += (4 * pnum);
+ } else {
+ snum = 8;
+ snum += (4 * pnum); /* RGB1 and RGB2 */
+ }
+
+ mask = 0x0f;
+ mask <<= snum;
+ data &= ~mask; /* clear old bits */
+
+ outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */
+
+ data = inpdw(MDP_BASE + 0x10100);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL; /* clear it */
+}
+
+void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe)
+{
+ struct mdp4_overlay_pipe *bg_pipe;
+ unsigned char *overlay_base, *rgb_base;
+ uint32 c0, c1, c2, blend_op, constant_color = 0, rgb_src_format;
+ int off;
+
+ if (pipe->mixer_num) /* mixer number, /dev/fb0, /dev/fb1 */
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
+ else
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+
+ /* stage 0 to stage 2 */
+ off = 0x20 * (pipe->mixer_stage - MDP4_MIXER_STAGE0);
+
+ bg_pipe = mdp4_overlay_stage_pipe(pipe->mixer_num,
+ MDP4_MIXER_STAGE_BASE);
+ if (bg_pipe == NULL) {
+ pr_err("%s: Error: no bg_pipe\n", __func__);
+ return;
+ }
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ blend_op = 0;
+
+ if (pipe->is_fg) {
+ blend_op |= (MDP4_BLEND_FG_ALPHA_FG_CONST |
+ MDP4_BLEND_BG_ALPHA_BG_CONST);
+ outpdw(overlay_base + off + 0x108, pipe->alpha);
+ outpdw(overlay_base + off + 0x10c, 0xff - pipe->alpha);
+ if (pipe->alpha == 0xff) {
+ rgb_base = MDP_BASE + MDP4_RGB_BASE;
+ rgb_base += MDP4_RGB_OFF * bg_pipe->pipe_num;
+ rgb_src_format = inpdw(rgb_base + 0x50);
+ rgb_src_format |= MDP4_FORMAT_SOLID_FILL;
+ outpdw(rgb_base + 0x50, rgb_src_format);
+ outpdw(rgb_base + 0x1008, constant_color);
+ }
+ } else {
+ if (bg_pipe->alpha_enable && pipe->alpha_enable) {
+ /* both pipe have alpha */
+ blend_op |= (MDP4_BLEND_FG_ALPHA_BG_PIXEL |
+ MDP4_BLEND_FG_INV_ALPHA |
+ MDP4_BLEND_BG_ALPHA_BG_PIXEL);
+ } else if (bg_pipe->alpha_enable && pipe->alpha_enable == 0) {
+ /* no alpha on both pipe */
+ blend_op = (MDP4_BLEND_BG_ALPHA_BG_PIXEL |
+ MDP4_BLEND_FG_ALPHA_BG_PIXEL |
+ MDP4_BLEND_FG_INV_ALPHA);
+ }
+ }
+
+
+ if (pipe->transp != MDP_TRANSP_NOP) {
+ if (pipe->is_fg) {
+ transp_color_key(pipe->src_format, pipe->transp,
+ &c0, &c1, &c2);
+ /* Fg blocked */
+ blend_op |= MDP4_BLEND_FG_TRANSP_EN;
+ /* lower limit */
+ outpdw(overlay_base + off + 0x110,
+ (c1 << 16 | c0));/* low */
+ outpdw(overlay_base + off + 0x114, c2);/* low */
+ /* upper limit */
+ outpdw(overlay_base + off + 0x118,
+ (c1 << 16 | c0));
+ outpdw(overlay_base + off + 0x11c, c2);
+ } else {
+ transp_color_key(bg_pipe->src_format,
+ pipe->transp, &c0, &c1, &c2);
+ /* bg blocked */
+ blend_op |= MDP4_BLEND_BG_TRANSP_EN;
+ /* lower limit */
+ outpdw(overlay_base + 0x180,
+ (c1 << 16 | c0));/* low */
+ outpdw(overlay_base + 0x184, c2);/* low */
+ /* upper limit */
+ outpdw(overlay_base + 0x188,
+ (c1 << 16 | c0));/* high */
+ outpdw(overlay_base + 0x18c, c2);/* high */
+ }
+ }
+
+ outpdw(overlay_base + off + 0x104, blend_op);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all)
+{
+ struct mdp4_overlay_pipe *bg_pipe;
+ uint32 bits = 0;
+
+ if (pipe->mixer_num == MDP4_MIXER1)
+ bits |= 0x02;
+ else
+ bits |= 0x01;
+
+ if (all) {
+ if (pipe->pipe_num <= OVERLAY_PIPE_RGB2) {
+ if (pipe->pipe_num == OVERLAY_PIPE_RGB2)
+ bits |= 0x20;
+ else
+ bits |= 0x10;
+ } else {
+ if (pipe->is_fg && pipe->alpha == 0xFF) {
+ bg_pipe = mdp4_overlay_stage_pipe(
+ pipe->mixer_num,
+ MDP4_MIXER_STAGE_BASE);
+ if (bg_pipe->pipe_num <= OVERLAY_PIPE_RGB2) {
+ if (bg_pipe->pipe_num ==
+ OVERLAY_PIPE_RGB2)
+ bits |= 0x20;
+ else
+ bits |= 0x10;
+ }
+ }
+ if (pipe->pipe_num == OVERLAY_PIPE_VG2)
+ bits |= 0x08;
+ else
+ bits |= 0x04;
+ }
+ }
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ outpdw(MDP_BASE + 0x18000, bits); /* MDP_OVERLAY_REG_FLUSH */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+struct mdp4_overlay_pipe *mdp4_overlay_stage_pipe(int mixer, int stage)
+{
+ return ctrl->stage[mixer][stage];
+}
+
+struct mdp4_overlay_pipe *mdp4_overlay_ndx2pipe(int ndx)
+{
+ struct mdp4_overlay_pipe *pipe;
+
+ if (ndx <= 0 || ndx > MDP4_MAX_PIPE)
+ return NULL;
+
+ pipe = &ctrl->plist[ndx - 1]; /* ndx start from 1 */
+
+ if (pipe->pipe_used == 0)
+ return NULL;
+
+ return pipe;
+}
+
+struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(
+ int ptype, int mixer, int req_share)
+{
+ int i, j, ndx, found;
+ struct mdp4_overlay_pipe *pipe, *opipe;
+ struct mdp4_pipe_desc *pd;
+
+ found = 0;
+ pipe = &ctrl->plist[0];
+
+ for (i = 0; i < MDP4_MAX_PIPE; i++) {
+ if (pipe->pipe_type == ptype && pipe->pipe_used == 0) {
+ pd = &ctrl->ov_pipe[pipe->pipe_num];
+ if (pd->share) { /* pipe can be shared */
+ if (pd->ref_cnt == 0) {
+ /* not yet been used */
+ found++;
+ break;
+ }
+ /* pipe occupied already */
+ if (req_share && pd->ref_cnt < MDP4_MAX_SHARE) {
+ for (j = 0; j < MDP4_MAX_SHARE; j++) {
+ ndx = pd->ndx_list[j];
+ if (ndx != 0)
+ break;
+ }
+ /* ndx satrt from 1 */
+ opipe = &ctrl->plist[ndx - 1];
+ /*
+ * occupied pipe willing to share and
+ * same mixer
+ */
+ if (opipe->pipe_share &&
+ opipe->mixer_num == mixer) {
+ found++;
+ break;
+ }
+ }
+ } else { /* not a shared pipe */
+ if (req_share == 0 && pd->ref_cnt == 0) {
+ found++;
+ break;
+ }
+ }
+ }
+ pipe++;
+ }
+
+ if (found) {
+ init_completion(&pipe->comp);
+ init_completion(&pipe->dmas_comp);
+ pr_info("%s: pipe=%x ndx=%d num=%d share=%d cnt=%d\n",
+ __func__, (int)pipe, pipe->pipe_ndx, pipe->pipe_num,
+ pd->share, pd->ref_cnt);
+ return pipe;
+ }
+
+ pr_debug("%s: ptype=%d mixer=%d req_share=%d FAILED\n",
+ __func__, ptype, mixer, req_share);
+
+ return NULL;
+}
+
+
+void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe)
+{
+ int i;
+ uint32 ptype, num, ndx;
+ struct mdp4_pipe_desc *pd;
+
+ pr_debug("%s: pipe=%x ndx=%d\n", __func__,
+ (int)pipe, pipe->pipe_ndx);
+ pd = &ctrl->ov_pipe[pipe->pipe_num];
+ if (pd->ref_cnt) {
+ pd->ref_cnt--;
+ for (i = 0; i < MDP4_MAX_SHARE; i++) {
+ if (pd->ndx_list[i] == pipe->pipe_ndx) {
+ pd->ndx_list[i] = 0;
+ break;
+ }
+ }
+ }
+
+ pd->player = NULL;
+
+ ptype = pipe->pipe_type;
+ num = pipe->pipe_num;
+ ndx = pipe->pipe_ndx;
+
+ memset(pipe, 0, sizeof(*pipe));
+
+ pipe->pipe_type = ptype;
+ pipe->pipe_num = num;
+ pipe->pipe_ndx = ndx;
+}
+
+int mdp4_overlay_req_check(uint32 id, uint32 z_order, uint32 mixer)
+{
+ struct mdp4_overlay_pipe *pipe;
+
+ pipe = ctrl->stage[mixer][z_order];
+
+ if (pipe == NULL)
+ return 0;
+
+ if (pipe->pipe_ndx == id) /* same req, recycle */
+ return 0;
+
+ if (id == MSMFB_NEW_REQUEST) { /* new request */
+ if (pipe->pipe_num >= OVERLAY_PIPE_VG1) /* share pipe */
+ return 0;
+ }
+
+ return -EPERM;
+}
+
+static int mdp4_overlay_validate_downscale(struct mdp_overlay *req,
+ struct msm_fb_data_type *mfd, uint32 perf_level, uint32 pclk_rate)
+{
+ __u32 panel_clk_khz, mdp_clk_khz;
+ __u32 num_hsync_pix_clks, mdp_clks_per_hsync, src_wh;
+ __u32 hsync_period_ps, mdp_period_ps, total_hsync_period_ps;
+ unsigned long fill_rate_y_dir, fill_rate_x_dir;
+ unsigned long fillratex100, mdp_pixels_produced;
+ unsigned long mdp_clk_hz;
+
+ pr_debug("%s: LCDC Mode Downscale validation with MDP Core"
+ " Clk rate\n", __func__);
+ pr_debug("src_w %u, src_h %u, dst_w %u, dst_h %u\n",
+ req->src_rect.w, req->src_rect.h, req->dst_rect.w,
+ req->dst_rect.h);
+
+
+ panel_clk_khz = pclk_rate/1000;
+ mdp_clk_hz = mdp_perf_level2clk_rate(perf_level);
+
+ if (!mdp_clk_hz) {
+ pr_debug("mdp_perf_level2clk_rate returned 0,"
+ "Downscale Validation incomplete\n");
+ return 0;
+ }
+
+ mdp_clk_khz = mdp_clk_hz/1000;
+
+ num_hsync_pix_clks = mfd->panel_info.lcdc.h_back_porch +
+ mfd->panel_info.lcdc.h_front_porch +
+ mfd->panel_info.lcdc.h_pulse_width +
+ mfd->panel_info.xres;
+
+ hsync_period_ps = 1000000000/panel_clk_khz;
+ mdp_period_ps = 1000000000/mdp_clk_khz;
+
+ total_hsync_period_ps = num_hsync_pix_clks * hsync_period_ps;
+ mdp_clks_per_hsync = total_hsync_period_ps/mdp_period_ps;
+
+ pr_debug("hsync_period_ps %u, mdp_period_ps %u,"
+ "total_hsync_period_ps %u\n", hsync_period_ps,
+ mdp_period_ps, total_hsync_period_ps);
+
+ src_wh = req->src_rect.w * req->src_rect.h;
+ if (src_wh % req->dst_rect.h)
+ fill_rate_y_dir = (src_wh / req->dst_rect.h) + 1;
+ else
+ fill_rate_y_dir = (src_wh / req->dst_rect.h);
+
+ fill_rate_x_dir = (mfd->panel_info.xres - req->dst_rect.w)
+ + req->src_rect.w;
+
+ if (fill_rate_y_dir >= fill_rate_x_dir)
+ fillratex100 = 100 * fill_rate_y_dir / mfd->panel_info.xres;
+ else
+ fillratex100 = 100 * fill_rate_x_dir / mfd->panel_info.xres;
+
+ pr_debug("mdp_clks_per_hsync %u, fill_rate_y_dir %lu,"
+ "fill_rate_x_dir %lu\n", mdp_clks_per_hsync,
+ fill_rate_y_dir, fill_rate_x_dir);
+
+ mdp_pixels_produced = 100 * mdp_clks_per_hsync/fillratex100;
+ pr_debug("fillratex100 %lu, mdp_pixels_produced %lu\n",
+ fillratex100, mdp_pixels_produced);
+ if (mdp_pixels_produced <= mfd->panel_info.xres) {
+ pr_err("%s(): LCDC underflow detected during downscale\n",
+ __func__);
+ return -ERANGE;
+ }
+
+ return 0;
+}
+
+static int mdp4_overlay_req2pipe(struct mdp_overlay *req, int mixer,
+ struct mdp4_overlay_pipe **ppipe,
+ struct msm_fb_data_type *mfd)
+{
+ struct mdp4_overlay_pipe *pipe;
+ struct mdp4_pipe_desc *pd;
+ int ret, ptype, req_share;
+ int j;
+
+ if (mfd == NULL) {
+ pr_err("%s: mfd == NULL, -ENODEV\n", __func__);
+ return -ENODEV;
+ }
+
+ if (mixer >= MDP4_MAX_MIXER) {
+ pr_err("%s: mixer out of range!\n", __func__);
+ mdp4_stat.err_mixer++;
+ return -ERANGE;
+ }
+
+ if (req->z_order < 0 || req->z_order > 2) {
+ pr_err("%s: z_order=%d out of range!\n", __func__,
+ req->z_order);
+ mdp4_stat.err_zorder++;
+ return -ERANGE;
+ }
+
+ if (req->src_rect.h == 0 || req->src_rect.w == 0) {
+ pr_err("%s: src img of zero size!\n", __func__);
+ mdp4_stat.err_size++;
+ return -EINVAL;
+ }
+
+
+ if (req->dst_rect.h > (req->src_rect.h * 8)) { /* too much */
+ mdp4_stat.err_scale++;
+ pr_err("%s: scale up, too much (h)!\n", __func__);
+ return -ERANGE;
+ }
+
+ if (req->src_rect.h > (req->dst_rect.h * 8)) { /* too little */
+ mdp4_stat.err_scale++;
+ pr_err("%s: scale down, too little (h)!\n", __func__);
+ return -ERANGE;
+ }
+
+ if (req->dst_rect.w > (req->src_rect.w * 8)) { /* too much */
+ mdp4_stat.err_scale++;
+ pr_err("%s: scale up, too much (w)!\n", __func__);
+ return -ERANGE;
+ }
+
+ if (req->src_rect.w > (req->dst_rect.w * 8)) { /* too little */
+ mdp4_stat.err_scale++;
+ pr_err("%s: scale down, too little (w)!\n", __func__);
+ return -ERANGE;
+ }
+
+ if (mdp_hw_revision == MDP4_REVISION_V1) {
+ /* non integer down saceling ratio smaller than 1/4
+ * is not supportted
+ */
+ if (req->src_rect.h > (req->dst_rect.h * 4)) {
+ if (req->src_rect.h % req->dst_rect.h) {
+ mdp4_stat.err_scale++;
+ pr_err("%s: need integer (h)!\n", __func__);
+ return -ERANGE;
+ }
+ }
+
+ if (req->src_rect.w > (req->dst_rect.w * 4)) {
+ if (req->src_rect.w % req->dst_rect.w) {
+ mdp4_stat.err_scale++;
+ pr_err("%s: need integer (w)!\n", __func__);
+ return -ERANGE;
+ }
+ }
+ }
+
+ if (((req->src_rect.x + req->src_rect.w) > req->src.width) ||
+ ((req->src_rect.y + req->src_rect.h) > req->src.height)) {
+ mdp4_stat.err_size++;
+ pr_err("%s invalid src rectangle\n", __func__);
+ return -ERANGE;
+ }
+
+ if (ctrl->panel_3d != MDP4_3D_SIDE_BY_SIDE) {
+ int xres;
+ int yres;
+
+ xres = mfd->panel_info.xres;
+ yres = mfd->panel_info.yres;
+
+ if (((req->dst_rect.x + req->dst_rect.w) > xres) ||
+ ((req->dst_rect.y + req->dst_rect.h) > yres)) {
+ mdp4_stat.err_size++;
+ pr_err("%s invalid dst rectangle\n", __func__);
+ return -ERANGE;
+ }
+ }
+
+ ptype = mdp4_overlay_format2type(req->src.format);
+ if (ptype < 0) {
+ pr_err("%s: mdp4_overlay_format2type!\n", __func__);
+ return ptype;
+ }
+
+ req_share = (req->flags & MDP_OV_PIPE_SHARE);
+
+ if (req->id == MSMFB_NEW_REQUEST) /* new request */
+ pipe = mdp4_overlay_pipe_alloc(ptype, mixer, req_share);
+ else
+ pipe = mdp4_overlay_ndx2pipe(req->id);
+
+ if (pipe == NULL) {
+ pr_err("%s: pipe == NULL!\n", __func__);
+ return -ENOMEM;
+ }
+
+ /* no down scale at rgb pipe */
+ if (pipe->pipe_num <= OVERLAY_PIPE_RGB2) {
+ if ((req->src_rect.h > req->dst_rect.h) ||
+ (req->src_rect.w > req->dst_rect.w)) {
+ pr_err("%s: h>h || w>w!\n", __func__);
+ return -ERANGE;
+ }
+ }
+
+ pipe->src_format = req->src.format;
+ ret = mdp4_overlay_format2pipe(pipe);
+ if (ret < 0) {
+ pr_err("%s: mdp4_overlay_format2pipe!\n", __func__);
+ return ret;
+ }
+
+ /*
+ * base layer == 1, reserved for frame buffer
+ * zorder 0 == stage 0 == 2
+ * zorder 1 == stage 1 == 3
+ * zorder 2 == stage 2 == 4
+ */
+ if (req->id == MSMFB_NEW_REQUEST) { /* new request */
+ pd = &ctrl->ov_pipe[pipe->pipe_num];
+ for (j = 0; j < MDP4_MAX_SHARE; j++) {
+ if (pd->ndx_list[j] == 0) {
+ pd->ndx_list[j] = pipe->pipe_ndx;
+ break;
+ }
+ }
+ pipe->pipe_share = req_share;
+ pd->ref_cnt++;
+ pipe->pipe_used++;
+ pipe->mixer_num = mixer;
+ pipe->mixer_stage = req->z_order + MDP4_MIXER_STAGE0;
+ pr_debug("%s: zorder=%d pipe ndx=%d num=%d\n", __func__,
+ req->z_order, pipe->pipe_ndx, pipe->pipe_num);
+
+ }
+
+ pipe->src_width = req->src.width & 0x07ff; /* source img width */
+ pipe->src_height = req->src.height & 0x07ff; /* source img height */
+ pipe->src_h = req->src_rect.h & 0x07ff;
+ pipe->src_w = req->src_rect.w & 0x07ff;
+ pipe->src_y = req->src_rect.y & 0x07ff;
+ pipe->src_x = req->src_rect.x & 0x07ff;
+ pipe->dst_h = req->dst_rect.h & 0x07ff;
+ pipe->dst_w = req->dst_rect.w & 0x07ff;
+ pipe->dst_y = req->dst_rect.y & 0x07ff;
+ pipe->dst_x = req->dst_rect.x & 0x07ff;
+
+ pipe->op_mode = 0;
+
+ if (req->flags & MDP_FLIP_LR)
+ pipe->op_mode |= MDP4_OP_FLIP_LR;
+
+ if (req->flags & MDP_FLIP_UD)
+ pipe->op_mode |= MDP4_OP_FLIP_UD;
+
+ if (req->flags & MDP_DITHER)
+ pipe->op_mode |= MDP4_OP_DITHER_EN;
+
+ if (req->flags & MDP_DEINTERLACE)
+ pipe->op_mode |= MDP4_OP_DEINT_EN;
+
+ if (req->flags & MDP_DEINTERLACE_ODD)
+ pipe->op_mode |= MDP4_OP_DEINT_ODD_REF;
+
+ pipe->is_fg = req->is_fg;/* control alpha and color key */
+
+ pipe->alpha = req->alpha & 0x0ff;
+
+ pipe->transp = req->transp_mask;
+
+ *ppipe = pipe;
+
+ return 0;
+}
+
+static int get_img(struct msmfb_data *img, struct fb_info *info,
+ unsigned long *start, unsigned long *len, struct file **pp_file)
+{
+ int put_needed, ret = 0, fb_num;
+ struct file *file;
+#ifdef CONFIG_ANDROID_PMEM
+ unsigned long vstart;
+#endif
+
+ if (img->flags & MDP_BLIT_SRC_GEM) {
+ *pp_file = NULL;
+ return kgsl_gem_obj_addr(img->memory_id, (int) img->priv,
+ start, len);
+ }
+
+#ifdef CONFIG_ANDROID_PMEM
+ if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file))
+ return 0;
+#endif
+ file = fget_light(img->memory_id, &put_needed);
+ if (file == NULL)
+ return -1;
+
+ if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
+ fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
+ if (get_fb_phys_info(start, len, fb_num))
+ ret = -1;
+ else
+ *pp_file = file;
+ } else
+ ret = -1;
+ if (ret)
+ fput_light(file, put_needed);
+ return ret;
+}
+
+int mdp4_overlay_3d(struct fb_info *info, struct msmfb_overlay_3d *req)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ int ret = -EPERM;
+
+ if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
+ return -EINTR;
+
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+ /* Only dsi_cmd panel support 3D */
+ if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
+ mdp4_dsi_cmd_3d(mfd, req);
+ ret = 0;
+ }
+#endif
+ mutex_unlock(&mfd->dma->ov_mutex);
+
+ return ret;
+}
+
+#ifdef CONFIG_FB_MSM_OVERLAY_WRITEBACK
+int mdp4_overlay_blt(struct fb_info *info, struct msmfb_overlay_blt *req)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ if (mfd == NULL)
+ return -ENODEV;
+
+ if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
+ return -EINTR;
+
+ if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
+ mdp4_dsi_overlay_blt(mfd, req);
+ else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
+ mdp4_dsi_video_overlay_blt(mfd, req);
+ else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
+ mdp4_lcdc_overlay_blt(mfd, req);
+
+ mutex_unlock(&mfd->dma->ov_mutex);
+
+ return 0;
+}
+
+int mdp4_overlay_blt_offset(struct fb_info *info, struct msmfb_overlay_blt *req)
+{
+ int ret = 0;
+
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
+ return -EINTR;
+
+ if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
+ ret = mdp4_dsi_overlay_blt_offset(mfd, req);
+ else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
+ ret = mdp4_dsi_video_overlay_blt_offset(mfd, req);
+ else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
+ ret = mdp4_lcdc_overlay_blt_offset(mfd, req);
+
+ mutex_unlock(&mfd->dma->ov_mutex);
+
+ return ret;
+}
+#endif
+
+int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req)
+{
+ struct mdp4_overlay_pipe *pipe;
+
+ pipe = mdp4_overlay_ndx2pipe(req->id);
+ if (pipe == NULL)
+ return -ENODEV;
+
+ *req = pipe->req_data;
+
+ return 0;
+}
+
+#define OVERLAY_VGA_SIZE 0x04B000
+#define OVERLAY_720P_TILE_SIZE 0x0E6000
+#define OVERLAY_WSVGA_SIZE 0x98000 /* 1024x608, align 600 to 32bit */
+#define OVERLAY_PERF_LEVEL1 1
+#define OVERLAY_PERF_LEVEL2 2
+#define OVERLAY_PERF_LEVEL3 3
+#define OVERLAY_PERF_LEVEL4 4
+
+#ifdef CONFIG_MSM_BUS_SCALING
+#define OVERLAY_BUS_SCALE_TABLE_BASE 6
+#endif
+
+static int mdp4_overlay_is_rgb_type(int format)
+{
+ switch (format) {
+ case MDP_RGB_565:
+ case MDP_RGB_888:
+ case MDP_BGR_565:
+ case MDP_XRGB_8888:
+ case MDP_ARGB_8888:
+ case MDP_RGBA_8888:
+ case MDP_BGRA_8888:
+ case MDP_RGBX_8888:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static uint32 mdp4_overlay_get_perf_level(struct mdp_overlay *req)
+{
+ int is_fg;
+
+ if (req->is_fg && ((req->alpha & 0x0ff) == 0xff))
+ is_fg = 1;
+
+ if (req->flags & MDP_DEINTERLACE)
+ return OVERLAY_PERF_LEVEL1;
+
+ if (mdp4_overlay_is_rgb_type(req->src.format) && is_fg &&
+ ((req->src.width * req->src.height) <= OVERLAY_WSVGA_SIZE))
+ return OVERLAY_PERF_LEVEL4;
+ else if (mdp4_overlay_is_rgb_type(req->src.format))
+ return OVERLAY_PERF_LEVEL1;
+
+ if (ctrl->ov_pipe[OVERLAY_PIPE_VG1].ref_cnt &&
+ ctrl->ov_pipe[OVERLAY_PIPE_VG2].ref_cnt)
+ return OVERLAY_PERF_LEVEL1;
+
+ if (req->src.width*req->src.height <= OVERLAY_VGA_SIZE)
+ return OVERLAY_PERF_LEVEL3;
+ else if (req->src.width*req->src.height <= OVERLAY_720P_TILE_SIZE)
+ return OVERLAY_PERF_LEVEL2;
+ else
+ return OVERLAY_PERF_LEVEL1;
+}
+
+int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ int ret, mixer;
+ struct mdp4_overlay_pipe *pipe;
+
+ if (mfd == NULL) {
+ pr_err("%s: mfd == NULL, -ENODEV\n", __func__);
+ return -ENODEV;
+ }
+
+ if (!mfd->panel_power_on) /* suspended */
+ return -EPERM;
+
+ if (req->src.format == MDP_FB_FORMAT)
+ req->src.format = mfd->fb_imgType;
+
+ if (mutex_lock_interruptible(&mfd->dma->ov_mutex)) {
+ pr_err("%s: mutex_lock_interruptible, -EINTR\n", __func__);
+ return -EINTR;
+ }
+
+ perf_level = mdp4_overlay_get_perf_level(req);
+
+ if ((mfd->panel_info.type == LCDC_PANEL) &&
+ (req->src_rect.h >
+ req->dst_rect.h || req->src_rect.w > req->dst_rect.w)) {
+ if (mdp4_overlay_validate_downscale(req, mfd,
+ perf_level, mfd->panel_info.clk_rate)) {
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return -ERANGE;
+ }
+ }
+ if ((mfd->panel_info.type == MIPI_VIDEO_PANEL) &&
+ (req->src_rect.h >
+ req->dst_rect.h || req->src_rect.w > req->dst_rect.w)) {
+ if (mdp4_overlay_validate_downscale(req, mfd,
+ perf_level, (&mfd->panel_info.mipi)->dsi_pclk_rate)) {
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return -ERANGE;
+ }
+ }
+ mixer = mfd->panel_info.pdest; /* DISPLAY_1 or DISPLAY_2 */
+
+ ret = mdp4_overlay_req2pipe(req, mixer, &pipe, mfd);
+ if (ret < 0) {
+ mutex_unlock(&mfd->dma->ov_mutex);
+ pr_err("%s: mdp4_overlay_req2pipe, ret=%d\n", __func__, ret);
+ return ret;
+ }
+
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+ /*
+ * writeback (blt) mode to provide work around for
+ * dsi cmd mode interface hardware bug.
+ */
+ if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
+ if (mixer == MDP4_MIXER0 && req->dst_rect.x != 0) {
+ mdp4_dsi_blt_dmap_busy_wait(mfd);
+ mdp4_dsi_overlay_blt_start(mfd);
+ }
+ }
+#endif
+
+ /* return id back to user */
+ req->id = pipe->pipe_ndx; /* pipe_ndx start from 1 */
+ pipe->req_data = *req; /* keep original req */
+
+ pipe->flags = req->flags;
+
+ if (pipe->flags & MDP_SHARPENING) {
+ bool test = ((pipe->req_data.dpp.sharp_strength > 0) &&
+ ((req->src_rect.w > req->dst_rect.w) &&
+ (req->src_rect.h > req->dst_rect.h)));
+ if (test) {
+ pr_warn("%s: No sharpening while downscaling.\n",
+ __func__);
+ pipe->flags &= ~MDP_SHARPENING;
+ }
+ }
+
+ mdp4_stat.overlay_set[pipe->mixer_num]++;
+
+ if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
+ if (mdp_hw_revision == MDP4_REVISION_V2_1 &&
+ pipe->mixer_num == MDP4_MIXER0)
+ mdp4_overlay_status_write(MDP4_OVERLAY_TYPE_SET, true);
+ }
+
+ mdp4_del_res_rel = 0;
+ mutex_unlock(&mfd->dma->ov_mutex);
+ mdp_set_core_clk(perf_level);
+
+#ifdef CONFIG_MSM_BUS_SCALING
+ if (pipe->mixer_num == MDP4_MIXER0) {
+ mdp_bus_scale_update_request(OVERLAY_BUS_SCALE_TABLE_BASE
+ - perf_level);
+ }
+#endif
+
+ return 0;
+}
+
+void mdp4_overlay_resource_release(void)
+{
+ if (mdp4_del_res_rel) {
+ mdp_set_core_clk(OVERLAY_PERF_LEVEL4);
+ mdp4_del_res_rel = 0;
+ }
+}
+
+int mdp4_overlay_unset(struct fb_info *info, int ndx)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct mdp4_overlay_pipe *pipe;
+ uint32 flags;
+
+ if (mfd == NULL)
+ return -ENODEV;
+
+ if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
+ return -EINTR;
+
+ pipe = mdp4_overlay_ndx2pipe(ndx);
+
+ if (pipe == NULL) {
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return -ENODEV;
+ }
+
+ if (pipe->mixer_num == MDP4_MIXER1)
+ ctrl->mixer1_played = 0;
+ else {
+ /* mixer 0 */
+ ctrl->mixer0_played = 0;
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+ if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
+ if (mfd->panel_power_on) {
+ mdp4_dsi_blt_dmap_busy_wait(mfd);
+ }
+ }
+#else
+ if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
+ if (mfd->panel_power_on)
+ mdp4_mddi_dma_busy_wait(mfd);
+ }
+#endif
+ }
+
+ mdp4_mixer_stage_down(pipe);
+
+ if (pipe->mixer_num == MDP4_MIXER0) {
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+ if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
+ if (mfd->panel_power_on)
+ if (mdp4_dsi_overlay_blt_stop(mfd) == 0)
+ mdp4_dsi_cmd_overlay_restore();
+ } else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
+ flags = pipe->flags;
+ pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
+ mdp4_overlay_dsi_video_vsync_push(mfd, pipe);
+ pipe->flags = flags;
+ }
+#else
+ if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
+ if (mdp_hw_revision == MDP4_REVISION_V2_1)
+ mdp4_overlay_status_write(
+ MDP4_OVERLAY_TYPE_UNSET, true);
+ if (mfd->panel_power_on)
+ mdp4_mddi_overlay_restore();
+ }
+#endif
+ else if (ctrl->panel_mode & MDP4_PANEL_LCDC) {
+ flags = pipe->flags;
+ pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
+ mdp4_overlay_lcdc_vsync_push(mfd, pipe);
+ pipe->flags = flags;
+ }
+ }
+#ifdef CONFIG_FB_MSM_DTV
+ else { /* mixer1, DTV, ATV */
+ flags = pipe->flags;
+ pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
+ mdp4_overlay_dtv_vsync_push(mfd, pipe);
+ pipe->flags = flags;
+ }
+#endif
+
+ mdp4_stat.overlay_unset[pipe->mixer_num]++;
+
+ mdp4_overlay_pipe_free(pipe);
+
+ if (!(ctrl->ov_pipe[OVERLAY_PIPE_VG1].ref_cnt +
+ ctrl->ov_pipe[OVERLAY_PIPE_VG2].ref_cnt))
+ mdp4_del_res_rel = 1;
+
+ mutex_unlock(&mfd->dma->ov_mutex);
+
+#ifdef CONFIG_MSM_BUS_SCALING
+ if (pipe->mixer_num == MDP4_MIXER0)
+ if (mfd->panel_power_on)
+ mdp_bus_scale_update_request(2);
+#endif
+ return 0;
+}
+
+struct tile_desc {
+ uint32 width; /* tile's width */
+ uint32 height; /* tile's height */
+ uint32 row_tile_w; /* tiles per row's width */
+ uint32 row_tile_h; /* tiles per row's height */
+};
+
+void tile_samsung(struct tile_desc *tp)
+{
+ /*
+ * each row of samsung tile consists of two tiles in height
+ * and two tiles in width which means width should align to
+ * 64 x 2 bytes and height should align to 32 x 2 bytes.
+ * video decoder generate two tiles in width and one tile
+ * in height which ends up height align to 32 X 1 bytes.
+ */
+ tp->width = 64; /* 64 bytes */
+ tp->row_tile_w = 2; /* 2 tiles per row's width */
+ tp->height = 32; /* 32 bytes */
+ tp->row_tile_h = 1; /* 1 tiles per row's height */
+}
+
+uint32 tile_mem_size(struct mdp4_overlay_pipe *pipe, struct tile_desc *tp)
+{
+ uint32 tile_w, tile_h;
+ uint32 row_num_w, row_num_h;
+
+
+ tile_w = tp->width * tp->row_tile_w;
+ tile_h = tp->height * tp->row_tile_h;
+
+ row_num_w = (pipe->src_width + tile_w - 1) / tile_w;
+ row_num_h = (pipe->src_height + tile_h - 1) / tile_h;
+ return ((row_num_w * row_num_h * tile_w * tile_h) + 8191) & ~8191;
+}
+
+int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
+ struct file **pp_src_file, struct file **pp_src_plane1_file,
+ struct file **pp_src_plane2_file)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct msmfb_data *img;
+ struct mdp4_overlay_pipe *pipe;
+ struct mdp4_pipe_desc *pd;
+ ulong start, addr;
+ ulong len = 0;
+ struct file *p_src_file = 0;
+ struct file *p_src_plane1_file = 0, *p_src_plane2_file = 0;
+ uint32_t overlay_version = 0;
+
+ if (mfd == NULL)
+ return -ENODEV;
+
+ if (!mfd->panel_power_on) /* suspended */
+ return -EPERM;
+
+ pipe = mdp4_overlay_ndx2pipe(req->id);
+ if (pipe == NULL) {
+ pr_err("%s: req_id=%d Error\n", __func__, req->id);
+ return -ENODEV;
+ }
+
+ if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
+ return -EINTR;
+
+ pd = &ctrl->ov_pipe[pipe->pipe_num];
+ if (pd->player && pipe != pd->player) {
+ if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return 0; /* ignore it, kicked out already */
+ }
+ }
+
+ pd->player = pipe; /* keep */
+
+ img = &req->data;
+ get_img(img, info, &start, &len, &p_src_file);
+ if (len == 0) {
+ mutex_unlock(&mfd->dma->ov_mutex);
+ pr_err("%s: pmem Error\n", __func__);
+ return -1;
+ }
+ *pp_src_file = p_src_file;
+
+ addr = start + img->offset;
+ pipe->srcp0_addr = addr;
+ pipe->srcp0_ystride = pipe->src_width * pipe->bpp;
+
+ if ((req->version_key & VERSION_KEY_MASK) == 0xF9E8D700)
+ overlay_version = (req->version_key & ~VERSION_KEY_MASK);
+
+ if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
+ if (overlay_version > 0) {
+ img = &req->plane1_data;
+ get_img(img, info, &start, &len, &p_src_plane1_file);
+ if (len == 0) {
+ mutex_unlock(&mfd->dma->ov_mutex);
+ pr_err("%s: Error to get plane1\n", __func__);
+ return -EINVAL;
+ }
+ pipe->srcp1_addr = start + img->offset;
+ *pp_src_plane1_file = p_src_plane1_file;
+ } else if (pipe->frame_format ==
+ MDP4_FRAME_FORMAT_VIDEO_SUPERTILE) {
+ struct tile_desc tile;
+
+ tile_samsung(&tile);
+ pipe->srcp1_addr = addr + tile_mem_size(pipe, &tile);
+ } else {
+ pipe->srcp1_addr = addr + (pipe->src_width *
+ pipe->src_height);
+ }
+ pipe->srcp0_ystride = pipe->src_width;
+ if ((pipe->src_format == MDP_Y_CRCB_H1V1) ||
+ (pipe->src_format == MDP_Y_CBCR_H1V1)) {
+ if (pipe->src_width > YUV_444_MAX_WIDTH)
+ pipe->srcp1_ystride = pipe->src_width << 2;
+ else
+ pipe->srcp1_ystride = pipe->src_width << 1;
+ } else
+ pipe->srcp1_ystride = pipe->src_width;
+
+ } else if (pipe->fetch_plane == OVERLAY_PLANE_PLANAR) {
+ if (overlay_version > 0) {
+ img = &req->plane1_data;
+ get_img(img, info, &start, &len, &p_src_plane1_file);
+ if (len == 0) {
+ mutex_unlock(&mfd->dma->ov_mutex);
+ pr_err("%s: Error to get plane1\n", __func__);
+ return -EINVAL;
+ }
+ pipe->srcp1_addr = start + img->offset;
+ *pp_src_plane1_file = p_src_plane1_file;
+
+ img = &req->plane2_data;
+ get_img(img, info, &start, &len, &p_src_plane2_file);
+ if (len == 0) {
+ mutex_unlock(&mfd->dma->ov_mutex);
+ pr_err("%s: Error to get plane2\n", __func__);
+ return -EINVAL;
+ }
+ pipe->srcp2_addr = start + img->offset;
+ *pp_src_plane2_file = p_src_plane2_file;
+ } else {
+ addr += (pipe->src_width * pipe->src_height);
+ pipe->srcp1_addr = addr;
+ addr += ((pipe->src_width / 2) *
+ (pipe->src_height / 2));
+ pipe->srcp2_addr = addr;
+ }
+ pipe->srcp0_ystride = pipe->src_width;
+ pipe->srcp1_ystride = pipe->src_width / 2;
+ pipe->srcp2_ystride = pipe->src_width / 2;
+ }
+
+ if (pipe->pipe_num >= OVERLAY_PIPE_VG1)
+ mdp4_overlay_vg_setup(pipe); /* video/graphic pipe */
+ else {
+ if (pipe->flags & MDP_SHARPENING) {
+ pr_warn(
+ "%s: Sharpening/Smoothing not supported on RGB pipe\n",
+ __func__);
+ pipe->flags &= ~MDP_SHARPENING;
+ }
+ mdp4_overlay_rgb_setup(pipe); /* rgb pipe */
+ }
+
+ mdp4_mixer_blend_setup(pipe);
+ mdp4_mixer_stage_up(pipe);
+
+ if (pipe->mixer_num == MDP4_MIXER1) {
+ ctrl->mixer1_played++;
+ /* enternal interface */
+ if (ctrl->panel_mode & MDP4_PANEL_DTV)
+#ifdef CONFIG_FB_MSM_DTV
+ mdp4_overlay_dtv_ov_done_push(mfd, pipe);
+#else
+ mdp4_overlay_reg_flush(pipe, 1);
+#endif
+ else if (ctrl->panel_mode & MDP4_PANEL_ATV)
+ mdp4_overlay_reg_flush(pipe, 1);
+ } else {
+ /* primary interface */
+ ctrl->mixer0_played++;
+ if (ctrl->panel_mode & MDP4_PANEL_LCDC)
+ mdp4_overlay_lcdc_vsync_push(mfd, pipe);
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+ else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
+ mdp4_overlay_dsi_video_vsync_push(mfd, pipe);
+#endif
+ else {
+ /* mddi & mipi dsi cmd mode */
+ if (pipe->flags & MDP_OV_PLAY_NOWAIT) {
+ mdp4_stat.overlay_play[pipe->mixer_num]++;
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return 0;
+ }
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+ if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
+ mdp4_dsi_cmd_dma_busy_wait(mfd);
+ mdp4_dsi_cmd_kickoff_video(mfd, pipe);
+ }
+#else
+ if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
+ mdp4_mddi_dma_busy_wait(mfd);
+ mdp4_mddi_kickoff_video(mfd, pipe);
+ }
+#endif
+ }
+ }
+
+ mdp4_stat.overlay_play[pipe->mixer_num]++;
+
+ mutex_unlock(&mfd->dma->ov_mutex);
+
+ return 0;
+}
diff --git a/drivers/video/msm/mdp4_overlay_atv.c b/drivers/video/msm/mdp4_overlay_atv.c
new file mode 100644
index 0000000..8dcdec0
--- /dev/null
+++ b/drivers/video/msm/mdp4_overlay_atv.c
@@ -0,0 +1,189 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+#include <linux/fb.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+
+static struct mdp4_overlay_pipe *atv_pipe;
+
+int mdp4_atv_on(struct platform_device *pdev)
+{
+ uint8 *buf;
+ int bpp, ptype;
+ struct fb_info *fbi;
+ struct fb_var_screeninfo *var;
+ struct msm_fb_data_type *mfd;
+ struct mdp4_overlay_pipe *pipe;
+ int ret;
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ fbi = mfd->fbi;
+ var = &fbi->var;
+
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf += fbi->var.xoffset * bpp +
+ fbi->var.yoffset * fbi->fix.line_length;
+
+ if (atv_pipe == NULL) {
+ ptype = mdp4_overlay_format2type(mfd->fb_imgType);
+ pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER1, 0);
+ if (pipe == NULL)
+ return -EBUSY;
+ pipe->pipe_used++;
+ pipe->mixer_stage = MDP4_MIXER_STAGE_BASE;
+ pipe->mixer_num = MDP4_MIXER1;
+ pipe->src_format = mfd->fb_imgType;
+ mdp4_overlay_panel_mode(pipe->mixer_num, MDP4_PANEL_ATV);
+ mdp4_overlay_format2pipe(pipe);
+
+ atv_pipe = pipe; /* keep it */
+ } else {
+ pipe = atv_pipe;
+ }
+
+ printk(KERN_INFO "mdp4_atv_overlay: pipe=%x ndx=%d\n",
+ (int)pipe, pipe->pipe_ndx);
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ /* Turn the next panel on, get correct resolution
+ before configuring overlay pipe */
+ ret = panel_next_on(pdev);
+
+ pr_info("%s: fbi->var.yres: %d | fbi->var.xres: %d",
+ __func__, fbi->var.yres, fbi->var.xres);
+
+ /* MDP4 Config */
+ pipe->src_height = fbi->var.yres;
+ pipe->src_width = fbi->var.xres;
+ pipe->src_h = fbi->var.yres;
+ pipe->src_w = fbi->var.xres;
+ pipe->src_y = 0;
+ pipe->src_x = 0;
+ pipe->srcp0_addr = (uint32) buf;
+ pipe->srcp0_ystride = fbi->fix.line_length;
+
+ mdp4_overlay_dmae_xy(pipe); /* dma_e */
+ mdp4_overlay_dmae_cfg(mfd, 1);
+
+ mdp4_overlay_rgb_setup(pipe);
+
+ mdp4_mixer_stage_up(pipe);
+
+ mdp4_overlayproc_cfg(pipe);
+
+ if (ret == 0)
+ mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ return ret;
+}
+
+int mdp4_atv_off(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ ret = panel_next_off(pdev);
+
+ /* delay to make sure the last frame finishes */
+ msleep(100);
+
+ /* dis-engage rgb2 from mixer1 */
+ if (atv_pipe)
+ mdp4_mixer_stage_down(atv_pipe);
+
+ return ret;
+}
+
+/*
+ * mdp4_overlay1_done_atv: called from isr
+ */
+void mdp4_overlay1_done_atv()
+{
+ complete(&atv_pipe->comp);
+}
+
+void mdp4_atv_overlay(struct msm_fb_data_type *mfd)
+{
+ struct fb_info *fbi = mfd->fbi;
+ uint8 *buf;
+ int bpp;
+ unsigned long flag;
+ struct mdp4_overlay_pipe *pipe;
+
+ if (!mfd->panel_power_on)
+ return;
+
+ /* no need to power on cmd block since it's lcdc mode */
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf += fbi->var.xoffset * bpp +
+ fbi->var.yoffset * fbi->fix.line_length;
+
+ mutex_lock(&mfd->dma->ov_mutex);
+
+ pipe = atv_pipe;
+ pipe->srcp0_addr = (uint32) buf;
+ mdp4_overlay_rgb_setup(pipe);
+ mdp4_overlay_reg_flush(pipe, 1); /* rgb2 and mixer1 */
+
+ printk(KERN_INFO "mdp4_atv_overlay: pipe=%x ndx=%d\n",
+ (int)pipe, pipe->pipe_ndx);
+
+ /* enable irq */
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_enable_irq(MDP_OVERLAY1_TERM);
+ INIT_COMPLETION(atv_pipe->comp);
+ mfd->dma->waiting = TRUE;
+ outp32(MDP_INTR_CLEAR, INTR_OVERLAY1_DONE);
+ mdp_intr_mask |= INTR_OVERLAY1_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ wait_for_completion_killable(&atv_pipe->comp);
+ mdp_disable_irq(MDP_OVERLAY1_TERM);
+
+ mdp4_stat.kickoff_atv++;
+ mdp4_overlay_resource_release();
+ mutex_unlock(&mfd->dma->ov_mutex);
+}
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
new file mode 100644
index 0000000..22d9d3b
--- /dev/null
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -0,0 +1,672 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+#include <linux/fb.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+#include "mipi_dsi.h"
+
+static struct mdp4_overlay_pipe *dsi_pipe;
+static struct msm_fb_data_type *dsi_mfd;
+static int busy_wait_cnt;
+static int dsi_state;
+static unsigned long tout_expired;
+
+#define TOUT_PERIOD HZ /* 1 second */
+#define MS_100 (HZ/10) /* 100 ms */
+
+static int vsync_start_y_adjust = 4;
+
+struct timer_list dsi_clock_timer;
+
+static int writeback_offset;
+
+void mdp4_overlay_dsi_state_set(int state)
+{
+ unsigned long flag;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ dsi_state = state;
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+}
+
+static void dsi_clock_tout(unsigned long data)
+{
+ if (mipi_dsi_clk_on) {
+ if (dsi_state == ST_DSI_PLAYING) {
+ mdp4_stat.dsi_clkoff++;
+ mipi_dsi_clk_disable();
+ mdp4_overlay_dsi_state_set(ST_DSI_CLK_OFF);
+ }
+ }
+}
+
+static __u32 msm_fb_line_length(__u32 fb_index, __u32 xres, int bpp)
+{
+ /*
+ * The adreno GPU hardware requires that the pitch be aligned to
+ * 32 pixels for color buffers, so for the cases where the GPU
+ * is writing directly to fb0, the framebuffer pitch
+ * also needs to be 32 pixel aligned
+ */
+
+ if (fb_index == 0)
+ return ALIGN(xres, 32) * bpp;
+ else
+ return xres * bpp;
+}
+
+void mdp4_mipi_vsync_enable(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe, int which)
+{
+ uint32 start_y, data, tear_en;
+
+ tear_en = (1 << which);
+
+ if ((mfd->use_mdp_vsync) && (mfd->ibuf.vsync_enable) &&
+ (mfd->panel_info.lcd.vsync_enable)) {
+
+ if (vsync_start_y_adjust <= pipe->dst_y)
+ start_y = pipe->dst_y - vsync_start_y_adjust;
+ else
+ start_y = (mfd->total_lcd_lines - 1) -
+ (vsync_start_y_adjust - pipe->dst_y);
+ if (which == 0)
+ MDP_OUTP(MDP_BASE + 0x210, start_y); /* primary */
+ else
+ MDP_OUTP(MDP_BASE + 0x214, start_y); /* secondary */
+
+ data = inpdw(MDP_BASE + 0x20c);
+ data |= tear_en;
+ MDP_OUTP(MDP_BASE + 0x20c, data);
+ } else {
+ data = inpdw(MDP_BASE + 0x20c);
+ data &= ~tear_en;
+ MDP_OUTP(MDP_BASE + 0x20c, data);
+ }
+}
+
+void mdp4_overlay_update_dsi_cmd(struct msm_fb_data_type *mfd)
+{
+ MDPIBUF *iBuf = &mfd->ibuf;
+ struct fb_info *fbi;
+ uint8 *src;
+ int ptype;
+ struct mdp4_overlay_pipe *pipe;
+ int bpp;
+ int ret;
+
+ if (mfd->key != MFD_KEY)
+ return;
+
+ dsi_mfd = mfd; /* keep it */
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ if (dsi_pipe == NULL) {
+ ptype = mdp4_overlay_format2type(mfd->fb_imgType);
+ if (ptype < 0)
+ printk(KERN_INFO "%s: format2type failed\n", __func__);
+ pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER0, 0);
+ if (pipe == NULL)
+ printk(KERN_INFO "%s: pipe_alloc failed\n", __func__);
+ pipe->pipe_used++;
+ pipe->mixer_stage = MDP4_MIXER_STAGE_BASE;
+ pipe->mixer_num = MDP4_MIXER0;
+ pipe->src_format = mfd->fb_imgType;
+ mdp4_overlay_panel_mode(pipe->mixer_num, MDP4_PANEL_DSI_CMD);
+ ret = mdp4_overlay_format2pipe(pipe);
+ if (ret < 0)
+ printk(KERN_INFO "%s: format2type failed\n", __func__);
+
+ init_timer(&dsi_clock_timer);
+ dsi_clock_timer.function = dsi_clock_tout;
+ dsi_clock_timer.data = (unsigned long) mfd;;
+ dsi_clock_timer.expires = 0xffffffff;
+ add_timer(&dsi_clock_timer);
+ tout_expired = jiffies;
+
+ dsi_pipe = pipe; /* keep it */
+
+ fbi = mfd->fbi;
+ bpp = fbi->var.bits_per_pixel / 8;
+ src = (uint8 *) iBuf->buf;
+ writeback_offset = mdp4_overlay_writeback_setup(
+ fbi, pipe, src, bpp);
+
+ /*
+ * configure dsi stream id
+ * dma_p = 0, dma_s = 1
+ */
+ MDP_OUTP(MDP_BASE + 0x000a0, 0x10);
+ /* enable dsi trigger on dma_p */
+ MDP_OUTP(MDP_BASE + 0x000a4, 0x01);
+ } else {
+ pipe = dsi_pipe;
+ }
+
+ /* whole screen for base layer */
+ src = (uint8 *) iBuf->buf;
+
+
+ {
+ struct fb_info *fbi;
+
+ fbi = mfd->fbi;
+ if (pipe->is_3d) {
+ bpp = fbi->var.bits_per_pixel / 8;
+ pipe->src_height = pipe->src_height_3d;
+ pipe->src_width = pipe->src_width_3d;
+ pipe->src_h = pipe->src_height_3d;
+ pipe->src_w = pipe->src_width_3d;
+ pipe->dst_h = pipe->src_height_3d;
+ pipe->dst_w = pipe->src_width_3d;
+ pipe->srcp0_ystride = msm_fb_line_length(0,
+ pipe->src_width, bpp);
+ } else {
+ /* 2D */
+ pipe->src_height = fbi->var.yres;
+ pipe->src_width = fbi->var.xres;
+ pipe->src_h = fbi->var.yres;
+ pipe->src_w = fbi->var.xres;
+ pipe->dst_h = fbi->var.yres;
+ pipe->dst_w = fbi->var.xres;
+ pipe->srcp0_ystride = fbi->fix.line_length;
+ }
+ pipe->src_y = 0;
+ pipe->src_x = 0;
+ pipe->dst_y = 0;
+ pipe->dst_x = 0;
+ pipe->srcp0_addr = (uint32)src;
+ }
+
+
+ mdp4_overlay_rgb_setup(pipe);
+
+ mdp4_mixer_stage_up(pipe);
+
+ mdp4_overlayproc_cfg(pipe);
+
+ mdp4_overlay_dmap_xy(pipe);
+
+ mdp4_overlay_dmap_cfg(mfd, 0);
+
+ mdp4_mipi_vsync_enable(mfd, pipe, 0);
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ wmb();
+}
+
+void mdp4_dsi_cmd_3d(struct msm_fb_data_type *mfd, struct msmfb_overlay_3d *r3d)
+{
+ struct fb_info *fbi;
+ struct mdp4_overlay_pipe *pipe;
+ int bpp;
+ uint8 *src = NULL;
+
+ if (dsi_pipe == NULL)
+ return;
+
+ dsi_pipe->is_3d = r3d->is_3d;
+ dsi_pipe->src_height_3d = r3d->height;
+ dsi_pipe->src_width_3d = r3d->width;
+
+ pipe = dsi_pipe;
+
+ if (pipe->is_3d)
+ mdp4_overlay_panel_3d(pipe->mixer_num, MDP4_3D_SIDE_BY_SIDE);
+ else
+ mdp4_overlay_panel_3d(pipe->mixer_num, MDP4_3D_NONE);
+
+ if (mfd->panel_power_on) {
+ mdp4_dsi_cmd_dma_busy_wait(mfd);
+ mdp4_dsi_blt_dmap_busy_wait(mfd);
+ }
+
+ fbi = mfd->fbi;
+ if (pipe->is_3d) {
+ bpp = fbi->var.bits_per_pixel / 8;
+ pipe->src_height = pipe->src_height_3d;
+ pipe->src_width = pipe->src_width_3d;
+ pipe->src_h = pipe->src_height_3d;
+ pipe->src_w = pipe->src_width_3d;
+ pipe->dst_h = pipe->src_height_3d;
+ pipe->dst_w = pipe->src_width_3d;
+ pipe->srcp0_ystride = msm_fb_line_length(0,
+ pipe->src_width, bpp);
+ } else {
+ /* 2D */
+ pipe->src_height = fbi->var.yres;
+ pipe->src_width = fbi->var.xres;
+ pipe->src_h = fbi->var.yres;
+ pipe->src_w = fbi->var.xres;
+ pipe->dst_h = fbi->var.yres;
+ pipe->dst_w = fbi->var.xres;
+ pipe->srcp0_ystride = fbi->fix.line_length;
+ }
+ pipe->src_y = 0;
+ pipe->src_x = 0;
+ pipe->dst_y = 0;
+ pipe->dst_x = 0;
+ pipe->srcp0_addr = (uint32)src;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ mdp4_overlay_rgb_setup(pipe);
+
+ mdp4_mixer_stage_up(pipe);
+
+ mdp4_overlayproc_cfg(pipe);
+
+ mdp4_overlay_dmap_xy(pipe);
+
+ mdp4_overlay_dmap_cfg(mfd, 0);
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+
+#ifdef CONFIG_FB_MSM_OVERLAY_WRITEBACK
+int mdp4_dsi_overlay_blt_start(struct msm_fb_data_type *mfd)
+{
+ unsigned long flag;
+
+ pr_debug("%s: blt_end=%d blt_addr=%x pid=%d\n",
+ __func__, dsi_pipe->blt_end, (int)dsi_pipe->blt_addr, current->pid);
+
+ if (dsi_pipe->blt_addr == 0) {
+ mdp4_dsi_cmd_dma_busy_wait(mfd);
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ dsi_pipe->blt_end = 0;
+ dsi_pipe->blt_cnt = 0;
+ dsi_pipe->ov_cnt = 0;
+ dsi_pipe->dmap_cnt = 0;
+ dsi_pipe->blt_addr = dsi_pipe->blt_base;
+ mdp4_stat.writeback++;
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ return 0;
+ }
+
+ return -EBUSY;
+}
+
+int mdp4_dsi_overlay_blt_stop(struct msm_fb_data_type *mfd)
+{
+ unsigned long flag;
+
+
+ pr_debug("%s: blt_end=%d blt_addr=%x\n",
+ __func__, dsi_pipe->blt_end, (int)dsi_pipe->blt_addr);
+
+ if ((dsi_pipe->blt_end == 0) && dsi_pipe->blt_addr) {
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ dsi_pipe->blt_end = 1; /* mark as end */
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ return 0;
+ }
+
+ return -EBUSY;
+}
+
+int mdp4_dsi_overlay_blt_offset(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req)
+{
+ req->offset = writeback_offset;
+ req->width = dsi_pipe->src_width;
+ req->height = dsi_pipe->src_height;
+ req->bpp = dsi_pipe->bpp;
+
+ return sizeof(*req);
+}
+
+void mdp4_dsi_overlay_blt(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req)
+{
+ if (req->enable)
+ mdp4_dsi_overlay_blt_start(mfd);
+ else if (req->enable == 0)
+ mdp4_dsi_overlay_blt_stop(mfd);
+
+}
+#else
+int mdp4_dsi_overlay_blt_offset(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req)
+{
+ return 0;
+}
+int mdp4_dsi_overlay_blt_start(struct msm_fb_data_type *mfd)
+{
+ return -EBUSY;
+}
+int mdp4_dsi_overlay_blt_stop(struct msm_fb_data_type *mfd)
+{
+ return -EBUSY;
+}
+#endif
+
+void mdp4_blt_xy_update(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 off, addr, addr2;
+ int bpp;
+ char *overlay_base;
+
+
+ if (pipe->blt_addr == 0)
+ return;
+
+
+#ifdef BLT_RGB565
+ bpp = 2; /* overlay ouput is RGB565 */
+#else
+ bpp = 3; /* overlay ouput is RGB888 */
+#endif
+ off = 0;
+ if (pipe->dmap_cnt & 0x01)
+ off = pipe->src_height * pipe->src_width * bpp;
+ addr = pipe->blt_addr + off;
+
+ /* dmap */
+ MDP_OUTP(MDP_BASE + 0x90008, addr);
+
+ off = 0;
+ if (pipe->ov_cnt & 0x01)
+ off = pipe->src_height * pipe->src_width * bpp;
+ addr2 = pipe->blt_addr + off;
+ /* overlay 0 */
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+ outpdw(overlay_base + 0x000c, addr2);
+ outpdw(overlay_base + 0x001c, addr2);
+}
+
+
+/*
+ * mdp4_dmap_done_dsi: called from isr
+ * DAM_P_DONE only used when blt enabled
+ */
+void mdp4_dma_p_done_dsi(struct mdp_dma_data *dma)
+{
+ int diff;
+
+ dsi_pipe->dmap_cnt++;
+ diff = dsi_pipe->ov_cnt - dsi_pipe->dmap_cnt;
+ pr_debug("%s: ov_cnt=%d dmap_cnt=%d\n",
+ __func__, dsi_pipe->ov_cnt, dsi_pipe->dmap_cnt);
+
+ if (diff <= 0) {
+ spin_lock(&mdp_spin_lock);
+ dma->dmap_busy = FALSE;
+ complete(&dma->dmap_comp);
+ spin_unlock(&mdp_spin_lock);
+ if (dsi_pipe->blt_end) {
+ dsi_pipe->blt_end = 0;
+ dsi_pipe->blt_addr = 0;
+ pr_debug("%s: END, ov_cnt=%d dmap_cnt=%d\n",
+ __func__, dsi_pipe->ov_cnt, dsi_pipe->dmap_cnt);
+ mdp_intr_mask &= ~INTR_DMA_P_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ }
+ mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+ mdp_disable_irq_nosync(MDP_DMA2_TERM); /* disable intr */
+ return;
+ }
+
+ spin_lock(&mdp_spin_lock);
+ dma->busy = FALSE;
+ spin_unlock(&mdp_spin_lock);
+ complete(&dma->comp);
+ if (busy_wait_cnt)
+ busy_wait_cnt--;
+
+ pr_debug("%s: kickoff dmap\n", __func__);
+
+ mdp4_blt_xy_update(dsi_pipe);
+ /* kick off dmap */
+ outpdw(MDP_BASE + 0x000c, 0x0);
+ /* trigger dsi cmd engine */
+ mipi_dsi_cmd_mdp_sw_trigger();
+
+ mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+}
+
+
+/*
+ * mdp4_overlay0_done_dsi_cmd: called from isr
+ */
+void mdp4_overlay0_done_dsi_cmd(struct mdp_dma_data *dma)
+{
+ int diff;
+
+ if (dsi_pipe->blt_addr == 0) {
+ mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+ spin_lock(&mdp_spin_lock);
+ dma->busy = FALSE;
+ spin_unlock(&mdp_spin_lock);
+ complete(&dma->comp);
+ if (busy_wait_cnt)
+ busy_wait_cnt--;
+ mdp_disable_irq_nosync(MDP_OVERLAY0_TERM);
+ return;
+ }
+
+ /* blt enabled */
+ if (dsi_pipe->blt_end == 0)
+ dsi_pipe->ov_cnt++;
+
+ pr_debug("%s: ov_cnt=%d dmap_cnt=%d\n",
+ __func__, dsi_pipe->ov_cnt, dsi_pipe->dmap_cnt);
+
+ if (dsi_pipe->blt_cnt == 0) {
+ /* first kickoff since blt enabled */
+ mdp_intr_mask |= INTR_DMA_P_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ }
+ dsi_pipe->blt_cnt++;
+
+ diff = dsi_pipe->ov_cnt - dsi_pipe->dmap_cnt;
+ if (diff >= 2) {
+ mdp_disable_irq_nosync(MDP_OVERLAY0_TERM);
+ return;
+ }
+
+ spin_lock(&mdp_spin_lock);
+ dma->busy = FALSE;
+ dma->dmap_busy = TRUE;
+ spin_unlock(&mdp_spin_lock);
+ complete(&dma->comp);
+ if (busy_wait_cnt)
+ busy_wait_cnt--;
+
+ pr_debug("%s: kickoff dmap\n", __func__);
+
+ mdp4_blt_xy_update(dsi_pipe);
+ mdp_enable_irq(MDP_DMA2_TERM); /* enable intr */
+ /* kick off dmap */
+ outpdw(MDP_BASE + 0x000c, 0x0);
+ /* trigger dsi cmd engine */
+ mipi_dsi_cmd_mdp_sw_trigger();
+ mdp_disable_irq_nosync(MDP_OVERLAY0_TERM);
+}
+
+void mdp4_dsi_cmd_overlay_restore(void)
+{
+ /* mutex holded by caller */
+ if (dsi_mfd && dsi_pipe) {
+ mdp4_dsi_cmd_dma_busy_wait(dsi_mfd);
+ mdp4_overlay_update_dsi_cmd(dsi_mfd);
+
+ if (dsi_pipe->blt_addr)
+ mdp4_dsi_blt_dmap_busy_wait(dsi_mfd);
+ mdp4_dsi_cmd_overlay_kickoff(dsi_mfd, dsi_pipe);
+ }
+}
+
+void mdp4_dsi_blt_dmap_busy_wait(struct msm_fb_data_type *mfd)
+{
+ unsigned long flag;
+ int need_wait = 0;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ if (mfd->dma->dmap_busy == TRUE) {
+ INIT_COMPLETION(mfd->dma->dmap_comp);
+ need_wait++;
+ }
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+ if (need_wait) {
+ /* wait until DMA finishes the current job */
+ wait_for_completion(&mfd->dma->dmap_comp);
+ }
+}
+
+/*
+ * mdp4_dsi_cmd_dma_busy_wait: check dsi link activity
+ * dsi link is a shared resource and it can only be used
+ * while it is in idle state.
+ * ov_mutex need to be acquired before call this function.
+ */
+void mdp4_dsi_cmd_dma_busy_wait(struct msm_fb_data_type *mfd)
+{
+ unsigned long flag;
+ int need_wait = 0;
+
+
+
+ if (dsi_clock_timer.function) {
+ if (time_after(jiffies, tout_expired)) {
+ tout_expired = jiffies + TOUT_PERIOD;
+ mod_timer(&dsi_clock_timer, tout_expired);
+ tout_expired -= MS_100;
+ }
+ }
+
+ pr_debug("%s: start pid=%d dsi_clk_on=%d\n",
+ __func__, current->pid, mipi_dsi_clk_on);
+
+ /* satrt dsi clock if necessary */
+ if (mipi_dsi_clk_on == 0) {
+ local_bh_disable();
+ mipi_dsi_clk_enable();
+ local_bh_enable();
+ }
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ if (mfd->dma->busy == TRUE) {
+ if (busy_wait_cnt == 0)
+ INIT_COMPLETION(mfd->dma->comp);
+ busy_wait_cnt++;
+ need_wait++;
+ }
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+ if (need_wait) {
+ /* wait until DMA finishes the current job */
+ pr_debug("%s: pending pid=%d dsi_clk_on=%d\n",
+ __func__, current->pid, mipi_dsi_clk_on);
+ wait_for_completion(&mfd->dma->comp);
+ }
+ pr_debug("%s: done pid=%d dsi_clk_on=%d\n",
+ __func__, current->pid, mipi_dsi_clk_on);
+}
+
+void mdp4_dsi_cmd_kickoff_video(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ if (dsi_pipe->blt_addr && dsi_pipe->blt_cnt == 0)
+ mdp4_overlay_update_dsi_cmd(mfd);
+
+ pr_debug("%s: pid=%d\n", __func__, current->pid);
+
+ if (dsi_pipe->blt_addr)
+ mdp4_dsi_blt_dmap_busy_wait(dsi_mfd);
+
+ mdp4_dsi_cmd_overlay_kickoff(mfd, pipe);
+}
+
+void mdp4_dsi_cmd_kickoff_ui(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+
+ pr_debug("%s: pid=%d\n", __func__, current->pid);
+ mdp4_dsi_cmd_overlay_kickoff(mfd, pipe);
+}
+
+
+void mdp4_dsi_cmd_overlay_kickoff(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ unsigned long flag;
+
+
+ mdp4_overlay_dsi_state_set(ST_DSI_PLAYING);
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_enable_irq(MDP_OVERLAY0_TERM);
+ mfd->dma->busy = TRUE;
+ if (dsi_pipe->blt_addr)
+ mfd->dma->dmap_busy = TRUE;
+ /* start OVERLAY pipe */
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
+
+ if (dsi_pipe->blt_addr == 0) {
+ /* trigger dsi cmd engine */
+ mipi_dsi_cmd_mdp_sw_trigger();
+ }
+}
+
+void mdp4_dsi_cmd_overlay(struct msm_fb_data_type *mfd)
+{
+ mutex_lock(&mfd->dma->ov_mutex);
+
+ if (mfd && mfd->panel_power_on) {
+ mdp4_dsi_cmd_dma_busy_wait(mfd);
+
+ if (dsi_pipe && dsi_pipe->blt_addr)
+ mdp4_dsi_blt_dmap_busy_wait(mfd);
+
+ mdp4_overlay_update_dsi_cmd(mfd);
+
+ mdp4_dsi_cmd_kickoff_ui(mfd, dsi_pipe);
+
+
+ mdp4_stat.kickoff_dsi++;
+
+ /* signal if pan function is waiting for the update completion */
+ if (mfd->pan_waiting) {
+ mfd->pan_waiting = FALSE;
+ complete(&mfd->pan_comp);
+ }
+ }
+ mdp4_overlay_resource_release();
+ mutex_unlock(&mfd->dma->ov_mutex);
+}
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
new file mode 100644
index 0000000..88b81e7
--- /dev/null
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -0,0 +1,404 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+#include <linux/fb.h>
+#include <linux/msm_mdp.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+#define DSI_VIDEO_BASE 0xE0000
+
+static int first_pixel_start_x;
+static int first_pixel_start_y;
+
+static int writeback_offset;
+
+static struct mdp4_overlay_pipe *dsi_pipe;
+
+static cmd_fxn_t display_on;
+
+void mdp4_dsi_video_fxn_register(cmd_fxn_t fxn)
+{
+ display_on = fxn;
+}
+
+int mdp4_dsi_video_on(struct platform_device *pdev)
+{
+ int dsi_width;
+ int dsi_height;
+ int dsi_bpp;
+ int dsi_border_clr;
+ int dsi_underflow_clr;
+ int dsi_hsync_skew;
+
+ int hsync_period;
+ int hsync_ctrl;
+ int vsync_period;
+ int display_hctl;
+ int display_v_start;
+ int display_v_end;
+ int active_hctl;
+ int active_h_start;
+ int active_h_end;
+ int active_v_start;
+ int active_v_end;
+ int ctrl_polarity;
+ int h_back_porch;
+ int h_front_porch;
+ int v_back_porch;
+ int v_front_porch;
+ int hsync_pulse_width;
+ int vsync_pulse_width;
+ int hsync_polarity;
+ int vsync_polarity;
+ int data_en_polarity;
+ int hsync_start_x;
+ int hsync_end_x;
+ uint8 *buf;
+ int bpp, ptype;
+ struct fb_info *fbi;
+ struct fb_var_screeninfo *var;
+ struct msm_fb_data_type *mfd;
+ struct mdp4_overlay_pipe *pipe;
+ int ret;
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ fbi = mfd->fbi;
+ var = &fbi->var;
+
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf += fbi->var.xoffset * bpp +
+ fbi->var.yoffset * fbi->fix.line_length;
+
+ if (dsi_pipe == NULL) {
+ ptype = mdp4_overlay_format2type(mfd->fb_imgType);
+ if (ptype < 0)
+ printk(KERN_INFO "%s: format2type failed\n", __func__);
+ pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER0, 0);
+ if (pipe == NULL) {
+ printk(KERN_INFO "%s: pipe_alloc failed\n", __func__);
+ return -EBUSY;
+ }
+ pipe->pipe_used++;
+ pipe->mixer_stage = MDP4_MIXER_STAGE_BASE;
+ pipe->mixer_num = MDP4_MIXER0;
+ pipe->src_format = mfd->fb_imgType;
+ mdp4_overlay_panel_mode(pipe->mixer_num, MDP4_PANEL_DSI_VIDEO);
+ ret = mdp4_overlay_format2pipe(pipe);
+ if (ret < 0)
+ printk(KERN_INFO "%s: format2type failed\n", __func__);
+
+ dsi_pipe = pipe; /* keep it */
+
+ writeback_offset = mdp4_overlay_writeback_setup(
+ fbi, pipe, buf, bpp);
+ } else {
+ pipe = dsi_pipe;
+ }
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ if (is_mdp4_hw_reset()) {
+ mdp4_hw_init();
+ outpdw(MDP_BASE + 0x0038, mdp4_display_intf);
+ }
+
+ pipe->src_height = fbi->var.yres;
+ pipe->src_width = fbi->var.xres;
+ pipe->src_h = fbi->var.yres;
+ pipe->src_w = fbi->var.xres;
+ pipe->src_y = 0;
+ pipe->src_x = 0;
+ pipe->srcp0_addr = (uint32) buf;
+ pipe->srcp0_ystride = fbi->fix.line_length;
+ pipe->bpp = bpp;
+
+ pipe->dst_h = fbi->var.yres;
+ pipe->dst_w = fbi->var.xres;
+
+ mdp4_overlay_dmap_xy(pipe); /* dma_p */
+ mdp4_overlay_dmap_cfg(mfd, 1);
+
+ mdp4_overlay_rgb_setup(pipe);
+
+ mdp4_mixer_stage_up(pipe);
+
+ mdp4_overlayproc_cfg(pipe);
+
+ /*
+ * DSI timing setting
+ */
+ h_back_porch = var->left_margin;
+ h_front_porch = var->right_margin;
+ v_back_porch = var->upper_margin;
+ v_front_porch = var->lower_margin;
+ hsync_pulse_width = var->hsync_len;
+ vsync_pulse_width = var->vsync_len;
+ dsi_border_clr = mfd->panel_info.lcdc.border_clr;
+ dsi_underflow_clr = mfd->panel_info.lcdc.underflow_clr;
+ dsi_hsync_skew = mfd->panel_info.lcdc.hsync_skew;
+ dsi_width = mfd->panel_info.xres +
+ mfd->panel_info.mipi.xres_pad;
+ dsi_height = mfd->panel_info.yres +
+ mfd->panel_info.mipi.yres_pad;
+ dsi_bpp = mfd->panel_info.bpp;
+
+ hsync_period = hsync_pulse_width + h_back_porch + dsi_width
+ + h_front_porch;
+ hsync_ctrl = (hsync_period << 16) | hsync_pulse_width;
+ hsync_start_x = h_back_porch + hsync_pulse_width;
+ hsync_end_x = hsync_period - h_front_porch - 1;
+ display_hctl = (hsync_end_x << 16) | hsync_start_x;
+
+ vsync_period =
+ (vsync_pulse_width + v_back_porch + dsi_height + v_front_porch);
+ display_v_start = ((vsync_pulse_width + v_back_porch) * hsync_period)
+ + dsi_hsync_skew;
+ display_v_end =
+ ((vsync_period - v_front_porch) * hsync_period) + dsi_hsync_skew - 1;
+
+ if (dsi_width != var->xres) {
+ active_h_start = hsync_start_x + first_pixel_start_x;
+ active_h_end = active_h_start + var->xres - 1;
+ active_hctl =
+ ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start;
+ } else {
+ active_hctl = 0;
+ }
+
+ if (dsi_height != var->yres) {
+ active_v_start =
+ display_v_start + first_pixel_start_y * hsync_period;
+ active_v_end = active_v_start + (var->yres) * hsync_period - 1;
+ active_v_start |= ACTIVE_START_Y_EN;
+ } else {
+ active_v_start = 0;
+ active_v_end = 0;
+ }
+
+ dsi_underflow_clr |= 0x80000000; /* enable recovery */
+ hsync_polarity = 0;
+ vsync_polarity = 0;
+ data_en_polarity = 0;
+
+ ctrl_polarity =
+ (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity);
+
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x4, hsync_ctrl);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x8, vsync_period * hsync_period);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0xc,
+ vsync_pulse_width * hsync_period);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x10, display_hctl);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x14, display_v_start);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x18, display_v_end);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x1c, active_hctl);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x20, active_v_start);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x24, active_v_end);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x28, dsi_border_clr);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x2c, dsi_underflow_clr);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x30, dsi_hsync_skew);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x38, ctrl_polarity);
+ mdp4_overlay_reg_flush(pipe, 1);
+ mdp_histogram_ctrl(TRUE);
+
+ ret = panel_next_on(pdev);
+ if (ret == 0) {
+ /* enable DSI block */
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 1);
+ mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ if (display_on != NULL) {
+ msleep(50);
+ display_on(pdev);
+ }
+ }
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ return ret;
+}
+
+int mdp4_dsi_video_off(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0);
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ mdp_histogram_ctrl(FALSE);
+ ret = panel_next_off(pdev);
+
+#ifdef MIPI_DSI_RGB_UNSTAGE
+ /* delay to make sure the last frame finishes */
+ msleep(100);
+
+ /* dis-engage rgb0 from mixer0 */
+ if (dsi_pipe)
+ mdp4_mixer_stage_down(dsi_pipe);
+#endif
+
+ return ret;
+}
+
+#ifdef CONFIG_FB_MSM_OVERLAY_WRITEBACK
+int mdp4_dsi_video_overlay_blt_offset(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req)
+{
+ req->offset = writeback_offset;
+ req->width = dsi_pipe->src_width;
+ req->height = dsi_pipe->src_height;
+ req->bpp = dsi_pipe->bpp;
+
+ return sizeof(*req);
+}
+
+void mdp4_dsi_video_overlay_blt(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req)
+{
+ unsigned long flag;
+ int change = 0;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ if (req->enable && dsi_pipe->blt_addr == 0) {
+ dsi_pipe->blt_addr = dsi_pipe->blt_base;
+ change++;
+ } else if (req->enable == 0 && dsi_pipe->blt_addr) {
+ dsi_pipe->blt_addr = 0;
+ change++;
+ }
+ pr_debug("%s: blt_addr=%x\n", __func__, (int)dsi_pipe->blt_addr);
+ dsi_pipe->blt_cnt = 0;
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+ if (!change)
+ return;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ /*
+ * it does not work by turnning dsi video timing enerator off
+ * and configure new changes and tune it back on like LCDC.
+ */
+ mdp4_overlayproc_cfg(dsi_pipe);
+ mdp4_overlay_dmap_xy(dsi_pipe);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+#else
+int mdp4_dsi_video_overlay_blt_offset(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req)
+{
+ return 0;
+}
+void mdp4_dsi_video_overlay_blt(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req)
+{
+ return;
+}
+#endif
+
+void mdp4_overlay_dsi_video_wait4vsync(struct msm_fb_data_type *mfd)
+{
+ unsigned long flag;
+
+ /* enable irq */
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_enable_irq(MDP_DMA2_TERM); /* enable intr */
+ INIT_COMPLETION(dsi_pipe->comp);
+ mfd->dma->waiting = TRUE;
+ outp32(MDP_INTR_CLEAR, INTR_PRIMARY_VSYNC);
+ mdp_intr_mask |= INTR_PRIMARY_VSYNC;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ wait_for_completion_killable(&dsi_pipe->comp);
+ mdp_disable_irq(MDP_DMA2_TERM);
+}
+
+void mdp4_overlay_dsi_video_vsync_push(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+
+ mdp4_overlay_reg_flush(pipe, 1);
+ if (pipe->flags & MDP_OV_PLAY_NOWAIT)
+ return;
+
+ mdp4_overlay_dsi_video_wait4vsync(mfd);
+}
+
+/*
+ * mdp4_primary_vsync_dsi_video: called from isr
+ */
+void mdp4_primary_vsync_dsi_video(void)
+{
+ complete_all(&dsi_pipe->comp);
+}
+
+/*
+ * mdp4_overlay1_done_dsi: called from isr
+ */
+void mdp4_overlay0_done_dsi_video()
+{
+ complete(&dsi_pipe->comp);
+}
+
+
+void mdp4_dsi_video_overlay(struct msm_fb_data_type *mfd)
+{
+ struct fb_info *fbi = mfd->fbi;
+ uint8 *buf;
+ int bpp;
+ struct mdp4_overlay_pipe *pipe;
+
+ if (!mfd->panel_power_on)
+ return;
+
+ /* no need to power on cmd block since it's dsi video mode */
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf += fbi->var.xoffset * bpp +
+ fbi->var.yoffset * fbi->fix.line_length;
+
+ mutex_lock(&mfd->dma->ov_mutex);
+
+ pipe = dsi_pipe;
+ pipe->srcp0_addr = (uint32) buf;
+ mdp4_overlay_rgb_setup(pipe);
+ mutex_unlock(&mfd->dma->ov_mutex);
+ mdp4_overlay_dsi_video_vsync_push(mfd, pipe);
+ mdp4_stat.kickoff_dsi++;
+ mdp4_overlay_resource_release();
+}
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
new file mode 100644
index 0000000..71b460c
--- /dev/null
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -0,0 +1,404 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+#include <linux/fb.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+#define DTV_BASE 0xD0000
+
+/*#define DEBUG*/
+#ifdef DEBUG
+static void __mdp_outp(uint32 port, uint32 value)
+{
+ uint32 in_val;
+
+ outpdw(port, value);
+ in_val = inpdw(port);
+ printk(KERN_INFO "MDP-DTV[%04x] => %08x [%08x]\n",
+ port-(uint32)(MDP_BASE + DTV_BASE), value, in_val);
+}
+
+#undef MDP_OUTP
+#define MDP_OUTP(port, value) __mdp_outp((uint32)(port), (value))
+#endif
+
+static int first_pixel_start_x;
+static int first_pixel_start_y;
+
+static struct mdp4_overlay_pipe *dtv_pipe;
+
+int mdp4_dtv_on(struct platform_device *pdev)
+{
+ int dtv_width;
+ int dtv_height;
+ int dtv_bpp;
+ int dtv_border_clr;
+ int dtv_underflow_clr;
+ int dtv_hsync_skew;
+
+ int hsync_period;
+ int hsync_ctrl;
+ int vsync_period;
+ int display_hctl;
+ int display_v_start;
+ int display_v_end;
+ int active_hctl;
+ int active_h_start;
+ int active_h_end;
+ int active_v_start;
+ int active_v_end;
+ int ctrl_polarity;
+ int h_back_porch;
+ int h_front_porch;
+ int v_back_porch;
+ int v_front_porch;
+ int hsync_pulse_width;
+ int vsync_pulse_width;
+ int hsync_polarity;
+ int vsync_polarity;
+ int data_en_polarity;
+ int hsync_start_x;
+ int hsync_end_x;
+ uint8 *buf;
+ int bpp, ptype;
+ uint32 format;
+ struct fb_info *fbi;
+ struct fb_var_screeninfo *var;
+ struct msm_fb_data_type *mfd;
+ struct mdp4_overlay_pipe *pipe;
+ int ret;
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ fbi = mfd->fbi;
+ var = &fbi->var;
+
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf += fbi->var.xoffset * bpp +
+ fbi->var.yoffset * fbi->fix.line_length;
+
+ if (bpp == 2)
+ format = MDP_RGB_565;
+ else if (bpp == 3)
+ format = MDP_RGB_888;
+ else
+ format = MDP_ARGB_8888;
+
+ if (dtv_pipe == NULL) {
+ ptype = mdp4_overlay_format2type(format);
+ if (ptype < 0)
+ printk(KERN_INFO "%s: format2type failed\n", __func__);
+ pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER1, 0);
+ if (pipe == NULL) {
+ printk(KERN_INFO "%s: pipe_alloc failed\n", __func__);
+ return -EBUSY;
+ }
+ pipe->pipe_used++;
+ pipe->mixer_stage = MDP4_MIXER_STAGE_BASE;
+ pipe->mixer_num = MDP4_MIXER1;
+ pipe->src_format = format;
+ mdp4_overlay_panel_mode(pipe->mixer_num, MDP4_PANEL_DTV);
+ ret = mdp4_overlay_format2pipe(pipe);
+ if (ret < 0)
+ printk(KERN_INFO "%s: format2type failed\n", __func__);
+
+ dtv_pipe = pipe; /* keep it */
+ } else {
+ pipe = dtv_pipe;
+ }
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ pipe->src_height = fbi->var.yres;
+ pipe->src_width = fbi->var.xres;
+ pipe->src_h = fbi->var.yres;
+ pipe->src_w = fbi->var.xres;
+ pipe->src_y = 0;
+ pipe->src_x = 0;
+ pipe->srcp0_addr = (uint32) buf;
+ pipe->srcp0_ystride = fbi->fix.line_length;
+
+ mdp4_overlay_dmae_xy(pipe); /* dma_e */
+ mdp4_overlay_dmae_cfg(mfd, 0);
+
+ mdp4_overlay_rgb_setup(pipe);
+
+ mdp4_mixer_stage_up(pipe);
+
+ mdp4_overlayproc_cfg(pipe);
+
+ /*
+ * DTV timing setting
+ */
+ h_back_porch = var->left_margin;
+ h_front_porch = var->right_margin;
+ v_back_porch = var->upper_margin;
+ v_front_porch = var->lower_margin;
+ hsync_pulse_width = var->hsync_len;
+ vsync_pulse_width = var->vsync_len;
+ dtv_border_clr = mfd->panel_info.lcdc.border_clr;
+ dtv_underflow_clr = mfd->panel_info.lcdc.underflow_clr;
+ dtv_hsync_skew = mfd->panel_info.lcdc.hsync_skew;
+
+ pr_info("%s: <ID=%d %dx%d (%d,%d,%d), (%d,%d,%d) %dMHz>\n", __func__,
+ var->reserved[3], var->xres, var->yres,
+ var->right_margin, var->hsync_len, var->left_margin,
+ var->lower_margin, var->vsync_len, var->upper_margin,
+ var->pixclock/1000/1000);
+
+ dtv_width = var->xres;
+ dtv_height = var->yres;
+ dtv_bpp = mfd->panel_info.bpp;
+
+ hsync_period =
+ hsync_pulse_width + h_back_porch + dtv_width + h_front_porch;
+ hsync_ctrl = (hsync_period << 16) | hsync_pulse_width;
+ hsync_start_x = hsync_pulse_width + h_back_porch;
+ hsync_end_x = hsync_period - h_front_porch - 1;
+ display_hctl = (hsync_end_x << 16) | hsync_start_x;
+
+ vsync_period =
+ (vsync_pulse_width + v_back_porch + dtv_height +
+ v_front_porch) * hsync_period;
+ display_v_start =
+ (vsync_pulse_width + v_back_porch) * hsync_period + dtv_hsync_skew;
+ display_v_end =
+ vsync_period - (v_front_porch * hsync_period) + dtv_hsync_skew - 1;
+
+ if (dtv_width != var->xres) {
+ active_h_start = hsync_start_x + first_pixel_start_x;
+ active_h_end = active_h_start + var->xres - 1;
+ active_hctl =
+ ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start;
+ } else {
+ active_hctl = 0;
+ }
+
+ if (dtv_height != var->yres) {
+ active_v_start =
+ display_v_start + first_pixel_start_y * hsync_period;
+ active_v_end = active_v_start + (var->yres) * hsync_period - 1;
+ active_v_start |= ACTIVE_START_Y_EN;
+ } else {
+ active_v_start = 0;
+ active_v_end = 0;
+ }
+
+ dtv_underflow_clr |= 0x80000000; /* enable recovery */
+ hsync_polarity = fbi->var.yres >= 720 ? 0 : 1;
+ vsync_polarity = fbi->var.yres >= 720 ? 0 : 1;
+ data_en_polarity = 0;
+
+ ctrl_polarity =
+ (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity);
+
+
+ MDP_OUTP(MDP_BASE + DTV_BASE + 0x4, hsync_ctrl);
+ MDP_OUTP(MDP_BASE + DTV_BASE + 0x8, vsync_period);
+ MDP_OUTP(MDP_BASE + DTV_BASE + 0xc, vsync_pulse_width * hsync_period);
+ MDP_OUTP(MDP_BASE + DTV_BASE + 0x18, display_hctl);
+ MDP_OUTP(MDP_BASE + DTV_BASE + 0x1c, display_v_start);
+ MDP_OUTP(MDP_BASE + DTV_BASE + 0x20, display_v_end);
+ MDP_OUTP(MDP_BASE + DTV_BASE + 0x40, dtv_border_clr);
+ MDP_OUTP(MDP_BASE + DTV_BASE + 0x44, dtv_underflow_clr);
+ MDP_OUTP(MDP_BASE + DTV_BASE + 0x48, dtv_hsync_skew);
+ MDP_OUTP(MDP_BASE + DTV_BASE + 0x50, ctrl_polarity);
+ MDP_OUTP(MDP_BASE + DTV_BASE + 0x2c, active_hctl);
+ MDP_OUTP(MDP_BASE + DTV_BASE + 0x30, active_v_start);
+ MDP_OUTP(MDP_BASE + DTV_BASE + 0x38, active_v_end);
+
+ /* Test pattern 8 x 8 pixel */
+ /* MDP_OUTP(MDP_BASE + DTV_BASE + 0x4C, 0x80000808); */
+
+ ret = panel_next_on(pdev);
+ if (ret == 0) {
+ /* enable DTV block */
+ MDP_OUTP(MDP_BASE + DTV_BASE, 1);
+ mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ dev_info(&pdev->dev, "mdp4_overlay_dtv: on");
+ } else {
+ dev_warn(&pdev->dev, "mdp4_overlay_dtv: panel_next_on failed");
+ }
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ return ret;
+}
+
+int mdp4_dtv_off(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ MDP_OUTP(MDP_BASE + DTV_BASE, 0);
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ /*
+ * wait for vsync == 16.6 ms to make sure
+ * the last frame finishes
+ */
+ msleep(20);
+ pr_info("%s\n", __func__);
+
+ ret = panel_next_off(pdev);
+
+ /* dis-engage rgb2 from mixer1 */
+ if (dtv_pipe)
+ mdp4_mixer_stage_down(dtv_pipe);
+
+ /*
+ * wait for another vsync == 16.6 ms to make sure
+ * rgb2 dis-engaged
+ */
+ msleep(20);
+
+ return ret;
+}
+
+static void mdp4_overlay_dtv_wait4vsync(struct msm_fb_data_type *mfd)
+{
+ unsigned long flag;
+
+ /* enable irq */
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_enable_irq(MDP_OVERLAY1_TERM);
+ INIT_COMPLETION(dtv_pipe->comp);
+ mfd->dma->waiting = TRUE;
+ outp32(MDP_INTR_CLEAR, INTR_EXTERNAL_VSYNC);
+ mdp_intr_mask |= INTR_EXTERNAL_VSYNC;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ wait_for_completion_killable(&dtv_pipe->comp);
+ mdp_disable_irq(MDP_OVERLAY1_TERM);
+}
+
+void mdp4_overlay_dtv_vsync_push(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+
+ mdp4_overlay_reg_flush(pipe, 1);
+ if (pipe->flags & MDP_OV_PLAY_NOWAIT)
+ return;
+
+ mdp4_overlay_dtv_wait4vsync(mfd);
+}
+
+static void mdp4_overlay_dtv_wait4_ov_done(struct msm_fb_data_type *mfd)
+{
+ unsigned long flag;
+
+ /* enable irq */
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_enable_irq(MDP_OVERLAY1_TERM);
+ INIT_COMPLETION(dtv_pipe->comp);
+ mfd->dma->waiting = TRUE;
+ outp32(MDP_INTR_CLEAR, INTR_OVERLAY1_DONE);
+ mdp_intr_mask |= INTR_OVERLAY1_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ wait_for_completion_killable(&dtv_pipe->comp);
+ mdp_disable_irq(MDP_OVERLAY1_TERM);
+}
+
+void mdp4_overlay_dtv_ov_done_push(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+
+ mdp4_overlay_reg_flush(pipe, 1);
+ if (pipe->flags & MDP_OV_PLAY_NOWAIT)
+ return;
+
+ mdp4_overlay_dtv_wait4_ov_done(mfd);
+}
+
+void mdp4_external_vsync_dtv()
+{
+ complete(&dtv_pipe->comp);
+}
+
+/*
+ * mdp4_overlay1_done_dtv: called from isr
+ */
+void mdp4_overlay1_done_dtv()
+{
+ complete(&dtv_pipe->comp);
+}
+
+void mdp4_dtv_overlay(struct msm_fb_data_type *mfd)
+{
+ struct fb_info *fbi = mfd->fbi;
+ uint8 *buf;
+ int bpp;
+ unsigned long flag;
+ struct mdp4_overlay_pipe *pipe;
+
+ if (!mfd->panel_power_on)
+ return;
+
+ /* no need to power on cmd block since it's lcdc mode */
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf += fbi->var.xoffset * bpp +
+ fbi->var.yoffset * fbi->fix.line_length;
+
+ mutex_lock(&mfd->dma->ov_mutex);
+
+ pipe = dtv_pipe;
+ pipe->srcp0_addr = (uint32) buf;
+ mdp4_overlay_rgb_setup(pipe);
+ mdp4_overlay_reg_flush(pipe, 1); /* rgb2 and mixer1 */
+
+ /* enable irq */
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_enable_irq(MDP_OVERLAY1_TERM);
+ INIT_COMPLETION(dtv_pipe->comp);
+ mfd->dma->waiting = TRUE;
+ outp32(MDP_INTR_CLEAR, INTR_OVERLAY1_DONE);
+ mdp_intr_mask |= INTR_OVERLAY1_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ wait_for_completion_killable(&dtv_pipe->comp);
+ mdp_disable_irq(MDP_OVERLAY1_TERM);
+
+ mdp4_stat.kickoff_dtv++;
+ mdp4_overlay_resource_release();
+ mutex_unlock(&mfd->dma->ov_mutex);
+}
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
new file mode 100644
index 0000000..ed44d54
--- /dev/null
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -0,0 +1,395 @@
+/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+#ifdef CONFIG_FB_MSM_MDP40
+#define LCDC_BASE 0xC0000
+#else
+#define LCDC_BASE 0xE0000
+#endif
+
+int first_pixel_start_x;
+int first_pixel_start_y;
+
+static int writeback_offset;
+
+static struct mdp4_overlay_pipe *lcdc_pipe;
+static struct completion lcdc_comp;
+
+int mdp_lcdc_on(struct platform_device *pdev)
+{
+ int lcdc_width;
+ int lcdc_height;
+ int lcdc_bpp;
+ int lcdc_border_clr;
+ int lcdc_underflow_clr;
+ int lcdc_hsync_skew;
+
+ int hsync_period;
+ int hsync_ctrl;
+ int vsync_period;
+ int display_hctl;
+ int display_v_start;
+ int display_v_end;
+ int active_hctl;
+ int active_h_start;
+ int active_h_end;
+ int active_v_start;
+ int active_v_end;
+ int ctrl_polarity;
+ int h_back_porch;
+ int h_front_porch;
+ int v_back_porch;
+ int v_front_porch;
+ int hsync_pulse_width;
+ int vsync_pulse_width;
+ int hsync_polarity;
+ int vsync_polarity;
+ int data_en_polarity;
+ int hsync_start_x;
+ int hsync_end_x;
+ uint8 *buf;
+ int bpp, ptype;
+ struct fb_info *fbi;
+ struct fb_var_screeninfo *var;
+ struct msm_fb_data_type *mfd;
+ struct mdp4_overlay_pipe *pipe;
+ int ret;
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ fbi = mfd->fbi;
+ var = &fbi->var;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ if (is_mdp4_hw_reset()) {
+ mdp4_hw_init();
+ outpdw(MDP_BASE + 0x0038, mdp4_display_intf);
+ }
+
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf += fbi->var.xoffset * bpp +
+ fbi->var.yoffset * fbi->fix.line_length;
+
+ if (lcdc_pipe == NULL) {
+ ptype = mdp4_overlay_format2type(mfd->fb_imgType);
+ if (ptype < 0)
+ printk(KERN_INFO "%s: format2type failed\n", __func__);
+ pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER0, 0);
+ if (pipe == NULL)
+ printk(KERN_INFO "%s: pipe_alloc failed\n", __func__);
+ pipe->pipe_used++;
+ pipe->mixer_stage = MDP4_MIXER_STAGE_BASE;
+ pipe->mixer_num = MDP4_MIXER0;
+ pipe->src_format = mfd->fb_imgType;
+ mdp4_overlay_panel_mode(pipe->mixer_num, MDP4_PANEL_LCDC);
+ ret = mdp4_overlay_format2pipe(pipe);
+ if (ret < 0)
+ printk(KERN_INFO "%s: format2pipe failed\n", __func__);
+ lcdc_pipe = pipe; /* keep it */
+ init_completion(&lcdc_comp);
+
+ writeback_offset = mdp4_overlay_writeback_setup(
+ fbi, pipe, buf, bpp);
+ } else {
+ pipe = lcdc_pipe;
+ }
+
+ pipe->src_height = fbi->var.yres;
+ pipe->src_width = fbi->var.xres;
+ pipe->src_h = fbi->var.yres;
+ pipe->src_w = fbi->var.xres;
+ pipe->src_y = 0;
+ pipe->src_x = 0;
+ pipe->srcp0_addr = (uint32) buf;
+ pipe->srcp0_ystride = fbi->fix.line_length;
+ pipe->bpp = bpp;
+
+ mdp4_overlay_dmap_xy(pipe);
+ mdp4_overlay_dmap_cfg(mfd, 1);
+
+ mdp4_overlay_rgb_setup(pipe);
+
+ mdp4_mixer_stage_up(pipe);
+
+ mdp4_overlayproc_cfg(pipe);
+
+ /*
+ * LCDC timing setting
+ */
+ h_back_porch = var->left_margin;
+ h_front_porch = var->right_margin;
+ v_back_porch = var->upper_margin;
+ v_front_porch = var->lower_margin;
+ hsync_pulse_width = var->hsync_len;
+ vsync_pulse_width = var->vsync_len;
+ lcdc_border_clr = mfd->panel_info.lcdc.border_clr;
+ lcdc_underflow_clr = mfd->panel_info.lcdc.underflow_clr;
+ lcdc_hsync_skew = mfd->panel_info.lcdc.hsync_skew;
+
+ lcdc_width = var->xres;
+ lcdc_height = var->yres;
+ lcdc_bpp = mfd->panel_info.bpp;
+
+ hsync_period =
+ hsync_pulse_width + h_back_porch + lcdc_width + h_front_porch;
+ hsync_ctrl = (hsync_period << 16) | hsync_pulse_width;
+ hsync_start_x = hsync_pulse_width + h_back_porch;
+ hsync_end_x = hsync_period - h_front_porch - 1;
+ display_hctl = (hsync_end_x << 16) | hsync_start_x;
+
+ vsync_period =
+ (vsync_pulse_width + v_back_porch + lcdc_height +
+ v_front_porch) * hsync_period;
+ display_v_start =
+ (vsync_pulse_width + v_back_porch) * hsync_period + lcdc_hsync_skew;
+ display_v_end =
+ vsync_period - (v_front_porch * hsync_period) + lcdc_hsync_skew - 1;
+
+ if (lcdc_width != var->xres) {
+ active_h_start = hsync_start_x + first_pixel_start_x;
+ active_h_end = active_h_start + var->xres - 1;
+ active_hctl =
+ ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start;
+ } else {
+ active_hctl = 0;
+ }
+
+ if (lcdc_height != var->yres) {
+ active_v_start =
+ display_v_start + first_pixel_start_y * hsync_period;
+ active_v_end = active_v_start + (var->yres) * hsync_period - 1;
+ active_v_start |= ACTIVE_START_Y_EN;
+ } else {
+ active_v_start = 0;
+ active_v_end = 0;
+ }
+
+
+#ifdef CONFIG_FB_MSM_MDP40
+ hsync_polarity = 1;
+ vsync_polarity = 1;
+ lcdc_underflow_clr |= 0x80000000; /* enable recovery */
+#else
+ hsync_polarity = 0;
+ vsync_polarity = 0;
+#endif
+ data_en_polarity = 0;
+
+ ctrl_polarity =
+ (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity);
+
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x4, hsync_ctrl);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x8, vsync_period);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0xc, vsync_pulse_width * hsync_period);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x10, display_hctl);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x14, display_v_start);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x18, display_v_end);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x28, lcdc_border_clr);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x2c, lcdc_underflow_clr);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x30, lcdc_hsync_skew);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x38, ctrl_polarity);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x1c, active_hctl);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x20, active_v_start);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x24, active_v_end);
+
+ mdp4_overlay_reg_flush(pipe, 1);
+#ifdef CONFIG_MSM_BUS_SCALING
+ mdp_bus_scale_update_request(2);
+#endif
+ mdp_histogram_ctrl(TRUE);
+
+ ret = panel_next_on(pdev);
+ if (ret == 0) {
+ /* enable LCDC block */
+ MDP_OUTP(MDP_BASE + LCDC_BASE, 1);
+ mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ }
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ return ret;
+}
+
+int mdp_lcdc_off(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ MDP_OUTP(MDP_BASE + LCDC_BASE, 0);
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ mdp_histogram_ctrl(FALSE);
+ ret = panel_next_off(pdev);
+
+ /* delay to make sure the last frame finishes */
+ msleep(16);
+
+#ifdef LCDC_RGB_UNSTAGE
+ /* dis-engage rgb0 from mixer0 */
+ if (lcdc_pipe)
+ mdp4_mixer_stage_down(lcdc_pipe);
+#endif
+#ifdef CONFIG_MSM_BUS_SCALING
+ mdp_bus_scale_update_request(0);
+#endif
+
+ return ret;
+}
+
+
+#ifdef CONFIG_FB_MSM_OVERLAY_WRITEBACK
+int mdp4_lcdc_overlay_blt_offset(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req)
+{
+ req->offset = writeback_offset;
+ req->width = lcdc_pipe->src_width;
+ req->height = lcdc_pipe->src_height;
+ req->bpp = lcdc_pipe->bpp;
+
+ return sizeof(*req);
+}
+
+void mdp4_lcdc_overlay_blt(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req)
+{
+ unsigned long flag;
+ int change = 0;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ if (req->enable && lcdc_pipe->blt_addr == 0) {
+ lcdc_pipe->blt_addr = lcdc_pipe->blt_base;
+ change++;
+ } else if (req->enable == 0 && lcdc_pipe->blt_addr) {
+ lcdc_pipe->blt_addr = 0;
+ change++;
+ }
+ pr_debug("%s: blt_addr=%x\n", __func__, (int)lcdc_pipe->blt_addr);
+ lcdc_pipe->blt_cnt = 0;
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+ if (!change)
+ return;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ MDP_OUTP(MDP_BASE + LCDC_BASE, 0); /* stop lcdc */
+ msleep(50);
+ mdp4_overlayproc_cfg(lcdc_pipe);
+ mdp4_overlay_dmap_xy(lcdc_pipe);
+ MDP_OUTP(MDP_BASE + LCDC_BASE, 1); /* start lcdc */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+#endif
+
+void mdp4_overlay_lcdc_wait4vsync(struct msm_fb_data_type *mfd)
+{
+ unsigned long flag;
+
+ /* enable irq */
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_enable_irq(MDP_DMA2_TERM); /* enable intr */
+ INIT_COMPLETION(lcdc_comp);
+ mfd->dma->waiting = TRUE;
+ outp32(MDP_INTR_CLEAR, INTR_PRIMARY_VSYNC);
+ mdp_intr_mask |= INTR_PRIMARY_VSYNC;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ wait_for_completion_killable(&lcdc_comp);
+ mdp_disable_irq(MDP_DMA2_TERM);
+}
+
+void mdp4_overlay_lcdc_vsync_push(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+
+ mdp4_overlay_reg_flush(pipe, 1);
+ if (pipe->flags & MDP_OV_PLAY_NOWAIT)
+ return;
+
+ mdp4_overlay_lcdc_wait4vsync(mfd);
+}
+
+/*
+ * mdp4_primary_vsync_lcdc: called from isr
+ */
+void mdp4_primary_vsync_lcdc(void)
+{
+ complete_all(&lcdc_comp);
+}
+
+/*
+ * mdp4_overlay0_done_lcdc: called from isr
+ */
+void mdp4_overlay0_done_lcdc(void)
+{
+ complete_all(&lcdc_comp);
+}
+
+void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd)
+{
+ struct fb_info *fbi = mfd->fbi;
+ uint8 *buf;
+ int bpp;
+ struct mdp4_overlay_pipe *pipe;
+
+ if (!mfd->panel_power_on)
+ return;
+
+ /* no need to power on cmd block since it's lcdc mode */
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf += fbi->var.xoffset * bpp +
+ fbi->var.yoffset * fbi->fix.line_length;
+
+ mutex_lock(&mfd->dma->ov_mutex);
+
+ pipe = lcdc_pipe;
+ pipe->srcp0_addr = (uint32) buf;
+ mdp4_overlay_rgb_setup(pipe);
+ mutex_unlock(&mfd->dma->ov_mutex);
+ mdp4_overlay_lcdc_vsync_push(mfd, pipe);
+ mdp4_stat.kickoff_lcdc++;
+ mdp4_overlay_resource_release();
+}
diff --git a/drivers/video/msm/mdp4_overlay_mddi.c b/drivers/video/msm/mdp4_overlay_mddi.c
new file mode 100644
index 0000000..2bf9faf
--- /dev/null
+++ b/drivers/video/msm/mdp4_overlay_mddi.c
@@ -0,0 +1,612 @@
+/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+static struct mdp4_overlay_pipe *mddi_pipe;
+static struct msm_fb_data_type *mddi_mfd;
+static int busy_wait_cnt;
+
+static int vsync_start_y_adjust = 4;
+
+static int dmap_vsync_enable;
+
+void mdp_dmap_vsync_set(int enable)
+{
+ dmap_vsync_enable = enable;
+}
+
+int mdp_dmap_vsync_get(void)
+{
+ return dmap_vsync_enable;
+}
+
+void mdp4_mddi_vsync_enable(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe, int which)
+{
+ uint32 start_y, data, tear_en;
+
+ tear_en = (1 << which);
+
+ if ((mfd->use_mdp_vsync) && (mfd->ibuf.vsync_enable) &&
+ (mfd->panel_info.lcd.vsync_enable)) {
+
+ if (mdp_hw_revision < MDP4_REVISION_V2_1) {
+ /* need dmas dmap switch */
+ if (which == 0 && dmap_vsync_enable == 0 &&
+ mfd->panel_info.lcd.rev < 2) /* dma_p */
+ return;
+ }
+
+ if (vsync_start_y_adjust <= pipe->dst_y)
+ start_y = pipe->dst_y - vsync_start_y_adjust;
+ else
+ start_y = (mfd->total_lcd_lines - 1) -
+ (vsync_start_y_adjust - pipe->dst_y);
+ if (which == 0)
+ MDP_OUTP(MDP_BASE + 0x210, start_y); /* primary */
+ else
+ MDP_OUTP(MDP_BASE + 0x214, start_y); /* secondary */
+
+ data = inpdw(MDP_BASE + 0x20c);
+ data |= tear_en;
+ MDP_OUTP(MDP_BASE + 0x20c, data);
+ } else {
+ data = inpdw(MDP_BASE + 0x20c);
+ data &= ~tear_en;
+ MDP_OUTP(MDP_BASE + 0x20c, data);
+ }
+}
+
+#define WHOLESCREEN
+
+void mdp4_overlay_update_lcd(struct msm_fb_data_type *mfd)
+{
+ MDPIBUF *iBuf = &mfd->ibuf;
+ uint8 *src;
+ int ptype;
+ uint32 mddi_ld_param;
+ uint16 mddi_vdo_packet_reg;
+ struct mdp4_overlay_pipe *pipe;
+ int ret;
+
+ if (mfd->key != MFD_KEY)
+ return;
+
+ mddi_mfd = mfd; /* keep it */
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ if (mddi_pipe == NULL) {
+ ptype = mdp4_overlay_format2type(mfd->fb_imgType);
+ if (ptype < 0)
+ printk(KERN_INFO "%s: format2type failed\n", __func__);
+ pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER0, 0);
+ if (pipe == NULL)
+ printk(KERN_INFO "%s: pipe_alloc failed\n", __func__);
+ pipe->pipe_used++;
+ pipe->mixer_num = MDP4_MIXER0;
+ pipe->src_format = mfd->fb_imgType;
+ mdp4_overlay_panel_mode(pipe->mixer_num, MDP4_PANEL_MDDI);
+ ret = mdp4_overlay_format2pipe(pipe);
+ if (ret < 0)
+ printk(KERN_INFO "%s: format2type failed\n", __func__);
+
+ mddi_pipe = pipe; /* keep it */
+ mddi_pipe->blt_end = 1; /* mark as end */
+ mddi_ld_param = 0;
+ mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt;
+
+ if (mdp_hw_revision == MDP4_REVISION_V2_1) {
+ uint32 data;
+
+ data = inpdw(MDP_BASE + 0x0028);
+ data &= ~0x0300; /* bit 8, 9, MASTER4 */
+ if (mfd->fbi->var.xres == 540) /* qHD, 540x960 */
+ data |= 0x0200;
+ else
+ data |= 0x0100;
+
+ MDP_OUTP(MDP_BASE + 0x00028, data);
+ }
+
+ if (mfd->panel_info.type == MDDI_PANEL) {
+ if (mfd->panel_info.pdest == DISPLAY_1)
+ mddi_ld_param = 0;
+ else
+ mddi_ld_param = 1;
+ } else {
+ mddi_ld_param = 2;
+ }
+
+ MDP_OUTP(MDP_BASE + 0x00090, mddi_ld_param);
+
+ if (mfd->panel_info.bpp == 24)
+ MDP_OUTP(MDP_BASE + 0x00094,
+ (MDDI_VDO_PACKET_DESC_24 << 16) | mddi_vdo_packet_reg);
+ else if (mfd->panel_info.bpp == 16)
+ MDP_OUTP(MDP_BASE + 0x00094,
+ (MDDI_VDO_PACKET_DESC_16 << 16) | mddi_vdo_packet_reg);
+ else
+ MDP_OUTP(MDP_BASE + 0x00094,
+ (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg);
+
+ MDP_OUTP(MDP_BASE + 0x00098, 0x01);
+ } else {
+ pipe = mddi_pipe;
+ }
+
+ /* 0 for dma_p, client_id = 0 */
+ MDP_OUTP(MDP_BASE + 0x00090, 0);
+
+
+ src = (uint8 *) iBuf->buf;
+
+#ifdef WHOLESCREEN
+
+ {
+ struct fb_info *fbi;
+
+ fbi = mfd->fbi;
+ pipe->src_height = fbi->var.yres;
+ pipe->src_width = fbi->var.xres;
+ pipe->src_h = fbi->var.yres;
+ pipe->src_w = fbi->var.xres;
+ pipe->src_y = 0;
+ pipe->src_x = 0;
+ pipe->dst_h = fbi->var.yres;
+ pipe->dst_w = fbi->var.xres;
+ pipe->dst_y = 0;
+ pipe->dst_x = 0;
+ pipe->srcp0_addr = (uint32)src;
+ pipe->srcp0_ystride = fbi->fix.line_length;
+ }
+
+#else
+ if (mdp4_overlay_active(MDP4_MIXER0)) {
+ struct fb_info *fbi;
+
+ fbi = mfd->fbi;
+ pipe->src_height = fbi->var.yres;
+ pipe->src_width = fbi->var.xres;
+ pipe->src_h = fbi->var.yres;
+ pipe->src_w = fbi->var.xres;
+ pipe->src_y = 0;
+ pipe->src_x = 0;
+ pipe->dst_h = fbi->var.yres;
+ pipe->dst_w = fbi->var.xres;
+ pipe->dst_y = 0;
+ pipe->dst_x = 0;
+ pipe->srcp0_addr = (uint32) src;
+ pipe->srcp0_ystride = fbi->fix.line_length;
+ } else {
+ /* starting input address */
+ src += (iBuf->dma_x + iBuf->dma_y * iBuf->ibuf_width)
+ * iBuf->bpp;
+
+ pipe->src_height = iBuf->dma_h;
+ pipe->src_width = iBuf->dma_w;
+ pipe->src_h = iBuf->dma_h;
+ pipe->src_w = iBuf->dma_w;
+ pipe->src_y = 0;
+ pipe->src_x = 0;
+ pipe->dst_h = iBuf->dma_h;
+ pipe->dst_w = iBuf->dma_w;
+ pipe->dst_y = iBuf->dma_y;
+ pipe->dst_x = iBuf->dma_x;
+ pipe->srcp0_addr = (uint32) src;
+ pipe->srcp0_ystride = iBuf->ibuf_width * iBuf->bpp;
+ }
+#endif
+
+ pipe->mixer_stage = MDP4_MIXER_STAGE_BASE;
+
+ mdp4_overlay_rgb_setup(pipe);
+
+ mdp4_mixer_stage_up(pipe);
+
+ mdp4_overlayproc_cfg(pipe);
+
+ mdp4_overlay_dmap_xy(pipe);
+
+ mdp4_overlay_dmap_cfg(mfd, 0);
+
+ mdp4_mddi_vsync_enable(mfd, pipe, 0);
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+}
+
+int mdp4_mddi_overlay_blt_offset(int *off)
+{
+ if (mdp_hw_revision < MDP4_REVISION_V2_1) { /* need dmas dmap switch */
+ if (mddi_pipe->blt_end ||
+ (mdp4_overlay_mixer_play(mddi_pipe->mixer_num) == 0)) {
+ *off = -1;
+ return -EINVAL;
+ }
+ } else {
+ /* no dmas dmap switch */
+ if (mddi_pipe->blt_end) {
+ *off = -1;
+ return -EINVAL;
+ }
+ }
+
+ if (mddi_pipe->blt_cnt & 0x01)
+ *off = mddi_pipe->src_height * mddi_pipe->src_width * 3;
+ else
+ *off = 0;
+
+ return 0;
+}
+
+void mdp4_mddi_overlay_blt(ulong addr)
+{
+ unsigned long flag;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ if (addr) {
+ mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ mdp_intr_mask |= INTR_DMA_P_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ mddi_pipe->blt_cnt = 0;
+ mddi_pipe->blt_end = 0;
+ mddi_pipe->blt_addr = addr;
+ } else {
+ mddi_pipe->blt_end = 1; /* mark as end */
+ }
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+}
+
+void mdp4_blt_xy_update(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 off, addr;
+ int bpp;
+ char *overlay_base;
+
+
+ if (pipe->blt_addr == 0)
+ return;
+
+
+#ifdef BLT_RGB565
+ bpp = 2; /* overlay ouput is RGB565 */
+#else
+ bpp = 3; /* overlay ouput is RGB888 */
+#endif
+ off = 0;
+ if (pipe->dmap_cnt & 0x01)
+ off = pipe->src_height * pipe->src_width * bpp;
+
+ addr = pipe->blt_addr + off;
+
+ /* dmap */
+ MDP_OUTP(MDP_BASE + 0x90008, addr);
+
+ /* overlay 0 */
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+ outpdw(overlay_base + 0x000c, addr);
+ outpdw(overlay_base + 0x001c, addr);
+}
+
+/*
+ * mdp4_dmap_done_mddi: called from isr
+ */
+void mdp4_dma_p_done_mddi(void)
+{
+ if (mddi_pipe->blt_end) {
+ mddi_pipe->blt_addr = 0;
+ mdp_intr_mask &= ~INTR_DMA_P_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ mdp4_overlayproc_cfg(mddi_pipe);
+ mdp4_overlay_dmap_xy(mddi_pipe);
+ }
+
+ /*
+ * single buffer, no need to increase
+ * mdd_pipe->dmap_cnt here
+ */
+}
+
+/*
+ * mdp4_overlay0_done_mddi: called from isr
+ */
+void mdp4_overlay0_done_mddi(struct mdp_dma_data *dma)
+{
+ mdp_disable_irq_nosync(MDP_OVERLAY0_TERM);
+
+ dma->busy = FALSE;
+ complete(&dma->comp);
+ mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK,
+ MDP_BLOCK_POWER_OFF, TRUE);
+
+ if (busy_wait_cnt)
+ busy_wait_cnt--;
+
+ pr_debug("%s: ISR-done\n", __func__);
+
+ if (mddi_pipe->blt_addr) {
+ if (mddi_pipe->blt_cnt == 0) {
+ mdp4_overlayproc_cfg(mddi_pipe);
+ mdp4_overlay_dmap_xy(mddi_pipe);
+ mddi_pipe->ov_cnt = 0;
+ mddi_pipe->dmap_cnt = 0;
+ /* BLT start from next frame */
+ } else {
+ mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON,
+ FALSE);
+ mdp4_blt_xy_update(mddi_pipe);
+ outpdw(MDP_BASE + 0x000c, 0x0); /* start DMAP */
+ }
+ mddi_pipe->blt_cnt++;
+ mddi_pipe->ov_cnt++;
+ }
+
+
+
+}
+
+void mdp4_mddi_overlay_restore(void)
+{
+ if (mddi_mfd == NULL)
+ return;
+
+ pr_debug("%s: resotre, pid=%d\n", __func__, current->pid);
+
+ if (mddi_mfd->panel_power_on == 0)
+ return;
+ if (mddi_mfd && mddi_pipe) {
+ mdp4_mddi_dma_busy_wait(mddi_mfd);
+ mdp4_overlay_update_lcd(mddi_mfd);
+ mdp4_mddi_overlay_kickoff(mddi_mfd, mddi_pipe);
+ mddi_mfd->dma_update_flag = 1;
+ }
+ if (mdp_hw_revision < MDP4_REVISION_V2_1) /* need dmas dmap switch */
+ mdp4_mddi_overlay_dmas_restore();
+}
+
+/*
+ * mdp4_mddi_cmd_dma_busy_wait: check mddi link activity
+ * dsi link is a shared resource and it can only be used
+ * while it is in idle state.
+ * ov_mutex need to be acquired before call this function.
+ */
+void mdp4_mddi_dma_busy_wait(struct msm_fb_data_type *mfd)
+{
+ unsigned long flag;
+ int need_wait = 0;
+
+ pr_debug("%s: START, pid=%d\n", __func__, current->pid);
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ if (mfd->dma->busy == TRUE) {
+ if (busy_wait_cnt == 0)
+ INIT_COMPLETION(mfd->dma->comp);
+ busy_wait_cnt++;
+ need_wait++;
+ }
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+
+ if (need_wait) {
+ /* wait until DMA finishes the current job */
+ pr_debug("%s: PENDING, pid=%d\n", __func__, current->pid);
+ wait_for_completion(&mfd->dma->comp);
+ }
+ pr_debug("%s: DONE, pid=%d\n", __func__, current->pid);
+}
+
+void mdp4_mddi_kickoff_video(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ pr_debug("%s: pid=%d\n", __func__, current->pid);
+ mdp4_mddi_overlay_kickoff(mfd, pipe);
+}
+
+void mdp4_mddi_kickoff_ui(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ pr_debug("%s: pid=%d\n", __func__, current->pid);
+ mdp4_mddi_overlay_kickoff(mfd, pipe);
+}
+
+
+void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ if (mdp_hw_revision == MDP4_REVISION_V2_1) {
+ if (mdp4_overlay_status_read(MDP4_OVERLAY_TYPE_UNSET)) {
+ uint32 data;
+ data = inpdw(MDP_BASE + 0x0028);
+ data &= ~0x0300; /* bit 8, 9, MASTER4 */
+ if (mfd->fbi->var.xres == 540) /* qHD, 540x960 */
+ data |= 0x0200;
+ else
+ data |= 0x0100;
+ MDP_OUTP(MDP_BASE + 0x00028, data);
+ mdp4_overlay_status_write(MDP4_OVERLAY_TYPE_UNSET,
+ false);
+ }
+ if (mdp4_overlay_status_read(MDP4_OVERLAY_TYPE_SET)) {
+ uint32 data;
+ data = inpdw(MDP_BASE + 0x0028);
+ data &= ~0x0300; /* bit 8, 9, MASTER4 */
+ MDP_OUTP(MDP_BASE + 0x00028, data);
+ mdp4_overlay_status_write(MDP4_OVERLAY_TYPE_SET, false);
+ }
+ }
+ mdp_enable_irq(MDP_OVERLAY0_TERM);
+ mfd->dma->busy = TRUE;
+ /* start OVERLAY pipe */
+ mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
+}
+
+void mdp4_dma_s_update_lcd(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ MDPIBUF *iBuf = &mfd->ibuf;
+ uint32 outBpp = iBuf->bpp;
+ uint16 mddi_vdo_packet_reg;
+ uint32 dma_s_cfg_reg;
+
+ dma_s_cfg_reg = 0;
+
+ if (mfd->fb_imgType == MDP_RGBA_8888)
+ dma_s_cfg_reg |= DMA_PACK_PATTERN_BGR; /* on purpose */
+ else if (mfd->fb_imgType == MDP_BGR_565)
+ dma_s_cfg_reg |= DMA_PACK_PATTERN_BGR;
+ else
+ dma_s_cfg_reg |= DMA_PACK_PATTERN_RGB;
+
+ if (outBpp == 4)
+ dma_s_cfg_reg |= (1 << 26); /* xRGB8888 */
+ else if (outBpp == 2)
+ dma_s_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
+
+ dma_s_cfg_reg |= DMA_DITHER_EN;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ /* PIXELSIZE */
+ MDP_OUTP(MDP_BASE + 0xa0004, (pipe->dst_h << 16 | pipe->dst_w));
+ MDP_OUTP(MDP_BASE + 0xa0008, pipe->srcp0_addr); /* ibuf address */
+ MDP_OUTP(MDP_BASE + 0xa000c, pipe->srcp0_ystride);/* ystride */
+
+ if (mfd->panel_info.bpp == 24) {
+ dma_s_cfg_reg |= DMA_DSTC0G_8BITS | /* 666 18BPP */
+ DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
+ } else if (mfd->panel_info.bpp == 18) {
+ dma_s_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */
+ DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+ } else {
+ dma_s_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */
+ DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
+ }
+
+ MDP_OUTP(MDP_BASE + 0xa0010, (pipe->dst_y << 16) | pipe->dst_x);
+
+ /* 1 for dma_s, client_id = 0 */
+ MDP_OUTP(MDP_BASE + 0x00090, 1);
+
+ mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt;
+
+ if (mfd->panel_info.bpp == 24)
+ MDP_OUTP(MDP_BASE + 0x00094,
+ (MDDI_VDO_PACKET_DESC_24 << 16) | mddi_vdo_packet_reg);
+ else if (mfd->panel_info.bpp == 16)
+ MDP_OUTP(MDP_BASE + 0x00094,
+ (MDDI_VDO_PACKET_DESC_16 << 16) | mddi_vdo_packet_reg);
+ else
+ MDP_OUTP(MDP_BASE + 0x00094,
+ (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg);
+
+ MDP_OUTP(MDP_BASE + 0x00098, 0x01);
+
+ MDP_OUTP(MDP_BASE + 0xa0000, dma_s_cfg_reg);
+
+ mdp4_mddi_vsync_enable(mfd, pipe, 1);
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_mddi_dma_s_kickoff(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ mdp_enable_irq(MDP_DMA_S_TERM);
+ mfd->dma->busy = TRUE;
+ mfd->ibuf_flushed = TRUE;
+ /* start dma_s pipe */
+ mdp_pipe_kickoff(MDP_DMA_S_TERM, mfd);
+
+ /* wait until DMA finishes the current job */
+ wait_for_completion(&mfd->dma->comp);
+ mdp_disable_irq(MDP_DMA_S_TERM);
+}
+
+void mdp4_mddi_overlay_dmas_restore(void)
+{
+ /* mutex held by caller */
+ if (mddi_mfd && mddi_pipe) {
+ mdp4_mddi_dma_busy_wait(mddi_mfd);
+ mdp4_dma_s_update_lcd(mddi_mfd, mddi_pipe);
+ mdp4_mddi_dma_s_kickoff(mddi_mfd, mddi_pipe);
+ mddi_mfd->dma_update_flag = 1;
+ }
+}
+
+void mdp4_mddi_overlay(struct msm_fb_data_type *mfd)
+{
+ mutex_lock(&mfd->dma->ov_mutex);
+
+ if (mfd && mfd->panel_power_on) {
+ mdp4_mddi_dma_busy_wait(mfd);
+ mdp4_overlay_update_lcd(mfd);
+
+ if (mdp_hw_revision < MDP4_REVISION_V2_1) {
+ /* dmas dmap switch */
+ if (mdp4_overlay_mixer_play(mddi_pipe->mixer_num)
+ == 0) {
+ mdp4_dma_s_update_lcd(mfd, mddi_pipe);
+ mdp4_mddi_dma_s_kickoff(mfd, mddi_pipe);
+ } else
+ mdp4_mddi_kickoff_ui(mfd, mddi_pipe);
+ } else /* no dams dmap switch */
+ mdp4_mddi_kickoff_ui(mfd, mddi_pipe);
+
+ mdp4_stat.kickoff_mddi++;
+
+ /* signal if pan function is waiting for the update completion */
+ if (mfd->pan_waiting) {
+ mfd->pan_waiting = FALSE;
+ complete(&mfd->pan_comp);
+ }
+ }
+ mdp4_overlay_resource_release();
+ mutex_unlock(&mfd->dma->ov_mutex);
+}
+
+int mdp4_mddi_overlay_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+ struct msm_fb_data_type *mfd = info->par;
+ mutex_lock(&mfd->dma->ov_mutex);
+ if (mfd && mfd->panel_power_on) {
+ mdp4_mddi_dma_busy_wait(mfd);
+ mdp_hw_cursor_update(info, cursor);
+ }
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return 0;
+}
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
new file mode 100644
index 0000000..52e4a82
--- /dev/null
+++ b/drivers/video/msm/mdp4_util.c
@@ -0,0 +1,2101 @@
+/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+struct mdp4_statistic mdp4_stat;
+
+unsigned is_mdp4_hw_reset(void)
+{
+ unsigned hw_reset = 0;
+
+ /* Only revisions > v2.1 may be reset or powered off/on at runtime */
+ if (mdp_hw_revision > MDP4_REVISION_V2_1) {
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ hw_reset = !inpdw(MDP_BASE + 0x003c);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ }
+
+ return hw_reset;
+}
+
+void mdp4_sw_reset(ulong bits)
+{
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ bits &= 0x1f; /* 5 bits */
+ outpdw(MDP_BASE + 0x001c, bits); /* MDP_SW_RESET */
+
+ while (inpdw(MDP_BASE + 0x001c) & bits) /* self clear when complete */
+ ;
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ MSM_FB_DEBUG("mdp4_sw_reset: 0x%x\n", (int)bits);
+}
+
+void mdp4_overlay_cfg(int overlayer, int blt_mode, int refresh, int direct_out)
+{
+ ulong bits = 0;
+
+ if (blt_mode)
+ bits |= (1 << 3);
+ refresh &= 0x03; /* 2 bites */
+ bits |= (refresh << 1);
+ direct_out &= 0x01;
+ bits |= direct_out;
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+
+ if (overlayer == MDP4_MIXER0)
+ outpdw(MDP_BASE + 0x10004, bits); /* MDP_OVERLAY0_CFG */
+ else
+ outpdw(MDP_BASE + 0x18004, bits); /* MDP_OVERLAY1_CFG */
+
+ MSM_FB_DEBUG("mdp4_overlay_cfg: 0x%x\n",
+ (int)inpdw(MDP_BASE + 0x10004));
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_display_intf_sel(int output, ulong intf)
+{
+ ulong bits, mask, data;
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ bits = inpdw(MDP_BASE + 0x0038); /* MDP_DISP_INTF_SEL */
+
+ if (intf == DSI_VIDEO_INTF) {
+ data = 0x40; /* bit 6 */
+ intf = MDDI_LCDC_INTF;
+ if (output == SECONDARY_INTF_SEL) {
+ MSM_FB_INFO("%s: Illegal INTF selected, output=%d \
+ intf=%d\n", __func__, output, (int)intf);
+ }
+ } else if (intf == DSI_CMD_INTF) {
+ data = 0x80; /* bit 7 */
+ intf = MDDI_INTF;
+ if (output == EXTERNAL_INTF_SEL) {
+ MSM_FB_INFO("%s: Illegal INTF selected, output=%d \
+ intf=%d\n", __func__, output, (int)intf);
+ }
+ } else
+ data = 0;
+
+ mask = 0x03; /* 2 bits */
+ intf &= 0x03; /* 2 bits */
+
+ switch (output) {
+ case EXTERNAL_INTF_SEL:
+ intf <<= 4;
+ mask <<= 4;
+ break;
+ case SECONDARY_INTF_SEL:
+ intf &= 0x02; /* only MDDI and EBI2 support */
+ intf <<= 2;
+ mask <<= 2;
+ break;
+ default:
+ break;
+ }
+
+ intf |= data;
+ mask |= data;
+
+ bits &= ~mask;
+ bits |= intf;
+
+ outpdw(MDP_BASE + 0x0038, bits); /* MDP_DISP_INTF_SEL */
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ MSM_FB_DEBUG("mdp4_display_intf_sel: 0x%x\n", (int)inpdw(MDP_BASE + 0x0038));
+}
+
+unsigned long mdp4_display_status(void)
+{
+ ulong status;
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ status = inpdw(MDP_BASE + 0x0018) & 0x3ff; /* MDP_DISPLAY_STATUS */
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ return status;
+}
+
+void mdp4_ebi2_lcd_setup(int lcd, ulong base, int ystride)
+{
+ /* always use memory map */
+ ystride &= 0x01fff; /* 13 bits */
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ if (lcd == EBI2_LCD0) {
+ outpdw(MDP_BASE + 0x0060, base);/* MDP_EBI2_LCD0 */
+ outpdw(MDP_BASE + 0x0068, ystride);/* MDP_EBI2_LCD0_YSTRIDE */
+ } else {
+ outpdw(MDP_BASE + 0x0064, base);/* MDP_EBI2_LCD1 */
+ outpdw(MDP_BASE + 0x006c, ystride);/* MDP_EBI2_LCD1_YSTRIDE */
+ }
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_mddi_setup(int mddi, unsigned long id)
+{
+ ulong bits;
+
+ if (mddi == MDDI_EXTERNAL_SET)
+ bits = 0x02;
+ else if (mddi == MDDI_SECONDARY_SET)
+ bits = 0x01;
+ else
+ bits = 0; /* PRIMARY_SET */
+
+ id <<= 16;
+
+ bits |= id;
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ outpdw(MDP_BASE + 0x0090, bits); /* MDP_MDDI_PARAM_WR_SEL */
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req)
+{
+
+ /* not implemented yet */
+ return -1;
+}
+
+void mdp4_fetch_cfg(uint32 core_clk)
+{
+
+ uint32 dmap_data, vg_data;
+ char *base;
+ int i;
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ if (core_clk >= 90000000) { /* 90 Mhz */
+ dmap_data = 0x47; /* 16 bytes-burst x 8 req */
+ vg_data = 0x47; /* 16 bytes-burs x 8 req */
+ } else {
+ dmap_data = 0x27; /* 8 bytes-burst x 8 req */
+ vg_data = 0x43; /* 16 bytes-burst x 4 req */
+ }
+
+ MSM_FB_DEBUG("mdp4_fetch_cfg: dmap=%x vg=%x\n",
+ dmap_data, vg_data);
+
+ /* dma_p fetch config */
+ outpdw(MDP_BASE + 0x91004, dmap_data);
+ /* dma_e fetch config */
+ outpdw(MDP_BASE + 0xB1004, dmap_data);
+
+ /*
+ * set up two vg pipes and two rgb pipes
+ */
+ base = MDP_BASE + MDP4_VIDEO_BASE;
+ for (i = 0; i < 4; i++) {
+ outpdw(base + 0x1004, vg_data);
+ base += MDP4_VIDEO_OFF;
+ }
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_hw_init(void)
+{
+ ulong bits;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+#ifdef MDP4_ERROR
+ /*
+ * Issue software reset on DMA_P will casue DMA_P dma engine stall
+ * on LCDC mode. However DMA_P does not stall at MDDI mode.
+ * This need further investigation.
+ */
+ mdp4_sw_reset(0x17);
+#endif
+
+ mdp4_clear_lcdc();
+
+ mdp4_mixer_blend_init(0);
+ mdp4_mixer_blend_init(1);
+ mdp4_vg_qseed_init(0);
+ mdp4_vg_qseed_init(1);
+
+ /* yuv2rgb */
+ mdp4_vg_csc_mv_setup(0);
+ mdp4_vg_csc_mv_setup(1);
+ mdp4_vg_csc_pre_bv_setup(0);
+ mdp4_vg_csc_pre_bv_setup(1);
+ mdp4_vg_csc_post_bv_setup(0);
+ mdp4_vg_csc_post_bv_setup(1);
+ mdp4_vg_csc_pre_lv_setup(0);
+ mdp4_vg_csc_pre_lv_setup(1);
+ mdp4_vg_csc_post_lv_setup(0);
+ mdp4_vg_csc_post_lv_setup(1);
+
+ /* rgb2yuv */
+ mdp4_mixer1_csc_mv_setup();
+ mdp4_mixer1_csc_pre_bv_setup();
+ mdp4_mixer1_csc_post_bv_setup();
+ mdp4_mixer1_csc_pre_lv_setup();
+ mdp4_mixer1_csc_post_lv_setup();
+
+ mdp4_vg_igc_lut_setup(0);
+ mdp4_vg_igc_lut_setup(1);
+
+ mdp4_rgb_igc_lut_setup(0);
+ mdp4_rgb_igc_lut_setup(1);
+
+ outp32(MDP_EBI2_PORTMAP_MODE, 0x3);
+
+ /* system interrupts */
+
+ bits = mdp_intr_mask;
+ outpdw(MDP_BASE + 0x0050, bits);/* enable specififed interrupts */
+
+ /* histogram */
+ MDP_OUTP(MDP_BASE + 0x95010, 1); /* auto clear HIST */
+
+ /* enable histogram interrupts */
+ outpdw(MDP_BASE + 0x9501c, INTR_HIST_DONE);
+
+ /* For the max read pending cmd config below, if the MDP clock */
+ /* is less than the AXI clock, then we must use 3 pending */
+ /* pending requests. Otherwise, we should use 8 pending requests. */
+ /* In the future we should do this detection automatically. */
+
+ /* max read pending cmd config */
+ outpdw(MDP_BASE + 0x004c, 0x02222); /* 3 pending requests */
+
+#ifndef CONFIG_FB_MSM_OVERLAY
+ /* both REFRESH_MODE and DIRECT_OUT are ignored at BLT mode */
+ mdp4_overlay_cfg(MDP4_MIXER0, OVERLAY_MODE_BLT, 0, 0);
+ mdp4_overlay_cfg(MDP4_MIXER1, OVERLAY_MODE_BLT, 0, 0);
+#endif
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ /* Mark hardware as initialized. Only revisions > v2.1 have a register
+ * for tracking core reset status. */
+ if (mdp_hw_revision > MDP4_REVISION_V2_1)
+ outpdw(MDP_BASE + 0x003c, 1);
+}
+
+
+void mdp4_clear_lcdc(void)
+{
+ uint32 bits;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ bits = inpdw(MDP_BASE + 0xc0000);
+ if (bits & 0x01) { /* enabled already */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ return;
+ }
+
+ outpdw(MDP_BASE + 0xc0004, 0); /* vsync ctrl out */
+ outpdw(MDP_BASE + 0xc0008, 0); /* vsync period */
+ outpdw(MDP_BASE + 0xc000c, 0); /* vsync pusle width */
+ outpdw(MDP_BASE + 0xc0010, 0); /* lcdc display HCTL */
+ outpdw(MDP_BASE + 0xc0014, 0); /* lcdc display v start */
+ outpdw(MDP_BASE + 0xc0018, 0); /* lcdc display v end */
+ outpdw(MDP_BASE + 0xc001c, 0); /* lcdc active hctl */
+ outpdw(MDP_BASE + 0xc0020, 0); /* lcdc active v start */
+ outpdw(MDP_BASE + 0xc0024, 0); /* lcdc active v end */
+ outpdw(MDP_BASE + 0xc0028, 0); /* lcdc board color */
+ outpdw(MDP_BASE + 0xc002c, 0); /* lcdc underflow ctrl */
+ outpdw(MDP_BASE + 0xc0030, 0); /* lcdc hsync skew */
+ outpdw(MDP_BASE + 0xc0034, 0); /* lcdc test ctl */
+ outpdw(MDP_BASE + 0xc0038, 0); /* lcdc ctl polarity */
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+irqreturn_t mdp4_isr(int irq, void *ptr)
+{
+ uint32 isr, mask, panel;
+ struct mdp_dma_data *dma;
+
+ mdp_is_in_isr = TRUE;
+
+ /* complete all the reads before reading the interrupt
+ * status register - eliminate effects of speculative
+ * reads by the cpu
+ */
+ rmb();
+ isr = inpdw(MDP_INTR_STATUS);
+ if (isr == 0)
+ goto out;
+
+ mdp4_stat.intr_tot++;
+ mask = inpdw(MDP_INTR_ENABLE);
+ outpdw(MDP_INTR_CLEAR, isr);
+
+ if (isr & INTR_PRIMARY_INTF_UDERRUN) {
+ mdp4_stat.intr_underrun_p++;
+ /* When underun occurs mdp clear the histogram registers
+ that are set before in hw_init so restore them back so
+ that histogram works.*/
+ MDP_OUTP(MDP_BASE + 0x95010, 1);
+ outpdw(MDP_BASE + 0x9501c, INTR_HIST_DONE);
+ if (mdp_is_hist_start == TRUE) {
+ MDP_OUTP(MDP_BASE + 0x95004,
+ mdp_hist.frame_cnt);
+ MDP_OUTP(MDP_BASE + 0x95000, 1);
+ }
+ }
+
+ if (isr & INTR_EXTERNAL_INTF_UDERRUN)
+ mdp4_stat.intr_underrun_e++;
+
+ isr &= mask;
+
+ if (isr == 0)
+ goto out;
+
+ panel = mdp4_overlay_panel_list();
+ if (isr & INTR_PRIMARY_VSYNC) {
+ dma = &dma2_data;
+ spin_lock(&mdp_spin_lock);
+ mdp_intr_mask &= ~INTR_PRIMARY_VSYNC;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ dma->waiting = FALSE;
+ spin_unlock(&mdp_spin_lock);
+ if (panel & MDP4_PANEL_LCDC)
+ mdp4_primary_vsync_lcdc();
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+ else if (panel & MDP4_PANEL_DSI_VIDEO)
+ mdp4_primary_vsync_dsi_video();
+#endif
+ }
+#ifdef CONFIG_FB_MSM_DTV
+ if (isr & INTR_EXTERNAL_VSYNC) {
+ dma = &dma_e_data;
+ spin_lock(&mdp_spin_lock);
+ mdp_intr_mask &= ~INTR_EXTERNAL_VSYNC;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ dma->waiting = FALSE;
+ spin_unlock(&mdp_spin_lock);
+ if (panel & MDP4_PANEL_DTV)
+ mdp4_external_vsync_dtv();
+ }
+#endif
+ if (isr & INTR_DMA_P_DONE) {
+ mdp4_stat.intr_dma_p++;
+ dma = &dma2_data;
+ if (panel & MDP4_PANEL_LCDC) {
+ /* disable LCDC interrupt */
+ spin_lock(&mdp_spin_lock);
+ mdp_intr_mask &= ~INTR_DMA_P_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ dma->waiting = FALSE;
+ spin_unlock(&mdp_spin_lock);
+ } else { /* MDDI */
+#ifdef CONFIG_FB_MSM_OVERLAY
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+ mdp4_dma_p_done_dsi(dma);
+#else
+ mdp4_dma_p_done_mddi();
+ mdp_pipe_ctrl(MDP_DMA2_BLOCK,
+ MDP_BLOCK_POWER_OFF, TRUE);
+#endif
+#else
+ spin_lock(&mdp_spin_lock);
+ dma->busy = FALSE;
+ spin_unlock(&mdp_spin_lock);
+#endif
+ }
+#ifndef CONFIG_FB_MSM_MIPI_DSI
+ complete(&dma->comp);
+#endif
+ }
+ if (isr & INTR_DMA_S_DONE) {
+ mdp4_stat.intr_dma_s++;
+#if defined(CONFIG_FB_MSM_OVERLAY) && defined(CONFIG_FB_MSM_MDDI)
+ dma = &dma2_data;
+#else
+ dma = &dma_s_data;
+#endif
+
+ dma->busy = FALSE;
+ mdp_pipe_ctrl(MDP_DMA_S_BLOCK,
+ MDP_BLOCK_POWER_OFF, TRUE);
+ complete(&dma->comp);
+ }
+ if (isr & INTR_DMA_E_DONE) {
+ mdp4_stat.intr_dma_e++;
+ dma = &dma_e_data;
+ spin_lock(&mdp_spin_lock);
+ mdp_intr_mask &= ~INTR_DMA_E_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ dma->busy = FALSE;
+
+ if (dma->waiting) {
+ dma->waiting = FALSE;
+ complete(&dma->comp);
+ }
+ spin_unlock(&mdp_spin_lock);
+ }
+#ifdef CONFIG_FB_MSM_OVERLAY
+ if (isr & INTR_OVERLAY0_DONE) {
+ mdp4_stat.intr_overlay0++;
+ dma = &dma2_data;
+ if (panel & (MDP4_PANEL_LCDC | MDP4_PANEL_DSI_VIDEO)) {
+ /* disable LCDC interrupt */
+ spin_lock(&mdp_spin_lock);
+ mdp_intr_mask &= ~INTR_OVERLAY0_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ dma->waiting = FALSE;
+ spin_unlock(&mdp_spin_lock);
+ if (panel & MDP4_PANEL_LCDC)
+ mdp4_overlay0_done_lcdc();
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+ else if (panel & MDP4_PANEL_DSI_VIDEO)
+ mdp4_overlay0_done_dsi_video();
+#endif
+ } else { /* MDDI, DSI_CMD */
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+ if (panel & MDP4_PANEL_DSI_CMD)
+ mdp4_overlay0_done_dsi_cmd(dma);
+#else
+ if (panel & MDP4_PANEL_MDDI)
+ mdp4_overlay0_done_mddi(dma);
+#endif
+ }
+ mdp_hw_cursor_done();
+ }
+ if (isr & INTR_OVERLAY1_DONE) {
+ mdp4_stat.intr_overlay1++;
+ /* disable DTV interrupt */
+ dma = &dma_e_data;
+ spin_lock(&mdp_spin_lock);
+ mdp_intr_mask &= ~INTR_OVERLAY1_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ dma->waiting = FALSE;
+ spin_unlock(&mdp_spin_lock);
+#if defined(CONFIG_FB_MSM_DTV)
+ if (panel & MDP4_PANEL_DTV)
+ mdp4_overlay1_done_dtv();
+#endif
+#if defined(CONFIG_FB_MSM_TVOUT)
+ if (panel & MDP4_PANEL_ATV)
+ mdp4_overlay1_done_atv();
+#endif
+ }
+#endif /* OVERLAY */
+ if (isr & INTR_DMA_P_HISTOGRAM) {
+ isr = inpdw(MDP_DMA_P_HIST_INTR_STATUS);
+ mask = inpdw(MDP_DMA_P_HIST_INTR_ENABLE);
+ outpdw(MDP_DMA_P_HIST_INTR_CLEAR, isr);
+ isr &= mask;
+ if (isr & INTR_HIST_DONE) {
+ if (mdp_hist.r)
+ memcpy(mdp_hist.r, MDP_BASE + 0x95100,
+ mdp_hist.bin_cnt*4);
+ if (mdp_hist.g)
+ memcpy(mdp_hist.g, MDP_BASE + 0x95200,
+ mdp_hist.bin_cnt*4);
+ if (mdp_hist.b)
+ memcpy(mdp_hist.b, MDP_BASE + 0x95300,
+ mdp_hist.bin_cnt*4);
+ complete(&mdp_hist_comp);
+ if (mdp_is_hist_start == TRUE) {
+ MDP_OUTP(MDP_BASE + 0x95004,
+ mdp_hist.frame_cnt);
+ MDP_OUTP(MDP_BASE + 0x95000, 1);
+ }
+ }
+ }
+
+out:
+ mdp_is_in_isr = FALSE;
+
+ return IRQ_HANDLED;
+}
+
+
+/*
+ * QSEED tables
+ */
+
+static uint32 vg_qseed_table0[] = {
+ 0x5556aaff, 0x00000000, 0x00000000, 0x00000000
+};
+
+static uint32 vg_qseed_table1[] = {
+ 0x76543210, 0xfedcba98
+};
+
+static uint32 vg_qseed_table2[] = {
+ 0x02000000, 0x00000000, 0x01ff0ff9, 0x00000008,
+ 0x01fb0ff2, 0x00000013, 0x01f50fed, 0x0ffe0020,
+ 0x01ed0fe8, 0x0ffd002e, 0x01e30fe4, 0x0ffb003e,
+ 0x01d80fe1, 0x0ff9004e, 0x01cb0fde, 0x0ff70060,
+ 0x01bc0fdc, 0x0ff40074, 0x01ac0fdb, 0x0ff20087,
+ 0x019a0fdb, 0x0fef009c, 0x01870fdb, 0x0fed00b1,
+ 0x01740fdb, 0x0fea00c7, 0x01600fdc, 0x0fe700dd,
+ 0x014b0fdd, 0x0fe500f3, 0x01350fdf, 0x0fe30109,
+ 0x01200fe0, 0x0fe00120, 0x01090fe3, 0x0fdf0135,
+ 0x00f30fe5, 0x0fdd014b, 0x00dd0fe7, 0x0fdc0160,
+ 0x00c70fea, 0x0fdb0174, 0x00b10fed, 0x0fdb0187,
+ 0x009c0fef, 0x0fdb019a, 0x00870ff2, 0x0fdb01ac,
+ 0x00740ff4, 0x0fdc01bc, 0x00600ff7, 0x0fde01cb,
+ 0x004e0ff9, 0x0fe101d8, 0x003e0ffb, 0x0fe401e3,
+ 0x002e0ffd, 0x0fe801ed, 0x00200ffe, 0x0fed01f5,
+ 0x00130000, 0x0ff201fb, 0x00080000, 0x0ff901ff,
+
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+
+ 0x02000000, 0x00000000, 0x01fc0ff9, 0x0ffe000d,
+ 0x01f60ff3, 0x0ffb001c, 0x01ef0fed, 0x0ff9002b,
+ 0x01e60fe8, 0x0ff6003c, 0x01dc0fe4, 0x0ff3004d,
+ 0x01d00fe0, 0x0ff1005f, 0x01c30fde, 0x0fee0071,
+ 0x01b50fdb, 0x0feb0085, 0x01a70fd9, 0x0fe80098,
+ 0x01960fd8, 0x0fe600ac, 0x01850fd7, 0x0fe300c1,
+ 0x01730fd7, 0x0fe100d5, 0x01610fd7, 0x0fdf00e9,
+ 0x014e0fd8, 0x0fdd00fd, 0x013b0fd8, 0x0fdb0112,
+ 0x01250fda, 0x0fda0127, 0x01120fdb, 0x0fd8013b,
+ 0x00fd0fdd, 0x0fd8014e, 0x00e90fdf, 0x0fd70161,
+ 0x00d50fe1, 0x0fd70173, 0x00c10fe3, 0x0fd70185,
+ 0x00ac0fe6, 0x0fd80196, 0x00980fe8, 0x0fd901a7,
+ 0x00850feb, 0x0fdb01b5, 0x00710fee, 0x0fde01c3,
+ 0x005f0ff1, 0x0fe001d0, 0x004d0ff3, 0x0fe401dc,
+ 0x003c0ff6, 0x0fe801e6, 0x002b0ff9, 0x0fed01ef,
+ 0x001c0ffb, 0x0ff301f6, 0x000d0ffe, 0x0ff901fc,
+
+ 0x020f0034, 0x0f7a0043, 0x01e80023, 0x0fa8004d,
+ 0x01d30016, 0x0fbe0059, 0x01c6000a, 0x0fc90067,
+ 0x01bd0000, 0x0fce0075, 0x01b50ff7, 0x0fcf0085,
+ 0x01ae0fee, 0x0fcf0095, 0x01a70fe6, 0x0fcd00a6,
+ 0x019d0fe0, 0x0fcb00b8, 0x01940fd9, 0x0fc900ca,
+ 0x01890fd4, 0x0fc700dc, 0x017d0fcf, 0x0fc600ee,
+ 0x01700fcc, 0x0fc40100, 0x01620fc9, 0x0fc40111,
+ 0x01540fc6, 0x0fc30123, 0x01430fc5, 0x0fc40134,
+ 0x01340fc4, 0x0fc50143, 0x01230fc3, 0x0fc60154,
+ 0x01110fc4, 0x0fc90162, 0x01000fc4, 0x0fcc0170,
+ 0x00ee0fc6, 0x0fcf017d, 0x00dc0fc7, 0x0fd40189,
+ 0x00ca0fc9, 0x0fd90194, 0x00b80fcb, 0x0fe0019d,
+ 0x00a60fcd, 0x0fe601a7, 0x00950fcf, 0x0fee01ae,
+ 0x00850fcf, 0x0ff701b5, 0x00750fce, 0x000001bd,
+ 0x00670fc9, 0x000a01c6, 0x00590fbe, 0x001601d3,
+ 0x004d0fa8, 0x002301e8, 0x00430f7a, 0x0034020f,
+
+ 0x015c005e, 0x0fde0068, 0x015c0054, 0x0fdd0073,
+ 0x015b004b, 0x0fdc007e, 0x015a0042, 0x0fdb0089,
+ 0x01590039, 0x0fda0094, 0x01560030, 0x0fda00a0,
+ 0x01530028, 0x0fda00ab, 0x014f0020, 0x0fda00b7,
+ 0x014a0019, 0x0fdb00c2, 0x01450011, 0x0fdc00ce,
+ 0x013e000b, 0x0fde00d9, 0x01390004, 0x0fdf00e4,
+ 0x01310ffe, 0x0fe200ef, 0x01290ff9, 0x0fe400fa,
+ 0x01200ff4, 0x0fe80104, 0x01180fef, 0x0feb010e,
+ 0x010e0feb, 0x0fef0118, 0x01040fe8, 0x0ff40120,
+ 0x00fa0fe4, 0x0ff90129, 0x00ef0fe2, 0x0ffe0131,
+ 0x00e40fdf, 0x00040139, 0x00d90fde, 0x000b013e,
+ 0x00ce0fdc, 0x00110145, 0x00c20fdb, 0x0019014a,
+ 0x00b70fda, 0x0020014f, 0x00ab0fda, 0x00280153,
+ 0x00a00fda, 0x00300156, 0x00940fda, 0x00390159,
+ 0x00890fdb, 0x0042015a, 0x007e0fdc, 0x004b015b,
+ 0x00730fdd, 0x0054015c, 0x00680fde, 0x005e015c,
+
+ 0x01300068, 0x0ff80070, 0x01300060, 0x0ff80078,
+ 0x012f0059, 0x0ff80080, 0x012d0052, 0x0ff80089,
+ 0x012b004b, 0x0ff90091, 0x01290044, 0x0ff9009a,
+ 0x0126003d, 0x0ffa00a3, 0x01220037, 0x0ffb00ac,
+ 0x011f0031, 0x0ffc00b4, 0x011a002b, 0x0ffe00bd,
+ 0x01150026, 0x000000c5, 0x010f0021, 0x000200ce,
+ 0x010a001c, 0x000400d6, 0x01030018, 0x000600df,
+ 0x00fd0014, 0x000900e6, 0x00f60010, 0x000c00ee,
+ 0x00ee000c, 0x001000f6, 0x00e60009, 0x001400fd,
+ 0x00df0006, 0x00180103, 0x00d60004, 0x001c010a,
+ 0x00ce0002, 0x0021010f, 0x00c50000, 0x00260115,
+ 0x00bd0ffe, 0x002b011a, 0x00b40ffc, 0x0031011f,
+ 0x00ac0ffb, 0x00370122, 0x00a30ffa, 0x003d0126,
+ 0x009a0ff9, 0x00440129, 0x00910ff9, 0x004b012b,
+ 0x00890ff8, 0x0052012d, 0x00800ff8, 0x0059012f,
+ 0x00780ff8, 0x00600130, 0x00700ff8, 0x00680130,
+
+ 0x01050079, 0x0003007f, 0x01040073, 0x00030086,
+ 0x0103006d, 0x0004008c, 0x01030066, 0x00050092,
+ 0x01010060, 0x00060099, 0x0100005a, 0x0007009f,
+ 0x00fe0054, 0x000900a5, 0x00fa004f, 0x000b00ac,
+ 0x00f80049, 0x000d00b2, 0x00f50044, 0x000f00b8,
+ 0x00f2003f, 0x001200bd, 0x00ef0039, 0x001500c3,
+ 0x00ea0035, 0x001800c9, 0x00e60030, 0x001c00ce,
+ 0x00e3002b, 0x001f00d3, 0x00dd0027, 0x002300d9,
+ 0x00d90023, 0x002700dd, 0x00d3001f, 0x002b00e3,
+ 0x00ce001c, 0x003000e6, 0x00c90018, 0x003500ea,
+ 0x00c30015, 0x003900ef, 0x00bd0012, 0x003f00f2,
+ 0x00b8000f, 0x004400f5, 0x00b2000d, 0x004900f8,
+ 0x00ac000b, 0x004f00fa, 0x00a50009, 0x005400fe,
+ 0x009f0007, 0x005a0100, 0x00990006, 0x00600101,
+ 0x00920005, 0x00660103, 0x008c0004, 0x006d0103,
+ 0x00860003, 0x00730104, 0x007f0003, 0x00790105,
+
+ 0x00cf0088, 0x001d008c, 0x00ce0084, 0x0020008e,
+ 0x00cd0080, 0x00210092, 0x00cd007b, 0x00240094,
+ 0x00ca0077, 0x00270098, 0x00c90073, 0x0029009b,
+ 0x00c8006f, 0x002c009d, 0x00c6006b, 0x002f00a0,
+ 0x00c50067, 0x003200a2, 0x00c30062, 0x003600a5,
+ 0x00c0005f, 0x003900a8, 0x00c0005b, 0x003b00aa,
+ 0x00be0057, 0x003e00ad, 0x00ba0054, 0x004200b0,
+ 0x00b90050, 0x004500b2, 0x00b7004c, 0x004900b4,
+ 0x00b40049, 0x004c00b7, 0x00b20045, 0x005000b9,
+ 0x00b00042, 0x005400ba, 0x00ad003e, 0x005700be,
+ 0x00aa003b, 0x005b00c0, 0x00a80039, 0x005f00c0,
+ 0x00a50036, 0x006200c3, 0x00a20032, 0x006700c5,
+ 0x00a0002f, 0x006b00c6, 0x009d002c, 0x006f00c8,
+ 0x009b0029, 0x007300c9, 0x00980027, 0x007700ca,
+ 0x00940024, 0x007b00cd, 0x00920021, 0x008000cd,
+ 0x008e0020, 0x008400ce, 0x008c001d, 0x008800cf,
+
+ 0x008e0083, 0x006b0084, 0x008d0083, 0x006c0084,
+ 0x008d0082, 0x006d0084, 0x008d0081, 0x006d0085,
+ 0x008d0080, 0x006e0085, 0x008c007f, 0x006f0086,
+ 0x008b007f, 0x00700086, 0x008b007e, 0x00710086,
+ 0x008b007d, 0x00720086, 0x008a007d, 0x00730086,
+ 0x008a007c, 0x00730087, 0x008a007b, 0x00740087,
+ 0x0089007b, 0x00750087, 0x008a0079, 0x00750088,
+ 0x008a0078, 0x00760088, 0x008a0077, 0x00770088,
+ 0x00880077, 0x0077008a, 0x00880076, 0x0078008a,
+ 0x00880075, 0x0079008a, 0x00870075, 0x007b0089,
+ 0x00870074, 0x007b008a, 0x00870073, 0x007c008a,
+ 0x00860073, 0x007d008a, 0x00860072, 0x007d008b,
+ 0x00860071, 0x007e008b, 0x00860070, 0x007f008b,
+ 0x0086006f, 0x007f008c, 0x0085006e, 0x0080008d,
+ 0x0085006d, 0x0081008d, 0x0084006d, 0x0082008d,
+ 0x0084006c, 0x0083008d, 0x0084006b, 0x0083008e,
+
+ 0x023c0fe2, 0x00000fe2, 0x023a0fdb, 0x00000feb,
+ 0x02360fd3, 0x0fff0ff8, 0x022e0fcf, 0x0ffc0007,
+ 0x02250fca, 0x0ffa0017, 0x021a0fc6, 0x0ff70029,
+ 0x020c0fc4, 0x0ff4003c, 0x01fd0fc1, 0x0ff10051,
+ 0x01eb0fc0, 0x0fed0068, 0x01d80fc0, 0x0fe9007f,
+ 0x01c30fc1, 0x0fe50097, 0x01ac0fc2, 0x0fe200b0,
+ 0x01960fc3, 0x0fdd00ca, 0x017e0fc5, 0x0fd900e4,
+ 0x01650fc8, 0x0fd500fe, 0x014b0fcb, 0x0fd20118,
+ 0x01330fcd, 0x0fcd0133, 0x01180fd2, 0x0fcb014b,
+ 0x00fe0fd5, 0x0fc80165, 0x00e40fd9, 0x0fc5017e,
+ 0x00ca0fdd, 0x0fc30196, 0x00b00fe2, 0x0fc201ac,
+ 0x00970fe5, 0x0fc101c3, 0x007f0fe9, 0x0fc001d8,
+ 0x00680fed, 0x0fc001eb, 0x00510ff1, 0x0fc101fd,
+ 0x003c0ff4, 0x0fc4020c, 0x00290ff7, 0x0fc6021a,
+ 0x00170ffa, 0x0fca0225, 0x00070ffc, 0x0fcf022e,
+ 0x0ff80fff, 0x0fd30236, 0x0feb0000, 0x0fdb023a,
+
+ 0x02780fc4, 0x00000fc4, 0x02770fbc, 0x0fff0fce,
+ 0x02710fb5, 0x0ffe0fdc, 0x02690fb0, 0x0ffa0fed,
+ 0x025f0fab, 0x0ff70fff, 0x02500fa8, 0x0ff30015,
+ 0x02410fa6, 0x0fef002a, 0x022f0fa4, 0x0feb0042,
+ 0x021a0fa4, 0x0fe5005d, 0x02040fa5, 0x0fe10076,
+ 0x01eb0fa7, 0x0fdb0093, 0x01d20fa9, 0x0fd600af,
+ 0x01b80fab, 0x0fd000cd, 0x019d0faf, 0x0fca00ea,
+ 0x01810fb2, 0x0fc50108, 0x01620fb7, 0x0fc10126,
+ 0x01440fbb, 0x0fbb0146, 0x01260fc1, 0x0fb70162,
+ 0x01080fc5, 0x0fb20181, 0x00ea0fca, 0x0faf019d,
+ 0x00cd0fd0, 0x0fab01b8, 0x00af0fd6, 0x0fa901d2,
+ 0x00930fdb, 0x0fa701eb, 0x00760fe1, 0x0fa50204,
+ 0x005d0fe5, 0x0fa4021a, 0x00420feb, 0x0fa4022f,
+ 0x002a0fef, 0x0fa60241, 0x00150ff3, 0x0fa80250,
+ 0x0fff0ff7, 0x0fab025f, 0x0fed0ffa, 0x0fb00269,
+ 0x0fdc0ffe, 0x0fb50271, 0x0fce0fff, 0x0fbc0277,
+
+ 0x02a00fb0, 0x00000fb0, 0x029e0fa8, 0x0fff0fbb,
+ 0x02980fa1, 0x0ffd0fca, 0x028f0f9c, 0x0ff90fdc,
+ 0x02840f97, 0x0ff50ff0, 0x02740f94, 0x0ff10007,
+ 0x02640f92, 0x0fec001e, 0x02500f91, 0x0fe70038,
+ 0x023a0f91, 0x0fe00055, 0x02220f92, 0x0fdb0071,
+ 0x02080f95, 0x0fd4008f, 0x01ec0f98, 0x0fce00ae,
+ 0x01cf0f9b, 0x0fc700cf, 0x01b10f9f, 0x0fc100ef,
+ 0x01920fa4, 0x0fbb010f, 0x01710faa, 0x0fb50130,
+ 0x01520fae, 0x0fae0152, 0x01300fb5, 0x0faa0171,
+ 0x010f0fbb, 0x0fa40192, 0x00ef0fc1, 0x0f9f01b1,
+ 0x00cf0fc7, 0x0f9b01cf, 0x00ae0fce, 0x0f9801ec,
+ 0x008f0fd4, 0x0f950208, 0x00710fdb, 0x0f920222,
+ 0x00550fe0, 0x0f91023a, 0x00380fe7, 0x0f910250,
+ 0x001e0fec, 0x0f920264, 0x00070ff1, 0x0f940274,
+ 0x0ff00ff5, 0x0f970284, 0x0fdc0ff9, 0x0f9c028f,
+ 0x0fca0ffd, 0x0fa10298, 0x0fbb0fff, 0x0fa8029e,
+
+ 0x02c80f9c, 0x00000f9c, 0x02c70f94, 0x0ffe0fa7,
+ 0x02c10f8c, 0x0ffc0fb7, 0x02b70f87, 0x0ff70fcb,
+ 0x02aa0f83, 0x0ff30fe0, 0x02990f80, 0x0fee0ff9,
+ 0x02870f7f, 0x0fe80012, 0x02720f7e, 0x0fe2002e,
+ 0x025a0f7e, 0x0fdb004d, 0x02400f80, 0x0fd5006b,
+ 0x02230f84, 0x0fcd008c, 0x02050f87, 0x0fc700ad,
+ 0x01e60f8b, 0x0fbf00d0, 0x01c60f90, 0x0fb700f3,
+ 0x01a30f96, 0x0fb00117, 0x01800f9c, 0x0faa013a,
+ 0x015d0fa2, 0x0fa2015f, 0x013a0faa, 0x0f9c0180,
+ 0x01170fb0, 0x0f9601a3, 0x00f30fb7, 0x0f9001c6,
+ 0x00d00fbf, 0x0f8b01e6, 0x00ad0fc7, 0x0f870205,
+ 0x008c0fcd, 0x0f840223, 0x006b0fd5, 0x0f800240,
+ 0x004d0fdb, 0x0f7e025a, 0x002e0fe2, 0x0f7e0272,
+ 0x00120fe8, 0x0f7f0287, 0x0ff90fee, 0x0f800299,
+ 0x0fe00ff3, 0x0f8302aa, 0x0fcb0ff7, 0x0f8702b7,
+ 0x0fb70ffc, 0x0f8c02c1, 0x0fa70ffe, 0x0f9402c7,
+
+ 0x02f00f88, 0x00000f88, 0x02ee0f80, 0x0ffe0f94,
+ 0x02e70f78, 0x0ffc0fa5, 0x02dd0f73, 0x0ff60fba,
+ 0x02ce0f6f, 0x0ff20fd1, 0x02be0f6c, 0x0feb0feb,
+ 0x02aa0f6b, 0x0fe50006, 0x02940f6a, 0x0fde0024,
+ 0x02790f6c, 0x0fd60045, 0x025e0f6e, 0x0fcf0065,
+ 0x023f0f72, 0x0fc60089, 0x021d0f77, 0x0fbf00ad,
+ 0x01fd0f7b, 0x0fb600d2, 0x01da0f81, 0x0fad00f8,
+ 0x01b50f87, 0x0fa6011e, 0x018f0f8f, 0x0f9e0144,
+ 0x016b0f95, 0x0f95016b, 0x01440f9e, 0x0f8f018f,
+ 0x011e0fa6, 0x0f8701b5, 0x00f80fad, 0x0f8101da,
+ 0x00d20fb6, 0x0f7b01fd, 0x00ad0fbf, 0x0f77021d,
+ 0x00890fc6, 0x0f72023f, 0x00650fcf, 0x0f6e025e,
+ 0x00450fd6, 0x0f6c0279, 0x00240fde, 0x0f6a0294,
+ 0x00060fe5, 0x0f6b02aa, 0x0feb0feb, 0x0f6c02be,
+ 0x0fd10ff2, 0x0f6f02ce, 0x0fba0ff6, 0x0f7302dd,
+ 0x0fa50ffc, 0x0f7802e7, 0x0f940ffe, 0x0f8002ee,
+
+ 0x03180f74, 0x00000f74, 0x03160f6b, 0x0ffe0f81,
+ 0x030e0f64, 0x0ffb0f93, 0x03030f5f, 0x0ff50fa9,
+ 0x02f40f5b, 0x0ff00fc1, 0x02e20f58, 0x0fe90fdd,
+ 0x02cd0f57, 0x0fe20ffa, 0x02b60f57, 0x0fda0019,
+ 0x02990f59, 0x0fd1003d, 0x027b0f5c, 0x0fc90060,
+ 0x02590f61, 0x0fc00086, 0x02370f66, 0x0fb700ac,
+ 0x02130f6b, 0x0fae00d4, 0x01ee0f72, 0x0fa400fc,
+ 0x01c70f79, 0x0f9b0125, 0x019f0f81, 0x0f93014d,
+ 0x01760f89, 0x0f890178, 0x014d0f93, 0x0f81019f,
+ 0x01250f9b, 0x0f7901c7, 0x00fc0fa4, 0x0f7201ee,
+ 0x00d40fae, 0x0f6b0213, 0x00ac0fb7, 0x0f660237,
+ 0x00860fc0, 0x0f610259, 0x00600fc9, 0x0f5c027b,
+ 0x003d0fd1, 0x0f590299, 0x00190fda, 0x0f5702b6,
+ 0x0ffa0fe2, 0x0f5702cd, 0x0fdd0fe9, 0x0f5802e2,
+ 0x0fc10ff0, 0x0f5b02f4, 0x0fa90ff5, 0x0f5f0303,
+ 0x0f930ffb, 0x0f64030e, 0x0f810ffe, 0x0f6b0316,
+
+ 0x03400f60, 0x00000f60, 0x033e0f57, 0x0ffe0f6d,
+ 0x03370f4f, 0x0ffa0f80, 0x032a0f4b, 0x0ff30f98,
+ 0x031a0f46, 0x0fee0fb2, 0x03070f44, 0x0fe60fcf,
+ 0x02f10f44, 0x0fde0fed, 0x02d70f44, 0x0fd6000f,
+ 0x02b80f46, 0x0fcc0036, 0x02990f4a, 0x0fc3005a,
+ 0x02750f4f, 0x0fb90083, 0x02500f55, 0x0fb000ab,
+ 0x022a0f5b, 0x0fa500d6, 0x02020f63, 0x0f9a0101,
+ 0x01d80f6b, 0x0f91012c, 0x01ae0f74, 0x0f870157,
+ 0x01840f7c, 0x0f7c0184, 0x01570f87, 0x0f7401ae,
+ 0x012c0f91, 0x0f6b01d8, 0x01010f9a, 0x0f630202,
+ 0x00d60fa5, 0x0f5b022a, 0x00ab0fb0, 0x0f550250,
+ 0x00830fb9, 0x0f4f0275, 0x005a0fc3, 0x0f4a0299,
+ 0x00360fcc, 0x0f4602b8, 0x000f0fd6, 0x0f4402d7,
+ 0x0fed0fde, 0x0f4402f1, 0x0fcf0fe6, 0x0f440307,
+ 0x0fb20fee, 0x0f46031a, 0x0f980ff3, 0x0f4b032a,
+ 0x0f800ffa, 0x0f4f0337, 0x0f6d0ffe, 0x0f57033e,
+
+ 0x02000000, 0x00000000, 0x01ff0ff9, 0x00000008,
+ 0x01fb0ff2, 0x00000013, 0x01f50fed, 0x0ffe0020,
+ 0x01ed0fe8, 0x0ffd002e, 0x01e30fe4, 0x0ffb003e,
+ 0x01d80fe1, 0x0ff9004e, 0x01cb0fde, 0x0ff70060,
+ 0x01bc0fdc, 0x0ff40074, 0x01ac0fdb, 0x0ff20087,
+ 0x019a0fdb, 0x0fef009c, 0x01870fdb, 0x0fed00b1,
+ 0x01740fdb, 0x0fea00c7, 0x01600fdc, 0x0fe700dd,
+ 0x014b0fdd, 0x0fe500f3, 0x01350fdf, 0x0fe30109,
+ 0x01200fe0, 0x0fe00120, 0x01090fe3, 0x0fdf0135,
+ 0x00f30fe5, 0x0fdd014b, 0x00dd0fe7, 0x0fdc0160,
+ 0x00c70fea, 0x0fdb0174, 0x00b10fed, 0x0fdb0187,
+ 0x009c0fef, 0x0fdb019a, 0x00870ff2, 0x0fdb01ac,
+ 0x00740ff4, 0x0fdc01bc, 0x00600ff7, 0x0fde01cb,
+ 0x004e0ff9, 0x0fe101d8, 0x003e0ffb, 0x0fe401e3,
+ 0x002e0ffd, 0x0fe801ed, 0x00200ffe, 0x0fed01f5,
+ 0x00130000, 0x0ff201fb, 0x00080000, 0x0ff901ff,
+
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+ 0x02000000, 0x00000000, 0x02000000, 0x00000000,
+
+ 0x02000000, 0x00000000, 0x01fc0ff9, 0x0ffe000d,
+ 0x01f60ff3, 0x0ffb001c, 0x01ef0fed, 0x0ff9002b,
+ 0x01e60fe8, 0x0ff6003c, 0x01dc0fe4, 0x0ff3004d,
+ 0x01d00fe0, 0x0ff1005f, 0x01c30fde, 0x0fee0071,
+ 0x01b50fdb, 0x0feb0085, 0x01a70fd9, 0x0fe80098,
+ 0x01960fd8, 0x0fe600ac, 0x01850fd7, 0x0fe300c1,
+ 0x01730fd7, 0x0fe100d5, 0x01610fd7, 0x0fdf00e9,
+ 0x014e0fd8, 0x0fdd00fd, 0x013b0fd8, 0x0fdb0112,
+ 0x01250fda, 0x0fda0127, 0x01120fdb, 0x0fd8013b,
+ 0x00fd0fdd, 0x0fd8014e, 0x00e90fdf, 0x0fd70161,
+ 0x00d50fe1, 0x0fd70173, 0x00c10fe3, 0x0fd70185,
+ 0x00ac0fe6, 0x0fd80196, 0x00980fe8, 0x0fd901a7,
+ 0x00850feb, 0x0fdb01b5, 0x00710fee, 0x0fde01c3,
+ 0x005f0ff1, 0x0fe001d0, 0x004d0ff3, 0x0fe401dc,
+ 0x003c0ff6, 0x0fe801e6, 0x002b0ff9, 0x0fed01ef,
+ 0x001c0ffb, 0x0ff301f6, 0x000d0ffe, 0x0ff901fc,
+
+ 0x020f0034, 0x0f7a0043, 0x01e80023, 0x0fa8004d,
+ 0x01d30016, 0x0fbe0059, 0x01c6000a, 0x0fc90067,
+ 0x01bd0000, 0x0fce0075, 0x01b50ff7, 0x0fcf0085,
+ 0x01ae0fee, 0x0fcf0095, 0x01a70fe6, 0x0fcd00a6,
+ 0x019d0fe0, 0x0fcb00b8, 0x01940fd9, 0x0fc900ca,
+ 0x01890fd4, 0x0fc700dc, 0x017d0fcf, 0x0fc600ee,
+ 0x01700fcc, 0x0fc40100, 0x01620fc9, 0x0fc40111,
+ 0x01540fc6, 0x0fc30123, 0x01430fc5, 0x0fc40134,
+ 0x01340fc4, 0x0fc50143, 0x01230fc3, 0x0fc60154,
+ 0x01110fc4, 0x0fc90162, 0x01000fc4, 0x0fcc0170,
+ 0x00ee0fc6, 0x0fcf017d, 0x00dc0fc7, 0x0fd40189,
+ 0x00ca0fc9, 0x0fd90194, 0x00b80fcb, 0x0fe0019d,
+ 0x00a60fcd, 0x0fe601a7, 0x00950fcf, 0x0fee01ae,
+ 0x00850fcf, 0x0ff701b5, 0x00750fce, 0x000001bd,
+ 0x00670fc9, 0x000a01c6, 0x00590fbe, 0x001601d3,
+ 0x004d0fa8, 0x002301e8, 0x00430f7a, 0x0034020f,
+
+ 0x015c005e, 0x0fde0068, 0x015c0054, 0x0fdd0073,
+ 0x015b004b, 0x0fdc007e, 0x015a0042, 0x0fdb0089,
+ 0x01590039, 0x0fda0094, 0x01560030, 0x0fda00a0,
+ 0x01530028, 0x0fda00ab, 0x014f0020, 0x0fda00b7,
+ 0x014a0019, 0x0fdb00c2, 0x01450011, 0x0fdc00ce,
+ 0x013e000b, 0x0fde00d9, 0x01390004, 0x0fdf00e4,
+ 0x01310ffe, 0x0fe200ef, 0x01290ff9, 0x0fe400fa,
+ 0x01200ff4, 0x0fe80104, 0x01180fef, 0x0feb010e,
+ 0x010e0feb, 0x0fef0118, 0x01040fe8, 0x0ff40120,
+ 0x00fa0fe4, 0x0ff90129, 0x00ef0fe2, 0x0ffe0131,
+ 0x00e40fdf, 0x00040139, 0x00d90fde, 0x000b013e,
+ 0x00ce0fdc, 0x00110145, 0x00c20fdb, 0x0019014a,
+ 0x00b70fda, 0x0020014f, 0x00ab0fda, 0x00280153,
+ 0x00a00fda, 0x00300156, 0x00940fda, 0x00390159,
+ 0x00890fdb, 0x0042015a, 0x007e0fdc, 0x004b015b,
+ 0x00730fdd, 0x0054015c, 0x00680fde, 0x005e015c,
+
+ 0x01300068, 0x0ff80070, 0x01300060, 0x0ff80078,
+ 0x012f0059, 0x0ff80080, 0x012d0052, 0x0ff80089,
+ 0x012b004b, 0x0ff90091, 0x01290044, 0x0ff9009a,
+ 0x0126003d, 0x0ffa00a3, 0x01220037, 0x0ffb00ac,
+ 0x011f0031, 0x0ffc00b4, 0x011a002b, 0x0ffe00bd,
+ 0x01150026, 0x000000c5, 0x010f0021, 0x000200ce,
+ 0x010a001c, 0x000400d6, 0x01030018, 0x000600df,
+ 0x00fd0014, 0x000900e6, 0x00f60010, 0x000c00ee,
+ 0x00ee000c, 0x001000f6, 0x00e60009, 0x001400fd,
+ 0x00df0006, 0x00180103, 0x00d60004, 0x001c010a,
+ 0x00ce0002, 0x0021010f, 0x00c50000, 0x00260115,
+ 0x00bd0ffe, 0x002b011a, 0x00b40ffc, 0x0031011f,
+ 0x00ac0ffb, 0x00370122, 0x00a30ffa, 0x003d0126,
+ 0x009a0ff9, 0x00440129, 0x00910ff9, 0x004b012b,
+ 0x00890ff8, 0x0052012d, 0x00800ff8, 0x0059012f,
+ 0x00780ff8, 0x00600130, 0x00700ff8, 0x00680130,
+
+ 0x01050079, 0x0003007f, 0x01040073, 0x00030086,
+ 0x0103006d, 0x0004008c, 0x01030066, 0x00050092,
+ 0x01010060, 0x00060099, 0x0100005a, 0x0007009f,
+ 0x00fe0054, 0x000900a5, 0x00fa004f, 0x000b00ac,
+ 0x00f80049, 0x000d00b2, 0x00f50044, 0x000f00b8,
+ 0x00f2003f, 0x001200bd, 0x00ef0039, 0x001500c3,
+ 0x00ea0035, 0x001800c9, 0x00e60030, 0x001c00ce,
+ 0x00e3002b, 0x001f00d3, 0x00dd0027, 0x002300d9,
+ 0x00d90023, 0x002700dd, 0x00d3001f, 0x002b00e3,
+ 0x00ce001c, 0x003000e6, 0x00c90018, 0x003500ea,
+ 0x00c30015, 0x003900ef, 0x00bd0012, 0x003f00f2,
+ 0x00b8000f, 0x004400f5, 0x00b2000d, 0x004900f8,
+ 0x00ac000b, 0x004f00fa, 0x00a50009, 0x005400fe,
+ 0x009f0007, 0x005a0100, 0x00990006, 0x00600101,
+ 0x00920005, 0x00660103, 0x008c0004, 0x006d0103,
+ 0x00860003, 0x00730104, 0x007f0003, 0x00790105,
+
+ 0x00cf0088, 0x001d008c, 0x00ce0084, 0x0020008e,
+ 0x00cd0080, 0x00210092, 0x00cd007b, 0x00240094,
+ 0x00ca0077, 0x00270098, 0x00c90073, 0x0029009b,
+ 0x00c8006f, 0x002c009d, 0x00c6006b, 0x002f00a0,
+ 0x00c50067, 0x003200a2, 0x00c30062, 0x003600a5,
+ 0x00c0005f, 0x003900a8, 0x00c0005b, 0x003b00aa,
+ 0x00be0057, 0x003e00ad, 0x00ba0054, 0x004200b0,
+ 0x00b90050, 0x004500b2, 0x00b7004c, 0x004900b4,
+ 0x00b40049, 0x004c00b7, 0x00b20045, 0x005000b9,
+ 0x00b00042, 0x005400ba, 0x00ad003e, 0x005700be,
+ 0x00aa003b, 0x005b00c0, 0x00a80039, 0x005f00c0,
+ 0x00a50036, 0x006200c3, 0x00a20032, 0x006700c5,
+ 0x00a0002f, 0x006b00c6, 0x009d002c, 0x006f00c8,
+ 0x009b0029, 0x007300c9, 0x00980027, 0x007700ca,
+ 0x00940024, 0x007b00cd, 0x00920021, 0x008000cd,
+ 0x008e0020, 0x008400ce, 0x008c001d, 0x008800cf,
+
+ 0x008e0083, 0x006b0084, 0x008d0083, 0x006c0084,
+ 0x008d0082, 0x006d0084, 0x008d0081, 0x006d0085,
+ 0x008d0080, 0x006e0085, 0x008c007f, 0x006f0086,
+ 0x008b007f, 0x00700086, 0x008b007e, 0x00710086,
+ 0x008b007d, 0x00720086, 0x008a007d, 0x00730086,
+ 0x008a007c, 0x00730087, 0x008a007b, 0x00740087,
+ 0x0089007b, 0x00750087, 0x008a0079, 0x00750088,
+ 0x008a0078, 0x00760088, 0x008a0077, 0x00770088,
+ 0x00880077, 0x0077008a, 0x00880076, 0x0078008a,
+ 0x00880075, 0x0079008a, 0x00870075, 0x007b0089,
+ 0x00870074, 0x007b008a, 0x00870073, 0x007c008a,
+ 0x00860073, 0x007d008a, 0x00860072, 0x007d008b,
+ 0x00860071, 0x007e008b, 0x00860070, 0x007f008b,
+ 0x0086006f, 0x007f008c, 0x0085006e, 0x0080008d,
+ 0x0085006d, 0x0081008d, 0x0084006d, 0x0082008d,
+ 0x0084006c, 0x0083008d, 0x0084006b, 0x0083008e,
+
+ 0x023c0fe2, 0x00000fe2, 0x023a0fdb, 0x00000feb,
+ 0x02360fd3, 0x0fff0ff8, 0x022e0fcf, 0x0ffc0007,
+ 0x02250fca, 0x0ffa0017, 0x021a0fc6, 0x0ff70029,
+ 0x020c0fc4, 0x0ff4003c, 0x01fd0fc1, 0x0ff10051,
+ 0x01eb0fc0, 0x0fed0068, 0x01d80fc0, 0x0fe9007f,
+ 0x01c30fc1, 0x0fe50097, 0x01ac0fc2, 0x0fe200b0,
+ 0x01960fc3, 0x0fdd00ca, 0x017e0fc5, 0x0fd900e4,
+ 0x01650fc8, 0x0fd500fe, 0x014b0fcb, 0x0fd20118,
+ 0x01330fcd, 0x0fcd0133, 0x01180fd2, 0x0fcb014b,
+ 0x00fe0fd5, 0x0fc80165, 0x00e40fd9, 0x0fc5017e,
+ 0x00ca0fdd, 0x0fc30196, 0x00b00fe2, 0x0fc201ac,
+ 0x00970fe5, 0x0fc101c3, 0x007f0fe9, 0x0fc001d8,
+ 0x00680fed, 0x0fc001eb, 0x00510ff1, 0x0fc101fd,
+ 0x003c0ff4, 0x0fc4020c, 0x00290ff7, 0x0fc6021a,
+ 0x00170ffa, 0x0fca0225, 0x00070ffc, 0x0fcf022e,
+ 0x0ff80fff, 0x0fd30236, 0x0feb0000, 0x0fdb023a,
+
+ 0x02780fc4, 0x00000fc4, 0x02770fbc, 0x0fff0fce,
+ 0x02710fb5, 0x0ffe0fdc, 0x02690fb0, 0x0ffa0fed,
+ 0x025f0fab, 0x0ff70fff, 0x02500fa8, 0x0ff30015,
+ 0x02410fa6, 0x0fef002a, 0x022f0fa4, 0x0feb0042,
+ 0x021a0fa4, 0x0fe5005d, 0x02040fa5, 0x0fe10076,
+ 0x01eb0fa7, 0x0fdb0093, 0x01d20fa9, 0x0fd600af,
+ 0x01b80fab, 0x0fd000cd, 0x019d0faf, 0x0fca00ea,
+ 0x01810fb2, 0x0fc50108, 0x01620fb7, 0x0fc10126,
+ 0x01440fbb, 0x0fbb0146, 0x01260fc1, 0x0fb70162,
+ 0x01080fc5, 0x0fb20181, 0x00ea0fca, 0x0faf019d,
+ 0x00cd0fd0, 0x0fab01b8, 0x00af0fd6, 0x0fa901d2,
+ 0x00930fdb, 0x0fa701eb, 0x00760fe1, 0x0fa50204,
+ 0x005d0fe5, 0x0fa4021a, 0x00420feb, 0x0fa4022f,
+ 0x002a0fef, 0x0fa60241, 0x00150ff3, 0x0fa80250,
+ 0x0fff0ff7, 0x0fab025f, 0x0fed0ffa, 0x0fb00269,
+ 0x0fdc0ffe, 0x0fb50271, 0x0fce0fff, 0x0fbc0277,
+
+ 0x02a00fb0, 0x00000fb0, 0x029e0fa8, 0x0fff0fbb,
+ 0x02980fa1, 0x0ffd0fca, 0x028f0f9c, 0x0ff90fdc,
+ 0x02840f97, 0x0ff50ff0, 0x02740f94, 0x0ff10007,
+ 0x02640f92, 0x0fec001e, 0x02500f91, 0x0fe70038,
+ 0x023a0f91, 0x0fe00055, 0x02220f92, 0x0fdb0071,
+ 0x02080f95, 0x0fd4008f, 0x01ec0f98, 0x0fce00ae,
+ 0x01cf0f9b, 0x0fc700cf, 0x01b10f9f, 0x0fc100ef,
+ 0x01920fa4, 0x0fbb010f, 0x01710faa, 0x0fb50130,
+ 0x01520fae, 0x0fae0152, 0x01300fb5, 0x0faa0171,
+ 0x010f0fbb, 0x0fa40192, 0x00ef0fc1, 0x0f9f01b1,
+ 0x00cf0fc7, 0x0f9b01cf, 0x00ae0fce, 0x0f9801ec,
+ 0x008f0fd4, 0x0f950208, 0x00710fdb, 0x0f920222,
+ 0x00550fe0, 0x0f91023a, 0x00380fe7, 0x0f910250,
+ 0x001e0fec, 0x0f920264, 0x00070ff1, 0x0f940274,
+ 0x0ff00ff5, 0x0f970284, 0x0fdc0ff9, 0x0f9c028f,
+ 0x0fca0ffd, 0x0fa10298, 0x0fbb0fff, 0x0fa8029e,
+
+ 0x02c80f9c, 0x00000f9c, 0x02c70f94, 0x0ffe0fa7,
+ 0x02c10f8c, 0x0ffc0fb7, 0x02b70f87, 0x0ff70fcb,
+ 0x02aa0f83, 0x0ff30fe0, 0x02990f80, 0x0fee0ff9,
+ 0x02870f7f, 0x0fe80012, 0x02720f7e, 0x0fe2002e,
+ 0x025a0f7e, 0x0fdb004d, 0x02400f80, 0x0fd5006b,
+ 0x02230f84, 0x0fcd008c, 0x02050f87, 0x0fc700ad,
+ 0x01e60f8b, 0x0fbf00d0, 0x01c60f90, 0x0fb700f3,
+ 0x01a30f96, 0x0fb00117, 0x01800f9c, 0x0faa013a,
+ 0x015d0fa2, 0x0fa2015f, 0x013a0faa, 0x0f9c0180,
+ 0x01170fb0, 0x0f9601a3, 0x00f30fb7, 0x0f9001c6,
+ 0x00d00fbf, 0x0f8b01e6, 0x00ad0fc7, 0x0f870205,
+ 0x008c0fcd, 0x0f840223, 0x006b0fd5, 0x0f800240,
+ 0x004d0fdb, 0x0f7e025a, 0x002e0fe2, 0x0f7e0272,
+ 0x00120fe8, 0x0f7f0287, 0x0ff90fee, 0x0f800299,
+ 0x0fe00ff3, 0x0f8302aa, 0x0fcb0ff7, 0x0f8702b7,
+ 0x0fb70ffc, 0x0f8c02c1, 0x0fa70ffe, 0x0f9402c7,
+
+ 0x02f00f88, 0x00000f88, 0x02ee0f80, 0x0ffe0f94,
+ 0x02e70f78, 0x0ffc0fa5, 0x02dd0f73, 0x0ff60fba,
+ 0x02ce0f6f, 0x0ff20fd1, 0x02be0f6c, 0x0feb0feb,
+ 0x02aa0f6b, 0x0fe50006, 0x02940f6a, 0x0fde0024,
+ 0x02790f6c, 0x0fd60045, 0x025e0f6e, 0x0fcf0065,
+ 0x023f0f72, 0x0fc60089, 0x021d0f77, 0x0fbf00ad,
+ 0x01fd0f7b, 0x0fb600d2, 0x01da0f81, 0x0fad00f8,
+ 0x01b50f87, 0x0fa6011e, 0x018f0f8f, 0x0f9e0144,
+ 0x016b0f95, 0x0f95016b, 0x01440f9e, 0x0f8f018f,
+ 0x011e0fa6, 0x0f8701b5, 0x00f80fad, 0x0f8101da,
+ 0x00d20fb6, 0x0f7b01fd, 0x00ad0fbf, 0x0f77021d,
+ 0x00890fc6, 0x0f72023f, 0x00650fcf, 0x0f6e025e,
+ 0x00450fd6, 0x0f6c0279, 0x00240fde, 0x0f6a0294,
+ 0x00060fe5, 0x0f6b02aa, 0x0feb0feb, 0x0f6c02be,
+ 0x0fd10ff2, 0x0f6f02ce, 0x0fba0ff6, 0x0f7302dd,
+ 0x0fa50ffc, 0x0f7802e7, 0x0f940ffe, 0x0f8002ee,
+
+ 0x03180f74, 0x00000f74, 0x03160f6b, 0x0ffe0f81,
+ 0x030e0f64, 0x0ffb0f93, 0x03030f5f, 0x0ff50fa9,
+ 0x02f40f5b, 0x0ff00fc1, 0x02e20f58, 0x0fe90fdd,
+ 0x02cd0f57, 0x0fe20ffa, 0x02b60f57, 0x0fda0019,
+ 0x02990f59, 0x0fd1003d, 0x027b0f5c, 0x0fc90060,
+ 0x02590f61, 0x0fc00086, 0x02370f66, 0x0fb700ac,
+ 0x02130f6b, 0x0fae00d4, 0x01ee0f72, 0x0fa400fc,
+ 0x01c70f79, 0x0f9b0125, 0x019f0f81, 0x0f93014d,
+ 0x01760f89, 0x0f890178, 0x014d0f93, 0x0f81019f,
+ 0x01250f9b, 0x0f7901c7, 0x00fc0fa4, 0x0f7201ee,
+ 0x00d40fae, 0x0f6b0213, 0x00ac0fb7, 0x0f660237,
+ 0x00860fc0, 0x0f610259, 0x00600fc9, 0x0f5c027b,
+ 0x003d0fd1, 0x0f590299, 0x00190fda, 0x0f5702b6,
+ 0x0ffa0fe2, 0x0f5702cd, 0x0fdd0fe9, 0x0f5802e2,
+ 0x0fc10ff0, 0x0f5b02f4, 0x0fa90ff5, 0x0f5f0303,
+ 0x0f930ffb, 0x0f64030e, 0x0f810ffe, 0x0f6b0316,
+
+ 0x03400f60, 0x00000f60, 0x033e0f57, 0x0ffe0f6d,
+ 0x03370f4f, 0x0ffa0f80, 0x032a0f4b, 0x0ff30f98,
+ 0x031a0f46, 0x0fee0fb2, 0x03070f44, 0x0fe60fcf,
+ 0x02f10f44, 0x0fde0fed, 0x02d70f44, 0x0fd6000f,
+ 0x02b80f46, 0x0fcc0036, 0x02990f4a, 0x0fc3005a,
+ 0x02750f4f, 0x0fb90083, 0x02500f55, 0x0fb000ab,
+ 0x022a0f5b, 0x0fa500d6, 0x02020f63, 0x0f9a0101,
+ 0x01d80f6b, 0x0f91012c, 0x01ae0f74, 0x0f870157,
+ 0x01840f7c, 0x0f7c0184, 0x01570f87, 0x0f7401ae,
+ 0x012c0f91, 0x0f6b01d8, 0x01010f9a, 0x0f630202,
+ 0x00d60fa5, 0x0f5b022a, 0x00ab0fb0, 0x0f550250,
+ 0x00830fb9, 0x0f4f0275, 0x005a0fc3, 0x0f4a0299,
+ 0x00360fcc, 0x0f4602b8, 0x000f0fd6, 0x0f4402d7,
+ 0x0fed0fde, 0x0f4402f1, 0x0fcf0fe6, 0x0f440307,
+ 0x0fb20fee, 0x0f46031a, 0x0f980ff3, 0x0f4b032a,
+ 0x0f800ffa, 0x0f4f0337, 0x0f6d0ffe, 0x0f57033e
+};
+
+
+#define MDP4_QSEED_TABLE0_OFF 0x8100
+#define MDP4_QSEED_TABLE1_OFF 0x8200
+#define MDP4_QSEED_TABLE2_OFF 0x9000
+
+void mdp4_vg_qseed_init(int vp_num)
+{
+ uint32 *off;
+ int i, voff;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ voff = MDP4_VIDEO_OFF * vp_num;
+ off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+ MDP4_QSEED_TABLE0_OFF);
+ for (i = 0; i < (sizeof(vg_qseed_table0) / sizeof(uint32)); i++) {
+ outpdw(off, vg_qseed_table0[i]);
+ off++;
+ /* This code is added to workaround the 1K Boundary AXI
+ Interleave operations from Scorpion that can potentially
+ corrupt the QSEED table. The idea is to complete the prevous
+ to the buffer before making the next write when address is
+ 1KB aligned to ensure the write has been committed prior to
+ next instruction write that can go out from the secondary AXI
+ port.This happens also because of the expected write sequence
+ from QSEED table, where LSP has to be written first then the
+ MSP to trigger both to write out to SRAM, if this has not been
+ the expectation, then corruption wouldn't have happened.*/
+
+ if (!((uint32)off & 0x3FF))
+ wmb();
+ }
+
+ off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+ MDP4_QSEED_TABLE1_OFF);
+ for (i = 0; i < (sizeof(vg_qseed_table1) / sizeof(uint32)); i++) {
+ outpdw(off, vg_qseed_table1[i]);
+ off++;
+ if (!((uint32)off & 0x3FF))
+ wmb();
+ }
+
+ off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+ MDP4_QSEED_TABLE2_OFF);
+ for (i = 0; i < (sizeof(vg_qseed_table2) / sizeof(uint32)); i++) {
+ outpdw(off, vg_qseed_table2[i]);
+ off++;
+ if (!((uint32)off & 0x3FF))
+ wmb();
+ }
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+}
+
+void mdp4_mixer_blend_init(mixer_num)
+{
+ unsigned char *overlay_base;
+ int off;
+
+ if (mixer_num) /* mixer number, /dev/fb0, /dev/fb1 */
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
+ else
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ /* stage 0 to stage 2 */
+ off = 0;
+ outpdw(overlay_base + off + 0x104, 0x010);
+ outpdw(overlay_base + off + 0x108, 0xff);/* FG */
+ outpdw(overlay_base + off + 0x10c, 0x00);/* BG */
+
+ off += 0x20;
+ outpdw(overlay_base + off + 0x104, 0x010);
+ outpdw(overlay_base + off + 0x108, 0xff);/* FG */
+ outpdw(overlay_base + off + 0x10c, 0x00);/* BG */
+
+ off += 0x20;
+ outpdw(overlay_base + off + 0x104, 0x010);
+ outpdw(overlay_base + off + 0x108, 0xff);/* FG */
+ outpdw(overlay_base + off + 0x10c, 0x00);/* BG */
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+
+static uint32 csc_matrix_tab[9] = {
+ 0x0254, 0x0000, 0x0331,
+ 0x0254, 0xff37, 0xfe60,
+ 0x0254, 0x0409, 0x0000
+};
+
+static uint32 csc_pre_bv_tab[3] = {0xfff0, 0xff80, 0xff80 };
+static uint32 csc_post_bv_tab[3] = {0, 0, 0 };
+
+static uint32 csc_pre_lv_tab[6] = {0, 0xff, 0, 0xff, 0, 0xff };
+static uint32 csc_post_lv_tab[6] = {0, 0xff, 0, 0xff, 0, 0xff };
+
+#define MDP4_CSC_MV_OFF 0x4400
+#define MDP4_CSC_PRE_BV_OFF 0x4500
+#define MDP4_CSC_POST_BV_OFF 0x4580
+#define MDP4_CSC_PRE_LV_OFF 0x4600
+#define MDP4_CSC_POST_LV_OFF 0x4680
+
+void mdp4_vg_csc_mv_setup(int vp_num)
+{
+ uint32 *off;
+ int i, voff;
+
+ voff = MDP4_VIDEO_OFF * vp_num;
+ off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+ MDP4_CSC_MV_OFF);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ for (i = 0; i < 9; i++) {
+ outpdw(off, csc_matrix_tab[i]);
+ off++;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_vg_csc_pre_bv_setup(int vp_num)
+{
+ uint32 *off;
+ int i, voff;
+
+ voff = MDP4_VIDEO_OFF * vp_num;
+ off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+ MDP4_CSC_PRE_BV_OFF);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ for (i = 0; i < 3; i++) {
+ outpdw(off, csc_pre_bv_tab[i]);
+ off++;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_vg_csc_post_bv_setup(int vp_num)
+{
+ uint32 *off;
+ int i, voff;
+
+ voff = MDP4_VIDEO_OFF * vp_num;
+ off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+ MDP4_CSC_POST_BV_OFF);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ for (i = 0; i < 3; i++) {
+ outpdw(off, csc_post_bv_tab[i]);
+ off++;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_vg_csc_pre_lv_setup(int vp_num)
+{
+ uint32 *off;
+ int i, voff;
+
+ voff = MDP4_VIDEO_OFF * vp_num;
+ off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+ MDP4_CSC_PRE_LV_OFF);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ for (i = 0; i < 6; i++) {
+ outpdw(off, csc_pre_lv_tab[i]);
+ off++;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_vg_csc_post_lv_setup(int vp_num)
+{
+ uint32 *off;
+ int i, voff;
+
+ voff = MDP4_VIDEO_OFF * vp_num;
+ off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+ MDP4_CSC_POST_LV_OFF);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ for (i = 0; i < 6; i++) {
+ outpdw(off, csc_post_lv_tab[i]);
+ off++;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+static uint32 csc_rgb2yuv_matrix_tab[9] = {
+ 0x0083, 0x0102, 0x0032,
+ 0x1fb5, 0x1f6c, 0x00e1,
+ 0x00e1, 0x1f45, 0x1fdc
+};
+
+static uint32 csc_rgb2yuv_pre_bv_tab[3] = {0, 0, 0};
+
+static uint32 csc_rgb2yuv_post_bv_tab[3] = {0x0010, 0x0080, 0x0080};
+
+static uint32 csc_rgb2yuv_pre_lv_tab[6] = {
+ 0x00, 0xff, 0x00,
+ 0xff, 0x00, 0xff
+};
+
+static uint32 csc_rgb2yuv_post_lv_tab[6] = {
+ 0x0010, 0x00eb, 0x0010,
+ 0x00f0, 0x0010, 0x00f0
+};
+
+void mdp4_mixer1_csc_mv_setup(void)
+{
+ uint32 *off;
+ int i;
+
+ off = (uint32 *)(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x2400);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ for (i = 0; i < 9; i++) {
+ outpdw(off, csc_rgb2yuv_matrix_tab[i]);
+ off++;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_mixer1_csc_pre_bv_setup(void)
+{
+ uint32 *off;
+ int i;
+
+ off = (uint32 *)(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x2500);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ for (i = 0; i < 3; i++) {
+ outpdw(off, csc_rgb2yuv_pre_bv_tab[i]);
+ off++;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_mixer1_csc_post_bv_setup(void)
+{
+ uint32 *off;
+ int i;
+
+ off = (uint32 *)(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x2580);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ for (i = 0; i < 3; i++) {
+ outpdw(off, csc_rgb2yuv_post_bv_tab[i]);
+ off++;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_mixer1_csc_pre_lv_setup(void)
+{
+ uint32 *off;
+ int i;
+
+ off = (uint32 *)(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x2600);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ for (i = 0; i < 6; i++) {
+ outpdw(off, csc_rgb2yuv_pre_lv_tab[i]);
+ off++;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_mixer1_csc_post_lv_setup(void)
+{
+ uint32 *off;
+ int i;
+
+ off = (uint32 *)(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x2680);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ for (i = 0; i < 6; i++) {
+ outpdw(off, csc_rgb2yuv_post_lv_tab[i]);
+ off++;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+
+char gc_lut[] = {
+ 0x0, 0x1, 0x2, 0x2, 0x3, 0x4, 0x5, 0x6,
+ 0x6, 0x7, 0x8, 0x9, 0xA, 0xA, 0xB, 0xC,
+ 0xD, 0xD, 0xE, 0xF, 0xF, 0x10, 0x10, 0x11,
+ 0x12, 0x12, 0x13, 0x13, 0x14, 0x14, 0x15, 0x15,
+ 0x16, 0x16, 0x17, 0x17, 0x17, 0x18, 0x18, 0x19,
+ 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1C,
+ 0x1C, 0x1D, 0x1D, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F,
+ 0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21,
+ 0x22, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24,
+ 0x24, 0x24, 0x25, 0x25, 0x25, 0x25, 0x26, 0x26,
+ 0x26, 0x26, 0x27, 0x27, 0x27, 0x28, 0x28, 0x28,
+ 0x28, 0x29, 0x29, 0x29, 0x29, 0x2A, 0x2A, 0x2A,
+ 0x2A, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2C, 0x2C,
+ 0x2C, 0x2C, 0x2D, 0x2D, 0x2D, 0x2D, 0x2E, 0x2E,
+ 0x2E, 0x2E, 0x2E, 0x2F, 0x2F, 0x2F, 0x2F, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31,
+ 0x31, 0x32, 0x32, 0x32, 0x32, 0x32, 0x33, 0x33,
+ 0x33, 0x33, 0x33, 0x34, 0x34, 0x34, 0x34, 0x34,
+ 0x35, 0x35, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x39, 0x39, 0x39,
+ 0x39, 0x39, 0x39, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A,
+ 0x3A, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3C,
+ 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3D, 0x3D, 0x3D,
+ 0x3D, 0x3D, 0x3D, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E,
+ 0x3E, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41,
+ 0x41, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x42,
+ 0x42, 0x42, 0x42, 0x43, 0x43, 0x43, 0x43, 0x43,
+ 0x43, 0x43, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
+ 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47,
+ 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x48, 0x48,
+ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49,
+ 0x49, 0x49, 0x49, 0x49, 0x49, 0x4A, 0x4A, 0x4A,
+ 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4B, 0x4B, 0x4B,
+ 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4C, 0x4C, 0x4C,
+ 0x4C, 0x4C, 0x4C, 0x4C, 0x4D, 0x4D, 0x4D, 0x4D,
+ 0x4D, 0x4D, 0x4D, 0x4D, 0x4E, 0x4E, 0x4E, 0x4E,
+ 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4F, 0x4F, 0x4F,
+ 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x50, 0x50, 0x50,
+ 0x50, 0x50, 0x50, 0x50, 0x50, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52,
+ 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x53, 0x53,
+ 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54,
+ 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56,
+ 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, 0x58, 0x58,
+ 0x58, 0x58, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59,
+ 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B,
+ 0x5B, 0x5B, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+ 0x5C, 0x5C, 0x5C, 0x5C, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5E, 0x5E,
+ 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E,
+ 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F,
+ 0x5F, 0x5F, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
+ 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x62,
+ 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62,
+ 0x62, 0x62, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x64, 0x64, 0x64,
+ 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
+ 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
+ 0x65, 0x65, 0x65, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x67,
+ 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67,
+ 0x67, 0x67, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68,
+ 0x68, 0x68, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69,
+ 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+ 0x69, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
+ 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6B, 0x6B, 0x6B,
+ 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B,
+ 0x6B, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C,
+ 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6D, 0x6D, 0x6D,
+ 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D,
+ 0x6D, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E,
+ 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6F, 0x6F, 0x6F,
+ 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F,
+ 0x6F, 0x6F, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
+ 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x71, 0x71,
+ 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
+ 0x71, 0x71, 0x71, 0x72, 0x72, 0x72, 0x72, 0x72,
+ 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
+ 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+ 0x73, 0x73, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74,
+ 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74,
+ 0x74, 0x74, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75,
+ 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75,
+ 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
+ 0x76, 0x76, 0x76, 0x76, 0x76, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0x78, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
+ 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x7A, 0x7A,
+ 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A,
+ 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7B, 0x7B, 0x7B,
+ 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B,
+ 0x7B, 0x7B, 0x7B, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C,
+ 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C,
+ 0x7C, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D,
+ 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D,
+ 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E,
+ 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82, 0x82,
+ 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
+ 0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+ 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+ 0x83, 0x83, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
+ 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
+ 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
+ 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
+ 0x85, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
+ 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
+ 0x86, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
+ 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
+ 0x87, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
+ 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
+ 0x89, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A,
+ 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A,
+ 0x8A, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B,
+ 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B,
+ 0x8B, 0x8B, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C,
+ 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C,
+ 0x8C, 0x8C, 0x8C, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D,
+ 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D,
+ 0x8D, 0x8D, 0x8D, 0x8D, 0x8E, 0x8E, 0x8E, 0x8E,
+ 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E,
+ 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F, 0x8F, 0x8F,
+ 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F,
+ 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x90, 0x90,
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
+ 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
+ 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
+ 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
+ 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
+ 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+ 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x95, 0x95,
+ 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
+ 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
+ 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
+ 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
+ 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97, 0x97,
+ 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97,
+ 0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+ 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
+ 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
+ 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
+ 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
+ 0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+ 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+ 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9B, 0x9B, 0x9B,
+ 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B,
+ 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B,
+ 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C,
+ 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C,
+ 0x9C, 0x9C, 0x9C, 0x9C, 0x9D, 0x9D, 0x9D, 0x9D,
+ 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D,
+ 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9E,
+ 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
+ 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
+ 0x9E, 0x9E, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F,
+ 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F,
+ 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0xA0, 0xA0,
+ 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+ 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+ 0xA0, 0xA0, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1,
+ 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1,
+ 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA2, 0xA2,
+ 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2,
+ 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2,
+ 0xA2, 0xA2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3,
+ 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3,
+ 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA4, 0xA4,
+ 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
+ 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
+ 0xA4, 0xA4, 0xA4, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
+ 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
+ 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
+ 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
+ 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
+ 0xA6, 0xA6, 0xA6, 0xA6, 0xA7, 0xA7, 0xA7, 0xA7,
+ 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7,
+ 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7,
+ 0xA7, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8,
+ 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8,
+ 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA9,
+ 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9,
+ 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9,
+ 0xA9, 0xA9, 0xA9, 0xA9, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB,
+ 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB,
+ 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAC,
+ 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
+ 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
+ 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAD, 0xAD, 0xAD,
+ 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD,
+ 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD,
+ 0xAD, 0xAD, 0xAD, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE,
+ 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE,
+ 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE,
+ 0xAE, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF,
+ 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF,
+ 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xB0,
+ 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0,
+ 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0,
+ 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB1, 0xB1,
+ 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1,
+ 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1,
+ 0xB1, 0xB1, 0xB1, 0xB1, 0xB2, 0xB2, 0xB2, 0xB2,
+ 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2,
+ 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2,
+ 0xB2, 0xB2, 0xB2, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3,
+ 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3,
+ 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3,
+ 0xB3, 0xB3, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
+ 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
+ 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
+ 0xB4, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5,
+ 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5,
+ 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5,
+ 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
+ 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
+ 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
+ 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7,
+ 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7,
+ 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB8,
+ 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8,
+ 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8,
+ 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB9,
+ 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9,
+ 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9,
+ 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xBA,
+ 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA,
+ 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA,
+ 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBB,
+ 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
+ 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
+ 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
+ 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC,
+ 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC,
+ 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC,
+ 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD,
+ 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD,
+ 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD,
+ 0xBD, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE,
+ 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE,
+ 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE,
+ 0xBE, 0xBE, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF,
+ 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF,
+ 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF,
+ 0xBF, 0xBF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
+ 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
+ 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
+ 0xC0, 0xC0, 0xC0, 0xC0, 0xC1, 0xC1, 0xC1, 0xC1,
+ 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1,
+ 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1,
+ 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC2, 0xC2, 0xC2,
+ 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2,
+ 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2,
+ 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC3, 0xC3,
+ 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
+ 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
+ 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
+ 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4,
+ 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4,
+ 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4,
+ 0xC4, 0xC4, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5,
+ 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5,
+ 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5,
+ 0xC5, 0xC5, 0xC5, 0xC5, 0xC6, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7, 0xC7,
+ 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7,
+ 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7,
+ 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7,
+ 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
+ 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
+ 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
+ 0xC8, 0xC8, 0xC8, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9,
+ 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9,
+ 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9,
+ 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xCA, 0xCA,
+ 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA,
+ 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA,
+ 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA,
+ 0xCA, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB,
+ 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB,
+ 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB,
+ 0xCB, 0xCB, 0xCB, 0xCB, 0xCC, 0xCC, 0xCC, 0xCC,
+ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
+ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
+ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD,
+ 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
+ 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
+ 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
+ 0xCD, 0xCD, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE,
+ 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE,
+ 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE,
+ 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCF, 0xCF,
+ 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF,
+ 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF,
+ 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF,
+ 0xCF, 0xCF, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0,
+ 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0,
+ 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0,
+ 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD1, 0xD1, 0xD1,
+ 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1,
+ 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1,
+ 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1,
+ 0xD1, 0xD1, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+ 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+ 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+ 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD3, 0xD3,
+ 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3,
+ 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3,
+ 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3,
+ 0xD3, 0xD3, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4,
+ 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4,
+ 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4,
+ 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD5,
+ 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5,
+ 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5,
+ 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5,
+ 0xD5, 0xD5, 0xD5, 0xD5, 0xD6, 0xD6, 0xD6, 0xD6,
+ 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6,
+ 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6,
+ 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6,
+ 0xD6, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7,
+ 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7,
+ 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7,
+ 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD8, 0xD8,
+ 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
+ 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
+ 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
+ 0xD8, 0xD8, 0xD8, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
+ 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
+ 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
+ 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
+ 0xD9, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
+ 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
+ 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
+ 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDB, 0xDB,
+ 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB,
+ 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB,
+ 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB,
+ 0xDB, 0xDB, 0xDB, 0xDB, 0xDC, 0xDC, 0xDC, 0xDC,
+ 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,
+ 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,
+ 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,
+ 0xDC, 0xDC, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
+ 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
+ 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
+ 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
+ 0xDD, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE,
+ 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE,
+ 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE,
+ 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDF,
+ 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF,
+ 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF,
+ 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF,
+ 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xE0, 0xE0,
+ 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
+ 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
+ 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
+ 0xE0, 0xE0, 0xE0, 0xE0, 0xE1, 0xE1, 0xE1, 0xE1,
+ 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1,
+ 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1,
+ 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1,
+ 0xE1, 0xE1, 0xE1, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
+ 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
+ 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
+ 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
+ 0xE2, 0xE2, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
+ 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
+ 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
+ 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
+ 0xE3, 0xE3, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
+ 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
+ 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
+ 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
+ 0xE4, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
+ 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
+ 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
+ 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
+ 0xE6, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
+ 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
+ 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
+ 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
+ 0xE7, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
+ 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
+ 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
+ 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
+ 0xE8, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
+ 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
+ 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
+ 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
+ 0xE9, 0xE9, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
+ 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
+ 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
+ 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
+ 0xEA, 0xEA, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
+ 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
+ 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
+ 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
+ 0xEB, 0xEB, 0xEB, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
+ 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
+ 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
+ 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
+ 0xEC, 0xEC, 0xEC, 0xEC, 0xED, 0xED, 0xED, 0xED,
+ 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
+ 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
+ 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
+ 0xED, 0xED, 0xED, 0xED, 0xED, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEF, 0xEF,
+ 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
+ 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
+ 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
+ 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
+ 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
+ 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
+ 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
+ 0xF1, 0xF1, 0xF1, 0xF1, 0xF2, 0xF2, 0xF2, 0xF2,
+ 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+ 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+ 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+ 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF3, 0xF3,
+ 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
+ 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
+ 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
+ 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
+ 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
+ 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
+ 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
+ 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
+ 0xF4, 0xF4, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
+ 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
+ 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
+ 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
+ 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF6, 0xF6, 0xF6,
+ 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
+ 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
+ 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
+ 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
+ 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
+ 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
+ 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
+ 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
+ 0xF7, 0xF7, 0xF7, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
+ 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
+ 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
+ 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
+ 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF9, 0xF9,
+ 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
+ 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
+ 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
+ 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
+ 0xF9, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFB, 0xFB, 0xFB,
+ 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
+ 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
+ 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
+ 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
+ 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFD, 0xFD, 0xFD,
+ 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
+ 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
+ 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
+ 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
+ 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
+ 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
+ 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
+ 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
+ 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+void mdp4_mixer_gc_lut_setup(int mixer_num)
+{
+ unsigned char *base;
+ uint32 data;
+ char val;
+ int i, off;
+
+ if (mixer_num) /* mixer number, /dev/fb0, /dev/fb1 */
+ base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
+ else
+ base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+
+ base += 0x4000; /* GC_LUT offset */
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ off = 0;
+ for (i = 0; i < 4096; i++) {
+ val = gc_lut[i];
+ data = (val << 16 | val << 8 | val); /* R, B, and G are same */
+ outpdw(base + off, data);
+ off += 4;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+uint32 igc_video_lut[] = { /* non linear */
+ 0x0, 0x1, 0x2, 0x4, 0x5, 0x6, 0x7, 0x9,
+ 0xA, 0xB, 0xC, 0xE, 0xF, 0x10, 0x12, 0x14,
+ 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F, 0x21, 0x23,
+ 0x25, 0x28, 0x2A, 0x2D, 0x30, 0x32, 0x35, 0x38,
+ 0x3B, 0x3E, 0x42, 0x45, 0x48, 0x4C, 0x4F, 0x53,
+ 0x57, 0x5B, 0x5F, 0x63, 0x67, 0x6B, 0x70, 0x74,
+ 0x79, 0x7E, 0x83, 0x88, 0x8D, 0x92, 0x97, 0x9C,
+ 0xA2, 0xA8, 0xAD, 0xB3, 0xB9, 0xBF, 0xC5, 0xCC,
+ 0xD2, 0xD8, 0xDF, 0xE6, 0xED, 0xF4, 0xFB, 0x102,
+ 0x109, 0x111, 0x118, 0x120, 0x128, 0x130, 0x138, 0x140,
+ 0x149, 0x151, 0x15A, 0x162, 0x16B, 0x174, 0x17D, 0x186,
+ 0x190, 0x199, 0x1A3, 0x1AC, 0x1B6, 0x1C0, 0x1CA, 0x1D5,
+ 0x1DF, 0x1EA, 0x1F4, 0x1FF, 0x20A, 0x215, 0x220, 0x22B,
+ 0x237, 0x242, 0x24E, 0x25A, 0x266, 0x272, 0x27F, 0x28B,
+ 0x298, 0x2A4, 0x2B1, 0x2BE, 0x2CB, 0x2D8, 0x2E6, 0x2F3,
+ 0x301, 0x30F, 0x31D, 0x32B, 0x339, 0x348, 0x356, 0x365,
+ 0x374, 0x383, 0x392, 0x3A1, 0x3B1, 0x3C0, 0x3D0, 0x3E0,
+ 0x3F0, 0x400, 0x411, 0x421, 0x432, 0x443, 0x454, 0x465,
+ 0x476, 0x487, 0x499, 0x4AB, 0x4BD, 0x4CF, 0x4E1, 0x4F3,
+ 0x506, 0x518, 0x52B, 0x53E, 0x551, 0x565, 0x578, 0x58C,
+ 0x5A0, 0x5B3, 0x5C8, 0x5DC, 0x5F0, 0x605, 0x61A, 0x62E,
+ 0x643, 0x659, 0x66E, 0x684, 0x699, 0x6AF, 0x6C5, 0x6DB,
+ 0x6F2, 0x708, 0x71F, 0x736, 0x74D, 0x764, 0x77C, 0x793,
+ 0x7AB, 0x7C3, 0x7DB, 0x7F3, 0x80B, 0x824, 0x83D, 0x855,
+ 0x86F, 0x888, 0x8A1, 0x8BB, 0x8D4, 0x8EE, 0x908, 0x923,
+ 0x93D, 0x958, 0x973, 0x98E, 0x9A9, 0x9C4, 0x9DF, 0x9FB,
+ 0xA17, 0xA33, 0xA4F, 0xA6C, 0xA88, 0xAA5, 0xAC2, 0xADF,
+ 0xAFC, 0xB19, 0xB37, 0xB55, 0xB73, 0xB91, 0xBAF, 0xBCE,
+ 0xBEC, 0xC0B, 0xC2A, 0xC4A, 0xC69, 0xC89, 0xCA8, 0xCC8,
+ 0xCE8, 0xD09, 0xD29, 0xD4A, 0xD6B, 0xD8C, 0xDAD, 0xDCF,
+ 0xDF0, 0xE12, 0xE34, 0xE56, 0xE79, 0xE9B, 0xEBE, 0xEE1,
+ 0xF04, 0xF27, 0xF4B, 0xF6E, 0xF92, 0xFB6, 0xFDB, 0xFFF,
+};
+
+void mdp4_vg_igc_lut_setup(int vp_num)
+{
+ unsigned char *base;
+ int i, voff, off;
+ uint32 data, val;
+
+ voff = MDP4_VIDEO_OFF * vp_num;
+ base = MDP_BASE + MDP4_VIDEO_BASE + voff + 0x5000;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ off = 0;
+ for (i = 0; i < 256; i++) {
+ val = igc_video_lut[i];
+ data = (val << 16 | val); /* color 0 and 1 */
+ outpdw(base + off, data);
+ outpdw(base + off + 0x800, val); /* color 2 */
+ off += 4;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+uint32 igc_rgb_lut[] = { /* linear */
+ 0x0, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
+ 0x80, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
+ 0x101, 0x111, 0x121, 0x131, 0x141, 0x151, 0x161, 0x171,
+ 0x181, 0x191, 0x1A2, 0x1B2, 0x1C2, 0x1D2, 0x1E2, 0x1F2,
+ 0x202, 0x212, 0x222, 0x232, 0x242, 0x252, 0x262, 0x272,
+ 0x282, 0x292, 0x2A2, 0x2B3, 0x2C3, 0x2D3, 0x2E3, 0x2F3,
+ 0x303, 0x313, 0x323, 0x333, 0x343, 0x353, 0x363, 0x373,
+ 0x383, 0x393, 0x3A3, 0x3B3, 0x3C4, 0x3D4, 0x3E4, 0x3F4,
+ 0x404, 0x414, 0x424, 0x434, 0x444, 0x454, 0x464, 0x474,
+ 0x484, 0x494, 0x4A4, 0x4B4, 0x4C4, 0x4D5, 0x4E5, 0x4F5,
+ 0x505, 0x515, 0x525, 0x535, 0x545, 0x555, 0x565, 0x575,
+ 0x585, 0x595, 0x5A5, 0x5B5, 0x5C5, 0x5D5, 0x5E6, 0x5F6,
+ 0x606, 0x616, 0x626, 0x636, 0x646, 0x656, 0x666, 0x676,
+ 0x686, 0x696, 0x6A6, 0x6B6, 0x6C6, 0x6D6, 0x6E6, 0x6F7,
+ 0x707, 0x717, 0x727, 0x737, 0x747, 0x757, 0x767, 0x777,
+ 0x787, 0x797, 0x7A7, 0x7B7, 0x7C7, 0x7D7, 0x7E7, 0x7F7,
+ 0x808, 0x818, 0x828, 0x838, 0x848, 0x858, 0x868, 0x878,
+ 0x888, 0x898, 0x8A8, 0x8B8, 0x8C8, 0x8D8, 0x8E8, 0x8F8,
+ 0x908, 0x919, 0x929, 0x939, 0x949, 0x959, 0x969, 0x979,
+ 0x989, 0x999, 0x9A9, 0x9B9, 0x9C9, 0x9D9, 0x9E9, 0x9F9,
+ 0xA09, 0xA19, 0xA2A, 0xA3A, 0xA4A, 0xA5A, 0xA6A, 0xA7A,
+ 0xA8A, 0xA9A, 0xAAA, 0xABA, 0xACA, 0xADA, 0xAEA, 0xAFA,
+ 0xB0A, 0xB1A, 0xB2A, 0xB3B, 0xB4B, 0xB5B, 0xB6B, 0xB7B,
+ 0xB8B, 0xB9B, 0xBAB, 0xBBB, 0xBCB, 0xBDB, 0xBEB, 0xBFB,
+ 0xC0B, 0xC1B, 0xC2B, 0xC3B, 0xC4C, 0xC5C, 0xC6C, 0xC7C,
+ 0xC8C, 0xC9C, 0xCAC, 0xCBC, 0xCCC, 0xCDC, 0xCEC, 0xCFC,
+ 0xD0C, 0xD1C, 0xD2C, 0xD3C, 0xD4C, 0xD5D, 0xD6D, 0xD7D,
+ 0xD8D, 0xD9D, 0xDAD, 0xDBD, 0xDCD, 0xDDD, 0xDED, 0xDFD,
+ 0xE0D, 0xE1D, 0xE2D, 0xE3D, 0xE4D, 0xE5D, 0xE6E, 0xE7E,
+ 0xE8E, 0xE9E, 0xEAE, 0xEBE, 0xECE, 0xEDE, 0xEEE, 0xEFE,
+ 0xF0E, 0xF1E, 0xF2E, 0xF3E, 0xF4E, 0xF5E, 0xF6E, 0xF7F,
+ 0xF8F, 0xF9F, 0xFAF, 0xFBF, 0xFCF, 0xFDF, 0xFEF, 0xFFF,
+};
+
+void mdp4_rgb_igc_lut_setup(int num)
+{
+ unsigned char *base;
+ int i, voff, off;
+ uint32 data, val;
+
+ voff = MDP4_RGB_OFF * num;
+ base = MDP_BASE + MDP4_RGB_BASE + voff + 0x5000;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ off = 0;
+ for (i = 0; i < 256; i++) {
+ val = igc_rgb_lut[i];
+ data = (val << 16 | val); /* color 0 and 1 */
+ outpdw(base + off, data);
+ outpdw(base + off + 0x800, val); /* color 2 */
+ off += 4;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+uint32 mdp4_rgb_igc_lut_cvt(uint32 ndx)
+{
+ return igc_rgb_lut[ndx & 0x0ff];
+}
+
+uint32_t mdp4_ss_table_value(int8_t value, int8_t index)
+{
+ uint32_t out = 0x0;
+ int8_t level = -1;
+ uint32_t mask = 0xffffffff;
+
+ if (value < 0) {
+ if (value == -128)
+ value = 127;
+ else
+ value = -value;
+ out = 0x11111111;
+ } else {
+ out = 0x88888888;
+ mask = 0x0fffffff;
+ }
+
+ if (value == 0)
+ level = 0;
+ else {
+ while (value > 0 && level < 7) {
+ level++;
+ value -= 16;
+ }
+ }
+
+ if (level == 0) {
+ if (index == 0)
+ out = 0x0;
+ else
+ out = 0x20000000;
+ } else {
+ out += (0x11111111 * level);
+ if (index == 1)
+ out &= mask;
+ }
+
+ return out;
+}
+
diff --git a/drivers/video/msm/mdp_csc_table.h b/drivers/video/msm/mdp_csc_table.h
index d1cde30..a0f72c0 100644
--- a/drivers/video/msm/mdp_csc_table.h
+++ b/drivers/video/msm/mdp_csc_table.h
@@ -1,4 +1,4 @@
-/* drivers/video/msm_fb/mdp_csc_table.h
+/* drivers/video/msm/mdp_csc_table.h
*
* Copyright (C) 2007 QUALCOMM Incorporated
* Copyright (C) 2007 Google Incorporated
@@ -16,57 +16,116 @@
static struct {
uint32_t reg;
uint32_t val;
-} csc_table[] = {
- { 0x40400, 0x83 },
- { 0x40404, 0x102 },
- { 0x40408, 0x32 },
- { 0x4040c, 0xffffffb5 },
- { 0x40410, 0xffffff6c },
- { 0x40414, 0xe1 },
- { 0x40418, 0xe1 },
- { 0x4041c, 0xffffff45 },
- { 0x40420, 0xffffffdc },
- { 0x40440, 0x254 },
- { 0x40444, 0x0 },
- { 0x40448, 0x331 },
- { 0x4044c, 0x254 },
- { 0x40450, 0xffffff38 },
- { 0x40454, 0xfffffe61 },
- { 0x40458, 0x254 },
- { 0x4045c, 0x409 },
- { 0x40460, 0x0 },
- { 0x40480, 0x5d },
- { 0x40484, 0x13a },
- { 0x40488, 0x20 },
- { 0x4048c, 0xffffffcd },
- { 0x40490, 0xffffff54 },
- { 0x40494, 0xe1 },
- { 0x40498, 0xe1 },
- { 0x4049c, 0xffffff35 },
- { 0x404a0, 0xffffffec },
- { 0x404c0, 0x254 },
- { 0x404c4, 0x0 },
- { 0x404c8, 0x396 },
- { 0x404cc, 0x254 },
- { 0x404d0, 0xffffff94 },
- { 0x404d4, 0xfffffef0 },
- { 0x404d8, 0x254 },
- { 0x404dc, 0x43a },
- { 0x404e0, 0x0 },
- { 0x40500, 0x10 },
- { 0x40504, 0x80 },
- { 0x40508, 0x80 },
- { 0x40540, 0x10 },
- { 0x40544, 0x80 },
- { 0x40548, 0x80 },
- { 0x40580, 0x10 },
- { 0x40584, 0xeb },
- { 0x40588, 0x10 },
- { 0x4058c, 0xf0 },
- { 0x405c0, 0x10 },
- { 0x405c4, 0xeb },
- { 0x405c8, 0x10 },
- { 0x405cc, 0xf0 },
+} csc_matrix_config_table[] = {
+ /* RGB -> YUV primary forward matrix (set1). */
+ { MDP_CSC_PFMVn(0), 0x83 },
+ { MDP_CSC_PFMVn(1), 0x102 },
+ { MDP_CSC_PFMVn(2), 0x32 },
+ { MDP_CSC_PFMVn(3), 0xffffffb5 },
+ { MDP_CSC_PFMVn(4), 0xffffff6c },
+ { MDP_CSC_PFMVn(5), 0xe1 },
+ { MDP_CSC_PFMVn(6), 0xe1 },
+ { MDP_CSC_PFMVn(7), 0xffffff45 },
+ { MDP_CSC_PFMVn(8), 0xffffffdc },
+
+ /* YUV -> RGB primary reverse matrix (set2) */
+ { MDP_CSC_PRMVn(0), 0x254 },
+ { MDP_CSC_PRMVn(1), 0x0 },
+ { MDP_CSC_PRMVn(2), 0x331 },
+ { MDP_CSC_PRMVn(3), 0x254 },
+ { MDP_CSC_PRMVn(4), 0xffffff38 },
+ { MDP_CSC_PRMVn(5), 0xfffffe61 },
+ { MDP_CSC_PRMVn(6), 0x254 },
+ { MDP_CSC_PRMVn(7), 0x409 },
+ { MDP_CSC_PRMVn(8), 0x0 },
+
+#ifndef CONFIG_MSM_MDP31
+ /* For MDP 2.2/3.0 */
+
+ /* primary limit vector */
+ { MDP_CSC_PLVn(0), 0x10 },
+ { MDP_CSC_PLVn(1), 0xeb },
+ { MDP_CSC_PLVn(2), 0x10 },
+ { MDP_CSC_PLVn(3), 0xf0 },
+
+ /* primary bias vector */
+ { MDP_CSC_PBVn(0), 0x10 },
+ { MDP_CSC_PBVn(1), 0x80 },
+ { MDP_CSC_PBVn(2), 0x80 },
+
+#else /* CONFIG_MSM_MDP31 */
+
+ /* limit vectors configuration */
+ /* rgb -> yuv (set1) pre-limit vector */
+ { MDP_PPP_CSC_PRE_LV1n(0), 0x10 },
+ { MDP_PPP_CSC_PRE_LV1n(1), 0xeb },
+ { MDP_PPP_CSC_PRE_LV1n(2), 0x10 },
+ { MDP_PPP_CSC_PRE_LV1n(3), 0xf0 },
+ { MDP_PPP_CSC_PRE_LV1n(4), 0x10 },
+ { MDP_PPP_CSC_PRE_LV1n(5), 0xf0 },
+
+ /* rgb -> yuv (set1) post-limit vector */
+ { MDP_PPP_CSC_POST_LV1n(0), 0x0 },
+ { MDP_PPP_CSC_POST_LV1n(1), 0xff },
+ { MDP_PPP_CSC_POST_LV1n(2), 0x0 },
+ { MDP_PPP_CSC_POST_LV1n(3), 0xff },
+ { MDP_PPP_CSC_POST_LV1n(4), 0x0 },
+ { MDP_PPP_CSC_POST_LV1n(5), 0xff },
+
+ /* yuv -> rgb (set2) pre-limit vector */
+ { MDP_PPP_CSC_PRE_LV2n(0), 0x0 },
+ { MDP_PPP_CSC_PRE_LV2n(1), 0xff },
+ { MDP_PPP_CSC_PRE_LV2n(2), 0x0 },
+ { MDP_PPP_CSC_PRE_LV2n(3), 0xff },
+ { MDP_PPP_CSC_PRE_LV2n(4), 0x0 },
+ { MDP_PPP_CSC_PRE_LV2n(5), 0xff },
+
+ /* yuv -> rgb (set2) post-limit vector */
+ { MDP_PPP_CSC_POST_LV2n(0), 0x10 },
+ { MDP_PPP_CSC_POST_LV2n(1), 0xeb },
+ { MDP_PPP_CSC_POST_LV2n(2), 0x10 },
+ { MDP_PPP_CSC_POST_LV2n(3), 0xf0 },
+ { MDP_PPP_CSC_POST_LV2n(4), 0x10 },
+ { MDP_PPP_CSC_POST_LV2n(5), 0xf0 },
+
+ /* bias vectors configuration */
+
+ /* XXX: why is set2 used for rgb->yuv, but set1 */
+ /* used for yuv -> rgb??!? Seems to be the reverse of the
+ * other vectors. */
+
+ /* RGB -> YUV pre-bias vector... */
+ { MDP_PPP_CSC_PRE_BV2n(0), 0 },
+ { MDP_PPP_CSC_PRE_BV2n(1), 0 },
+ { MDP_PPP_CSC_PRE_BV2n(2), 0 },
+
+ /* RGB -> YUV post-bias vector */
+ { MDP_PPP_CSC_POST_BV2n(0), 0x10 },
+ { MDP_PPP_CSC_POST_BV2n(1), 0x80 },
+ { MDP_PPP_CSC_POST_BV2n(2), 0x80 },
+
+ /* YUV -> RGB pre-bias vector... */
+ { MDP_PPP_CSC_PRE_BV1n(0), 0x1f0 },
+ { MDP_PPP_CSC_PRE_BV1n(1), 0x180 },
+ { MDP_PPP_CSC_PRE_BV1n(2), 0x180 },
+
+ /* YUV -> RGB post-bias vector */
+ { MDP_PPP_CSC_POST_BV1n(0), 0 },
+ { MDP_PPP_CSC_POST_BV1n(1), 0 },
+ { MDP_PPP_CSC_POST_BV1n(2), 0 },
+
+ /* luma filter coefficients */
+ { MDP_PPP_DEINT_COEFFn(0), 0x3e0 },
+ { MDP_PPP_DEINT_COEFFn(1), 0x360 },
+ { MDP_PPP_DEINT_COEFFn(2), 0x120 },
+ { MDP_PPP_DEINT_COEFFn(3), 0x140 },
+#endif
+};
+
+static struct {
+ uint32_t reg;
+ uint32_t val;
+} csc_color_lut[] = {
{ 0x40800, 0x0 },
{ 0x40804, 0x151515 },
{ 0x40808, 0x1d1d1d },
diff --git a/drivers/video/msm/mdp_cursor.c b/drivers/video/msm/mdp_cursor.c
new file mode 100644
index 0000000..f8c08e3
--- /dev/null
+++ b/drivers/video/msm/mdp_cursor.c
@@ -0,0 +1,264 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+
+#include <mach/hardware.h>
+#include <asm/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+static int cursor_enabled;
+
+#include "mdp4.h"
+
+#if defined(CONFIG_FB_MSM_OVERLAY) && defined(CONFIG_FB_MSM_MDP40)
+static struct workqueue_struct *mdp_cursor_ctrl_wq;
+static struct work_struct mdp_cursor_ctrl_worker;
+
+/* cursor configuration */
+static void *cursor_buf_phys;
+static __u32 width, height, bg_color;
+static int calpha_en, transp_en, alpha;
+static int sync_disabled = -1;
+
+void mdp_cursor_ctrl_workqueue_handler(struct work_struct *work)
+{
+ unsigned long flag;
+
+ /* disable vsync */
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_disable_irq(MDP_OVERLAY0_TERM);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+}
+
+void mdp_hw_cursor_init(void)
+{
+ mdp_cursor_ctrl_wq =
+ create_singlethread_workqueue("mdp_cursor_ctrl_wq");
+ INIT_WORK(&mdp_cursor_ctrl_worker, mdp_cursor_ctrl_workqueue_handler);
+}
+
+void mdp_hw_cursor_done(void)
+{
+ /* Cursor configuration:
+ *
+ * This is done in DMA_P_DONE ISR because the following registers are
+ * not double buffered in hardware:
+ *
+ * MDP_DMA_P_CURSOR_SIZE, address = 0x90044
+ * MDP_DMA_P_CURSOR_BLEND_CONFIG, address = 0x90060
+ * MDP_DMA_P_CURSOR_BLEND_PARAM, address = 0x90064
+ * MDP_DMA_P_CURSOR_BLEND_TRANS_LOW, address = 0x90068
+ * MDP_DMA_P_CURSOR_BLEND_TRANS_HIG, address = 0x9006C
+ *
+ * Moving this code out of the ISR will cause the MDP to underrun!
+ */
+ spin_lock(&mdp_spin_lock);
+ if (sync_disabled) {
+ spin_unlock(&mdp_spin_lock);
+ return;
+ }
+
+ MDP_OUTP(MDP_BASE + 0x90044, (height << 16) | width);
+ MDP_OUTP(MDP_BASE + 0x90048, cursor_buf_phys);
+
+ MDP_OUTP(MDP_BASE + 0x90060,
+ (transp_en << 3) | (calpha_en << 1) |
+ (inp32(MDP_BASE + 0x90060) & 0x1));
+
+ MDP_OUTP(MDP_BASE + 0x90064, (alpha << 24));
+ MDP_OUTP(MDP_BASE + 0x90068, (0xffffff & bg_color));
+ MDP_OUTP(MDP_BASE + 0x9006C, (0xffffff & bg_color));
+
+ /* enable/disable the cursor as per the last request */
+ if (cursor_enabled && !(inp32(MDP_BASE + 0x90060) & (0x1)))
+ MDP_OUTP(MDP_BASE + 0x90060, inp32(MDP_BASE + 0x90060) | 0x1);
+ else if (!cursor_enabled && (inp32(MDP_BASE + 0x90060) & (0x1)))
+ MDP_OUTP(MDP_BASE + 0x90060,
+ inp32(MDP_BASE + 0x90060) & (~0x1));
+
+ /* enqueue the task to disable MDP interrupts */
+ queue_work(mdp_cursor_ctrl_wq, &mdp_cursor_ctrl_worker);
+
+ /* update done */
+ sync_disabled = 1;
+ spin_unlock(&mdp_spin_lock);
+}
+
+static void mdp_hw_cursor_enable_vsync(void)
+{
+ /* if the cursor registers were updated (once or more) since the
+ * last vsync, enable the vsync interrupt (if not already enabled)
+ * for the next update
+ */
+ if (sync_disabled) {
+
+ /* cancel pending task to disable MDP interrupts */
+ if (work_pending(&mdp_cursor_ctrl_worker))
+ cancel_work_sync(&mdp_cursor_ctrl_worker);
+ else
+ /* enable irq */
+ mdp_enable_irq(MDP_OVERLAY0_TERM);
+
+ sync_disabled = 0;
+
+ /* enable vsync intr */
+ outp32(MDP_INTR_CLEAR, INTR_OVERLAY0_DONE);
+ mdp_intr_mask |= INTR_OVERLAY0_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ }
+}
+
+int mdp_hw_cursor_sync_update(struct fb_info *info, struct fb_cursor *cursor)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct fb_image *img = &cursor->image;
+ unsigned long flag;
+ int sync_needed = 0, ret = 0;
+
+ if ((img->width > MDP_CURSOR_WIDTH) ||
+ (img->height > MDP_CURSOR_HEIGHT) ||
+ (img->depth != 32))
+ return -EINVAL;
+
+ if (cursor->set & FB_CUR_SETPOS)
+ MDP_OUTP(MDP_BASE + 0x9004c, (img->dy << 16) | img->dx);
+
+ if (cursor->set & FB_CUR_SETIMAGE) {
+ ret = copy_from_user(mfd->cursor_buf, img->data,
+ img->width*img->height*4);
+ if (ret)
+ return ret;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ if (img->bg_color == 0xffffffff)
+ transp_en = 0;
+ else
+ transp_en = 1;
+
+ alpha = (img->fg_color & 0xff000000) >> 24;
+
+ if (alpha)
+ calpha_en = 0x2; /* xrgb */
+ else
+ calpha_en = 0x1; /* argb */
+
+ /* cursor parameters */
+ height = img->height;
+ width = img->width;
+ bg_color = img->bg_color;
+ cursor_buf_phys = mfd->cursor_buf_phys;
+
+ sync_needed = 1;
+ } else
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+
+ if ((cursor->enable) && (!cursor_enabled)) {
+ cursor_enabled = 1;
+ sync_needed = 1;
+ } else if ((!cursor->enable) && (cursor_enabled)) {
+ cursor_enabled = 0;
+ sync_needed = 1;
+ }
+
+ /* if sync cursor update is needed, enable vsync */
+ if (sync_needed)
+ mdp_hw_cursor_enable_vsync();
+
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+ return 0;
+}
+#endif /* CONFIG_FB_MSM_OVERLAY && CONFIG_FB_MSM_MDP40 */
+
+int mdp_hw_cursor_update(struct fb_info *info, struct fb_cursor *cursor)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct fb_image *img = &cursor->image;
+ int calpha_en, transp_en;
+ int alpha;
+ int ret = 0;
+
+ if ((img->width > MDP_CURSOR_WIDTH) ||
+ (img->height > MDP_CURSOR_HEIGHT) ||
+ (img->depth != 32))
+ return -EINVAL;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ if (cursor->set & FB_CUR_SETPOS)
+ MDP_OUTP(MDP_BASE + 0x9004c, (img->dy << 16) | img->dx);
+
+ if (cursor->set & FB_CUR_SETIMAGE) {
+ ret = copy_from_user(mfd->cursor_buf, img->data,
+ img->width*img->height*4);
+ if (ret)
+ return ret;
+
+ if (img->bg_color == 0xffffffff)
+ transp_en = 0;
+ else
+ transp_en = 1;
+
+ alpha = (img->fg_color & 0xff000000) >> 24;
+
+ if (alpha)
+ calpha_en = 0x2; /* xrgb */
+ else
+ calpha_en = 0x1; /* argb */
+
+ MDP_OUTP(MDP_BASE + 0x90044, (img->height << 16) | img->width);
+ MDP_OUTP(MDP_BASE + 0x90048, mfd->cursor_buf_phys);
+ /* order the writes the cursor_buf before updating the
+ * hardware */
+ dma_coherent_pre_ops();
+ MDP_OUTP(MDP_BASE + 0x90060,
+ (transp_en << 3) | (calpha_en << 1) |
+ (inp32(MDP_BASE + 0x90060) & 0x1));
+#ifdef CONFIG_FB_MSM_MDP40
+ MDP_OUTP(MDP_BASE + 0x90064, (alpha << 24));
+ MDP_OUTP(MDP_BASE + 0x90068, (0xffffff & img->bg_color));
+ MDP_OUTP(MDP_BASE + 0x9006C, (0xffffff & img->bg_color));
+#else
+ MDP_OUTP(MDP_BASE + 0x90064,
+ (alpha << 24) | (0xffffff & img->bg_color));
+ MDP_OUTP(MDP_BASE + 0x90068, 0);
+#endif
+ }
+
+ if ((cursor->enable) && (!cursor_enabled)) {
+ cursor_enabled = 1;
+ MDP_OUTP(MDP_BASE + 0x90060, inp32(MDP_BASE + 0x90060) | 0x1);
+ } else if ((!cursor->enable) && (cursor_enabled)) {
+ cursor_enabled = 0;
+ MDP_OUTP(MDP_BASE + 0x90060,
+ inp32(MDP_BASE + 0x90060) & (~0x1));
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ return 0;
+}
diff --git a/drivers/video/msm/mdp_debugfs.c b/drivers/video/msm/mdp_debugfs.c
new file mode 100644
index 0000000..b89e8c7
--- /dev/null
+++ b/drivers/video/msm/mdp_debugfs.c
@@ -0,0 +1,1289 @@
+/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#ifdef CONFIG_FB_MSM_MDP40
+#include "mdp4.h"
+#endif
+#include "mddihosti.h"
+#include "tvenc.h"
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+#include "hdmi_msm.h"
+#endif
+
+#define MDP_DEBUG_BUF 2048
+
+static uint32 mdp_offset;
+static uint32 mdp_count;
+
+static char debug_buf[MDP_DEBUG_BUF];
+
+/*
+ * MDP4
+ *
+ */
+
+static int mdp_offset_open(struct inode *inode, struct file *file)
+{
+ /* non-seekable */
+ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+ return 0;
+}
+
+static int mdp_offset_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static ssize_t mdp_offset_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ uint32 off, cnt;
+
+ if (count >= sizeof(debug_buf))
+ return -EFAULT;
+
+ if (copy_from_user(debug_buf, buff, count))
+ return -EFAULT;
+
+ debug_buf[count] = 0; /* end of string */
+
+ sscanf(debug_buf, "%x %d", &off, &cnt);
+
+ if (cnt <= 0)
+ cnt = 1;
+
+ mdp_offset = off;
+ mdp_count = cnt;
+
+ printk(KERN_INFO "%s: offset=%x cnt=%d\n", __func__,
+ mdp_offset, mdp_count);
+
+ return count;
+}
+
+static ssize_t mdp_offset_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int len = 0;
+
+
+ if (*ppos)
+ return 0; /* the end */
+
+ len = snprintf(debug_buf, sizeof(debug_buf), "0x%08x %d\n",
+ mdp_offset, mdp_count);
+ if (len < 0)
+ return 0;
+
+ if (copy_to_user(buff, debug_buf, len))
+ return -EFAULT;
+
+ *ppos += len; /* increase offset */
+
+ return len;
+}
+
+static const struct file_operations mdp_off_fops = {
+ .open = mdp_offset_open,
+ .release = mdp_offset_release,
+ .read = mdp_offset_read,
+ .write = mdp_offset_write,
+};
+
+static int mdp_reg_open(struct inode *inode, struct file *file)
+{
+ /* non-seekable */
+ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+ return 0;
+}
+
+static int mdp_reg_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static ssize_t mdp_reg_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ uint32 off, data;
+ int cnt;
+
+ if (count >= sizeof(debug_buf))
+ return -EFAULT;
+
+ if (copy_from_user(debug_buf, buff, count))
+ return -EFAULT;
+
+ debug_buf[count] = 0; /* end of string */
+
+ cnt = sscanf(debug_buf, "%x %x", &off, &data);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ outpdw(MDP_BASE + off, data);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ printk(KERN_INFO "%s: addr=%x data=%x\n", __func__, off, data);
+
+ return count;
+}
+
+static ssize_t mdp_reg_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int len = 0;
+ uint32 data;
+ int i, j, off, dlen, num;
+ char *bp, *cp;
+ int tot = 0;
+
+
+ if (*ppos)
+ return 0; /* the end */
+
+ j = 0;
+ num = 0;
+ bp = debug_buf;
+ cp = MDP_BASE + mdp_offset;
+ dlen = sizeof(debug_buf);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ while (j++ < 8) {
+ len = snprintf(bp, dlen, "0x%08x: ", (int)cp);
+ tot += len;
+ bp += len;
+ dlen -= len;
+ off = 0;
+ i = 0;
+ while (i++ < 4) {
+ data = inpdw(cp + off);
+ len = snprintf(bp, dlen, "%08x ", data);
+ tot += len;
+ bp += len;
+ dlen -= len;
+ off += 4;
+ num++;
+ if (num >= mdp_count)
+ break;
+ }
+ *bp++ = '\n';
+ --dlen;
+ tot++;
+ cp += off;
+ if (num >= mdp_count)
+ break;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ *bp = 0;
+ tot++;
+
+ if (copy_to_user(buff, debug_buf, tot))
+ return -EFAULT;
+
+ *ppos += tot; /* increase offset */
+
+ return tot;
+}
+
+
+static const struct file_operations mdp_reg_fops = {
+ .open = mdp_reg_open,
+ .release = mdp_reg_release,
+ .read = mdp_reg_read,
+ .write = mdp_reg_write,
+};
+
+#ifdef CONFIG_FB_MSM_MDP40
+static int mdp_stat_open(struct inode *inode, struct file *file)
+{
+ /* non-seekable */
+ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+ return 0;
+}
+
+static int mdp_stat_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static ssize_t mdp_stat_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ unsigned long flag;
+
+ if (count > sizeof(debug_buf))
+ return -EFAULT;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ memset((char *)&mdp4_stat, 0 , sizeof(mdp4_stat)); /* reset */
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+ return count;
+}
+
+static ssize_t mdp_stat_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int len = 0;
+ int tot = 0;
+ int dlen;
+ char *bp;
+ unsigned long flag;
+
+
+ if (*ppos)
+ return 0; /* the end */
+
+ bp = debug_buf;
+ dlen = sizeof(debug_buf);
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ len = snprintf(bp, dlen, "intr_total: %08lu\n",
+ mdp4_stat.intr_tot);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "intr_dma_p: %08lu\n",
+ mdp4_stat.intr_dma_p);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "intr_dma_s: %08lu\n",
+ mdp4_stat.intr_dma_s);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "intr_dma_e: %08lu\n",
+ mdp4_stat.intr_dma_e);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "intr_overlay0: %08lu\n",
+ mdp4_stat.intr_overlay0);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "intr_overlay1: %08lu\n",
+ mdp4_stat.intr_overlay1);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "unerrun_primary: %08lu\n",
+ mdp4_stat.intr_underrun_p);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "unerrun_external: %08lu\n\n",
+ mdp4_stat.intr_underrun_e);
+
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "intr_dsi : %08lu\n\n",
+ mdp4_stat.intr_dsi);
+
+ bp += len;
+ dlen -= len;
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+ len = snprintf(bp, dlen, "kickoff_mddi: %08lu\n",
+ mdp4_stat.kickoff_mddi);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "kickoff_lcdc: %08lu\n",
+ mdp4_stat.kickoff_lcdc);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "kickoff_dtv: %08lu\n",
+ mdp4_stat.kickoff_dtv);
+
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "kickoff_atv: %08lu\n",
+ mdp4_stat.kickoff_atv);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "kickoff_dsi: %08lu\n\n",
+ mdp4_stat.kickoff_dsi);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "writeback: %08lu\n",
+ mdp4_stat.writeback);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "overlay0_set: %08lu\n",
+ mdp4_stat.overlay_set[0]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "overlay0_unset: %08lu\n",
+ mdp4_stat.overlay_unset[0]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "overlay0_play: %08lu\n",
+ mdp4_stat.overlay_play[0]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "overlay1_set: %08lu\n",
+ mdp4_stat.overlay_set[1]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "overlay1_unset: %08lu\n",
+ mdp4_stat.overlay_unset[1]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "overlay1_play: %08lu\n\n",
+ mdp4_stat.overlay_play[1]);
+
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "pipe_rgb1: %08lu\n", mdp4_stat.pipe[0]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "pipe_rgb2: %08lu\n", mdp4_stat.pipe[1]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "pipe_vg1: %08lu\n", mdp4_stat.pipe[2]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "pipe_vg2: %08lu\n\n", mdp4_stat.pipe[3]);
+
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "dsi_clkoff: %08lu\n\n", mdp4_stat.dsi_clkoff);
+
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "err_mixer: %08lu\n", mdp4_stat.err_mixer);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "err_size: %08lu\n", mdp4_stat.err_size);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "err_scale: %08lu\n", mdp4_stat.err_scale);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "err_format: %08lu\n", mdp4_stat.err_format);
+ bp += len;
+ dlen -= len;
+
+ tot = (uint32)bp - (uint32)debug_buf;
+ *bp = 0;
+ tot++;
+
+ if (tot < 0)
+ return 0;
+ if (copy_to_user(buff, debug_buf, tot))
+ return -EFAULT;
+
+ *ppos += tot; /* increase offset */
+
+ return tot;
+}
+
+static const struct file_operations mdp_stat_fops = {
+ .open = mdp_stat_open,
+ .release = mdp_stat_release,
+ .read = mdp_stat_read,
+ .write = mdp_stat_write,
+};
+#endif
+
+/*
+ * MDDI
+ *
+ */
+
+struct mddi_reg {
+ char *name;
+ int off;
+};
+
+static struct mddi_reg mddi_regs_list[] = {
+ {"MDDI_CMD", MDDI_CMD}, /* 0x0000 */
+ {"MDDI_VERSION", MDDI_VERSION}, /* 0x0004 */
+ {"MDDI_PRI_PTR", MDDI_PRI_PTR}, /* 0x0008 */
+ {"MDDI_BPS", MDDI_BPS}, /* 0x0010 */
+ {"MDDI_SPM", MDDI_SPM}, /* 0x0014 */
+ {"MDDI_INT", MDDI_INT}, /* 0x0018 */
+ {"MDDI_INTEN", MDDI_INTEN}, /* 0x001c */
+ {"MDDI_REV_PTR", MDDI_REV_PTR}, /* 0x0020 */
+ {"MDDI_ REV_SIZE", MDDI_REV_SIZE},/* 0x0024 */
+ {"MDDI_STAT", MDDI_STAT}, /* 0x0028 */
+ {"MDDI_REV_RATE_DIV", MDDI_REV_RATE_DIV}, /* 0x002c */
+ {"MDDI_REV_CRC_ERR", MDDI_REV_CRC_ERR}, /* 0x0030 */
+ {"MDDI_TA1_LEN", MDDI_TA1_LEN}, /* 0x0034 */
+ {"MDDI_TA2_LEN", MDDI_TA2_LEN}, /* 0x0038 */
+ {"MDDI_TEST", MDDI_TEST}, /* 0x0040 */
+ {"MDDI_REV_PKT_CNT", MDDI_REV_PKT_CNT}, /* 0x0044 */
+ {"MDDI_DRIVE_HI", MDDI_DRIVE_HI},/* 0x0048 */
+ {"MDDI_DRIVE_LO", MDDI_DRIVE_LO}, /* 0x004c */
+ {"MDDI_DISP_WAKE", MDDI_DISP_WAKE},/* 0x0050 */
+ {"MDDI_REV_ENCAP_SZ", MDDI_REV_ENCAP_SZ}, /* 0x0054 */
+ {"MDDI_RTD_VAL", MDDI_RTD_VAL}, /* 0x0058 */
+ {"MDDI_PAD_CTL", MDDI_PAD_CTL}, /* 0x0068 */
+ {"MDDI_DRIVER_START_CNT", MDDI_DRIVER_START_CNT}, /* 0x006c */
+ {"MDDI_CORE_VER", MDDI_CORE_VER}, /* 0x008c */
+ {"MDDI_FIFO_ALLOC", MDDI_FIFO_ALLOC}, /* 0x0090 */
+ {"MDDI_PAD_IO_CTL", MDDI_PAD_IO_CTL}, /* 0x00a0 */
+ {"MDDI_PAD_CAL", MDDI_PAD_CAL}, /* 0x00a4 */
+ {0, 0}
+};
+
+static int mddi_reg_open(struct inode *inode, struct file *file)
+{
+ /* non-seekable */
+ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+ return 0;
+}
+
+static int mddi_reg_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static void mddi_reg_write(int ndx, uint32 off, uint32 data)
+{
+ char *base;
+
+ if (ndx)
+ base = (char *)msm_emdh_base;
+ else
+ base = (char *)msm_pmdh_base;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ writel(data, base + off);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ printk(KERN_INFO "%s: addr=%x data=%x\n",
+ __func__, (int)(base+off), (int)data);
+}
+
+static int mddi_reg_read(int ndx)
+{
+ struct mddi_reg *reg;
+ unsigned char *base;
+ int data;
+ char *bp;
+ int len = 0;
+ int tot = 0;
+ int dlen;
+
+ if (ndx)
+ base = msm_emdh_base;
+ else
+ base = msm_pmdh_base;
+
+ reg = mddi_regs_list;
+ bp = debug_buf;
+ dlen = sizeof(debug_buf);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ while (reg->name) {
+ data = readl((u32)base + reg->off);
+ len = snprintf(bp, dlen, "%s:0x%08x\t\t= 0x%08x\n",
+ reg->name, reg->off, data);
+ tot += len;
+ bp += len;
+ dlen -= len;
+ reg++;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ *bp = 0;
+ tot++;
+
+ return tot;
+}
+
+static ssize_t pmdh_reg_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ uint32 off, data;
+ int cnt;
+
+ if (count >= sizeof(debug_buf))
+ return -EFAULT;
+
+ if (copy_from_user(debug_buf, buff, count))
+ return -EFAULT;
+
+ debug_buf[count] = 0; /* end of string */
+
+ cnt = sscanf(debug_buf, "%x %x", &off, &data);
+
+ mddi_reg_write(0, off, data);
+
+ return count;
+}
+
+static ssize_t pmdh_reg_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int tot = 0;
+
+ if (*ppos)
+ return 0; /* the end */
+
+ tot = mddi_reg_read(0); /* pmdh */
+
+ if (tot < 0)
+ return 0;
+ if (copy_to_user(buff, debug_buf, tot))
+ return -EFAULT;
+
+ *ppos += tot; /* increase offset */
+
+ return tot;
+}
+
+
+static const struct file_operations pmdh_fops = {
+ .open = mddi_reg_open,
+ .release = mddi_reg_release,
+ .read = pmdh_reg_read,
+ .write = pmdh_reg_write,
+};
+
+
+
+#if defined(CONFIG_FB_MSM_OVERLAY) && defined(CONFIG_FB_MSM_MDDI)
+static int vsync_reg_open(struct inode *inode, struct file *file)
+{
+ /* non-seekable */
+ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+ return 0;
+}
+
+static int vsync_reg_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static ssize_t vsync_reg_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ uint32 enable;
+ int cnt;
+
+ if (count >= sizeof(debug_buf))
+ return -EFAULT;
+
+ if (copy_from_user(debug_buf, buff, count))
+ return -EFAULT;
+
+ debug_buf[count] = 0; /* end of string */
+
+ cnt = sscanf(debug_buf, "%x", &enable);
+
+ mdp_dmap_vsync_set(enable);
+
+ return count;
+}
+
+static ssize_t vsync_reg_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ char *bp;
+ int len = 0;
+ int tot = 0;
+ int dlen;
+
+ if (*ppos)
+ return 0; /* the end */
+
+ bp = debug_buf;
+ dlen = sizeof(debug_buf);
+ len = snprintf(bp, dlen, "%x\n", mdp_dmap_vsync_get());
+ tot += len;
+ bp += len;
+ *bp = 0;
+ tot++;
+
+ if (copy_to_user(buff, debug_buf, tot))
+ return -EFAULT;
+
+ *ppos += tot; /* increase offset */
+
+ return tot;
+}
+
+
+static const struct file_operations vsync_fops = {
+ .open = vsync_reg_open,
+ .release = vsync_reg_release,
+ .read = vsync_reg_read,
+ .write = vsync_reg_write,
+};
+#endif
+
+static ssize_t emdh_reg_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ uint32 off, data;
+ int cnt;
+
+ if (count >= sizeof(debug_buf))
+ return -EFAULT;
+
+ if (copy_from_user(debug_buf, buff, count))
+ return -EFAULT;
+
+ debug_buf[count] = 0; /* end of string */
+
+ cnt = sscanf(debug_buf, "%x %x", &off, &data);
+
+ mddi_reg_write(1, off, data);
+
+ return count;
+}
+
+static ssize_t emdh_reg_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int tot = 0;
+
+ if (*ppos)
+ return 0; /* the end */
+
+ tot = mddi_reg_read(1); /* emdh */
+
+ if (tot < 0)
+ return 0;
+ if (copy_to_user(buff, debug_buf, tot))
+ return -EFAULT;
+
+ *ppos += tot; /* increase offset */
+
+ return tot;
+}
+
+static const struct file_operations emdh_fops = {
+ .open = mddi_reg_open,
+ .release = mddi_reg_release,
+ .read = emdh_reg_read,
+ .write = emdh_reg_write,
+};
+
+
+uint32 dbg_offset;
+uint32 dbg_count;
+char *dbg_base;
+
+
+static int dbg_open(struct inode *inode, struct file *file)
+{
+ /* non-seekable */
+ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+ return 0;
+}
+
+static int dbg_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static ssize_t dbg_base_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ return count;
+}
+
+static ssize_t dbg_base_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int len = 0;
+ int tot = 0;
+ int dlen;
+ char *bp;
+
+
+ if (*ppos)
+ return 0; /* the end */
+
+
+ bp = debug_buf;
+ dlen = sizeof(debug_buf);
+
+ len = snprintf(bp, dlen, "mdp_base : %08x\n",
+ (int)msm_mdp_base);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "mddi_base : %08x\n",
+ (int)msm_pmdh_base);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "emdh_base : %08x\n",
+ (int)msm_emdh_base);
+ bp += len;
+ dlen -= len;
+#ifdef CONFIG_FB_MSM_TVOUT
+ len = snprintf(bp, dlen, "tvenv_base: %08x\n",
+ (int)tvenc_base);
+ bp += len;
+ dlen -= len;
+#endif
+
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+ len = snprintf(bp, dlen, "mipi_dsi_base: %08x\n",
+ (int)mipi_dsi_base);
+ bp += len;
+ dlen -= len;
+#endif
+
+ tot = (uint32)bp - (uint32)debug_buf;
+ *bp = 0;
+ tot++;
+
+ if (tot < 0)
+ return 0;
+ if (copy_to_user(buff, debug_buf, tot))
+ return -EFAULT;
+
+ *ppos += tot; /* increase offset */
+
+ return tot;
+}
+
+static const struct file_operations dbg_base_fops = {
+ .open = dbg_open,
+ .release = dbg_release,
+ .read = dbg_base_read,
+ .write = dbg_base_write,
+};
+
+static ssize_t dbg_offset_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ uint32 off, cnt, num, base;
+
+ if (count >= sizeof(debug_buf))
+ return -EFAULT;
+
+ if (copy_from_user(debug_buf, buff, count))
+ return -EFAULT;
+
+ debug_buf[count] = 0; /* end of string */
+
+ cnt = sscanf(debug_buf, "%x %d %x", &off, &num, &base);
+
+ if (cnt < 0)
+ cnt = 0;
+
+ if (cnt >= 1)
+ dbg_offset = off;
+ if (cnt >= 2)
+ dbg_count = num;
+ if (cnt >= 3)
+ dbg_base = (char *)base;
+
+ printk(KERN_INFO "%s: offset=%x cnt=%d base=%x\n", __func__,
+ dbg_offset, dbg_count, (int)dbg_base);
+
+ return count;
+}
+
+static ssize_t dbg_offset_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int len = 0;
+
+
+ if (*ppos)
+ return 0; /* the end */
+
+ len = snprintf(debug_buf, sizeof(debug_buf), "0x%08x %d 0x%08x\n",
+ dbg_offset, dbg_count, (int)dbg_base);
+ if (len < 0)
+ return 0;
+
+ if (copy_to_user(buff, debug_buf, len))
+ return -EFAULT;
+
+ *ppos += len; /* increase offset */
+
+ return len;
+}
+
+static const struct file_operations dbg_off_fops = {
+ .open = dbg_open,
+ .release = dbg_release,
+ .read = dbg_offset_read,
+ .write = dbg_offset_write,
+};
+
+
+static ssize_t dbg_reg_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ uint32 off, data;
+ int cnt;
+
+ if (count >= sizeof(debug_buf))
+ return -EFAULT;
+
+ if (copy_from_user(debug_buf, buff, count))
+ return -EFAULT;
+
+ debug_buf[count] = 0; /* end of string */
+
+ cnt = sscanf(debug_buf, "%x %x", &off, &data);
+
+ writel(data, dbg_base + off);
+
+ printk(KERN_INFO "%s: addr=%x data=%x\n",
+ __func__, (int)(dbg_base+off), (int)data);
+
+ return count;
+}
+
+static ssize_t dbg_reg_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int len = 0;
+ uint32 data;
+ int i, j, off, dlen, num;
+ char *bp, *cp;
+ int tot = 0;
+
+
+ if (*ppos)
+ return 0; /* the end */
+
+ if (dbg_base == 0)
+ return 0; /* nothing to read */
+
+ j = 0;
+ num = 0;
+ bp = debug_buf;
+ cp = (char *)(dbg_base + dbg_offset);
+ dlen = sizeof(debug_buf);
+ while (j++ < 16) {
+ len = snprintf(bp, dlen, "0x%08x: ", (int)cp);
+ tot += len;
+ bp += len;
+ dlen -= len;
+ off = 0;
+ i = 0;
+ while (i++ < 4) {
+ data = readl(cp + off);
+ len = snprintf(bp, dlen, "%08x ", data);
+ tot += len;
+ bp += len;
+ dlen -= len;
+ off += 4;
+ num++;
+ if (num >= dbg_count)
+ break;
+ }
+ data = readl((u32)cp + off);
+ *bp++ = '\n';
+ --dlen;
+ tot++;
+ cp += off;
+ if (num >= dbg_count)
+ break;
+ }
+ *bp = 0;
+ tot++;
+
+ if (copy_to_user(buff, debug_buf, tot))
+ return -EFAULT;
+
+ *ppos += tot; /* increase offset */
+
+ return tot;
+}
+
+
+static const struct file_operations dbg_reg_fops = {
+ .open = dbg_open,
+ .release = dbg_release,
+ .read = dbg_reg_read,
+ .write = dbg_reg_write,
+};
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+static uint32 hdmi_offset;
+static uint32 hdmi_count;
+
+static int hdmi_open(struct inode *inode, struct file *file)
+{
+ /* non-seekable */
+ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+ return 0;
+}
+
+static int hdmi_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static ssize_t hdmi_offset_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ uint32 off, cnt, num;
+
+ if (count >= sizeof(debug_buf))
+ return -EFAULT;
+
+ if (copy_from_user(debug_buf, buff, count))
+ return -EFAULT;
+
+ debug_buf[count] = 0; /* end of string */
+
+ cnt = sscanf(debug_buf, "%x %d", &off, &num);
+
+ if (cnt < 0)
+ cnt = 0;
+
+ if (cnt >= 1)
+ hdmi_offset = off;
+ if (cnt >= 2)
+ hdmi_count = num;
+
+ printk(KERN_INFO "%s: offset=%x cnt=%d\n", __func__,
+ hdmi_offset, hdmi_count);
+
+ return count;
+}
+
+static ssize_t hdmi_offset_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int len = 0;
+
+
+ if (*ppos)
+ return 0; /* the end */
+
+ len = snprintf(debug_buf, sizeof(debug_buf), "0x%08x %d\n",
+ hdmi_offset, hdmi_count);
+ if (len < 0)
+ return 0;
+
+ if (copy_to_user(buff, debug_buf, len))
+ return -EFAULT;
+
+ *ppos += len; /* increase offset */
+
+ return len;
+}
+
+static const struct file_operations hdmi_off_fops = {
+ .open = hdmi_open,
+ .release = hdmi_release,
+ .read = hdmi_offset_read,
+ .write = hdmi_offset_write,
+};
+
+
+static ssize_t hdmi_reg_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ uint32 off, data, base;
+ int cnt;
+
+ if (count >= sizeof(debug_buf))
+ return -EFAULT;
+
+ if (copy_from_user(debug_buf, buff, count))
+ return -EFAULT;
+
+ base = hdmi_msm_get_io_base();
+ if (base == 0)
+ return -EFAULT;
+
+ debug_buf[count] = 0; /* end of string */
+
+ cnt = sscanf(debug_buf, "%x %x", &off, &data);
+
+ writel(data, base + off);
+
+ printk(KERN_INFO "%s: addr=%x data=%x\n",
+ __func__, (int)(base+off), (int)data);
+
+ return count;
+}
+
+static ssize_t hdmi_reg_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int len = 0;
+ uint32 data;
+ int i, j, off, dlen, num;
+ char *bp, *cp;
+ int tot = 0;
+
+
+ if (*ppos)
+ return 0; /* the end */
+
+ if (hdmi_msm_get_io_base() == 0)
+ return 0; /* nothing to read */
+
+ j = 0;
+ num = 0;
+ bp = debug_buf;
+ cp = (char *)(hdmi_msm_get_io_base() + hdmi_offset);
+ dlen = sizeof(debug_buf);
+ while (j++ < 16) {
+ len = snprintf(bp, dlen, "0x%08x: ", (int)cp);
+ tot += len;
+ bp += len;
+ dlen -= len;
+ off = 0;
+ i = 0;
+ while (i++ < 4) {
+ data = readl(cp + off);
+ len = snprintf(bp, dlen, "%08x ", data);
+ tot += len;
+ bp += len;
+ dlen -= len;
+ off += 4;
+ num++;
+ if (num >= hdmi_count)
+ break;
+ }
+ data = readl((u32)cp + off);
+ *bp++ = '\n';
+ --dlen;
+ tot++;
+ cp += off;
+ if (num >= hdmi_count)
+ break;
+ }
+ *bp = 0;
+ tot++;
+
+ if (copy_to_user(buff, debug_buf, tot))
+ return -EFAULT;
+
+ *ppos += tot; /* increase offset */
+
+ return tot;
+}
+
+
+static const struct file_operations hdmi_reg_fops = {
+ .open = hdmi_open,
+ .release = hdmi_release,
+ .read = hdmi_reg_read,
+ .write = hdmi_reg_write,
+};
+#endif
+
+/*
+ * debugfs
+ *
+ */
+
+int mdp_debugfs_init(void)
+{
+ struct dentry *dent = debugfs_create_dir("mdp", NULL);
+
+ if (IS_ERR(dent)) {
+ printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
+ __FILE__, __LINE__, PTR_ERR(dent));
+ return -1;
+ }
+
+ if (debugfs_create_file("off", 0644, dent, 0, &mdp_off_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: index fail\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+
+ if (debugfs_create_file("reg", 0644, dent, 0, &mdp_reg_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+
+#ifdef CONFIG_FB_MSM_MDP40
+ if (debugfs_create_file("stat", 0644, dent, 0, &mdp_stat_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+#endif
+
+ dent = debugfs_create_dir("mddi", NULL);
+
+ if (IS_ERR(dent)) {
+ printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
+ __FILE__, __LINE__, PTR_ERR(dent));
+ return -1;
+ }
+
+ if (debugfs_create_file("reg", 0644, dent, 0, &pmdh_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+
+#if defined(CONFIG_FB_MSM_OVERLAY) && defined(CONFIG_FB_MSM_MDDI)
+ if (debugfs_create_file("vsync", 0644, dent, 0, &vsync_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+#endif
+
+ dent = debugfs_create_dir("emdh", NULL);
+
+ if (IS_ERR(dent)) {
+ printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
+ __FILE__, __LINE__, PTR_ERR(dent));
+ return -1;
+ }
+
+ if (debugfs_create_file("reg", 0644, dent, 0, &emdh_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+
+ dent = debugfs_create_dir("mdp-dbg", NULL);
+
+ if (IS_ERR(dent)) {
+ printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
+ __FILE__, __LINE__, PTR_ERR(dent));
+ return -1;
+ }
+
+ if (debugfs_create_file("base", 0644, dent, 0, &dbg_base_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: index fail\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+
+ if (debugfs_create_file("off", 0644, dent, 0, &dbg_off_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: index fail\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+
+ if (debugfs_create_file("reg", 0644, dent, 0, &dbg_reg_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+ dent = debugfs_create_dir("hdmi", NULL);
+
+ if (IS_ERR(dent)) {
+ printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
+ __FILE__, __LINE__, PTR_ERR(dent));
+ return PTR_ERR(dent);
+ }
+
+ if (debugfs_create_file("off", 0644, dent, 0, &hdmi_off_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: 'off' fail\n",
+ __FILE__, __LINE__);
+ return -ENOENT;
+ }
+
+ if (debugfs_create_file("reg", 0644, dent, 0, &hdmi_reg_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: 'reg' fail\n",
+ __FILE__, __LINE__);
+ return -ENOENT;
+ }
+#endif
+
+ return 0;
+}
diff --git a/drivers/video/msm/mdp_dma.c b/drivers/video/msm/mdp_dma.c
new file mode 100644
index 0000000..a78c0db
--- /dev/null
+++ b/drivers/video/msm/mdp_dma.c
@@ -0,0 +1,602 @@
+/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mddihost.h"
+
+static uint32 mdp_last_dma2_update_width;
+static uint32 mdp_last_dma2_update_height;
+static uint32 mdp_curr_dma2_update_width;
+static uint32 mdp_curr_dma2_update_height;
+
+ktime_t mdp_dma2_last_update_time = { 0 };
+
+int mdp_lcd_rd_cnt_offset_slow = 20;
+int mdp_lcd_rd_cnt_offset_fast = 20;
+int mdp_vsync_usec_wait_line_too_short = 5;
+uint32 mdp_dma2_update_time_in_usec;
+uint32 mdp_total_vdopkts;
+
+extern u32 msm_fb_debug_enabled;
+extern struct workqueue_struct *mdp_dma_wq;
+
+int vsync_start_y_adjust = 4;
+
+static void mdp_dma2_update_lcd(struct msm_fb_data_type *mfd)
+{
+ MDPIBUF *iBuf = &mfd->ibuf;
+ int mddi_dest = FALSE;
+ int cmd_mode = FALSE;
+ uint32 outBpp = iBuf->bpp;
+ uint32 dma2_cfg_reg;
+ uint8 *src;
+ uint32 mddi_ld_param;
+ uint16 mddi_vdo_packet_reg;
+#ifndef CONFIG_FB_MSM_MDP303
+ struct msm_fb_panel_data *pdata =
+ (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+#endif
+ uint32 ystride = mfd->fbi->fix.line_length;
+ uint32 mddi_pkt_desc;
+
+ dma2_cfg_reg = DMA_PACK_ALIGN_LSB |
+ DMA_OUT_SEL_AHB | DMA_IBUF_NONCONTIGUOUS;
+
+#ifdef CONFIG_FB_MSM_MDP22
+ dma2_cfg_reg |= DMA_PACK_TIGHT;
+#endif
+
+#ifdef CONFIG_FB_MSM_MDP30
+ /*
+ * Software workaround: On 7x25/7x27, the MDP will not
+ * respond if dma_w is 1 pixel. Set the update width to
+ * 2 pixels and adjust the x offset if needed.
+ */
+ if (iBuf->dma_w == 1) {
+ iBuf->dma_w = 2;
+ if (iBuf->dma_x == (iBuf->ibuf_width - 2))
+ iBuf->dma_x--;
+ }
+#endif
+
+ if (mfd->fb_imgType == MDP_BGR_565)
+ dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
+ else if (mfd->fb_imgType == MDP_RGBA_8888)
+ dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
+ else
+ dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
+
+ if (outBpp == 4) {
+ dma2_cfg_reg |= DMA_IBUF_C3ALPHA_EN;
+ dma2_cfg_reg |= DMA_IBUF_FORMAT_xRGB8888_OR_ARGB8888;
+ }
+
+ if (outBpp == 2)
+ dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
+
+ mddi_ld_param = 0;
+ mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt;
+
+ if ((mfd->panel_info.type == MDDI_PANEL) ||
+ (mfd->panel_info.type == EXT_MDDI_PANEL)) {
+ dma2_cfg_reg |= DMA_OUT_SEL_MDDI;
+ mddi_dest = TRUE;
+
+ if (mfd->panel_info.type == MDDI_PANEL) {
+ mdp_total_vdopkts++;
+ if (mfd->panel_info.pdest == DISPLAY_1) {
+ dma2_cfg_reg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
+ mddi_ld_param = 0;
+#ifdef MDDI_HOST_WINDOW_WORKAROUND
+ mddi_window_adjust(mfd, iBuf->dma_x,
+ iBuf->dma_w - 1, iBuf->dma_y,
+ iBuf->dma_h - 1);
+#endif
+ } else {
+ dma2_cfg_reg |=
+ DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY;
+ mddi_ld_param = 1;
+#ifdef MDDI_HOST_WINDOW_WORKAROUND
+ mddi_window_adjust(mfd, iBuf->dma_x,
+ iBuf->dma_w - 1, iBuf->dma_y,
+ iBuf->dma_h - 1);
+#endif
+ }
+ } else {
+ dma2_cfg_reg |= DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL;
+ mddi_ld_param = 2;
+ }
+#ifdef CONFIG_FB_MSM_MDP303
+ } else if (mfd->panel_info.type == MIPI_CMD_PANEL) {
+ cmd_mode = TRUE;
+ dma2_cfg_reg |= DMA_OUT_SEL_DSI_CMD;
+#endif
+ } else {
+ if (mfd->panel_info.pdest == DISPLAY_1) {
+ dma2_cfg_reg |= DMA_AHBM_LCD_SEL_PRIMARY;
+ outp32(MDP_EBI2_LCD0, mfd->data_port_phys);
+ } else {
+ dma2_cfg_reg |= DMA_AHBM_LCD_SEL_SECONDARY;
+ outp32(MDP_EBI2_LCD1, mfd->data_port_phys);
+ }
+ }
+
+ src = (uint8 *) iBuf->buf;
+ /* starting input address */
+ src += iBuf->dma_x * outBpp + iBuf->dma_y * ystride;
+
+ mdp_curr_dma2_update_width = iBuf->dma_w;
+ mdp_curr_dma2_update_height = iBuf->dma_h;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+#ifdef CONFIG_FB_MSM_MDP22
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0184,
+ (iBuf->dma_h << 16 | iBuf->dma_w));
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0188, src);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x018C, ystride);
+#else
+ if (cmd_mode)
+ MDP_OUTP(MDP_BASE + 0x90004,
+ (mfd->panel_info.yres << 16 | mfd->panel_info.xres));
+ else
+ MDP_OUTP(MDP_BASE + 0x90004, (iBuf->dma_h << 16 | iBuf->dma_w));
+
+ MDP_OUTP(MDP_BASE + 0x90008, src);
+ MDP_OUTP(MDP_BASE + 0x9000c, ystride);
+#endif
+
+ if (mfd->panel_info.bpp == 18) {
+ mddi_pkt_desc = MDDI_VDO_PACKET_DESC;
+ dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */
+ DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+ } else if (mfd->panel_info.bpp == 24) {
+ mddi_pkt_desc = MDDI_VDO_PACKET_DESC_24;
+ dma2_cfg_reg |= DMA_DSTC0G_8BITS | /* 888 24BPP */
+ DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
+ } else {
+ mddi_pkt_desc = MDDI_VDO_PACKET_DESC_16;
+ dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */
+ DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
+ }
+
+#ifndef CONFIG_FB_MSM_MDP303
+
+ if (mddi_dest) {
+#ifdef CONFIG_FB_MSM_MDP22
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0194,
+ (iBuf->dma_y << 16) | iBuf->dma_x);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01a0, mddi_ld_param);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01a4,
+ (mddi_pkt_desc << 16) | mddi_vdo_packet_reg);
+#else
+ MDP_OUTP(MDP_BASE + 0x90010, (iBuf->dma_y << 16) | iBuf->dma_x);
+ MDP_OUTP(MDP_BASE + 0x00090, mddi_ld_param);
+ MDP_OUTP(MDP_BASE + 0x00094,
+ (mddi_pkt_desc << 16) | mddi_vdo_packet_reg);
+#endif
+ } else {
+ /* setting EBI2 LCDC write window */
+ pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w,
+ iBuf->dma_h);
+ }
+#else
+ if (mfd->panel_info.type == MIPI_CMD_PANEL) {
+ /* dma_p = 0, dma_s = 1 */
+ MDP_OUTP(MDP_BASE + 0xF1000, 0x10);
+ /* enable dsi trigger on dma_p */
+ MDP_OUTP(MDP_BASE + 0xF1004, 0x01);
+ }
+#endif
+
+ /* dma2 config register */
+#ifdef MDP_HW_VSYNC
+ MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
+
+ if ((mfd->use_mdp_vsync) &&
+ (mfd->ibuf.vsync_enable) && (mfd->panel_info.lcd.vsync_enable)) {
+ uint32 start_y;
+
+ if (vsync_start_y_adjust <= iBuf->dma_y)
+ start_y = iBuf->dma_y - vsync_start_y_adjust;
+ else
+ start_y =
+ (mfd->total_lcd_lines - 1) - (vsync_start_y_adjust -
+ iBuf->dma_y);
+
+ /*
+ * MDP VSYNC clock must be On by now so, we don't have to
+ * re-enable it
+ */
+ MDP_OUTP(MDP_BASE + 0x210, start_y);
+ MDP_OUTP(MDP_BASE + 0x20c, 1); /* enable prim vsync */
+ } else {
+ MDP_OUTP(MDP_BASE + 0x20c, 0); /* disable prim vsync */
+ }
+#else
+#ifdef CONFIG_FB_MSM_MDP22
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0180, dma2_cfg_reg);
+#else
+ MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
+#endif
+#endif /* MDP_HW_VSYNC */
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+static ktime_t vt = { 0 };
+int mdp_usec_diff_threshold = 100;
+int mdp_expected_usec_wait;
+
+enum hrtimer_restart mdp_dma2_vsync_hrtimer_handler(struct hrtimer *ht)
+{
+ struct msm_fb_data_type *mfd = NULL;
+
+ mfd = container_of(ht, struct msm_fb_data_type, dma_hrtimer);
+
+ mdp_pipe_kickoff(MDP_DMA2_TERM, mfd);
+
+ if (msm_fb_debug_enabled) {
+ ktime_t t;
+ int usec_diff;
+ int actual_wait;
+
+ t = ktime_get_real();
+
+ actual_wait = ktime_to_us(ktime_sub(t, vt));
+ usec_diff = actual_wait - mdp_expected_usec_wait;
+
+ if ((mdp_usec_diff_threshold < usec_diff) || (usec_diff < 0))
+ MSM_FB_DEBUG
+ ("HRT Diff = %d usec Exp=%d usec Act=%d usec\n",
+ usec_diff, mdp_expected_usec_wait, actual_wait);
+ }
+
+ return HRTIMER_NORESTART;
+}
+
+
+#ifdef CONFIG_FB_MSM_MDP303
+static int busy_wait_cnt;
+
+void mdp3_dsi_cmd_dma_busy_wait(struct msm_fb_data_type *mfd)
+{
+ unsigned long flag;
+ int need_wait = 0;
+
+#ifdef DSI_CLK_CTRL
+ mod_timer(&dsi_clock_timer, jiffies + HZ); /* one second */
+#endif
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+#ifdef DSI_CLK_CTRL
+ if (mipi_dsi_clk_on == 0)
+ mipi_dsi_clk_enable();
+#endif
+
+ if (mfd->dma->busy == TRUE) {
+ if (busy_wait_cnt == 0)
+ INIT_COMPLETION(mfd->dma->comp);
+ busy_wait_cnt++;
+ need_wait++;
+ }
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+ if (need_wait) {
+ /* wait until DMA finishes the current job */
+ wait_for_completion(&mfd->dma->comp);
+ }
+}
+#endif
+
+static void mdp_dma_schedule(struct msm_fb_data_type *mfd, uint32 term)
+{
+ /*
+ * dma2 configure VSYNC block
+ * vsync supported on Primary LCD only for now
+ */
+ int32 mdp_lcd_rd_cnt;
+ uint32 usec_wait_time;
+ uint32 start_y;
+
+ /*
+ * ToDo: if we can move HRT timer callback to workqueue, we can
+ * move DMA2 power on under mdp_pipe_kickoff().
+ * This will save a power for hrt time wait.
+ * However if the latency for context switch (hrt irq -> workqueue)
+ * is too big, we will miss the vsync timing.
+ */
+ if (term == MDP_DMA2_TERM)
+ mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ mdp_dma2_update_time_in_usec = ktime_to_us(mdp_dma2_last_update_time);
+
+ if ((!mfd->ibuf.vsync_enable) || (!mfd->panel_info.lcd.vsync_enable)
+ || (mfd->use_mdp_vsync)) {
+ mdp_pipe_kickoff(term, mfd);
+ return;
+ }
+ /* SW vsync logic starts here */
+
+ /* get current rd counter */
+ mdp_lcd_rd_cnt = mdp_get_lcd_line_counter(mfd);
+ if (mdp_dma2_update_time_in_usec != 0) {
+ uint32 num, den;
+
+ /*
+ * roi width boundary calculation to know the size of pixel
+ * width that MDP can send faster or slower than LCD read
+ * pointer
+ */
+
+ num = mdp_last_dma2_update_width * mdp_last_dma2_update_height;
+ den =
+ (((mfd->panel_info.lcd.refx100 * mfd->total_lcd_lines) /
+ 1000) * (mdp_dma2_update_time_in_usec / 100)) / 1000;
+
+ if (den == 0)
+ mfd->vsync_width_boundary[mdp_last_dma2_update_width] =
+ mfd->panel_info.xres + 1;
+ else
+ mfd->vsync_width_boundary[mdp_last_dma2_update_width] =
+ (int)(num / den);
+ }
+
+ if (mfd->vsync_width_boundary[mdp_last_dma2_update_width] >
+ mdp_curr_dma2_update_width) {
+ /* MDP wrp is faster than LCD rdp */
+ mdp_lcd_rd_cnt += mdp_lcd_rd_cnt_offset_fast;
+ } else {
+ /* MDP wrp is slower than LCD rdp */
+ mdp_lcd_rd_cnt -= mdp_lcd_rd_cnt_offset_slow;
+ }
+
+ if (mdp_lcd_rd_cnt < 0)
+ mdp_lcd_rd_cnt = mfd->total_lcd_lines + mdp_lcd_rd_cnt;
+ else if (mdp_lcd_rd_cnt > mfd->total_lcd_lines)
+ mdp_lcd_rd_cnt = mdp_lcd_rd_cnt - mfd->total_lcd_lines - 1;
+
+ /* get wrt pointer position */
+ start_y = mfd->ibuf.dma_y;
+
+ /* measure line difference between start_y and rd counter */
+ if (start_y > mdp_lcd_rd_cnt) {
+ /*
+ * *100 for lcd_ref_hzx100 was already multiplied by 100
+ * *1000000 is for usec conversion
+ */
+
+ if ((start_y - mdp_lcd_rd_cnt) <=
+ mdp_vsync_usec_wait_line_too_short)
+ usec_wait_time = 0;
+ else
+ usec_wait_time =
+ ((start_y -
+ mdp_lcd_rd_cnt) * 1000000) /
+ ((mfd->total_lcd_lines *
+ mfd->panel_info.lcd.refx100) / 100);
+ } else {
+ if ((start_y + (mfd->total_lcd_lines - mdp_lcd_rd_cnt)) <=
+ mdp_vsync_usec_wait_line_too_short)
+ usec_wait_time = 0;
+ else
+ usec_wait_time =
+ ((start_y +
+ (mfd->total_lcd_lines -
+ mdp_lcd_rd_cnt)) * 1000000) /
+ ((mfd->total_lcd_lines *
+ mfd->panel_info.lcd.refx100) / 100);
+ }
+
+ mdp_last_dma2_update_width = mdp_curr_dma2_update_width;
+ mdp_last_dma2_update_height = mdp_curr_dma2_update_height;
+
+ if (usec_wait_time == 0) {
+ mdp_pipe_kickoff(term, mfd);
+ } else {
+ ktime_t wait_time;
+
+ wait_time = ns_to_ktime(usec_wait_time * 1000);
+
+ if (msm_fb_debug_enabled) {
+ vt = ktime_get_real();
+ mdp_expected_usec_wait = usec_wait_time;
+ }
+ hrtimer_start(&mfd->dma_hrtimer, wait_time, HRTIMER_MODE_REL);
+ }
+}
+
+#ifdef MDDI_HOST_WINDOW_WORKAROUND
+static void mdp_dma2_update_sub(struct msm_fb_data_type *mfd);
+void mdp_dma2_update(struct msm_fb_data_type *mfd)
+{
+ MDPIBUF *iBuf;
+ uint32 upper_height;
+
+ if (mfd->panel.type == EXT_MDDI_PANEL) {
+ mdp_dma2_update_sub(mfd);
+ return;
+ }
+
+ iBuf = &mfd->ibuf;
+
+ upper_height =
+ (uint32) mddi_assign_pkt_height((uint16) iBuf->dma_w,
+ (uint16) iBuf->dma_h, 18);
+
+ if (upper_height >= iBuf->dma_h) {
+ mdp_dma2_update_sub(mfd);
+ } else {
+ uint32 lower_height;
+
+ /* sending the upper region first */
+ lower_height = iBuf->dma_h - upper_height;
+ iBuf->dma_h = upper_height;
+ mdp_dma2_update_sub(mfd);
+
+ /* sending the lower region second */
+ iBuf->dma_h = lower_height;
+ iBuf->dma_y += lower_height;
+ iBuf->vsync_enable = FALSE;
+ mdp_dma2_update_sub(mfd);
+ }
+}
+
+static void mdp_dma2_update_sub(struct msm_fb_data_type *mfd)
+#else
+void mdp_dma2_update(struct msm_fb_data_type *mfd)
+#endif
+{
+ down(&mfd->dma->mutex);
+ if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
+ down(&mfd->sem);
+ mfd->ibuf_flushed = TRUE;
+ mdp_dma2_update_lcd(mfd);
+
+ mdp_enable_irq(MDP_DMA2_TERM);
+ mfd->dma->busy = TRUE;
+ INIT_COMPLETION(mfd->dma->comp);
+
+ /* schedule DMA to start */
+ mdp_dma_schedule(mfd, MDP_DMA2_TERM);
+ up(&mfd->sem);
+
+ /* wait until DMA finishes the current job */
+ wait_for_completion_killable(&mfd->dma->comp);
+ mdp_disable_irq(MDP_DMA2_TERM);
+
+ /* signal if pan function is waiting for the update completion */
+ if (mfd->pan_waiting) {
+ mfd->pan_waiting = FALSE;
+ complete(&mfd->pan_comp);
+ }
+ }
+ up(&mfd->dma->mutex);
+}
+
+void mdp_lcd_update_workqueue_handler(struct work_struct *work)
+{
+ struct msm_fb_data_type *mfd = NULL;
+
+ mfd = container_of(work, struct msm_fb_data_type, dma_update_worker);
+ if (mfd)
+ mfd->dma_fnc(mfd);
+}
+
+void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty,
+ boolean sync)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ MDPIBUF *iBuf;
+ int bpp = info->var.bits_per_pixel / 8;
+
+ down(&mfd->sem);
+ iBuf = &mfd->ibuf;
+ iBuf->buf = (uint8 *) info->fix.smem_start;
+ iBuf->buf += info->var.xoffset * bpp +
+ info->var.yoffset * info->fix.line_length;
+
+ iBuf->ibuf_width = info->var.xres_virtual;
+ iBuf->bpp = bpp;
+
+ iBuf->vsync_enable = sync;
+
+ if (dirty) {
+ /*
+ * ToDo: dirty region check inside var.xoffset+xres
+ * <-> var.yoffset+yres
+ */
+ iBuf->dma_x = dirty->xoffset % info->var.xres;
+ iBuf->dma_y = dirty->yoffset % info->var.yres;
+ iBuf->dma_w = dirty->width;
+ iBuf->dma_h = dirty->height;
+ } else {
+ iBuf->dma_x = 0;
+ iBuf->dma_y = 0;
+ iBuf->dma_w = info->var.xres;
+ iBuf->dma_h = info->var.yres;
+ }
+ mfd->ibuf_flushed = FALSE;
+ up(&mfd->sem);
+}
+
+void mdp_dma_pan_update(struct fb_info *info)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ MDPIBUF *iBuf;
+
+ iBuf = &mfd->ibuf;
+
+ if (mfd->sw_currently_refreshing) {
+ /* we need to wait for the pending update */
+ mfd->pan_waiting = TRUE;
+ if (!mfd->ibuf_flushed) {
+ wait_for_completion_killable(&mfd->pan_comp);
+ }
+ /* waiting for this update to complete */
+ mfd->pan_waiting = TRUE;
+ wait_for_completion_killable(&mfd->pan_comp);
+ } else
+ mfd->dma_fnc(mfd);
+}
+
+void mdp_refresh_screen(unsigned long data)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
+
+ if ((mfd->sw_currently_refreshing) && (mfd->sw_refreshing_enable)) {
+ init_timer(&mfd->refresh_timer);
+ mfd->refresh_timer.function = mdp_refresh_screen;
+ mfd->refresh_timer.data = data;
+
+ if (mfd->dma->busy)
+ /* come back in 1 msec */
+ mfd->refresh_timer.expires = jiffies + (HZ / 1000);
+ else
+ mfd->refresh_timer.expires =
+ jiffies + mfd->refresh_timer_duration;
+
+ add_timer(&mfd->refresh_timer);
+
+ if (!mfd->dma->busy) {
+ if (!queue_work(mdp_dma_wq, &mfd->dma_update_worker)) {
+ MSM_FB_DEBUG("mdp_dma: can't queue_work! -> \
+ MDP/MDDI/LCD clock speed needs to be increased\n");
+ }
+ }
+ } else {
+ if (!mfd->hw_refresh)
+ complete(&mfd->refresher_comp);
+ }
+}
diff --git a/drivers/video/msm/mdp_dma_dsi_video.c b/drivers/video/msm/mdp_dma_dsi_video.c
new file mode 100644
index 0000000..505eb74
--- /dev/null
+++ b/drivers/video/msm/mdp_dma_dsi_video.c
@@ -0,0 +1,270 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+#include <linux/fb.h>
+#include <asm/system.h>
+#include <mach/hardware.h>
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+#define DSI_VIDEO_BASE 0xF0000
+#define DMA_P_BASE 0x90000
+
+static int first_pixel_start_x;
+static int first_pixel_start_y;
+
+int mdp_dsi_video_on(struct platform_device *pdev)
+{
+ int dsi_width;
+ int dsi_height;
+ int dsi_bpp;
+ int dsi_border_clr;
+ int dsi_underflow_clr;
+ int dsi_hsync_skew;
+
+ int hsync_period;
+ int hsync_ctrl;
+ int vsync_period;
+ int display_hctl;
+ int display_v_start;
+ int display_v_end;
+ int active_hctl;
+ int active_h_start;
+ int active_h_end;
+ int active_v_start;
+ int active_v_end;
+ int ctrl_polarity;
+ int h_back_porch;
+ int h_front_porch;
+ int v_back_porch;
+ int v_front_porch;
+ int hsync_pulse_width;
+ int vsync_pulse_width;
+ int hsync_polarity;
+ int vsync_polarity;
+ int data_en_polarity;
+ int hsync_start_x;
+ int hsync_end_x;
+ uint8 *buf;
+ uint32 dma2_cfg_reg;
+
+ int bpp;
+ struct fb_info *fbi;
+ struct fb_var_screeninfo *var;
+ struct msm_fb_data_type *mfd;
+ int ret;
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ fbi = mfd->fbi;
+ var = &fbi->var;
+
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf += fbi->var.xoffset * bpp +
+ fbi->var.yoffset * fbi->fix.line_length;
+
+ dma2_cfg_reg = DMA_PACK_ALIGN_LSB | DMA_OUT_SEL_DSI_VIDEO;
+
+ if (mfd->fb_imgType == MDP_BGR_565)
+ dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
+ else if (mfd->fb_imgType == MDP_RGBA_8888)
+ dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
+ else
+ dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
+
+ if (bpp == 2)
+ dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
+ else if (bpp == 3)
+ dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB888;
+ else
+ dma2_cfg_reg |= DMA_IBUF_FORMAT_xRGB8888_OR_ARGB8888;
+
+ switch (mfd->panel_info.bpp) {
+ case 24:
+ dma2_cfg_reg |= DMA_DSTC0G_8BITS |
+ DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
+ break;
+ case 18:
+ dma2_cfg_reg |= DMA_DSTC0G_6BITS |
+ DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+ break;
+ case 16:
+ dma2_cfg_reg |= DMA_DSTC0G_6BITS |
+ DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
+ break;
+ default:
+ printk(KERN_ERR "mdp lcdc can't support format %d bpp!\n",
+ mfd->panel_info.bpp);
+ return -ENODEV;
+ }
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ /* starting address */
+ MDP_OUTP(MDP_BASE + DMA_P_BASE + 0x8, (uint32) buf);
+
+ /* active window width and height */
+ MDP_OUTP(MDP_BASE + DMA_P_BASE + 0x4, ((fbi->var.yres) << 16) |
+ (fbi->var.xres));
+
+ /* buffer ystride */
+ MDP_OUTP(MDP_BASE + DMA_P_BASE + 0xc, fbi->fix.line_length);
+
+ /* x/y coordinate = always 0 for lcdc */
+ MDP_OUTP(MDP_BASE + DMA_P_BASE + 0x10, 0);
+
+ /* dma config */
+ MDP_OUTP(MDP_BASE + DMA_P_BASE, dma2_cfg_reg);
+
+ /*
+ * DSI timing setting
+ */
+ h_back_porch = var->left_margin;
+ h_front_porch = var->right_margin;
+ v_back_porch = var->upper_margin;
+ v_front_porch = var->lower_margin;
+ hsync_pulse_width = var->hsync_len;
+ vsync_pulse_width = var->vsync_len;
+ dsi_border_clr = mfd->panel_info.lcdc.border_clr;
+ dsi_underflow_clr = mfd->panel_info.lcdc.underflow_clr;
+ dsi_hsync_skew = mfd->panel_info.lcdc.hsync_skew;
+ dsi_width = mfd->panel_info.xres;
+ dsi_height = mfd->panel_info.yres;
+ dsi_bpp = mfd->panel_info.bpp;
+ hsync_period = h_back_porch + dsi_width + h_front_porch + 1;
+ hsync_ctrl = (hsync_period << 16) | hsync_pulse_width;
+ hsync_start_x = h_back_porch;
+ hsync_end_x = dsi_width + h_back_porch - 1;
+ display_hctl = (hsync_end_x << 16) | hsync_start_x;
+
+ vsync_period =
+ (v_back_porch + dsi_height + v_front_porch + 1) * hsync_period;
+ display_v_start = v_back_porch * hsync_period + dsi_hsync_skew;
+ display_v_end = (dsi_height + v_back_porch) * hsync_period;
+
+ active_h_start = hsync_start_x + first_pixel_start_x;
+ active_h_end = active_h_start + var->xres - 1;
+ active_hctl = ACTIVE_START_X_EN |
+ (active_h_end << 16) | active_h_start;
+
+ active_v_start = display_v_start +
+ first_pixel_start_y * hsync_period;
+ active_v_end = active_v_start + (var->yres) * hsync_period - 1;
+ active_v_start |= ACTIVE_START_Y_EN;
+
+ dsi_underflow_clr |= 0x80000000; /* enable recovery */
+ hsync_polarity = 0;
+ vsync_polarity = 0;
+ data_en_polarity = 0;
+
+ ctrl_polarity = (data_en_polarity << 2) |
+ (vsync_polarity << 1) | (hsync_polarity);
+
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x4, hsync_ctrl);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x8, vsync_period);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0xc, vsync_pulse_width);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x10, display_hctl);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x14, display_v_start);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x18, display_v_end);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x1c, active_hctl);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x20, active_v_start);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x24, active_v_end);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x28, dsi_border_clr);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x2c, dsi_underflow_clr);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x30, dsi_hsync_skew);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x38, ctrl_polarity);
+
+ ret = panel_next_on(pdev);
+ if (ret == 0) {
+ /* enable DSI block */
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 1);
+ /*Turning on DMA_P block*/
+ mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ }
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ return ret;
+}
+
+int mdp_dsi_video_off(struct platform_device *pdev)
+{
+ int ret = 0;
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0);
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ /*Turning off DMA_P block*/
+ mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ ret = panel_next_off(pdev);
+ /* delay to make sure the last frame finishes */
+ msleep(20);
+
+ return ret;
+}
+
+void mdp_dsi_video_update(struct msm_fb_data_type *mfd)
+{
+ struct fb_info *fbi = mfd->fbi;
+ uint8 *buf;
+ int bpp;
+ unsigned long flag;
+ int irq_block = MDP_DMA2_TERM;
+
+ if (!mfd->panel_power_on)
+ return;
+
+ down(&mfd->dma->mutex);
+
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf += fbi->var.xoffset * bpp +
+ fbi->var.yoffset * fbi->fix.line_length;
+ /* no need to power on cmd block since it's dsi mode */
+ /* starting address */
+ MDP_OUTP(MDP_BASE + DMA_P_BASE + 0x8, (uint32) buf);
+ /* enable irq */
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_enable_irq(irq_block);
+ INIT_COMPLETION(mfd->dma->comp);
+ mfd->dma->waiting = TRUE;
+
+ outp32(MDP_INTR_CLEAR, LCDC_FRAME_START);
+ mdp_intr_mask |= LCDC_FRAME_START;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ wait_for_completion_killable(&mfd->dma->comp);
+ mdp_disable_irq(irq_block);
+ up(&mfd->dma->mutex);
+}
diff --git a/drivers/video/msm/mdp_dma_lcdc.c b/drivers/video/msm/mdp_dma_lcdc.c
new file mode 100644
index 0000000..9ce7e13
--- /dev/null
+++ b/drivers/video/msm/mdp_dma_lcdc.c
@@ -0,0 +1,368 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+#ifdef CONFIG_FB_MSM_MDP40
+#define LCDC_BASE 0xC0000
+#define DTV_BASE 0xD0000
+#define DMA_E_BASE 0xB0000
+#else
+#define LCDC_BASE 0xE0000
+#endif
+
+#define DMA_P_BASE 0x90000
+
+extern spinlock_t mdp_spin_lock;
+#ifndef CONFIG_FB_MSM_MDP40
+extern uint32 mdp_intr_mask;
+#endif
+
+int first_pixel_start_x;
+int first_pixel_start_y;
+
+int mdp_lcdc_on(struct platform_device *pdev)
+{
+ int lcdc_width;
+ int lcdc_height;
+ int lcdc_bpp;
+ int lcdc_border_clr;
+ int lcdc_underflow_clr;
+ int lcdc_hsync_skew;
+
+ int hsync_period;
+ int hsync_ctrl;
+ int vsync_period;
+ int display_hctl;
+ int display_v_start;
+ int display_v_end;
+ int active_hctl;
+ int active_h_start;
+ int active_h_end;
+ int active_v_start;
+ int active_v_end;
+ int ctrl_polarity;
+ int h_back_porch;
+ int h_front_porch;
+ int v_back_porch;
+ int v_front_porch;
+ int hsync_pulse_width;
+ int vsync_pulse_width;
+ int hsync_polarity;
+ int vsync_polarity;
+ int data_en_polarity;
+ int hsync_start_x;
+ int hsync_end_x;
+ uint8 *buf;
+ int bpp;
+ uint32 dma2_cfg_reg;
+ struct fb_info *fbi;
+ struct fb_var_screeninfo *var;
+ struct msm_fb_data_type *mfd;
+ uint32 dma_base;
+ uint32 timer_base = LCDC_BASE;
+ uint32 block = MDP_DMA2_BLOCK;
+ int ret;
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ fbi = mfd->fbi;
+ var = &fbi->var;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf += fbi->var.xoffset * bpp + fbi->var.yoffset * fbi->fix.line_length;
+
+ dma2_cfg_reg = DMA_PACK_ALIGN_LSB | DMA_OUT_SEL_LCDC;
+
+ if (mfd->fb_imgType == MDP_BGR_565)
+ dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
+ else if (mfd->fb_imgType == MDP_RGBA_8888)
+ dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
+ else
+ dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
+
+ if (bpp == 2)
+ dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
+ else if (bpp == 3)
+ dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB888;
+ else
+ dma2_cfg_reg |= DMA_IBUF_FORMAT_xRGB8888_OR_ARGB8888;
+
+ switch (mfd->panel_info.bpp) {
+ case 24:
+ dma2_cfg_reg |= DMA_DSTC0G_8BITS |
+ DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
+ break;
+
+ case 18:
+ dma2_cfg_reg |= DMA_DSTC0G_6BITS |
+ DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+ break;
+
+ case 16:
+ dma2_cfg_reg |= DMA_DSTC0G_6BITS |
+ DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
+ break;
+
+ default:
+ printk(KERN_ERR "mdp lcdc can't support format %d bpp!\n",
+ mfd->panel_info.bpp);
+ return -ENODEV;
+ }
+
+ /* DMA register config */
+
+ dma_base = DMA_P_BASE;
+
+#ifdef CONFIG_FB_MSM_MDP40
+ if (mfd->panel.type == HDMI_PANEL)
+ dma_base = DMA_E_BASE;
+#endif
+
+ /* starting address */
+ MDP_OUTP(MDP_BASE + dma_base + 0x8, (uint32) buf);
+ /* active window width and height */
+ MDP_OUTP(MDP_BASE + dma_base + 0x4, ((fbi->var.yres) << 16) |
+ (fbi->var.xres));
+ /* buffer ystride */
+ MDP_OUTP(MDP_BASE + dma_base + 0xc, fbi->fix.line_length);
+ /* x/y coordinate = always 0 for lcdc */
+ MDP_OUTP(MDP_BASE + dma_base + 0x10, 0);
+ /* dma config */
+ MDP_OUTP(MDP_BASE + dma_base, dma2_cfg_reg);
+
+ /*
+ * LCDC timing setting
+ */
+ h_back_porch = var->left_margin;
+ h_front_porch = var->right_margin;
+ v_back_porch = var->upper_margin;
+ v_front_porch = var->lower_margin;
+ hsync_pulse_width = var->hsync_len;
+ vsync_pulse_width = var->vsync_len;
+ lcdc_border_clr = mfd->panel_info.lcdc.border_clr;
+ lcdc_underflow_clr = mfd->panel_info.lcdc.underflow_clr;
+ lcdc_hsync_skew = mfd->panel_info.lcdc.hsync_skew;
+
+ lcdc_width = mfd->panel_info.xres;
+ lcdc_height = mfd->panel_info.yres;
+ lcdc_bpp = mfd->panel_info.bpp;
+
+ hsync_period =
+ hsync_pulse_width + h_back_porch + lcdc_width + h_front_porch;
+ hsync_ctrl = (hsync_period << 16) | hsync_pulse_width;
+ hsync_start_x = hsync_pulse_width + h_back_porch;
+ hsync_end_x = hsync_period - h_front_porch - 1;
+ display_hctl = (hsync_end_x << 16) | hsync_start_x;
+
+ vsync_period =
+ (vsync_pulse_width + v_back_porch + lcdc_height +
+ v_front_porch) * hsync_period;
+ display_v_start =
+ (vsync_pulse_width + v_back_porch) * hsync_period + lcdc_hsync_skew;
+ display_v_end =
+ vsync_period - (v_front_porch * hsync_period) + lcdc_hsync_skew - 1;
+
+ if (lcdc_width != var->xres) {
+ active_h_start = hsync_start_x + first_pixel_start_x;
+ active_h_end = active_h_start + var->xres - 1;
+ active_hctl =
+ ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start;
+ } else {
+ active_hctl = 0;
+ }
+
+ if (lcdc_height != var->yres) {
+ active_v_start =
+ display_v_start + first_pixel_start_y * hsync_period;
+ active_v_end = active_v_start + (var->yres) * hsync_period - 1;
+ active_v_start |= ACTIVE_START_Y_EN;
+ } else {
+ active_v_start = 0;
+ active_v_end = 0;
+ }
+
+
+#ifdef CONFIG_FB_MSM_MDP40
+ if (mfd->panel.type == HDMI_PANEL) {
+ block = MDP_DMA_E_BLOCK;
+ timer_base = DTV_BASE;
+ hsync_polarity = 0;
+ vsync_polarity = 0;
+ } else {
+ hsync_polarity = 1;
+ vsync_polarity = 1;
+ }
+
+ lcdc_underflow_clr |= 0x80000000; /* enable recovery */
+#else
+ hsync_polarity = 0;
+ vsync_polarity = 0;
+#endif
+ data_en_polarity = 0;
+
+ ctrl_polarity =
+ (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity);
+
+ MDP_OUTP(MDP_BASE + timer_base + 0x4, hsync_ctrl);
+ MDP_OUTP(MDP_BASE + timer_base + 0x8, vsync_period);
+ MDP_OUTP(MDP_BASE + timer_base + 0xc, vsync_pulse_width * hsync_period);
+ if (timer_base == LCDC_BASE) {
+ MDP_OUTP(MDP_BASE + timer_base + 0x10, display_hctl);
+ MDP_OUTP(MDP_BASE + timer_base + 0x14, display_v_start);
+ MDP_OUTP(MDP_BASE + timer_base + 0x18, display_v_end);
+ MDP_OUTP(MDP_BASE + timer_base + 0x28, lcdc_border_clr);
+ MDP_OUTP(MDP_BASE + timer_base + 0x2c, lcdc_underflow_clr);
+ MDP_OUTP(MDP_BASE + timer_base + 0x30, lcdc_hsync_skew);
+ MDP_OUTP(MDP_BASE + timer_base + 0x38, ctrl_polarity);
+ MDP_OUTP(MDP_BASE + timer_base + 0x1c, active_hctl);
+ MDP_OUTP(MDP_BASE + timer_base + 0x20, active_v_start);
+ MDP_OUTP(MDP_BASE + timer_base + 0x24, active_v_end);
+ } else {
+ MDP_OUTP(MDP_BASE + timer_base + 0x18, display_hctl);
+ MDP_OUTP(MDP_BASE + timer_base + 0x1c, display_v_start);
+ MDP_OUTP(MDP_BASE + timer_base + 0x20, display_v_end);
+ MDP_OUTP(MDP_BASE + timer_base + 0x40, lcdc_border_clr);
+ MDP_OUTP(MDP_BASE + timer_base + 0x44, lcdc_underflow_clr);
+ MDP_OUTP(MDP_BASE + timer_base + 0x48, lcdc_hsync_skew);
+ MDP_OUTP(MDP_BASE + timer_base + 0x50, ctrl_polarity);
+ MDP_OUTP(MDP_BASE + timer_base + 0x2c, active_hctl);
+ MDP_OUTP(MDP_BASE + timer_base + 0x30, active_v_start);
+ MDP_OUTP(MDP_BASE + timer_base + 0x38, active_v_end);
+ }
+
+ ret = panel_next_on(pdev);
+ if (ret == 0) {
+ /* enable LCDC block */
+ MDP_OUTP(MDP_BASE + timer_base, 1);
+ mdp_pipe_ctrl(block, MDP_BLOCK_POWER_ON, FALSE);
+ }
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ return ret;
+}
+
+int mdp_lcdc_off(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct msm_fb_data_type *mfd;
+ uint32 timer_base = LCDC_BASE;
+ uint32 block = MDP_DMA2_BLOCK;
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+#ifdef CONFIG_FB_MSM_MDP40
+ if (mfd->panel.type == HDMI_PANEL) {
+ block = MDP_DMA_E_BLOCK;
+ timer_base = DTV_BASE;
+ }
+#endif
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ MDP_OUTP(MDP_BASE + timer_base, 0);
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ mdp_pipe_ctrl(block, MDP_BLOCK_POWER_OFF, FALSE);
+
+ ret = panel_next_off(pdev);
+
+ /* delay to make sure the last frame finishes */
+ msleep(16);
+
+ return ret;
+}
+
+void mdp_lcdc_update(struct msm_fb_data_type *mfd)
+{
+ struct fb_info *fbi = mfd->fbi;
+ uint8 *buf;
+ int bpp;
+ unsigned long flag;
+ uint32 dma_base;
+ int irq_block = MDP_DMA2_TERM;
+#ifdef CONFIG_FB_MSM_MDP40
+ int intr = INTR_DMA_P_DONE;
+#endif
+
+ if (!mfd->panel_power_on)
+ return;
+
+ /* no need to power on cmd block since it's lcdc mode */
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf += fbi->var.xoffset * bpp +
+ fbi->var.yoffset * fbi->fix.line_length;
+
+ dma_base = DMA_P_BASE;
+
+#ifdef CONFIG_FB_MSM_MDP40
+ if (mfd->panel.type == HDMI_PANEL) {
+ intr = INTR_DMA_E_DONE;
+ irq_block = MDP_DMA_E_TERM;
+ dma_base = DMA_E_BASE;
+ }
+#endif
+
+ /* starting address */
+ MDP_OUTP(MDP_BASE + dma_base + 0x8, (uint32) buf);
+
+ /* enable LCDC irq */
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_enable_irq(irq_block);
+ INIT_COMPLETION(mfd->dma->comp);
+ mfd->dma->waiting = TRUE;
+#ifdef CONFIG_FB_MSM_MDP40
+ outp32(MDP_INTR_CLEAR, intr);
+ mdp_intr_mask |= intr;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+#else
+ outp32(MDP_INTR_CLEAR, LCDC_FRAME_START);
+ mdp_intr_mask |= LCDC_FRAME_START;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+#endif
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ wait_for_completion_killable(&mfd->dma->comp);
+ mdp_disable_irq(irq_block);
+}
diff --git a/drivers/video/msm/mdp_dma_s.c b/drivers/video/msm/mdp_dma_s.c
new file mode 100644
index 0000000..22d79be
--- /dev/null
+++ b/drivers/video/msm/mdp_dma_s.c
@@ -0,0 +1,166 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+static void mdp_dma_s_update_lcd(struct msm_fb_data_type *mfd)
+{
+ MDPIBUF *iBuf = &mfd->ibuf;
+ int mddi_dest = FALSE;
+ uint32 outBpp = iBuf->bpp;
+ uint32 dma_s_cfg_reg;
+ uint8 *src;
+ struct msm_fb_panel_data *pdata =
+ (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+
+ dma_s_cfg_reg = DMA_PACK_TIGHT | DMA_PACK_ALIGN_LSB |
+ DMA_OUT_SEL_AHB | DMA_IBUF_NONCONTIGUOUS;
+
+ if (mfd->fb_imgType == MDP_BGR_565)
+ dma_s_cfg_reg |= DMA_PACK_PATTERN_BGR;
+ else
+ dma_s_cfg_reg |= DMA_PACK_PATTERN_RGB;
+
+ if (outBpp == 4)
+ dma_s_cfg_reg |= DMA_IBUF_C3ALPHA_EN;
+
+ if (outBpp == 2)
+ dma_s_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
+
+ if (mfd->panel_info.pdest != DISPLAY_2) {
+ printk(KERN_ERR "error: non-secondary type through dma_s!\n");
+ return;
+ }
+
+ if (mfd->panel_info.type == MDDI_PANEL ||
+ mfd->panel_info.type == EXT_MDDI_PANEL) {
+ dma_s_cfg_reg |= DMA_OUT_SEL_MDDI;
+ mddi_dest = TRUE;
+ } else {
+ dma_s_cfg_reg |= DMA_AHBM_LCD_SEL_SECONDARY;
+ outp32(MDP_EBI2_LCD1, mfd->data_port_phys);
+ }
+
+ src = (uint8 *) iBuf->buf;
+ /* starting input address */
+ src += (iBuf->dma_x + iBuf->dma_y * iBuf->ibuf_width) * outBpp;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ /* PIXELSIZE */
+ if (mfd->panel_info.type == MDDI_PANEL) {
+ MDP_OUTP(MDP_BASE + 0xa0004,
+ (iBuf->dma_h << 16 | iBuf->dma_w));
+ MDP_OUTP(MDP_BASE + 0xa0008, src); /* ibuf address */
+ MDP_OUTP(MDP_BASE + 0xa000c,
+ iBuf->ibuf_width * outBpp);/* ystride */
+ } else {
+ MDP_OUTP(MDP_BASE + 0xb0004,
+ (iBuf->dma_h << 16 | iBuf->dma_w));
+ MDP_OUTP(MDP_BASE + 0xb0008, src); /* ibuf address */
+ MDP_OUTP(MDP_BASE + 0xb000c,
+ iBuf->ibuf_width * outBpp);/* ystride */
+ }
+
+ if (mfd->panel_info.bpp == 18) {
+ dma_s_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */
+ DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+ } else {
+ dma_s_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */
+ DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
+ }
+
+ if (mddi_dest) {
+ if (mfd->panel_info.type == MDDI_PANEL) {
+ MDP_OUTP(MDP_BASE + 0xa0010,
+ (iBuf->dma_y << 16) | iBuf->dma_x);
+ MDP_OUTP(MDP_BASE + 0x00090, 1);
+ } else {
+ MDP_OUTP(MDP_BASE + 0xb0010,
+ (iBuf->dma_y << 16) | iBuf->dma_x);
+ MDP_OUTP(MDP_BASE + 0x00090, 2);
+ }
+ MDP_OUTP(MDP_BASE + 0x00094,
+ (MDDI_VDO_PACKET_DESC << 16) |
+ mfd->panel_info.mddi.vdopkt);
+ } else {
+ /* setting LCDC write window */
+ pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w,
+ iBuf->dma_h);
+ }
+
+ if (mfd->panel_info.type == MDDI_PANEL)
+ MDP_OUTP(MDP_BASE + 0xa0000, dma_s_cfg_reg);
+ else
+ MDP_OUTP(MDP_BASE + 0xb0000, dma_s_cfg_reg);
+
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ if (mfd->panel_info.type == MDDI_PANEL)
+ mdp_pipe_kickoff(MDP_DMA_S_TERM, mfd);
+ else
+ mdp_pipe_kickoff(MDP_DMA_E_TERM, mfd);
+
+}
+
+void mdp_dma_s_update(struct msm_fb_data_type *mfd)
+{
+ down(&mfd->dma->mutex);
+ if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
+ down(&mfd->sem);
+ mdp_enable_irq(MDP_DMA_S_TERM);
+ if (mfd->panel_info.type == MDDI_PANEL)
+ mdp_enable_irq(MDP_DMA_S_TERM);
+ else
+ mdp_enable_irq(MDP_DMA_E_TERM);
+ mfd->dma->busy = TRUE;
+ INIT_COMPLETION(mfd->dma->comp);
+ mfd->ibuf_flushed = TRUE;
+ mdp_dma_s_update_lcd(mfd);
+ up(&mfd->sem);
+
+ /* wait until DMA finishes the current job */
+ wait_for_completion_killable(&mfd->dma->comp);
+ if (mfd->panel_info.type == MDDI_PANEL)
+ mdp_disable_irq(MDP_DMA_S_TERM);
+ else
+ mdp_disable_irq(MDP_DMA_E_TERM);
+
+ /* signal if pan function is waiting for the update completion */
+ if (mfd->pan_waiting) {
+ mfd->pan_waiting = FALSE;
+ complete(&mfd->pan_comp);
+ }
+ }
+ up(&mfd->dma->mutex);
+}
diff --git a/drivers/video/msm/mdp_dma_tv.c b/drivers/video/msm/mdp_dma_tv.c
new file mode 100644
index 0000000..66d9422
--- /dev/null
+++ b/drivers/video/msm/mdp_dma_tv.c
@@ -0,0 +1,138 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+extern spinlock_t mdp_spin_lock;
+extern uint32 mdp_intr_mask;
+
+int mdp_dma3_on(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct fb_info *fbi;
+ uint8 *buf;
+ int bpp;
+ int ret = 0;
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ fbi = mfd->fbi;
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf += fbi->var.xoffset * bpp +
+ fbi->var.yoffset * fbi->fix.line_length;
+
+ /* starting address[31..8] of Video frame buffer is CS0 */
+ MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3);
+
+ mdp_pipe_ctrl(MDP_DMA3_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ MDP_OUTP(MDP_BASE + 0xC0004, 0x4c60674); /* flicker filter enabled */
+ MDP_OUTP(MDP_BASE + 0xC0010, 0x20); /* sobel treshold */
+
+ MDP_OUTP(MDP_BASE + 0xC0018, 0xeb0010); /* Y Max, Y min */
+ MDP_OUTP(MDP_BASE + 0xC001C, 0xf00010); /* Cb Max, Cb min */
+ MDP_OUTP(MDP_BASE + 0xC0020, 0xf00010); /* Cb Max, Cb min */
+
+ MDP_OUTP(MDP_BASE + 0xC000C, 0x67686970); /* add a few chars for CC */
+ MDP_OUTP(MDP_BASE + 0xC0000, 0x1); /* MDP tv out enable */
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ ret = panel_next_on(pdev);
+
+ return ret;
+}
+
+int mdp_dma3_off(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ ret = panel_next_off(pdev);
+ if (ret)
+ return ret;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ MDP_OUTP(MDP_BASE + 0xC0000, 0x0);
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ mdp_pipe_ctrl(MDP_DMA3_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ /* delay to make sure the last frame finishes */
+ msleep(16);
+
+ return ret;
+}
+
+void mdp_dma3_update(struct msm_fb_data_type *mfd)
+{
+ struct fb_info *fbi = mfd->fbi;
+ uint8 *buf;
+ int bpp;
+ unsigned long flag;
+
+ if (!mfd->panel_power_on)
+ return;
+
+ /* no need to power on cmd block since dma3 is running */
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf += fbi->var.xoffset * bpp +
+ fbi->var.yoffset * fbi->fix.line_length;
+ MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3);
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_enable_irq(MDP_DMA3_TERM);
+ INIT_COMPLETION(mfd->dma->comp);
+ mfd->dma->waiting = TRUE;
+
+ outp32(MDP_INTR_CLEAR, TV_OUT_DMA3_START);
+ mdp_intr_mask |= TV_OUT_DMA3_START;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+ wait_for_completion_killable(&mfd->dma->comp);
+ mdp_disable_irq(MDP_DMA3_TERM);
+}
diff --git a/drivers/video/msm/mdp_hw.h b/drivers/video/msm/mdp_hw.h
index d804774..f35a757 100644
--- a/drivers/video/msm/mdp_hw.h
+++ b/drivers/video/msm/mdp_hw.h
@@ -15,20 +15,61 @@
#ifndef _MDP_HW_H_
#define _MDP_HW_H_
+#include <linux/platform_device.h>
+#include <linux/wait.h>
#include <mach/msm_iomap.h>
#include <mach/msm_fb.h>
+typedef void (*mdp_dma_start_func_t)(void *private_data, uint32_t addr,
+ uint32_t stride, uint32_t width,
+ uint32_t height, uint32_t x, uint32_t y);
+
+struct mdp_out_interface {
+ uint32_t registered:1;
+ void *priv;
+
+ /* If the interface client wants to get DMA_DONE events */
+ uint32_t dma_mask;
+ mdp_dma_start_func_t dma_start;
+
+ struct msmfb_callback *dma_cb;
+ wait_queue_head_t dma_waitqueue;
+
+ /* If the interface client wants to be notified of non-DMA irqs,
+ * e.g. LCDC/TV-out frame start */
+ uint32_t irq_mask;
+ struct msmfb_callback *irq_cb;
+};
+
struct mdp_info {
+ spinlock_t lock;
struct mdp_device mdp_dev;
char * __iomem base;
int irq;
+ struct clk *clk;
+ struct clk *ebi1_clk;
+ struct mdp_out_interface out_if[MSM_MDP_NUM_INTERFACES];
+ int format;
+ int pack_pattern;
+ bool dma_config_dirty;
};
+
+extern int mdp_out_if_register(struct mdp_device *mdp_dev, int interface,
+ void *private_data, uint32_t dma_mask,
+ mdp_dma_start_func_t dma_start);
+
+extern int mdp_out_if_req_irq(struct mdp_device *mdp_dev, int interface,
+ uint32_t mask, struct msmfb_callback *cb);
+
struct mdp_blit_req;
struct mdp_device;
int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
struct file *src_file, unsigned long src_start,
unsigned long src_len, struct file *dst_file,
unsigned long dst_start, unsigned long dst_len);
+
+void mdp_ppp_dump_debug(const struct mdp_info *mdp);
+
#define mdp_writel(mdp, value, offset) writel(value, mdp->base + offset)
#define mdp_readl(mdp, offset) readl(mdp->base + offset)
@@ -48,10 +89,18 @@
#define MDP_DISPLAY_STATUS (0x00038)
#define MDP_EBI2_LCD0 (0x0003c)
#define MDP_EBI2_LCD1 (0x00040)
+#define MDP_EBI2_PORTMAP_MODE (0x0005c)
+
+#ifndef CONFIG_MSM_MDP31
#define MDP_DISPLAY0_ADDR (0x00054)
#define MDP_DISPLAY1_ADDR (0x00058)
-#define MDP_EBI2_PORTMAP_MODE (0x0005c)
-#define MDP_MODE (0x00060)
+#define MDP_PPP_CMD_MODE (0x00060)
+#else
+#define MDP_DISPLAY0_ADDR (0x10000)
+#define MDP_DISPLAY1_ADDR (0x10004)
+#define MDP_PPP_CMD_MODE (0x10060)
+#endif
+
#define MDP_TV_OUT_STATUS (0x00064)
#define MDP_HW_VERSION (0x00070)
#define MDP_SW_RESET (0x00074)
@@ -61,6 +110,8 @@
#define MDP_SECONDARY_VSYNC_OUT_CTRL (0x00084)
#define MDP_EXTERNAL_VSYNC_OUT_CTRL (0x00088)
#define MDP_VSYNC_CTRL (0x0008c)
+#define MDP_MDDI_PARAM_WR_SEL (0x00090)
+#define MDP_MDDI_PARAM (0x00094)
#define MDP_CGC_EN (0x00100)
#define MDP_CMD_STATUS (0x10008)
#define MDP_PROFILE_EN (0x10010)
@@ -107,6 +158,7 @@
#define MDP_FULL_BYPASS_WORD35 (0x1018c)
#define MDP_FULL_BYPASS_WORD37 (0x10194)
#define MDP_FULL_BYPASS_WORD39 (0x1019c)
+#define MDP_PPP_OUT_XY (0x1019c)
#define MDP_FULL_BYPASS_WORD40 (0x101a0)
#define MDP_FULL_BYPASS_WORD41 (0x101a4)
#define MDP_FULL_BYPASS_WORD43 (0x101ac)
@@ -129,11 +181,27 @@
#define MDP_FULL_BYPASS_WORD61 (0x101f4)
#define MDP_FULL_BYPASS_WORD62 (0x101f8)
#define MDP_FULL_BYPASS_WORD63 (0x101fc)
+
+#ifdef CONFIG_MSM_MDP31
+#define MDP_PPP_SRC_XY (0x10200)
+#define MDP_PPP_BG_XY (0x10204)
+#define MDP_PPP_SRC_IMAGE_SIZE (0x10208)
+#define MDP_PPP_BG_IMAGE_SIZE (0x1020c)
+#define MDP_PPP_SCALE_CONFIG (0x10230)
+#define MDP_PPP_CSC_CONFIG (0x10240)
+#define MDP_PPP_BLEND_BG_ALPHA_SEL (0x70010)
+#endif
+
#define MDP_TFETCH_TEST_MODE (0x20004)
#define MDP_TFETCH_STATUS (0x20008)
#define MDP_TFETCH_TILE_COUNT (0x20010)
#define MDP_TFETCH_FETCH_COUNT (0x20014)
#define MDP_TFETCH_CONSTANT_COLOR (0x20040)
+#define MDP_BGTFETCH_TEST_MODE (0x28004)
+#define MDP_BGTFETCH_STATUS (0x28008)
+#define MDP_BGTFETCH_TILE_COUNT (0x28010)
+#define MDP_BGTFETCH_FETCH_COUNT (0x28014)
+#define MDP_BGTFETCH_CONSTANT_COLOR (0x28040)
#define MDP_CSC_BYPASS (0x40004)
#define MDP_SCALE_COEFF_LSB (0x5fffc)
#define MDP_TV_OUT_CTL (0xc0000)
@@ -158,55 +226,49 @@
#define MDP_TEST_MISR_CURR_VAL_DCLK (0xd020c)
#define MDP_TEST_CAPTURED_DCLK (0xd0210)
#define MDP_TEST_MISR_CAPT_VAL_DCLK (0xd0214)
-#define MDP_LCDC_CTL (0xe0000)
+
+#define MDP_DMA_P_START (0x00044)
+#define MDP_DMA_P_CONFIG (0x90000)
+#define MDP_DMA_P_SIZE (0x90004)
+#define MDP_DMA_P_IBUF_ADDR (0x90008)
+#define MDP_DMA_P_IBUF_Y_STRIDE (0x9000c)
+#define MDP_DMA_P_OUT_XY (0x90010)
+#define MDP_DMA_P_COLOR_CORRECT_CONFIG (0x90070)
+
+#define MDP_LCDC_EN (0xe0000)
#define MDP_LCDC_HSYNC_CTL (0xe0004)
-#define MDP_LCDC_VSYNC_CTL (0xe0008)
-#define MDP_LCDC_ACTIVE_HCTL (0xe000c)
-#define MDP_LCDC_ACTIVE_VCTL (0xe0010)
-#define MDP_LCDC_BORDER_CLR (0xe0014)
-#define MDP_LCDC_H_BLANK (0xe0018)
-#define MDP_LCDC_V_BLANK (0xe001c)
-#define MDP_LCDC_UNDERFLOW_CLR (0xe0020)
-#define MDP_LCDC_HSYNC_SKEW (0xe0024)
-#define MDP_LCDC_TEST_CTL (0xe0028)
-#define MDP_LCDC_LINE_IRQ (0xe002c)
-#define MDP_LCDC_CTL_POLARITY (0xe0030)
-#define MDP_LCDC_DMA_CONFIG (0xe1000)
-#define MDP_LCDC_DMA_SIZE (0xe1004)
-#define MDP_LCDC_DMA_IBUF_ADDR (0xe1008)
-#define MDP_LCDC_DMA_IBUF_Y_STRIDE (0xe100c)
+#define MDP_LCDC_VSYNC_PERIOD (0xe0008)
+#define MDP_LCDC_VSYNC_PULSE_WIDTH (0xe000c)
+#define MDP_LCDC_DISPLAY_HCTL (0xe0010)
+#define MDP_LCDC_DISPLAY_V_START (0xe0014)
+#define MDP_LCDC_DISPLAY_V_END (0xe0018)
+#define MDP_LCDC_ACTIVE_HCTL (0xe001c)
+#define MDP_LCDC_ACTIVE_V_START (0xe0020)
+#define MDP_LCDC_ACTIVE_V_END (0xe0024)
+#define MDP_LCDC_BORDER_CLR (0xe0028)
+#define MDP_LCDC_UNDERFLOW_CTL (0xe002c)
+#define MDP_LCDC_HSYNC_SKEW (0xe0030)
+#define MDP_LCDC_TEST_CTL (0xe0034)
+#define MDP_LCDC_CTL_POLARITY (0xe0038)
+#define MDP_PPP_SCALE_STATUS (0x50000)
+#define MDP_PPP_BLEND_STATUS (0x70000)
-#define MDP_DMA2_TERM 0x1
-#define MDP_DMA3_TERM 0x2
-#define MDP_PPP_TERM 0x3
+/* MDP_SW_RESET */
+#define MDP_PPP_SW_RESET (1<<4)
/* MDP_INTR_ENABLE */
-#define DL0_ROI_DONE (1<<0)
-#define DL1_ROI_DONE (1<<1)
-#define DL0_DMA2_TERM_DONE (1<<2)
-#define DL1_DMA2_TERM_DONE (1<<3)
-#define DL0_PPP_TERM_DONE (1<<4)
-#define DL1_PPP_TERM_DONE (1<<5)
-#define TV_OUT_DMA3_DONE (1<<6)
-#define TV_ENC_UNDERRUN (1<<7)
-#define DL0_FETCH_DONE (1<<11)
-#define DL1_FETCH_DONE (1<<12)
+#define DL0_ROI_DONE (1<<0)
+#define TV_OUT_DMA3_DONE (1<<6)
+#define TV_ENC_UNDERRUN (1<<7)
-#define MDP_PPP_BUSY_STATUS (DL0_ROI_DONE| \
- DL1_ROI_DONE| \
- DL0_PPP_TERM_DONE| \
- DL1_PPP_TERM_DONE)
-
-#define MDP_ANY_INTR_MASK (DL0_ROI_DONE| \
- DL1_ROI_DONE| \
- DL0_DMA2_TERM_DONE| \
- DL1_DMA2_TERM_DONE| \
- DL0_PPP_TERM_DONE| \
- DL1_PPP_TERM_DONE| \
- DL0_FETCH_DONE| \
- DL1_FETCH_DONE| \
- TV_ENC_UNDERRUN)
+#ifdef CONFIG_MSM_MDP22
+#define MDP_DMA_P_DONE (1 << 2)
+#else /* CONFIG_MSM_MDP31 */
+#define MDP_DMA_P_DONE (1 << 14)
+#define MDP_LCDC_UNDERFLOW (1 << 16)
+#define MDP_LCDC_FRAME_START (1 << 15)
+#endif
#define MDP_TOP_LUMA 16
#define MDP_TOP_CHROMA 0
@@ -316,7 +378,12 @@
#define PPP_OP_SCALE_X_ON (1<<0)
#define PPP_OP_SCALE_Y_ON (1<<1)
+#ifndef CONFIG_MSM_MDP31
#define PPP_OP_CONVERT_RGB2YCBCR 0
+#else
+#define PPP_OP_CONVERT_RGB2YCBCR (1<<30)
+#endif
+
#define PPP_OP_CONVERT_YCBCR2RGB (1<<2)
#define PPP_OP_CONVERT_ON (1<<3)
@@ -372,6 +439,13 @@
#define PPP_OP_BG_CHROMA_SITE_COSITE 0
#define PPP_OP_BG_CHROMA_SITE_OFFSITE (1<<27)
+#define PPP_BLEND_BG_USE_ALPHA_SEL (1 << 0)
+#define PPP_BLEND_BG_ALPHA_REVERSE (1 << 3)
+#define PPP_BLEND_BG_SRCPIXEL_ALPHA (0 << 1)
+#define PPP_BLEND_BG_DSTPIXEL_ALPHA (1 << 1)
+#define PPP_BLEND_BG_CONSTANT_ALPHA (2 << 1)
+#define PPP_BLEND_BG_CONST_ALPHA_VAL(x) ((x) << 24)
+
/* MDP_PPP_DESTINATION_CONFIG / MDP_FULL_BYPASS_WORD20 */
#define PPP_DST_C0G_8BIT ((1<<0)|(1<<1))
#define PPP_DST_C1B_8BIT ((1<<3)|(1<<2))
@@ -589,20 +663,71 @@
#define PPP_ADDR_BG_CFG MDP_FULL_BYPASS_WORD53
#define PPP_ADDR_BG_PACK_PATTERN MDP_FULL_BYPASS_WORD54
+/* color conversion matrix configuration registers */
+/* pfmv is mv1, prmv is mv2 */
+#define MDP_CSC_PFMVn(n) (0x40400 + (4 * (n)))
+#define MDP_CSC_PRMVn(n) (0x40440 + (4 * (n)))
+
+#ifdef CONFIG_MSM_MDP31
+#define MDP_PPP_CSC_PRE_BV1n(n) (0x40500 + (4 * (n)))
+#define MDP_PPP_CSC_PRE_BV2n(n) (0x40540 + (4 * (n)))
+#define MDP_PPP_CSC_POST_BV1n(n) (0x40580 + (4 * (n)))
+#define MDP_PPP_CSC_POST_BV2n(n) (0x405c0 + (4 * (n)))
+
+#define MDP_PPP_CSC_PRE_LV1n(n) (0x40600 + (4 * (n)))
+#define MDP_PPP_CSC_PRE_LV2n(n) (0x40640 + (4 * (n)))
+#define MDP_PPP_CSC_POST_LV1n(n) (0x40680 + (4 * (n)))
+#define MDP_PPP_CSC_POST_LV2n(n) (0x406c0 + (4 * (n)))
+
+#define MDP_PPP_SCALE_COEFF_D0_SET (0)
+#define MDP_PPP_SCALE_COEFF_D1_SET (1)
+#define MDP_PPP_SCALE_COEFF_D2_SET (2)
+#define MDP_PPP_SCALE_COEFF_U1_SET (3)
+#define MDP_PPP_SCALE_COEFF_LSBn(n) (0x50400 + (8 * (n)))
+#define MDP_PPP_SCALE_COEFF_MSBn(n) (0x50404 + (8 * (n)))
+
+#define MDP_PPP_DEINT_COEFFn(n) (0x30010 + (4 * (n)))
+
+#define MDP_PPP_SCALER_FIR (0)
+#define MDP_PPP_SCALER_MN (1)
+
+#else /* !defined(CONFIG_MSM_MDP31) */
+
+#define MDP_CSC_PBVn(n) (0x40500 + (4 * (n)))
+#define MDP_CSC_SBVn(n) (0x40540 + (4 * (n)))
+#define MDP_CSC_PLVn(n) (0x40580 + (4 * (n)))
+#define MDP_CSC_SLVn(n) (0x405c0 + (4 * (n)))
+
+#endif
+
+
/* MDP_DMA_CONFIG / MDP_FULL_BYPASS_WORD32 */
-#define DMA_DSTC0G_6BITS (1<<1)
-#define DMA_DSTC1B_6BITS (1<<3)
-#define DMA_DSTC2R_6BITS (1<<5)
#define DMA_DSTC0G_5BITS (1<<0)
#define DMA_DSTC1B_5BITS (1<<2)
#define DMA_DSTC2R_5BITS (1<<4)
+#define DMA_DSTC0G_6BITS (2<<0)
+#define DMA_DSTC1B_6BITS (2<<2)
+#define DMA_DSTC2R_6BITS (2<<4)
+
+#define DMA_DSTC0G_8BITS (3<<0)
+#define DMA_DSTC1B_8BITS (3<<2)
+#define DMA_DSTC2R_8BITS (3<<4)
+
+#define DMA_DST_BITS_MASK 0x3F
+
#define DMA_PACK_TIGHT (1<<6)
#define DMA_PACK_LOOSE 0
#define DMA_PACK_ALIGN_LSB 0
#define DMA_PACK_ALIGN_MSB (1<<7)
+#define DMA_PACK_PATTERN_MASK (0x3f<<8)
#define DMA_PACK_PATTERN_RGB \
(MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 2)<<8)
+#define DMA_PACK_PATTERN_BGR \
+ (MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 2)<<8)
+
+
+#ifdef CONFIG_MSM_MDP22
#define DMA_OUT_SEL_AHB 0
#define DMA_OUT_SEL_MDDI (1<<14)
@@ -610,16 +735,32 @@
#define DMA_AHBM_LCD_SEL_SECONDARY (1<<15)
#define DMA_IBUF_C3ALPHA_EN (1<<16)
#define DMA_DITHER_EN (1<<17)
-
#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0
#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY (1<<18)
#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL (1<<19)
-
#define DMA_IBUF_FORMAT_RGB565 (1<<20)
#define DMA_IBUF_FORMAT_RGB888_OR_ARGB8888 0
-
+#define DMA_IBUF_FORMAT_MASK (1 << 20)
#define DMA_IBUF_NONCONTIGUOUS (1<<21)
+#else /* CONFIG_MSM_MDP31 */
+
+#define DMA_OUT_SEL_AHB (0 << 19)
+#define DMA_OUT_SEL_MDDI (1 << 19)
+#define DMA_OUT_SEL_LCDC (2 << 19)
+#define DMA_OUT_SEL_LCDC_MDDI (3 << 19)
+#define DMA_DITHER_EN (1 << 24)
+#define DMA_IBUF_FORMAT_RGB888 (0 << 25)
+#define DMA_IBUF_FORMAT_RGB565 (1 << 25)
+#define DMA_IBUF_FORMAT_XRGB8888 (2 << 25)
+#define DMA_IBUF_FORMAT_MASK (3 << 25)
+#define DMA_IBUF_NONCONTIGUOUS (0)
+
+#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY (0)
+#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY (0)
+#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL (0)
+#endif
+
/* MDDI REGISTER ? */
#define MDDI_VDO_PACKET_DESC 0x5666
#define MDDI_VDO_PACKET_PRIM 0xC3
diff --git a/drivers/video/msm/mdp_hw40.c b/drivers/video/msm/mdp_hw40.c
new file mode 100644
index 0000000..d36125e
--- /dev/null
+++ b/drivers/video/msm/mdp_hw40.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2010 Google, Inc.
+ * Author: Dima Zavin <dima@android.com>
+ *
+ * Based on code from Code Aurora Forum.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include "mdp_hw.h"
+
+static void mdp_dma_to_mddi(void *priv, uint32_t addr, uint32_t stride,
+ uint32_t width, uint32_t height, uint32_t x,
+ uint32_t y)
+{
+ struct mdp_info *mdp = priv;
+ uint32_t dma2_cfg;
+ uint16_t ld_param = 0; /* 0=PRIM, 1=SECD, 2=EXT */
+
+ dma2_cfg = DMA_PACK_TIGHT |
+ DMA_PACK_ALIGN_LSB;
+
+ dma2_cfg |= mdp->dma_format;
+ dma2_cfg |= mdp->dma_pack_pattern;
+ dma2_cfg |= DMA_DITHER_EN;
+
+ /* 666 18BPP */
+ dma2_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+
+ /* setup size, address, and stride */
+ mdp_writel(mdp, (height << 16) | (width), MDP_DMA_P_SIZE);
+ mdp_writel(mdp, addr, MDP_DMA_P_IBUF_ADDR);
+ mdp_writel(mdp, stride, MDP_DMA_P_IBUF_Y_STRIDE);
+
+ /* set y & x offset and MDDI transaction parameters */
+ mdp_writel(mdp, (y << 16) | (x), MDP_DMA_P_OUT_XY);
+ mdp_writel(mdp, ld_param, MDP_MDDI_PARAM_WR_SEL);
+ mdp_writel(mdp, (MDDI_VDO_PACKET_DESC << 16) | MDDI_VDO_PACKET_PRIM,
+ MDP_MDDI_PARAM);
+
+ mdp_writel(mdp, 0x1, MDP_MDDI_DATA_XFR);
+ mdp_writel(mdp, dma2_cfg, MDP_DMA_P_CONFIG);
+ mdp_writel(mdp, 0, MDP_DMA_P_START);
+}
+
+int mdp_hw_init(struct mdp_info *mdp)
+{
+ int ret;
+
+ ret = mdp_out_if_register(&mdp->mdp_dev, MSM_MDDI_PMDH_INTERFACE, mdp,
+ MDP_DMA_P_DONE, mdp_dma_to_mddi);
+ if (ret)
+ return ret;
+
+ mdp_writel(mdp, 0, MDP_INTR_ENABLE);
+ mdp_writel(mdp, 0, MDP_DMA_P_HIST_INTR_ENABLE);
+
+ /* XXX: why set this? QCT says it should be > mdp_pclk,
+ * but they never set the clkrate of pclk */
+ mdp_set_core_clk(4);
+ pr_info("%s: mdp_clk=%lu\n", __func__, clk_get_rate(mdp->clk));
+
+ /* TODO: Configure the VG/RGB pipes fetch data */
+
+ /* this should work for any mdp_clk freq.
+ * TODO: use different value for mdp_clk freqs >= 90Mhz */
+ mdp_writel(mdp, 0x27, MDP_DMA_P_FETCH_CFG); /* 8 bytes-burst x 8 req */
+
+ mdp_writel(mdp, 0x3, MDP_EBI2_PORTMAP_MODE);
+
+ /* 3 pending requests */
+ mdp_writel(mdp, 0x02222, MDP_MAX_RD_PENDING_CMD_CONFIG);
+
+ /* no overlay processing, sw controls everything */
+ mdp_writel(mdp, 0, MDP_LAYERMIXER_IN_CFG);
+ mdp_writel(mdp, 1 << 3, MDP_OVERLAYPROC0_CFG);
+ mdp_writel(mdp, 1 << 3, MDP_OVERLAYPROC1_CFG);
+
+ /* XXX: HACK! hardcode to do mddi on primary */
+ mdp_writel(mdp, 0x2, MDP_DISP_INTF_SEL);
+ return 0;
+}
+
diff --git a/drivers/video/msm/mdp_hw_init.c b/drivers/video/msm/mdp_hw_init.c
new file mode 100644
index 0000000..8f8b4d3
--- /dev/null
+++ b/drivers/video/msm/mdp_hw_init.c
@@ -0,0 +1,716 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "mdp.h"
+
+/* mdp primary csc limit vector */
+uint32 mdp_plv[] = { 0x10, 0xeb, 0x10, 0xf0 };
+
+/* Color Coefficient matrix for YUV -> RGB */
+struct mdp_ccs mdp_ccs_yuv2rgb = {
+ MDP_CCS_YUV2RGB,
+ {
+ 0x254,
+ 0x000,
+ 0x331,
+ 0x254,
+ 0xff38,
+ 0xfe61,
+ 0x254,
+ 0x409,
+ 0x000,
+ },
+ {
+#ifdef CONFIG_FB_MSM_MDP31
+ 0x1f0,
+ 0x180,
+ 0x180
+#else
+ 0x10,
+ 0x80,
+ 0x80
+#endif
+ }
+};
+
+/* Color Coefficient matrix for RGB -> YUV */
+struct mdp_ccs mdp_ccs_rgb2yuv = {
+ MDP_CCS_RGB2YUV,
+ {
+ 0x83,
+ 0x102,
+ 0x32,
+ 0xffb5,
+ 0xff6c,
+ 0xe1,
+ 0xe1,
+ 0xff45,
+ 0xffdc,
+ },
+#ifdef CONFIG_FB_MSM_MDP31
+ {
+ 0x10,
+ 0x80,
+ 0x80
+ }
+#endif
+};
+
+static void mdp_load_lut_param(void)
+{
+ outpdw(MDP_BASE + 0x40800, 0x0);
+ outpdw(MDP_BASE + 0x40804, 0x151515);
+ outpdw(MDP_BASE + 0x40808, 0x1d1d1d);
+ outpdw(MDP_BASE + 0x4080c, 0x232323);
+ outpdw(MDP_BASE + 0x40810, 0x272727);
+ outpdw(MDP_BASE + 0x40814, 0x2b2b2b);
+ outpdw(MDP_BASE + 0x40818, 0x2f2f2f);
+ outpdw(MDP_BASE + 0x4081c, 0x333333);
+ outpdw(MDP_BASE + 0x40820, 0x363636);
+ outpdw(MDP_BASE + 0x40824, 0x393939);
+ outpdw(MDP_BASE + 0x40828, 0x3b3b3b);
+ outpdw(MDP_BASE + 0x4082c, 0x3e3e3e);
+ outpdw(MDP_BASE + 0x40830, 0x404040);
+ outpdw(MDP_BASE + 0x40834, 0x434343);
+ outpdw(MDP_BASE + 0x40838, 0x454545);
+ outpdw(MDP_BASE + 0x4083c, 0x474747);
+ outpdw(MDP_BASE + 0x40840, 0x494949);
+ outpdw(MDP_BASE + 0x40844, 0x4b4b4b);
+ outpdw(MDP_BASE + 0x40848, 0x4d4d4d);
+ outpdw(MDP_BASE + 0x4084c, 0x4f4f4f);
+ outpdw(MDP_BASE + 0x40850, 0x515151);
+ outpdw(MDP_BASE + 0x40854, 0x535353);
+ outpdw(MDP_BASE + 0x40858, 0x555555);
+ outpdw(MDP_BASE + 0x4085c, 0x565656);
+ outpdw(MDP_BASE + 0x40860, 0x585858);
+ outpdw(MDP_BASE + 0x40864, 0x5a5a5a);
+ outpdw(MDP_BASE + 0x40868, 0x5b5b5b);
+ outpdw(MDP_BASE + 0x4086c, 0x5d5d5d);
+ outpdw(MDP_BASE + 0x40870, 0x5e5e5e);
+ outpdw(MDP_BASE + 0x40874, 0x606060);
+ outpdw(MDP_BASE + 0x40878, 0x616161);
+ outpdw(MDP_BASE + 0x4087c, 0x636363);
+ outpdw(MDP_BASE + 0x40880, 0x646464);
+ outpdw(MDP_BASE + 0x40884, 0x666666);
+ outpdw(MDP_BASE + 0x40888, 0x676767);
+ outpdw(MDP_BASE + 0x4088c, 0x686868);
+ outpdw(MDP_BASE + 0x40890, 0x6a6a6a);
+ outpdw(MDP_BASE + 0x40894, 0x6b6b6b);
+ outpdw(MDP_BASE + 0x40898, 0x6c6c6c);
+ outpdw(MDP_BASE + 0x4089c, 0x6e6e6e);
+ outpdw(MDP_BASE + 0x408a0, 0x6f6f6f);
+ outpdw(MDP_BASE + 0x408a4, 0x707070);
+ outpdw(MDP_BASE + 0x408a8, 0x717171);
+ outpdw(MDP_BASE + 0x408ac, 0x727272);
+ outpdw(MDP_BASE + 0x408b0, 0x747474);
+ outpdw(MDP_BASE + 0x408b4, 0x757575);
+ outpdw(MDP_BASE + 0x408b8, 0x767676);
+ outpdw(MDP_BASE + 0x408bc, 0x777777);
+ outpdw(MDP_BASE + 0x408c0, 0x787878);
+ outpdw(MDP_BASE + 0x408c4, 0x797979);
+ outpdw(MDP_BASE + 0x408c8, 0x7a7a7a);
+ outpdw(MDP_BASE + 0x408cc, 0x7c7c7c);
+ outpdw(MDP_BASE + 0x408d0, 0x7d7d7d);
+ outpdw(MDP_BASE + 0x408d4, 0x7e7e7e);
+ outpdw(MDP_BASE + 0x408d8, 0x7f7f7f);
+ outpdw(MDP_BASE + 0x408dc, 0x808080);
+ outpdw(MDP_BASE + 0x408e0, 0x818181);
+ outpdw(MDP_BASE + 0x408e4, 0x828282);
+ outpdw(MDP_BASE + 0x408e8, 0x838383);
+ outpdw(MDP_BASE + 0x408ec, 0x848484);
+ outpdw(MDP_BASE + 0x408f0, 0x858585);
+ outpdw(MDP_BASE + 0x408f4, 0x868686);
+ outpdw(MDP_BASE + 0x408f8, 0x878787);
+ outpdw(MDP_BASE + 0x408fc, 0x888888);
+ outpdw(MDP_BASE + 0x40900, 0x898989);
+ outpdw(MDP_BASE + 0x40904, 0x8a8a8a);
+ outpdw(MDP_BASE + 0x40908, 0x8b8b8b);
+ outpdw(MDP_BASE + 0x4090c, 0x8c8c8c);
+ outpdw(MDP_BASE + 0x40910, 0x8d8d8d);
+ outpdw(MDP_BASE + 0x40914, 0x8e8e8e);
+ outpdw(MDP_BASE + 0x40918, 0x8f8f8f);
+ outpdw(MDP_BASE + 0x4091c, 0x8f8f8f);
+ outpdw(MDP_BASE + 0x40920, 0x909090);
+ outpdw(MDP_BASE + 0x40924, 0x919191);
+ outpdw(MDP_BASE + 0x40928, 0x929292);
+ outpdw(MDP_BASE + 0x4092c, 0x939393);
+ outpdw(MDP_BASE + 0x40930, 0x949494);
+ outpdw(MDP_BASE + 0x40934, 0x959595);
+ outpdw(MDP_BASE + 0x40938, 0x969696);
+ outpdw(MDP_BASE + 0x4093c, 0x969696);
+ outpdw(MDP_BASE + 0x40940, 0x979797);
+ outpdw(MDP_BASE + 0x40944, 0x989898);
+ outpdw(MDP_BASE + 0x40948, 0x999999);
+ outpdw(MDP_BASE + 0x4094c, 0x9a9a9a);
+ outpdw(MDP_BASE + 0x40950, 0x9b9b9b);
+ outpdw(MDP_BASE + 0x40954, 0x9c9c9c);
+ outpdw(MDP_BASE + 0x40958, 0x9c9c9c);
+ outpdw(MDP_BASE + 0x4095c, 0x9d9d9d);
+ outpdw(MDP_BASE + 0x40960, 0x9e9e9e);
+ outpdw(MDP_BASE + 0x40964, 0x9f9f9f);
+ outpdw(MDP_BASE + 0x40968, 0xa0a0a0);
+ outpdw(MDP_BASE + 0x4096c, 0xa0a0a0);
+ outpdw(MDP_BASE + 0x40970, 0xa1a1a1);
+ outpdw(MDP_BASE + 0x40974, 0xa2a2a2);
+ outpdw(MDP_BASE + 0x40978, 0xa3a3a3);
+ outpdw(MDP_BASE + 0x4097c, 0xa4a4a4);
+ outpdw(MDP_BASE + 0x40980, 0xa4a4a4);
+ outpdw(MDP_BASE + 0x40984, 0xa5a5a5);
+ outpdw(MDP_BASE + 0x40988, 0xa6a6a6);
+ outpdw(MDP_BASE + 0x4098c, 0xa7a7a7);
+ outpdw(MDP_BASE + 0x40990, 0xa7a7a7);
+ outpdw(MDP_BASE + 0x40994, 0xa8a8a8);
+ outpdw(MDP_BASE + 0x40998, 0xa9a9a9);
+ outpdw(MDP_BASE + 0x4099c, 0xaaaaaa);
+ outpdw(MDP_BASE + 0x409a0, 0xaaaaaa);
+ outpdw(MDP_BASE + 0x409a4, 0xababab);
+ outpdw(MDP_BASE + 0x409a8, 0xacacac);
+ outpdw(MDP_BASE + 0x409ac, 0xadadad);
+ outpdw(MDP_BASE + 0x409b0, 0xadadad);
+ outpdw(MDP_BASE + 0x409b4, 0xaeaeae);
+ outpdw(MDP_BASE + 0x409b8, 0xafafaf);
+ outpdw(MDP_BASE + 0x409bc, 0xafafaf);
+ outpdw(MDP_BASE + 0x409c0, 0xb0b0b0);
+ outpdw(MDP_BASE + 0x409c4, 0xb1b1b1);
+ outpdw(MDP_BASE + 0x409c8, 0xb2b2b2);
+ outpdw(MDP_BASE + 0x409cc, 0xb2b2b2);
+ outpdw(MDP_BASE + 0x409d0, 0xb3b3b3);
+ outpdw(MDP_BASE + 0x409d4, 0xb4b4b4);
+ outpdw(MDP_BASE + 0x409d8, 0xb4b4b4);
+ outpdw(MDP_BASE + 0x409dc, 0xb5b5b5);
+ outpdw(MDP_BASE + 0x409e0, 0xb6b6b6);
+ outpdw(MDP_BASE + 0x409e4, 0xb6b6b6);
+ outpdw(MDP_BASE + 0x409e8, 0xb7b7b7);
+ outpdw(MDP_BASE + 0x409ec, 0xb8b8b8);
+ outpdw(MDP_BASE + 0x409f0, 0xb8b8b8);
+ outpdw(MDP_BASE + 0x409f4, 0xb9b9b9);
+ outpdw(MDP_BASE + 0x409f8, 0xbababa);
+ outpdw(MDP_BASE + 0x409fc, 0xbababa);
+ outpdw(MDP_BASE + 0x40a00, 0xbbbbbb);
+ outpdw(MDP_BASE + 0x40a04, 0xbcbcbc);
+ outpdw(MDP_BASE + 0x40a08, 0xbcbcbc);
+ outpdw(MDP_BASE + 0x40a0c, 0xbdbdbd);
+ outpdw(MDP_BASE + 0x40a10, 0xbebebe);
+ outpdw(MDP_BASE + 0x40a14, 0xbebebe);
+ outpdw(MDP_BASE + 0x40a18, 0xbfbfbf);
+ outpdw(MDP_BASE + 0x40a1c, 0xc0c0c0);
+ outpdw(MDP_BASE + 0x40a20, 0xc0c0c0);
+ outpdw(MDP_BASE + 0x40a24, 0xc1c1c1);
+ outpdw(MDP_BASE + 0x40a28, 0xc1c1c1);
+ outpdw(MDP_BASE + 0x40a2c, 0xc2c2c2);
+ outpdw(MDP_BASE + 0x40a30, 0xc3c3c3);
+ outpdw(MDP_BASE + 0x40a34, 0xc3c3c3);
+ outpdw(MDP_BASE + 0x40a38, 0xc4c4c4);
+ outpdw(MDP_BASE + 0x40a3c, 0xc5c5c5);
+ outpdw(MDP_BASE + 0x40a40, 0xc5c5c5);
+ outpdw(MDP_BASE + 0x40a44, 0xc6c6c6);
+ outpdw(MDP_BASE + 0x40a48, 0xc6c6c6);
+ outpdw(MDP_BASE + 0x40a4c, 0xc7c7c7);
+ outpdw(MDP_BASE + 0x40a50, 0xc8c8c8);
+ outpdw(MDP_BASE + 0x40a54, 0xc8c8c8);
+ outpdw(MDP_BASE + 0x40a58, 0xc9c9c9);
+ outpdw(MDP_BASE + 0x40a5c, 0xc9c9c9);
+ outpdw(MDP_BASE + 0x40a60, 0xcacaca);
+ outpdw(MDP_BASE + 0x40a64, 0xcbcbcb);
+ outpdw(MDP_BASE + 0x40a68, 0xcbcbcb);
+ outpdw(MDP_BASE + 0x40a6c, 0xcccccc);
+ outpdw(MDP_BASE + 0x40a70, 0xcccccc);
+ outpdw(MDP_BASE + 0x40a74, 0xcdcdcd);
+ outpdw(MDP_BASE + 0x40a78, 0xcecece);
+ outpdw(MDP_BASE + 0x40a7c, 0xcecece);
+ outpdw(MDP_BASE + 0x40a80, 0xcfcfcf);
+ outpdw(MDP_BASE + 0x40a84, 0xcfcfcf);
+ outpdw(MDP_BASE + 0x40a88, 0xd0d0d0);
+ outpdw(MDP_BASE + 0x40a8c, 0xd0d0d0);
+ outpdw(MDP_BASE + 0x40a90, 0xd1d1d1);
+ outpdw(MDP_BASE + 0x40a94, 0xd2d2d2);
+ outpdw(MDP_BASE + 0x40a98, 0xd2d2d2);
+ outpdw(MDP_BASE + 0x40a9c, 0xd3d3d3);
+ outpdw(MDP_BASE + 0x40aa0, 0xd3d3d3);
+ outpdw(MDP_BASE + 0x40aa4, 0xd4d4d4);
+ outpdw(MDP_BASE + 0x40aa8, 0xd4d4d4);
+ outpdw(MDP_BASE + 0x40aac, 0xd5d5d5);
+ outpdw(MDP_BASE + 0x40ab0, 0xd6d6d6);
+ outpdw(MDP_BASE + 0x40ab4, 0xd6d6d6);
+ outpdw(MDP_BASE + 0x40ab8, 0xd7d7d7);
+ outpdw(MDP_BASE + 0x40abc, 0xd7d7d7);
+ outpdw(MDP_BASE + 0x40ac0, 0xd8d8d8);
+ outpdw(MDP_BASE + 0x40ac4, 0xd8d8d8);
+ outpdw(MDP_BASE + 0x40ac8, 0xd9d9d9);
+ outpdw(MDP_BASE + 0x40acc, 0xd9d9d9);
+ outpdw(MDP_BASE + 0x40ad0, 0xdadada);
+ outpdw(MDP_BASE + 0x40ad4, 0xdbdbdb);
+ outpdw(MDP_BASE + 0x40ad8, 0xdbdbdb);
+ outpdw(MDP_BASE + 0x40adc, 0xdcdcdc);
+ outpdw(MDP_BASE + 0x40ae0, 0xdcdcdc);
+ outpdw(MDP_BASE + 0x40ae4, 0xdddddd);
+ outpdw(MDP_BASE + 0x40ae8, 0xdddddd);
+ outpdw(MDP_BASE + 0x40aec, 0xdedede);
+ outpdw(MDP_BASE + 0x40af0, 0xdedede);
+ outpdw(MDP_BASE + 0x40af4, 0xdfdfdf);
+ outpdw(MDP_BASE + 0x40af8, 0xdfdfdf);
+ outpdw(MDP_BASE + 0x40afc, 0xe0e0e0);
+ outpdw(MDP_BASE + 0x40b00, 0xe0e0e0);
+ outpdw(MDP_BASE + 0x40b04, 0xe1e1e1);
+ outpdw(MDP_BASE + 0x40b08, 0xe1e1e1);
+ outpdw(MDP_BASE + 0x40b0c, 0xe2e2e2);
+ outpdw(MDP_BASE + 0x40b10, 0xe3e3e3);
+ outpdw(MDP_BASE + 0x40b14, 0xe3e3e3);
+ outpdw(MDP_BASE + 0x40b18, 0xe4e4e4);
+ outpdw(MDP_BASE + 0x40b1c, 0xe4e4e4);
+ outpdw(MDP_BASE + 0x40b20, 0xe5e5e5);
+ outpdw(MDP_BASE + 0x40b24, 0xe5e5e5);
+ outpdw(MDP_BASE + 0x40b28, 0xe6e6e6);
+ outpdw(MDP_BASE + 0x40b2c, 0xe6e6e6);
+ outpdw(MDP_BASE + 0x40b30, 0xe7e7e7);
+ outpdw(MDP_BASE + 0x40b34, 0xe7e7e7);
+ outpdw(MDP_BASE + 0x40b38, 0xe8e8e8);
+ outpdw(MDP_BASE + 0x40b3c, 0xe8e8e8);
+ outpdw(MDP_BASE + 0x40b40, 0xe9e9e9);
+ outpdw(MDP_BASE + 0x40b44, 0xe9e9e9);
+ outpdw(MDP_BASE + 0x40b48, 0xeaeaea);
+ outpdw(MDP_BASE + 0x40b4c, 0xeaeaea);
+ outpdw(MDP_BASE + 0x40b50, 0xebebeb);
+ outpdw(MDP_BASE + 0x40b54, 0xebebeb);
+ outpdw(MDP_BASE + 0x40b58, 0xececec);
+ outpdw(MDP_BASE + 0x40b5c, 0xececec);
+ outpdw(MDP_BASE + 0x40b60, 0xededed);
+ outpdw(MDP_BASE + 0x40b64, 0xededed);
+ outpdw(MDP_BASE + 0x40b68, 0xeeeeee);
+ outpdw(MDP_BASE + 0x40b6c, 0xeeeeee);
+ outpdw(MDP_BASE + 0x40b70, 0xefefef);
+ outpdw(MDP_BASE + 0x40b74, 0xefefef);
+ outpdw(MDP_BASE + 0x40b78, 0xf0f0f0);
+ outpdw(MDP_BASE + 0x40b7c, 0xf0f0f0);
+ outpdw(MDP_BASE + 0x40b80, 0xf1f1f1);
+ outpdw(MDP_BASE + 0x40b84, 0xf1f1f1);
+ outpdw(MDP_BASE + 0x40b88, 0xf2f2f2);
+ outpdw(MDP_BASE + 0x40b8c, 0xf2f2f2);
+ outpdw(MDP_BASE + 0x40b90, 0xf2f2f2);
+ outpdw(MDP_BASE + 0x40b94, 0xf3f3f3);
+ outpdw(MDP_BASE + 0x40b98, 0xf3f3f3);
+ outpdw(MDP_BASE + 0x40b9c, 0xf4f4f4);
+ outpdw(MDP_BASE + 0x40ba0, 0xf4f4f4);
+ outpdw(MDP_BASE + 0x40ba4, 0xf5f5f5);
+ outpdw(MDP_BASE + 0x40ba8, 0xf5f5f5);
+ outpdw(MDP_BASE + 0x40bac, 0xf6f6f6);
+ outpdw(MDP_BASE + 0x40bb0, 0xf6f6f6);
+ outpdw(MDP_BASE + 0x40bb4, 0xf7f7f7);
+ outpdw(MDP_BASE + 0x40bb8, 0xf7f7f7);
+ outpdw(MDP_BASE + 0x40bbc, 0xf8f8f8);
+ outpdw(MDP_BASE + 0x40bc0, 0xf8f8f8);
+ outpdw(MDP_BASE + 0x40bc4, 0xf9f9f9);
+ outpdw(MDP_BASE + 0x40bc8, 0xf9f9f9);
+ outpdw(MDP_BASE + 0x40bcc, 0xfafafa);
+ outpdw(MDP_BASE + 0x40bd0, 0xfafafa);
+ outpdw(MDP_BASE + 0x40bd4, 0xfafafa);
+ outpdw(MDP_BASE + 0x40bd8, 0xfbfbfb);
+ outpdw(MDP_BASE + 0x40bdc, 0xfbfbfb);
+ outpdw(MDP_BASE + 0x40be0, 0xfcfcfc);
+ outpdw(MDP_BASE + 0x40be4, 0xfcfcfc);
+ outpdw(MDP_BASE + 0x40be8, 0xfdfdfd);
+ outpdw(MDP_BASE + 0x40bec, 0xfdfdfd);
+ outpdw(MDP_BASE + 0x40bf0, 0xfefefe);
+ outpdw(MDP_BASE + 0x40bf4, 0xfefefe);
+ outpdw(MDP_BASE + 0x40bf8, 0xffffff);
+ outpdw(MDP_BASE + 0x40bfc, 0xffffff);
+ outpdw(MDP_BASE + 0x40c00, 0x0);
+ outpdw(MDP_BASE + 0x40c04, 0x0);
+ outpdw(MDP_BASE + 0x40c08, 0x0);
+ outpdw(MDP_BASE + 0x40c0c, 0x0);
+ outpdw(MDP_BASE + 0x40c10, 0x0);
+ outpdw(MDP_BASE + 0x40c14, 0x0);
+ outpdw(MDP_BASE + 0x40c18, 0x0);
+ outpdw(MDP_BASE + 0x40c1c, 0x0);
+ outpdw(MDP_BASE + 0x40c20, 0x0);
+ outpdw(MDP_BASE + 0x40c24, 0x0);
+ outpdw(MDP_BASE + 0x40c28, 0x0);
+ outpdw(MDP_BASE + 0x40c2c, 0x0);
+ outpdw(MDP_BASE + 0x40c30, 0x0);
+ outpdw(MDP_BASE + 0x40c34, 0x0);
+ outpdw(MDP_BASE + 0x40c38, 0x0);
+ outpdw(MDP_BASE + 0x40c3c, 0x0);
+ outpdw(MDP_BASE + 0x40c40, 0x10101);
+ outpdw(MDP_BASE + 0x40c44, 0x10101);
+ outpdw(MDP_BASE + 0x40c48, 0x10101);
+ outpdw(MDP_BASE + 0x40c4c, 0x10101);
+ outpdw(MDP_BASE + 0x40c50, 0x10101);
+ outpdw(MDP_BASE + 0x40c54, 0x10101);
+ outpdw(MDP_BASE + 0x40c58, 0x10101);
+ outpdw(MDP_BASE + 0x40c5c, 0x10101);
+ outpdw(MDP_BASE + 0x40c60, 0x10101);
+ outpdw(MDP_BASE + 0x40c64, 0x10101);
+ outpdw(MDP_BASE + 0x40c68, 0x20202);
+ outpdw(MDP_BASE + 0x40c6c, 0x20202);
+ outpdw(MDP_BASE + 0x40c70, 0x20202);
+ outpdw(MDP_BASE + 0x40c74, 0x20202);
+ outpdw(MDP_BASE + 0x40c78, 0x20202);
+ outpdw(MDP_BASE + 0x40c7c, 0x20202);
+ outpdw(MDP_BASE + 0x40c80, 0x30303);
+ outpdw(MDP_BASE + 0x40c84, 0x30303);
+ outpdw(MDP_BASE + 0x40c88, 0x30303);
+ outpdw(MDP_BASE + 0x40c8c, 0x30303);
+ outpdw(MDP_BASE + 0x40c90, 0x30303);
+ outpdw(MDP_BASE + 0x40c94, 0x40404);
+ outpdw(MDP_BASE + 0x40c98, 0x40404);
+ outpdw(MDP_BASE + 0x40c9c, 0x40404);
+ outpdw(MDP_BASE + 0x40ca0, 0x40404);
+ outpdw(MDP_BASE + 0x40ca4, 0x40404);
+ outpdw(MDP_BASE + 0x40ca8, 0x50505);
+ outpdw(MDP_BASE + 0x40cac, 0x50505);
+ outpdw(MDP_BASE + 0x40cb0, 0x50505);
+ outpdw(MDP_BASE + 0x40cb4, 0x50505);
+ outpdw(MDP_BASE + 0x40cb8, 0x60606);
+ outpdw(MDP_BASE + 0x40cbc, 0x60606);
+ outpdw(MDP_BASE + 0x40cc0, 0x60606);
+ outpdw(MDP_BASE + 0x40cc4, 0x70707);
+ outpdw(MDP_BASE + 0x40cc8, 0x70707);
+ outpdw(MDP_BASE + 0x40ccc, 0x70707);
+ outpdw(MDP_BASE + 0x40cd0, 0x70707);
+ outpdw(MDP_BASE + 0x40cd4, 0x80808);
+ outpdw(MDP_BASE + 0x40cd8, 0x80808);
+ outpdw(MDP_BASE + 0x40cdc, 0x80808);
+ outpdw(MDP_BASE + 0x40ce0, 0x90909);
+ outpdw(MDP_BASE + 0x40ce4, 0x90909);
+ outpdw(MDP_BASE + 0x40ce8, 0xa0a0a);
+ outpdw(MDP_BASE + 0x40cec, 0xa0a0a);
+ outpdw(MDP_BASE + 0x40cf0, 0xa0a0a);
+ outpdw(MDP_BASE + 0x40cf4, 0xb0b0b);
+ outpdw(MDP_BASE + 0x40cf8, 0xb0b0b);
+ outpdw(MDP_BASE + 0x40cfc, 0xb0b0b);
+ outpdw(MDP_BASE + 0x40d00, 0xc0c0c);
+ outpdw(MDP_BASE + 0x40d04, 0xc0c0c);
+ outpdw(MDP_BASE + 0x40d08, 0xd0d0d);
+ outpdw(MDP_BASE + 0x40d0c, 0xd0d0d);
+ outpdw(MDP_BASE + 0x40d10, 0xe0e0e);
+ outpdw(MDP_BASE + 0x40d14, 0xe0e0e);
+ outpdw(MDP_BASE + 0x40d18, 0xe0e0e);
+ outpdw(MDP_BASE + 0x40d1c, 0xf0f0f);
+ outpdw(MDP_BASE + 0x40d20, 0xf0f0f);
+ outpdw(MDP_BASE + 0x40d24, 0x101010);
+ outpdw(MDP_BASE + 0x40d28, 0x101010);
+ outpdw(MDP_BASE + 0x40d2c, 0x111111);
+ outpdw(MDP_BASE + 0x40d30, 0x111111);
+ outpdw(MDP_BASE + 0x40d34, 0x121212);
+ outpdw(MDP_BASE + 0x40d38, 0x121212);
+ outpdw(MDP_BASE + 0x40d3c, 0x131313);
+ outpdw(MDP_BASE + 0x40d40, 0x131313);
+ outpdw(MDP_BASE + 0x40d44, 0x141414);
+ outpdw(MDP_BASE + 0x40d48, 0x151515);
+ outpdw(MDP_BASE + 0x40d4c, 0x151515);
+ outpdw(MDP_BASE + 0x40d50, 0x161616);
+ outpdw(MDP_BASE + 0x40d54, 0x161616);
+ outpdw(MDP_BASE + 0x40d58, 0x171717);
+ outpdw(MDP_BASE + 0x40d5c, 0x171717);
+ outpdw(MDP_BASE + 0x40d60, 0x181818);
+ outpdw(MDP_BASE + 0x40d64, 0x191919);
+ outpdw(MDP_BASE + 0x40d68, 0x191919);
+ outpdw(MDP_BASE + 0x40d6c, 0x1a1a1a);
+ outpdw(MDP_BASE + 0x40d70, 0x1b1b1b);
+ outpdw(MDP_BASE + 0x40d74, 0x1b1b1b);
+ outpdw(MDP_BASE + 0x40d78, 0x1c1c1c);
+ outpdw(MDP_BASE + 0x40d7c, 0x1c1c1c);
+ outpdw(MDP_BASE + 0x40d80, 0x1d1d1d);
+ outpdw(MDP_BASE + 0x40d84, 0x1e1e1e);
+ outpdw(MDP_BASE + 0x40d88, 0x1f1f1f);
+ outpdw(MDP_BASE + 0x40d8c, 0x1f1f1f);
+ outpdw(MDP_BASE + 0x40d90, 0x202020);
+ outpdw(MDP_BASE + 0x40d94, 0x212121);
+ outpdw(MDP_BASE + 0x40d98, 0x212121);
+ outpdw(MDP_BASE + 0x40d9c, 0x222222);
+ outpdw(MDP_BASE + 0x40da0, 0x232323);
+ outpdw(MDP_BASE + 0x40da4, 0x242424);
+ outpdw(MDP_BASE + 0x40da8, 0x242424);
+ outpdw(MDP_BASE + 0x40dac, 0x252525);
+ outpdw(MDP_BASE + 0x40db0, 0x262626);
+ outpdw(MDP_BASE + 0x40db4, 0x272727);
+ outpdw(MDP_BASE + 0x40db8, 0x272727);
+ outpdw(MDP_BASE + 0x40dbc, 0x282828);
+ outpdw(MDP_BASE + 0x40dc0, 0x292929);
+ outpdw(MDP_BASE + 0x40dc4, 0x2a2a2a);
+ outpdw(MDP_BASE + 0x40dc8, 0x2b2b2b);
+ outpdw(MDP_BASE + 0x40dcc, 0x2c2c2c);
+ outpdw(MDP_BASE + 0x40dd0, 0x2c2c2c);
+ outpdw(MDP_BASE + 0x40dd4, 0x2d2d2d);
+ outpdw(MDP_BASE + 0x40dd8, 0x2e2e2e);
+ outpdw(MDP_BASE + 0x40ddc, 0x2f2f2f);
+ outpdw(MDP_BASE + 0x40de0, 0x303030);
+ outpdw(MDP_BASE + 0x40de4, 0x313131);
+ outpdw(MDP_BASE + 0x40de8, 0x323232);
+ outpdw(MDP_BASE + 0x40dec, 0x333333);
+ outpdw(MDP_BASE + 0x40df0, 0x333333);
+ outpdw(MDP_BASE + 0x40df4, 0x343434);
+ outpdw(MDP_BASE + 0x40df8, 0x353535);
+ outpdw(MDP_BASE + 0x40dfc, 0x363636);
+ outpdw(MDP_BASE + 0x40e00, 0x373737);
+ outpdw(MDP_BASE + 0x40e04, 0x383838);
+ outpdw(MDP_BASE + 0x40e08, 0x393939);
+ outpdw(MDP_BASE + 0x40e0c, 0x3a3a3a);
+ outpdw(MDP_BASE + 0x40e10, 0x3b3b3b);
+ outpdw(MDP_BASE + 0x40e14, 0x3c3c3c);
+ outpdw(MDP_BASE + 0x40e18, 0x3d3d3d);
+ outpdw(MDP_BASE + 0x40e1c, 0x3e3e3e);
+ outpdw(MDP_BASE + 0x40e20, 0x3f3f3f);
+ outpdw(MDP_BASE + 0x40e24, 0x404040);
+ outpdw(MDP_BASE + 0x40e28, 0x414141);
+ outpdw(MDP_BASE + 0x40e2c, 0x424242);
+ outpdw(MDP_BASE + 0x40e30, 0x434343);
+ outpdw(MDP_BASE + 0x40e34, 0x444444);
+ outpdw(MDP_BASE + 0x40e38, 0x464646);
+ outpdw(MDP_BASE + 0x40e3c, 0x474747);
+ outpdw(MDP_BASE + 0x40e40, 0x484848);
+ outpdw(MDP_BASE + 0x40e44, 0x494949);
+ outpdw(MDP_BASE + 0x40e48, 0x4a4a4a);
+ outpdw(MDP_BASE + 0x40e4c, 0x4b4b4b);
+ outpdw(MDP_BASE + 0x40e50, 0x4c4c4c);
+ outpdw(MDP_BASE + 0x40e54, 0x4d4d4d);
+ outpdw(MDP_BASE + 0x40e58, 0x4f4f4f);
+ outpdw(MDP_BASE + 0x40e5c, 0x505050);
+ outpdw(MDP_BASE + 0x40e60, 0x515151);
+ outpdw(MDP_BASE + 0x40e64, 0x525252);
+ outpdw(MDP_BASE + 0x40e68, 0x535353);
+ outpdw(MDP_BASE + 0x40e6c, 0x545454);
+ outpdw(MDP_BASE + 0x40e70, 0x565656);
+ outpdw(MDP_BASE + 0x40e74, 0x575757);
+ outpdw(MDP_BASE + 0x40e78, 0x585858);
+ outpdw(MDP_BASE + 0x40e7c, 0x595959);
+ outpdw(MDP_BASE + 0x40e80, 0x5b5b5b);
+ outpdw(MDP_BASE + 0x40e84, 0x5c5c5c);
+ outpdw(MDP_BASE + 0x40e88, 0x5d5d5d);
+ outpdw(MDP_BASE + 0x40e8c, 0x5e5e5e);
+ outpdw(MDP_BASE + 0x40e90, 0x606060);
+ outpdw(MDP_BASE + 0x40e94, 0x616161);
+ outpdw(MDP_BASE + 0x40e98, 0x626262);
+ outpdw(MDP_BASE + 0x40e9c, 0x646464);
+ outpdw(MDP_BASE + 0x40ea0, 0x656565);
+ outpdw(MDP_BASE + 0x40ea4, 0x666666);
+ outpdw(MDP_BASE + 0x40ea8, 0x686868);
+ outpdw(MDP_BASE + 0x40eac, 0x696969);
+ outpdw(MDP_BASE + 0x40eb0, 0x6a6a6a);
+ outpdw(MDP_BASE + 0x40eb4, 0x6c6c6c);
+ outpdw(MDP_BASE + 0x40eb8, 0x6d6d6d);
+ outpdw(MDP_BASE + 0x40ebc, 0x6f6f6f);
+ outpdw(MDP_BASE + 0x40ec0, 0x707070);
+ outpdw(MDP_BASE + 0x40ec4, 0x717171);
+ outpdw(MDP_BASE + 0x40ec8, 0x737373);
+ outpdw(MDP_BASE + 0x40ecc, 0x747474);
+ outpdw(MDP_BASE + 0x40ed0, 0x767676);
+ outpdw(MDP_BASE + 0x40ed4, 0x777777);
+ outpdw(MDP_BASE + 0x40ed8, 0x797979);
+ outpdw(MDP_BASE + 0x40edc, 0x7a7a7a);
+ outpdw(MDP_BASE + 0x40ee0, 0x7c7c7c);
+ outpdw(MDP_BASE + 0x40ee4, 0x7d7d7d);
+ outpdw(MDP_BASE + 0x40ee8, 0x7f7f7f);
+ outpdw(MDP_BASE + 0x40eec, 0x808080);
+ outpdw(MDP_BASE + 0x40ef0, 0x828282);
+ outpdw(MDP_BASE + 0x40ef4, 0x838383);
+ outpdw(MDP_BASE + 0x40ef8, 0x858585);
+ outpdw(MDP_BASE + 0x40efc, 0x868686);
+ outpdw(MDP_BASE + 0x40f00, 0x888888);
+ outpdw(MDP_BASE + 0x40f04, 0x898989);
+ outpdw(MDP_BASE + 0x40f08, 0x8b8b8b);
+ outpdw(MDP_BASE + 0x40f0c, 0x8d8d8d);
+ outpdw(MDP_BASE + 0x40f10, 0x8e8e8e);
+ outpdw(MDP_BASE + 0x40f14, 0x909090);
+ outpdw(MDP_BASE + 0x40f18, 0x919191);
+ outpdw(MDP_BASE + 0x40f1c, 0x939393);
+ outpdw(MDP_BASE + 0x40f20, 0x959595);
+ outpdw(MDP_BASE + 0x40f24, 0x969696);
+ outpdw(MDP_BASE + 0x40f28, 0x989898);
+ outpdw(MDP_BASE + 0x40f2c, 0x9a9a9a);
+ outpdw(MDP_BASE + 0x40f30, 0x9b9b9b);
+ outpdw(MDP_BASE + 0x40f34, 0x9d9d9d);
+ outpdw(MDP_BASE + 0x40f38, 0x9f9f9f);
+ outpdw(MDP_BASE + 0x40f3c, 0xa1a1a1);
+ outpdw(MDP_BASE + 0x40f40, 0xa2a2a2);
+ outpdw(MDP_BASE + 0x40f44, 0xa4a4a4);
+ outpdw(MDP_BASE + 0x40f48, 0xa6a6a6);
+ outpdw(MDP_BASE + 0x40f4c, 0xa7a7a7);
+ outpdw(MDP_BASE + 0x40f50, 0xa9a9a9);
+ outpdw(MDP_BASE + 0x40f54, 0xababab);
+ outpdw(MDP_BASE + 0x40f58, 0xadadad);
+ outpdw(MDP_BASE + 0x40f5c, 0xafafaf);
+ outpdw(MDP_BASE + 0x40f60, 0xb0b0b0);
+ outpdw(MDP_BASE + 0x40f64, 0xb2b2b2);
+ outpdw(MDP_BASE + 0x40f68, 0xb4b4b4);
+ outpdw(MDP_BASE + 0x40f6c, 0xb6b6b6);
+ outpdw(MDP_BASE + 0x40f70, 0xb8b8b8);
+ outpdw(MDP_BASE + 0x40f74, 0xbababa);
+ outpdw(MDP_BASE + 0x40f78, 0xbbbbbb);
+ outpdw(MDP_BASE + 0x40f7c, 0xbdbdbd);
+ outpdw(MDP_BASE + 0x40f80, 0xbfbfbf);
+ outpdw(MDP_BASE + 0x40f84, 0xc1c1c1);
+ outpdw(MDP_BASE + 0x40f88, 0xc3c3c3);
+ outpdw(MDP_BASE + 0x40f8c, 0xc5c5c5);
+ outpdw(MDP_BASE + 0x40f90, 0xc7c7c7);
+ outpdw(MDP_BASE + 0x40f94, 0xc9c9c9);
+ outpdw(MDP_BASE + 0x40f98, 0xcbcbcb);
+ outpdw(MDP_BASE + 0x40f9c, 0xcdcdcd);
+ outpdw(MDP_BASE + 0x40fa0, 0xcfcfcf);
+ outpdw(MDP_BASE + 0x40fa4, 0xd1d1d1);
+ outpdw(MDP_BASE + 0x40fa8, 0xd3d3d3);
+ outpdw(MDP_BASE + 0x40fac, 0xd5d5d5);
+ outpdw(MDP_BASE + 0x40fb0, 0xd7d7d7);
+ outpdw(MDP_BASE + 0x40fb4, 0xd9d9d9);
+ outpdw(MDP_BASE + 0x40fb8, 0xdbdbdb);
+ outpdw(MDP_BASE + 0x40fbc, 0xdddddd);
+ outpdw(MDP_BASE + 0x40fc0, 0xdfdfdf);
+ outpdw(MDP_BASE + 0x40fc4, 0xe1e1e1);
+ outpdw(MDP_BASE + 0x40fc8, 0xe3e3e3);
+ outpdw(MDP_BASE + 0x40fcc, 0xe5e5e5);
+ outpdw(MDP_BASE + 0x40fd0, 0xe7e7e7);
+ outpdw(MDP_BASE + 0x40fd4, 0xe9e9e9);
+ outpdw(MDP_BASE + 0x40fd8, 0xebebeb);
+ outpdw(MDP_BASE + 0x40fdc, 0xeeeeee);
+ outpdw(MDP_BASE + 0x40fe0, 0xf0f0f0);
+ outpdw(MDP_BASE + 0x40fe4, 0xf2f2f2);
+ outpdw(MDP_BASE + 0x40fe8, 0xf4f4f4);
+ outpdw(MDP_BASE + 0x40fec, 0xf6f6f6);
+ outpdw(MDP_BASE + 0x40ff0, 0xf8f8f8);
+ outpdw(MDP_BASE + 0x40ff4, 0xfbfbfb);
+ outpdw(MDP_BASE + 0x40ff8, 0xfdfdfd);
+ outpdw(MDP_BASE + 0x40ffc, 0xffffff);
+}
+
+#define IRQ_EN_1__MDP_IRQ___M 0x00000800
+
+void mdp_hw_init(void)
+{
+ int i;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ /* debug interface write access */
+ outpdw(MDP_BASE + 0x60, 1);
+
+ outp32(MDP_INTR_ENABLE, MDP_ANY_INTR_MASK);
+ outp32(MDP_EBI2_PORTMAP_MODE, 0x3);
+ outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8, 0x0);
+ outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc, 0x0);
+ outpdw(MDP_BASE + 0x60, 0x1);
+ mdp_load_lut_param();
+
+ /*
+ * clear up unused fg/main registers
+ */
+ /* comp.plane 2&3 ystride */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0120, 0x0);
+ /* unpacked pattern */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x012c, 0x0);
+ /* unpacked pattern */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0130, 0x0);
+ /* unpacked pattern */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0134, 0x0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0158, 0x0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x15c, 0x0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0160, 0x0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0170, 0x0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0174, 0x0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x017c, 0x0);
+
+ /* comp.plane 2 */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0114, 0x0);
+ /* comp.plane 3 */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0118, 0x0);
+
+ /* clear up unused bg registers */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8, 0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0, 0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc, 0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0, 0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4, 0);
+
+#ifndef CONFIG_FB_MSM_MDP22
+ MDP_OUTP(MDP_BASE + 0xE0000, 0);
+ MDP_OUTP(MDP_BASE + 0x100, 0xffffffff);
+ MDP_OUTP(MDP_BASE + 0x90070, 0);
+ MDP_OUTP(MDP_BASE + 0x94010, 1);
+ MDP_OUTP(MDP_BASE + 0x9401c, 2);
+#endif
+
+ /*
+ * limit vector
+ * pre gets applied before color matrix conversion
+ * post is after ccs
+ */
+ writel(mdp_plv[0], MDP_CSC_PRE_LV1n(0));
+ writel(mdp_plv[1], MDP_CSC_PRE_LV1n(1));
+ writel(mdp_plv[2], MDP_CSC_PRE_LV1n(2));
+ writel(mdp_plv[3], MDP_CSC_PRE_LV1n(3));
+
+#ifdef CONFIG_FB_MSM_MDP31
+ writel(mdp_plv[2], MDP_CSC_PRE_LV1n(4));
+ writel(mdp_plv[3], MDP_CSC_PRE_LV1n(5));
+
+ writel(0, MDP_CSC_POST_LV1n(0));
+ writel(0xff, MDP_CSC_POST_LV1n(1));
+ writel(0, MDP_CSC_POST_LV1n(2));
+ writel(0xff, MDP_CSC_POST_LV1n(3));
+ writel(0, MDP_CSC_POST_LV1n(4));
+ writel(0xff, MDP_CSC_POST_LV1n(5));
+
+ writel(0, MDP_CSC_PRE_LV2n(0));
+ writel(0xff, MDP_CSC_PRE_LV2n(1));
+ writel(0, MDP_CSC_PRE_LV2n(2));
+ writel(0xff, MDP_CSC_PRE_LV2n(3));
+ writel(0, MDP_CSC_PRE_LV2n(4));
+ writel(0xff, MDP_CSC_PRE_LV2n(5));
+
+ writel(mdp_plv[0], MDP_CSC_POST_LV2n(0));
+ writel(mdp_plv[1], MDP_CSC_POST_LV2n(1));
+ writel(mdp_plv[2], MDP_CSC_POST_LV2n(2));
+ writel(mdp_plv[3], MDP_CSC_POST_LV2n(3));
+ writel(mdp_plv[2], MDP_CSC_POST_LV2n(4));
+ writel(mdp_plv[3], MDP_CSC_POST_LV2n(5));
+#endif
+
+ /* primary forward matrix */
+ for (i = 0; i < MDP_CCS_SIZE; i++)
+ writel(mdp_ccs_rgb2yuv.ccs[i], MDP_CSC_PFMVn(i));
+
+#ifdef CONFIG_FB_MSM_MDP31
+ for (i = 0; i < MDP_BV_SIZE; i++)
+ writel(mdp_ccs_rgb2yuv.bv[i], MDP_CSC_POST_BV2n(i));
+
+ writel(0, MDP_CSC_PRE_BV2n(0));
+ writel(0, MDP_CSC_PRE_BV2n(1));
+ writel(0, MDP_CSC_PRE_BV2n(2));
+#endif
+ /* primary reverse matrix */
+ for (i = 0; i < MDP_CCS_SIZE; i++)
+ writel(mdp_ccs_yuv2rgb.ccs[i], MDP_CSC_PRMVn(i));
+
+ for (i = 0; i < MDP_BV_SIZE; i++)
+ writel(mdp_ccs_yuv2rgb.bv[i], MDP_CSC_PRE_BV1n(i));
+
+#ifdef CONFIG_FB_MSM_MDP31
+ writel(0, MDP_CSC_POST_BV1n(0));
+ writel(0, MDP_CSC_POST_BV1n(1));
+ writel(0, MDP_CSC_POST_BV1n(2));
+
+ outpdw(MDP_BASE + 0x30010, 0x03e0);
+ outpdw(MDP_BASE + 0x30014, 0x0360);
+ outpdw(MDP_BASE + 0x30018, 0x0120);
+ outpdw(MDP_BASE + 0x3001c, 0x0140);
+#endif
+ mdp_init_scale_table();
+
+#ifndef CONFIG_FB_MSM_MDP31
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0104,
+ ((16 << 6) << 16) | (16) << 6);
+#endif
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
diff --git a/drivers/video/msm/mdp_lcdc.c b/drivers/video/msm/mdp_lcdc.c
new file mode 100644
index 0000000..be8d39d
--- /dev/null
+++ b/drivers/video/msm/mdp_lcdc.c
@@ -0,0 +1,432 @@
+/* drivers/video/msm/mdp_lcdc.c
+ *
+ * Copyright (c) 2009 Google Inc.
+ * Copyright (c) 2009 Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ * Author: Dima Zavin <dima@android.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/mach-types.h>
+
+#include <mach/msm_fb.h>
+
+#include "mdp_hw.h"
+
+struct mdp_lcdc_info {
+ struct mdp_info *mdp;
+ struct clk *mdp_clk;
+ struct clk *pclk;
+ struct clk *pad_pclk;
+ struct msm_panel_data fb_panel_data;
+ struct platform_device fb_pdev;
+ struct msm_lcdc_platform_data *pdata;
+ uint32_t fb_start;
+
+ struct msmfb_callback frame_start_cb;
+ wait_queue_head_t vsync_waitq;
+ int got_vsync;
+
+ struct {
+ uint32_t clk_rate;
+ uint32_t hsync_ctl;
+ uint32_t vsync_period;
+ uint32_t vsync_pulse_width;
+ uint32_t display_hctl;
+ uint32_t display_vstart;
+ uint32_t display_vend;
+ uint32_t hsync_skew;
+ uint32_t polarity;
+ } parms;
+};
+
+static struct mdp_device *mdp_dev;
+
+#define panel_to_lcdc(p) container_of((p), struct mdp_lcdc_info, fb_panel_data)
+
+static int lcdc_unblank(struct msm_panel_data *fb_panel)
+{
+ struct mdp_lcdc_info *lcdc = panel_to_lcdc(fb_panel);
+ struct msm_lcdc_panel_ops *panel_ops = lcdc->pdata->panel_ops;
+
+ pr_info("%s: ()\n", __func__);
+ panel_ops->unblank(panel_ops);
+
+ return 0;
+}
+
+static int lcdc_blank(struct msm_panel_data *fb_panel)
+{
+ struct mdp_lcdc_info *lcdc = panel_to_lcdc(fb_panel);
+ struct msm_lcdc_panel_ops *panel_ops = lcdc->pdata->panel_ops;
+
+ pr_info("%s: ()\n", __func__);
+ panel_ops->blank(panel_ops);
+
+ return 0;
+}
+
+static int lcdc_suspend(struct msm_panel_data *fb_panel)
+{
+ struct mdp_lcdc_info *lcdc = panel_to_lcdc(fb_panel);
+
+ pr_info("%s: suspending\n", __func__);
+
+ mdp_writel(lcdc->mdp, 0, MDP_LCDC_EN);
+ clk_disable(lcdc->pad_pclk);
+ clk_disable(lcdc->pclk);
+ clk_disable(lcdc->mdp_clk);
+
+ return 0;
+}
+
+static int lcdc_resume(struct msm_panel_data *fb_panel)
+{
+ struct mdp_lcdc_info *lcdc = panel_to_lcdc(fb_panel);
+
+ pr_info("%s: resuming\n", __func__);
+
+ clk_enable(lcdc->mdp_clk);
+ clk_enable(lcdc->pclk);
+ clk_enable(lcdc->pad_pclk);
+ mdp_writel(lcdc->mdp, 1, MDP_LCDC_EN);
+
+ return 0;
+}
+
+static int lcdc_hw_init(struct mdp_lcdc_info *lcdc)
+{
+ struct msm_panel_data *fb_panel = &lcdc->fb_panel_data;
+ uint32_t dma_cfg;
+
+ clk_enable(lcdc->mdp_clk);
+ clk_enable(lcdc->pclk);
+ clk_enable(lcdc->pad_pclk);
+
+ clk_set_rate(lcdc->pclk, lcdc->parms.clk_rate);
+ clk_set_rate(lcdc->pad_pclk, lcdc->parms.clk_rate);
+
+ /* write the lcdc params */
+ mdp_writel(lcdc->mdp, lcdc->parms.hsync_ctl, MDP_LCDC_HSYNC_CTL);
+ mdp_writel(lcdc->mdp, lcdc->parms.vsync_period, MDP_LCDC_VSYNC_PERIOD);
+ mdp_writel(lcdc->mdp, lcdc->parms.vsync_pulse_width,
+ MDP_LCDC_VSYNC_PULSE_WIDTH);
+ mdp_writel(lcdc->mdp, lcdc->parms.display_hctl, MDP_LCDC_DISPLAY_HCTL);
+ mdp_writel(lcdc->mdp, lcdc->parms.display_vstart,
+ MDP_LCDC_DISPLAY_V_START);
+ mdp_writel(lcdc->mdp, lcdc->parms.display_vend, MDP_LCDC_DISPLAY_V_END);
+ mdp_writel(lcdc->mdp, lcdc->parms.hsync_skew, MDP_LCDC_HSYNC_SKEW);
+
+ mdp_writel(lcdc->mdp, 0, MDP_LCDC_BORDER_CLR);
+ mdp_writel(lcdc->mdp, 0xff, MDP_LCDC_UNDERFLOW_CTL);
+ mdp_writel(lcdc->mdp, 0, MDP_LCDC_ACTIVE_HCTL);
+ mdp_writel(lcdc->mdp, 0, MDP_LCDC_ACTIVE_V_START);
+ mdp_writel(lcdc->mdp, 0, MDP_LCDC_ACTIVE_V_END);
+ mdp_writel(lcdc->mdp, lcdc->parms.polarity, MDP_LCDC_CTL_POLARITY);
+
+ /* config the dma_p block that drives the lcdc data */
+ mdp_writel(lcdc->mdp, lcdc->fb_start, MDP_DMA_P_IBUF_ADDR);
+ mdp_writel(lcdc->mdp, (((fb_panel->fb_data->yres & 0x7ff) << 16) |
+ (fb_panel->fb_data->xres & 0x7ff)),
+ MDP_DMA_P_SIZE);
+
+ mdp_writel(lcdc->mdp, 0, MDP_DMA_P_OUT_XY);
+
+ dma_cfg = mdp_readl(lcdc->mdp, MDP_DMA_P_CONFIG);
+ dma_cfg |= (DMA_PACK_ALIGN_LSB |
+ DMA_PACK_PATTERN_RGB |
+ DMA_DITHER_EN);
+ dma_cfg |= DMA_OUT_SEL_LCDC;
+ dma_cfg &= ~DMA_DST_BITS_MASK;
+
+ if (fb_panel->fb_data->output_format == MSM_MDP_OUT_IF_FMT_RGB666)
+ dma_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+ else
+ dma_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
+
+ mdp_writel(lcdc->mdp, dma_cfg, MDP_DMA_P_CONFIG);
+
+ /* enable the lcdc timing generation */
+ mdp_writel(lcdc->mdp, 1, MDP_LCDC_EN);
+
+ return 0;
+}
+
+static void lcdc_wait_vsync(struct msm_panel_data *panel)
+{
+ struct mdp_lcdc_info *lcdc = panel_to_lcdc(panel);
+ int ret;
+
+ ret = wait_event_timeout(lcdc->vsync_waitq, lcdc->got_vsync, HZ / 2);
+ if (!ret && !lcdc->got_vsync)
+ pr_err("%s: timeout waiting for VSYNC\n", __func__);
+ lcdc->got_vsync = 0;
+}
+
+static void lcdc_request_vsync(struct msm_panel_data *fb_panel,
+ struct msmfb_callback *vsync_cb)
+{
+ struct mdp_lcdc_info *lcdc = panel_to_lcdc(fb_panel);
+
+ /* the vsync callback will start the dma */
+ vsync_cb->func(vsync_cb);
+ lcdc->got_vsync = 0;
+ mdp_out_if_req_irq(mdp_dev, MSM_LCDC_INTERFACE, MDP_LCDC_FRAME_START,
+ &lcdc->frame_start_cb);
+ lcdc_wait_vsync(fb_panel);
+}
+
+static void lcdc_clear_vsync(struct msm_panel_data *fb_panel)
+{
+ struct mdp_lcdc_info *lcdc = panel_to_lcdc(fb_panel);
+ lcdc->got_vsync = 0;
+ mdp_out_if_req_irq(mdp_dev, MSM_LCDC_INTERFACE, 0, NULL);
+}
+
+/* called in irq context with mdp lock held, when mdp gets the
+ * MDP_LCDC_FRAME_START interrupt */
+static void lcdc_frame_start(struct msmfb_callback *cb)
+{
+ struct mdp_lcdc_info *lcdc;
+
+ lcdc = container_of(cb, struct mdp_lcdc_info, frame_start_cb);
+
+ lcdc->got_vsync = 1;
+ wake_up(&lcdc->vsync_waitq);
+}
+
+static void lcdc_dma_start(void *priv, uint32_t addr, uint32_t stride,
+ uint32_t width, uint32_t height, uint32_t x,
+ uint32_t y)
+{
+ struct mdp_lcdc_info *lcdc = priv;
+
+ struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
+ if (mdp->dma_config_dirty)
+ {
+ mdp_writel(lcdc->mdp, 0, MDP_LCDC_EN);
+ mdelay(20);
+ mdp_dev->configure_dma(mdp_dev);
+ mdp_writel(lcdc->mdp, 1, MDP_LCDC_EN);
+ }
+ mdp_writel(lcdc->mdp, stride, MDP_DMA_P_IBUF_Y_STRIDE);
+ mdp_writel(lcdc->mdp, addr, MDP_DMA_P_IBUF_ADDR);
+}
+
+static void precompute_timing_parms(struct mdp_lcdc_info *lcdc)
+{
+ struct msm_lcdc_timing *timing = lcdc->pdata->timing;
+ struct msm_fb_data *fb_data = lcdc->pdata->fb_data;
+ unsigned int hsync_period;
+ unsigned int hsync_start_x;
+ unsigned int hsync_end_x;
+ unsigned int vsync_period;
+ unsigned int display_vstart;
+ unsigned int display_vend;
+
+ hsync_period = (timing->hsync_back_porch +
+ fb_data->xres + timing->hsync_front_porch);
+ hsync_start_x = timing->hsync_back_porch;
+ hsync_end_x = hsync_start_x + fb_data->xres - 1;
+
+ vsync_period = (timing->vsync_back_porch +
+ fb_data->yres + timing->vsync_front_porch);
+ vsync_period *= hsync_period;
+
+ display_vstart = timing->vsync_back_porch;
+ display_vstart *= hsync_period;
+ display_vstart += timing->hsync_skew;
+
+ display_vend = (timing->vsync_back_porch + fb_data->yres) *
+ hsync_period;
+ display_vend += timing->hsync_skew - 1;
+
+ /* register values we pre-compute at init time from the timing
+ * information in the panel info */
+ lcdc->parms.hsync_ctl = (((hsync_period & 0xfff) << 16) |
+ (timing->hsync_pulse_width & 0xfff));
+ lcdc->parms.vsync_period = vsync_period & 0xffffff;
+ lcdc->parms.vsync_pulse_width = (timing->vsync_pulse_width *
+ hsync_period) & 0xffffff;
+
+ lcdc->parms.display_hctl = (((hsync_end_x & 0xfff) << 16) |
+ (hsync_start_x & 0xfff));
+ lcdc->parms.display_vstart = display_vstart & 0xffffff;
+ lcdc->parms.display_vend = display_vend & 0xffffff;
+ lcdc->parms.hsync_skew = timing->hsync_skew & 0xfff;
+ lcdc->parms.polarity = ((timing->hsync_act_low << 0) |
+ (timing->vsync_act_low << 1) |
+ (timing->den_act_low << 2));
+ lcdc->parms.clk_rate = timing->clk_rate;
+}
+
+static int mdp_lcdc_probe(struct platform_device *pdev)
+{
+ struct msm_lcdc_platform_data *pdata = pdev->dev.platform_data;
+ struct mdp_lcdc_info *lcdc;
+ int ret = 0;
+
+ if (!pdata) {
+ pr_err("%s: no LCDC platform data found\n", __func__);
+ return -EINVAL;
+ }
+
+ lcdc = kzalloc(sizeof(struct mdp_lcdc_info), GFP_KERNEL);
+ if (!lcdc)
+ return -ENOMEM;
+
+ /* We don't actually own the clocks, the mdp does. */
+ lcdc->mdp_clk = clk_get(mdp_dev->dev.parent, "mdp_clk");
+ if (IS_ERR(lcdc->mdp_clk)) {
+ pr_err("%s: failed to get mdp_clk\n", __func__);
+ ret = PTR_ERR(lcdc->mdp_clk);
+ goto err_get_mdp_clk;
+ }
+
+ lcdc->pclk = clk_get(mdp_dev->dev.parent, "lcdc_pclk_clk");
+ if (IS_ERR(lcdc->pclk)) {
+ pr_err("%s: failed to get lcdc_pclk\n", __func__);
+ ret = PTR_ERR(lcdc->pclk);
+ goto err_get_pclk;
+ }
+
+ lcdc->pad_pclk = clk_get(mdp_dev->dev.parent, "lcdc_pad_pclk_clk");
+ if (IS_ERR(lcdc->pad_pclk)) {
+ pr_err("%s: failed to get lcdc_pad_pclk\n", __func__);
+ ret = PTR_ERR(lcdc->pad_pclk);
+ goto err_get_pad_pclk;
+ }
+
+ init_waitqueue_head(&lcdc->vsync_waitq);
+ lcdc->pdata = pdata;
+ lcdc->frame_start_cb.func = lcdc_frame_start;
+
+ platform_set_drvdata(pdev, lcdc);
+
+ mdp_out_if_register(mdp_dev, MSM_LCDC_INTERFACE, lcdc, MDP_DMA_P_DONE,
+ lcdc_dma_start);
+
+ precompute_timing_parms(lcdc);
+
+ lcdc->fb_start = pdata->fb_resource->start;
+ lcdc->mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
+
+ lcdc->fb_panel_data.suspend = lcdc_suspend;
+ lcdc->fb_panel_data.resume = lcdc_resume;
+ lcdc->fb_panel_data.wait_vsync = lcdc_wait_vsync;
+ lcdc->fb_panel_data.request_vsync = lcdc_request_vsync;
+ lcdc->fb_panel_data.clear_vsync = lcdc_clear_vsync;
+ lcdc->fb_panel_data.blank = lcdc_blank;
+ lcdc->fb_panel_data.unblank = lcdc_unblank;
+ lcdc->fb_panel_data.fb_data = pdata->fb_data;
+ lcdc->fb_panel_data.interface_type = MSM_LCDC_INTERFACE;
+
+ ret = lcdc_hw_init(lcdc);
+ if (ret) {
+ pr_err("%s: Cannot initialize the mdp_lcdc\n", __func__);
+ goto err_hw_init;
+ }
+
+ lcdc->fb_pdev.name = "msm_panel";
+ lcdc->fb_pdev.id = pdata->fb_id;
+ lcdc->fb_pdev.resource = pdata->fb_resource;
+ lcdc->fb_pdev.num_resources = 1;
+ lcdc->fb_pdev.dev.platform_data = &lcdc->fb_panel_data;
+
+ if (pdata->panel_ops->init)
+ pdata->panel_ops->init(pdata->panel_ops);
+
+ ret = platform_device_register(&lcdc->fb_pdev);
+ if (ret) {
+ pr_err("%s: Cannot register msm_panel pdev\n", __func__);
+ goto err_plat_dev_reg;
+ }
+
+ pr_info("%s: initialized\n", __func__);
+
+ return 0;
+
+err_plat_dev_reg:
+err_hw_init:
+ platform_set_drvdata(pdev, NULL);
+ clk_put(lcdc->pad_pclk);
+err_get_pad_pclk:
+ clk_put(lcdc->pclk);
+err_get_pclk:
+ clk_put(lcdc->mdp_clk);
+err_get_mdp_clk:
+ kfree(lcdc);
+ return ret;
+}
+
+static int mdp_lcdc_remove(struct platform_device *pdev)
+{
+ struct mdp_lcdc_info *lcdc = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ clk_put(lcdc->pclk);
+ clk_put(lcdc->pad_pclk);
+ kfree(lcdc);
+
+ return 0;
+}
+
+static struct platform_driver mdp_lcdc_driver = {
+ .probe = mdp_lcdc_probe,
+ .remove = mdp_lcdc_remove,
+ .driver = {
+ .name = "msm_mdp_lcdc",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int mdp_lcdc_add_mdp_device(struct device *dev,
+ struct class_interface *class_intf)
+{
+ /* might need locking if mulitple mdp devices */
+ if (mdp_dev)
+ return 0;
+ mdp_dev = container_of(dev, struct mdp_device, dev);
+ return platform_driver_register(&mdp_lcdc_driver);
+}
+
+static void mdp_lcdc_remove_mdp_device(struct device *dev,
+ struct class_interface *class_intf)
+{
+ /* might need locking if mulitple mdp devices */
+ if (dev != &mdp_dev->dev)
+ return;
+ platform_driver_unregister(&mdp_lcdc_driver);
+ mdp_dev = NULL;
+}
+
+static struct class_interface mdp_lcdc_interface = {
+ .add_dev = &mdp_lcdc_add_mdp_device,
+ .remove_dev = &mdp_lcdc_remove_mdp_device,
+};
+
+static int __init mdp_lcdc_init(void)
+{
+ return register_mdp_client(&mdp_lcdc_interface);
+}
+
+module_init(mdp_lcdc_init);
diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
index 2b6564e..19dfe82 100644
--- a/drivers/video/msm/mdp_ppp.c
+++ b/drivers/video/msm/mdp_ppp.c
@@ -1,7 +1,7 @@
-/* drivers/video/msm/mdp_ppp.c
+/* drivers/video/msm/src/drv/mdp/mdp_ppp.c
*
- * Copyright (C) 2007 QUALCOMM Incorporated
* Copyright (C) 2007 Google Incorporated
+ * Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -12,55 +12,35 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/fb.h>
-#include <linux/file.h>
-#include <linux/delay.h>
#include <linux/msm_mdp.h>
-#include <mach/msm_fb.h>
+#include <linux/file.h>
+#include <linux/android_pmem.h>
+#include <linux/major.h>
-#include "mdp_hw.h"
-#include "mdp_scale_tables.h"
+#include "linux/proc_fs.h"
-#define DLOG(x...) do {} while (0)
+#include <mach/hardware.h>
+#include <linux/io.h>
-#define MDP_DOWNSCALE_BLUR (MDP_DOWNSCALE_MAX + 1)
-static int downscale_y_table = MDP_DOWNSCALE_MAX;
-static int downscale_x_table = MDP_DOWNSCALE_MAX;
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/msm_kgsl.h>
-struct mdp_regs {
- uint32_t src0;
- uint32_t src1;
- uint32_t dst0;
- uint32_t dst1;
- uint32_t src_cfg;
- uint32_t dst_cfg;
- uint32_t src_pack;
- uint32_t dst_pack;
- uint32_t src_rect;
- uint32_t dst_rect;
- uint32_t src_ystride;
- uint32_t dst_ystride;
- uint32_t op;
- uint32_t src_bpp;
- uint32_t dst_bpp;
- uint32_t edge;
- uint32_t phasex_init;
- uint32_t phasey_init;
- uint32_t phasex_step;
- uint32_t phasey_step;
-};
+#include "mdp.h"
+#include "msm_fb.h"
-static uint32_t pack_pattern[] = {
- PPP_ARRAY0(PACK_PATTERN)
-};
-
-static uint32_t src_img_cfg[] = {
- PPP_ARRAY1(CFG, SRC)
-};
-
-static uint32_t dst_img_cfg[] = {
- PPP_ARRAY1(CFG, DST)
-};
+#define MDP_IS_IMGTYPE_BAD(x) (((x) >= MDP_IMGTYPE_LIMIT) && \
+ (((x) < MDP_IMGTYPE2_START) || \
+ ((x) >= MDP_IMGTYPE_LIMIT2)))
static uint32_t bytes_per_pixel[] = {
[MDP_RGB_565] = 2,
@@ -74,457 +54,499 @@
[MDP_Y_CBCR_H2V2] = 1,
[MDP_Y_CRCB_H2V1] = 1,
[MDP_Y_CRCB_H2V2] = 1,
- [MDP_YCRYCB_H2V1] = 2
+ [MDP_YCRYCB_H2V1] = 2,
+ [MDP_BGR_565] = 2
};
-static uint32_t dst_op_chroma[] = {
- PPP_ARRAY1(CHROMA_SAMP, DST)
-};
+extern uint32 mdp_plv[];
+extern struct semaphore mdp_ppp_mutex;
-static uint32_t src_op_chroma[] = {
- PPP_ARRAY1(CHROMA_SAMP, SRC)
-};
-
-static uint32_t bg_op_chroma[] = {
- PPP_ARRAY1(CHROMA_SAMP, BG)
-};
-
-static void rotate_dst_addr_x(struct mdp_blit_req *req, struct mdp_regs *regs)
+int mdp_get_bytes_per_pixel(uint32_t format,
+ struct msm_fb_data_type *mfd)
{
- regs->dst0 += (req->dst_rect.w -
- min((uint32_t)16, req->dst_rect.w)) * regs->dst_bpp;
- regs->dst1 += (req->dst_rect.w -
- min((uint32_t)16, req->dst_rect.w)) * regs->dst_bpp;
+ int bpp = -EINVAL;
+ if (format == MDP_FB_FORMAT)
+ format = mfd->fb_imgType;
+ if (format < ARRAY_SIZE(bytes_per_pixel))
+ bpp = bytes_per_pixel[format];
+
+ if (bpp <= 0)
+ printk(KERN_ERR "%s incorrect format %d\n", __func__, format);
+ return bpp;
}
-static void rotate_dst_addr_y(struct mdp_blit_req *req, struct mdp_regs *regs)
+static uint32 mdp_conv_matx_rgb2yuv(uint32 input_pixel,
+ uint16 *matrix_and_bias_vector,
+ uint32 *clamp_vector,
+ uint32 *look_up_table)
{
- regs->dst0 += (req->dst_rect.h -
- min((uint32_t)16, req->dst_rect.h)) *
- regs->dst_ystride;
- regs->dst1 += (req->dst_rect.h -
- min((uint32_t)16, req->dst_rect.h)) *
- regs->dst_ystride;
-}
+ uint8 input_C2, input_C0, input_C1;
+ uint32 output;
+ int32 comp_C2, comp_C1, comp_C0, temp;
+ int32 temp1, temp2, temp3;
+ int32 matrix[9];
+ int32 bias_vector[3];
+ int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit;
+ int32 i;
+ uint32 _is_lookup_table_enabled;
-static void blit_rotate(struct mdp_blit_req *req,
- struct mdp_regs *regs)
-{
- if (req->flags == MDP_ROT_NOP)
- return;
+ input_C2 = (input_pixel >> 16) & 0xFF;
+ input_C1 = (input_pixel >> 8) & 0xFF;
+ input_C0 = (input_pixel >> 0) & 0xFF;
- regs->op |= PPP_OP_ROT_ON;
- if ((req->flags & MDP_ROT_90 || req->flags & MDP_FLIP_LR) &&
- !(req->flags & MDP_ROT_90 && req->flags & MDP_FLIP_LR))
- rotate_dst_addr_x(req, regs);
- if (req->flags & MDP_ROT_90)
- regs->op |= PPP_OP_ROT_90;
- if (req->flags & MDP_FLIP_UD) {
- regs->op |= PPP_OP_FLIP_UD;
- rotate_dst_addr_y(req, regs);
- }
- if (req->flags & MDP_FLIP_LR)
- regs->op |= PPP_OP_FLIP_LR;
-}
+ comp_C0 = input_C0;
+ comp_C1 = input_C1;
+ comp_C2 = input_C2;
-static void blit_convert(struct mdp_blit_req *req, struct mdp_regs *regs)
-{
- if (req->src.format == req->dst.format)
- return;
- if (IS_RGB(req->src.format) && IS_YCRCB(req->dst.format)) {
- regs->op |= PPP_OP_CONVERT_RGB2YCBCR | PPP_OP_CONVERT_ON;
- } else if (IS_YCRCB(req->src.format) && IS_RGB(req->dst.format)) {
- regs->op |= PPP_OP_CONVERT_YCBCR2RGB | PPP_OP_CONVERT_ON;
- if (req->dst.format == MDP_RGB_565)
- regs->op |= PPP_OP_CONVERT_MATRIX_SECONDARY;
- }
-}
+ for (i = 0; i < 9; i++)
+ matrix[i] =
+ ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20;
-#define GET_BIT_RANGE(value, high, low) \
- (((1 << (high - low + 1)) - 1) & (value >> low))
-static uint32_t transp_convert(struct mdp_blit_req *req)
-{
- uint32_t transp = 0;
- if (req->src.format == MDP_RGB_565) {
- /* pad each value to 8 bits by copying the high bits into the
- * low end, convert RGB to RBG by switching low 2 components */
- transp |= ((GET_BIT_RANGE(req->transp_mask, 15, 11) << 3) |
- (GET_BIT_RANGE(req->transp_mask, 15, 13))) << 16;
+ bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF);
+ bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF);
+ bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF);
- transp |= ((GET_BIT_RANGE(req->transp_mask, 4, 0) << 3) |
- (GET_BIT_RANGE(req->transp_mask, 4, 2))) << 8;
+ Y_low_limit = (int32) clamp_vector[0];
+ Y_high_limit = (int32) clamp_vector[1];
+ C_low_limit = (int32) clamp_vector[2];
+ C_high_limit = (int32) clamp_vector[3];
- transp |= (GET_BIT_RANGE(req->transp_mask, 10, 5) << 2) |
- (GET_BIT_RANGE(req->transp_mask, 10, 9));
- } else {
- /* convert RGB to RBG */
- transp |= (GET_BIT_RANGE(req->transp_mask, 15, 8)) |
- (GET_BIT_RANGE(req->transp_mask, 23, 16) << 16) |
- (GET_BIT_RANGE(req->transp_mask, 7, 0) << 8);
- }
- return transp;
-}
-#undef GET_BIT_RANGE
-
-static void blit_blend(struct mdp_blit_req *req, struct mdp_regs *regs)
-{
- /* TRANSP BLEND */
- if (req->transp_mask != MDP_TRANSP_NOP) {
- req->transp_mask = transp_convert(req);
- if (req->alpha != MDP_ALPHA_NOP) {
- /* use blended transparancy mode
- * pixel = (src == transp) ? dst : blend
- * blend is combo of blend_eq_sel and
- * blend_alpha_sel */
- regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
- PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
- PPP_OP_BLEND_CONSTANT_ALPHA |
- PPP_BLEND_ALPHA_TRANSP;
- } else {
- /* simple transparancy mode
- * pixel = (src == transp) ? dst : src */
- regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
- PPP_OP_BLEND_SRCPIXEL_TRANSP;
- }
- }
-
- req->alpha &= 0xff;
- /* ALPHA BLEND */
- if (HAS_ALPHA(req->src.format)) {
- regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
- PPP_OP_BLEND_SRCPIXEL_ALPHA;
- } else if (req->alpha < MDP_ALPHA_NOP) {
- /* just blend by alpha */
- regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
- PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
- PPP_OP_BLEND_CONSTANT_ALPHA;
- }
-
- regs->op |= bg_op_chroma[req->dst.format];
-}
-
-#define ONE_HALF (1LL << 32)
-#define ONE (1LL << 33)
-#define TWO (2LL << 33)
-#define THREE (3LL << 33)
-#define FRAC_MASK (ONE - 1)
-#define INT_MASK (~FRAC_MASK)
-
-static int scale_params(uint32_t dim_in, uint32_t dim_out, uint32_t origin,
- uint32_t *phase_init, uint32_t *phase_step)
-{
- /* to improve precicsion calculations are done in U31.33 and converted
- * to U3.29 at the end */
- int64_t k1, k2, k3, k4, tmp;
- uint64_t n, d, os, os_p, od, od_p, oreq;
- unsigned rpa = 0;
- int64_t ip64, delta;
-
- if (dim_out % 3 == 0)
- rpa = !(dim_in % (dim_out / 3));
-
- n = ((uint64_t)dim_out) << 34;
- d = dim_in;
- if (!d)
- return -1;
- do_div(n, d);
- k3 = (n + 1) >> 1;
- if ((k3 >> 4) < (1LL << 27) || (k3 >> 4) > (1LL << 31)) {
- DLOG("crap bad scale\n");
- return -1;
- }
- n = ((uint64_t)dim_in) << 34;
- d = (uint64_t)dim_out;
- if (!d)
- return -1;
- do_div(n, d);
- k1 = (n + 1) >> 1;
- k2 = (k1 - ONE) >> 1;
-
- *phase_init = (int)(k2 >> 4);
- k4 = (k3 - ONE) >> 1;
-
- if (rpa) {
- os = ((uint64_t)origin << 33) - ONE_HALF;
- tmp = (dim_out * os) + ONE_HALF;
- if (!dim_in)
- return -1;
- do_div(tmp, dim_in);
- od = tmp - ONE_HALF;
- } else {
- os = ((uint64_t)origin << 1) - 1;
- od = (((k3 * os) >> 1) + k4);
- }
-
- od_p = od & INT_MASK;
- if (od_p != od)
- od_p += ONE;
-
- if (rpa) {
- tmp = (dim_in * od_p) + ONE_HALF;
- if (!dim_in)
- return -1;
- do_div(tmp, dim_in);
- os_p = tmp - ONE_HALF;
- } else {
- os_p = ((k1 * (od_p >> 33)) + k2);
- }
-
- oreq = (os_p & INT_MASK) - ONE;
-
- ip64 = os_p - oreq;
- delta = ((int64_t)(origin) << 33) - oreq;
- ip64 -= delta;
- /* limit to valid range before the left shift */
- delta = (ip64 & (1LL << 63)) ? 4 : -4;
- delta <<= 33;
- while (abs((int)(ip64 >> 33)) > 4)
- ip64 += delta;
- *phase_init = (int)(ip64 >> 4);
- *phase_step = (uint32_t)(k1 >> 4);
- return 0;
-}
-
-static void load_scale_table(const struct mdp_info *mdp,
- struct mdp_table_entry *table, int len)
-{
- int i;
- for (i = 0; i < len; i++)
- mdp_writel(mdp, table[i].val, table[i].reg);
-}
-
-enum {
-IMG_LEFT,
-IMG_RIGHT,
-IMG_TOP,
-IMG_BOTTOM,
-};
-
-static void get_edge_info(uint32_t src, uint32_t src_coord, uint32_t dst,
- uint32_t *interp1, uint32_t *interp2,
- uint32_t *repeat1, uint32_t *repeat2) {
- if (src > 3 * dst) {
- *interp1 = 0;
- *interp2 = src - 1;
- *repeat1 = 0;
- *repeat2 = 0;
- } else if (src == 3 * dst) {
- *interp1 = 0;
- *interp2 = src;
- *repeat1 = 0;
- *repeat2 = 1;
- } else if (src > dst && src < 3 * dst) {
- *interp1 = -1;
- *interp2 = src;
- *repeat1 = 1;
- *repeat2 = 1;
- } else if (src == dst) {
- *interp1 = -1;
- *interp2 = src + 1;
- *repeat1 = 1;
- *repeat2 = 2;
- } else {
- *interp1 = -2;
- *interp2 = src + 1;
- *repeat1 = 2;
- *repeat2 = 2;
- }
- *interp1 += src_coord;
- *interp2 += src_coord;
-}
-
-static int get_edge_cond(struct mdp_blit_req *req, struct mdp_regs *regs)
-{
- int32_t luma_interp[4];
- int32_t luma_repeat[4];
- int32_t chroma_interp[4];
- int32_t chroma_bound[4];
- int32_t chroma_repeat[4];
- uint32_t dst_w, dst_h;
-
- memset(&luma_interp, 0, sizeof(int32_t) * 4);
- memset(&luma_repeat, 0, sizeof(int32_t) * 4);
- memset(&chroma_interp, 0, sizeof(int32_t) * 4);
- memset(&chroma_bound, 0, sizeof(int32_t) * 4);
- memset(&chroma_repeat, 0, sizeof(int32_t) * 4);
- regs->edge = 0;
-
- if (req->flags & MDP_ROT_90) {
- dst_w = req->dst_rect.h;
- dst_h = req->dst_rect.w;
- } else {
- dst_w = req->dst_rect.w;
- dst_h = req->dst_rect.h;
- }
-
- if (regs->op & (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON)) {
- get_edge_info(req->src_rect.h, req->src_rect.y, dst_h,
- &luma_interp[IMG_TOP], &luma_interp[IMG_BOTTOM],
- &luma_repeat[IMG_TOP], &luma_repeat[IMG_BOTTOM]);
- get_edge_info(req->src_rect.w, req->src_rect.x, dst_w,
- &luma_interp[IMG_LEFT], &luma_interp[IMG_RIGHT],
- &luma_repeat[IMG_LEFT], &luma_repeat[IMG_RIGHT]);
- } else {
- luma_interp[IMG_LEFT] = req->src_rect.x;
- luma_interp[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1;
- luma_interp[IMG_TOP] = req->src_rect.y;
- luma_interp[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1;
- luma_repeat[IMG_LEFT] = 0;
- luma_repeat[IMG_TOP] = 0;
- luma_repeat[IMG_RIGHT] = 0;
- luma_repeat[IMG_BOTTOM] = 0;
- }
-
- chroma_interp[IMG_LEFT] = luma_interp[IMG_LEFT];
- chroma_interp[IMG_RIGHT] = luma_interp[IMG_RIGHT];
- chroma_interp[IMG_TOP] = luma_interp[IMG_TOP];
- chroma_interp[IMG_BOTTOM] = luma_interp[IMG_BOTTOM];
-
- chroma_bound[IMG_LEFT] = req->src_rect.x;
- chroma_bound[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1;
- chroma_bound[IMG_TOP] = req->src_rect.y;
- chroma_bound[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1;
-
- if (IS_YCRCB(req->src.format)) {
- chroma_interp[IMG_LEFT] = chroma_interp[IMG_LEFT] >> 1;
- chroma_interp[IMG_RIGHT] = (chroma_interp[IMG_RIGHT] + 1) >> 1;
-
- chroma_bound[IMG_LEFT] = chroma_bound[IMG_LEFT] >> 1;
- chroma_bound[IMG_RIGHT] = chroma_bound[IMG_RIGHT] >> 1;
- }
-
- if (req->src.format == MDP_Y_CBCR_H2V2 ||
- req->src.format == MDP_Y_CRCB_H2V2) {
- chroma_interp[IMG_TOP] = (chroma_interp[IMG_TOP] - 1) >> 1;
- chroma_interp[IMG_BOTTOM] = (chroma_interp[IMG_BOTTOM] + 1)
- >> 1;
- chroma_bound[IMG_TOP] = (chroma_bound[IMG_TOP] + 1) >> 1;
- chroma_bound[IMG_BOTTOM] = chroma_bound[IMG_BOTTOM] >> 1;
- }
-
- chroma_repeat[IMG_LEFT] = chroma_bound[IMG_LEFT] -
- chroma_interp[IMG_LEFT];
- chroma_repeat[IMG_RIGHT] = chroma_interp[IMG_RIGHT] -
- chroma_bound[IMG_RIGHT];
- chroma_repeat[IMG_TOP] = chroma_bound[IMG_TOP] -
- chroma_interp[IMG_TOP];
- chroma_repeat[IMG_BOTTOM] = chroma_interp[IMG_BOTTOM] -
- chroma_bound[IMG_BOTTOM];
-
- if (chroma_repeat[IMG_LEFT] < 0 || chroma_repeat[IMG_LEFT] > 3 ||
- chroma_repeat[IMG_RIGHT] < 0 || chroma_repeat[IMG_RIGHT] > 3 ||
- chroma_repeat[IMG_TOP] < 0 || chroma_repeat[IMG_TOP] > 3 ||
- chroma_repeat[IMG_BOTTOM] < 0 || chroma_repeat[IMG_BOTTOM] > 3 ||
- luma_repeat[IMG_LEFT] < 0 || luma_repeat[IMG_LEFT] > 3 ||
- luma_repeat[IMG_RIGHT] < 0 || luma_repeat[IMG_RIGHT] > 3 ||
- luma_repeat[IMG_TOP] < 0 || luma_repeat[IMG_TOP] > 3 ||
- luma_repeat[IMG_BOTTOM] < 0 || luma_repeat[IMG_BOTTOM] > 3)
- return -1;
-
- regs->edge |= (chroma_repeat[IMG_LEFT] & 3) << MDP_LEFT_CHROMA;
- regs->edge |= (chroma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_CHROMA;
- regs->edge |= (chroma_repeat[IMG_TOP] & 3) << MDP_TOP_CHROMA;
- regs->edge |= (chroma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_CHROMA;
- regs->edge |= (luma_repeat[IMG_LEFT] & 3) << MDP_LEFT_LUMA;
- regs->edge |= (luma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_LUMA;
- regs->edge |= (luma_repeat[IMG_TOP] & 3) << MDP_TOP_LUMA;
- regs->edge |= (luma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_LUMA;
- return 0;
-}
-
-static int blit_scale(const struct mdp_info *mdp, struct mdp_blit_req *req,
- struct mdp_regs *regs)
-{
- uint32_t phase_init_x, phase_init_y, phase_step_x, phase_step_y;
- uint32_t scale_factor_x, scale_factor_y;
- uint32_t downscale;
- uint32_t dst_w, dst_h;
-
- if (req->flags & MDP_ROT_90) {
- dst_w = req->dst_rect.h;
- dst_h = req->dst_rect.w;
- } else {
- dst_w = req->dst_rect.w;
- dst_h = req->dst_rect.h;
- }
- if ((req->src_rect.w == dst_w) && (req->src_rect.h == dst_h) &&
- !(req->flags & MDP_BLUR)) {
- regs->phasex_init = 0;
- regs->phasey_init = 0;
- regs->phasex_step = 0;
- regs->phasey_step = 0;
- return 0;
- }
-
- if (scale_params(req->src_rect.w, dst_w, 1, &phase_init_x,
- &phase_step_x) ||
- scale_params(req->src_rect.h, dst_h, 1, &phase_init_y,
- &phase_step_y))
- return -1;
-
- scale_factor_x = (dst_w * 10) / req->src_rect.w;
- scale_factor_y = (dst_h * 10) / req->src_rect.h;
-
- if (scale_factor_x > 8)
- downscale = MDP_DOWNSCALE_PT8TO1;
- else if (scale_factor_x > 6)
- downscale = MDP_DOWNSCALE_PT6TOPT8;
- else if (scale_factor_x > 4)
- downscale = MDP_DOWNSCALE_PT4TOPT6;
+ if (look_up_table == 0) /* check for NULL point */
+ _is_lookup_table_enabled = 0;
else
- downscale = MDP_DOWNSCALE_PT2TOPT4;
- if (downscale != downscale_x_table) {
- load_scale_table(mdp, mdp_downscale_x_table[downscale], 64);
- downscale_x_table = downscale;
+ _is_lookup_table_enabled = 1;
+
+ if (_is_lookup_table_enabled == 1) {
+ comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF;
+ comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF;
+ comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF;
}
+ /*
+ * Color Conversion
+ * reorder input colors
+ */
+ temp = comp_C2;
+ comp_C2 = comp_C1;
+ comp_C1 = comp_C0;
+ comp_C0 = temp;
- if (scale_factor_y > 8)
- downscale = MDP_DOWNSCALE_PT8TO1;
- else if (scale_factor_y > 6)
- downscale = MDP_DOWNSCALE_PT6TOPT8;
- else if (scale_factor_y > 4)
- downscale = MDP_DOWNSCALE_PT4TOPT6;
- else
- downscale = MDP_DOWNSCALE_PT2TOPT4;
- if (downscale != downscale_y_table) {
- load_scale_table(mdp, mdp_downscale_y_table[downscale], 64);
- downscale_y_table = downscale;
- }
+ /* matrix multiplication */
+ temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2];
+ temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5];
+ temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8];
- regs->phasex_init = phase_init_x;
- regs->phasey_init = phase_init_y;
- regs->phasex_step = phase_step_x;
- regs->phasey_step = phase_step_y;
- regs->op |= (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
- return 0;
+ comp_C0 = temp1 + 0x100;
+ comp_C1 = temp2 + 0x100;
+ comp_C2 = temp3 + 0x100;
+ /* take interger part */
+ comp_C0 >>= 9;
+ comp_C1 >>= 9;
+ comp_C2 >>= 9;
+
+ /* post bias (+) */
+ comp_C0 += bias_vector[0];
+ comp_C1 += bias_vector[1];
+ comp_C2 += bias_vector[2];
+
+ /* limit pixel to 8-bit */
+ if (comp_C0 < 0)
+ comp_C0 = 0;
+
+ if (comp_C0 > 255)
+ comp_C0 = 255;
+
+ if (comp_C1 < 0)
+ comp_C1 = 0;
+
+ if (comp_C1 > 255)
+ comp_C1 = 255;
+
+ if (comp_C2 < 0)
+ comp_C2 = 0;
+
+ if (comp_C2 > 255)
+ comp_C2 = 255;
+
+ /* clamp */
+ if (comp_C0 < Y_low_limit)
+ comp_C0 = Y_low_limit;
+
+ if (comp_C0 > Y_high_limit)
+ comp_C0 = Y_high_limit;
+
+ if (comp_C1 < C_low_limit)
+ comp_C1 = C_low_limit;
+
+ if (comp_C1 > C_high_limit)
+ comp_C1 = C_high_limit;
+
+ if (comp_C2 < C_low_limit)
+ comp_C2 = C_low_limit;
+
+ if (comp_C2 > C_high_limit)
+ comp_C2 = C_high_limit;
+
+ output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0;
+ return output;
}
-static void blit_blur(const struct mdp_info *mdp, struct mdp_blit_req *req,
- struct mdp_regs *regs)
+uint32 mdp_conv_matx_yuv2rgb(uint32 input_pixel,
+ uint16 *matrix_and_bias_vector,
+ uint32 *clamp_vector, uint32 *look_up_table)
{
- if (!(req->flags & MDP_BLUR))
- return;
+ uint8 input_C2, input_C0, input_C1;
+ uint32 output;
+ int32 comp_C2, comp_C1, comp_C0, temp;
+ int32 temp1, temp2, temp3;
+ int32 matrix[9];
+ int32 bias_vector[3];
+ int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit;
+ int32 i;
+ uint32 _is_lookup_table_enabled;
- if (!(downscale_x_table == MDP_DOWNSCALE_BLUR &&
- downscale_y_table == MDP_DOWNSCALE_BLUR)) {
- load_scale_table(mdp, mdp_gaussian_blur_table, 128);
- downscale_x_table = MDP_DOWNSCALE_BLUR;
- downscale_y_table = MDP_DOWNSCALE_BLUR;
+ input_C2 = (input_pixel >> 16) & 0xFF;
+ input_C1 = (input_pixel >> 8) & 0xFF;
+ input_C0 = (input_pixel >> 0) & 0xFF;
+
+ comp_C0 = input_C0;
+ comp_C1 = input_C1;
+ comp_C2 = input_C2;
+
+ for (i = 0; i < 9; i++)
+ matrix[i] =
+ ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20;
+
+ bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF);
+ bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF);
+ bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF);
+
+ Y_low_limit = (int32) clamp_vector[0];
+ Y_high_limit = (int32) clamp_vector[1];
+ C_low_limit = (int32) clamp_vector[2];
+ C_high_limit = (int32) clamp_vector[3];
+
+ if (look_up_table == 0) /* check for NULL point */
+ _is_lookup_table_enabled = 0;
+ else
+ _is_lookup_table_enabled = 1;
+
+ /* clamp */
+ if (comp_C0 < Y_low_limit)
+ comp_C0 = Y_low_limit;
+
+ if (comp_C0 > Y_high_limit)
+ comp_C0 = Y_high_limit;
+
+ if (comp_C1 < C_low_limit)
+ comp_C1 = C_low_limit;
+
+ if (comp_C1 > C_high_limit)
+ comp_C1 = C_high_limit;
+
+ if (comp_C2 < C_low_limit)
+ comp_C2 = C_low_limit;
+
+ if (comp_C2 > C_high_limit)
+ comp_C2 = C_high_limit;
+
+ /*
+ * Color Conversion
+ * pre bias (-)
+ */
+ comp_C0 -= bias_vector[0];
+ comp_C1 -= bias_vector[1];
+ comp_C2 -= bias_vector[2];
+
+ /* matrix multiplication */
+ temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2];
+ temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5];
+ temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8];
+
+ comp_C0 = temp1 + 0x100;
+ comp_C1 = temp2 + 0x100;
+ comp_C2 = temp3 + 0x100;
+
+ /* take interger part */
+ comp_C0 >>= 9;
+ comp_C1 >>= 9;
+ comp_C2 >>= 9;
+
+ /* reorder output colors */
+ temp = comp_C0;
+ comp_C0 = comp_C1;
+ comp_C1 = comp_C2;
+ comp_C2 = temp;
+
+ /* limit pixel to 8-bit */
+ if (comp_C0 < 0)
+ comp_C0 = 0;
+
+ if (comp_C0 > 255)
+ comp_C0 = 255;
+
+ if (comp_C1 < 0)
+ comp_C1 = 0;
+
+ if (comp_C1 > 255)
+ comp_C1 = 255;
+
+ if (comp_C2 < 0)
+ comp_C2 = 0;
+
+ if (comp_C2 > 255)
+ comp_C2 = 255;
+
+ /* Look-up table */
+ if (_is_lookup_table_enabled == 1) {
+ comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF;
+ comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF;
+ comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF;
}
- regs->op |= (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
+ output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0;
+ return output;
}
+static uint32 mdp_calc_tpval(MDPIMG *mdpImg)
+{
+ uint32 tpVal;
+ uint8 plane_tp;
+
+ tpVal = 0;
+ if ((mdpImg->imgType == MDP_RGB_565)
+ || (mdpImg->imgType == MDP_BGR_565)) {
+ /*
+ * transparent color conversion into 24 bpp
+ *
+ * C2R_8BIT
+ * left shift the entire bit and or it with the upper most bits
+ */
+ plane_tp = (uint8) ((mdpImg->tpVal & 0xF800) >> 11);
+ tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 16;
+
+ /* C1B_8BIT */
+ plane_tp = (uint8) (mdpImg->tpVal & 0x1F);
+ tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 8;
+
+ /* C0G_8BIT */
+ plane_tp = (uint8) ((mdpImg->tpVal & 0x7E0) >> 5);
+ tpVal |= ((plane_tp << 2) | ((plane_tp & 0x30) >> 4));
+ } else {
+ /* 24bit RGB to RBG conversion */
+
+ tpVal = (mdpImg->tpVal & 0xFF00) >> 8;
+ tpVal |= (mdpImg->tpVal & 0xFF) << 8;
+ tpVal |= (mdpImg->tpVal & 0xFF0000);
+ }
+
+ return tpVal;
+}
+
+static uint8 *mdp_get_chroma_addr(MDPIBUF *iBuf)
+{
+ uint8 *dest1;
+
+ dest1 = NULL;
+ switch (iBuf->ibuf_type) {
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V1:
+ dest1 = (uint8 *) iBuf->buf;
+ dest1 += iBuf->ibuf_width * iBuf->ibuf_height * iBuf->bpp;
+ break;
+
+ default:
+ break;
+ }
+
+ return dest1;
+}
+
+static void mdp_ppp_setbg(MDPIBUF *iBuf)
+{
+ uint8 *bg0_addr;
+ uint8 *bg1_addr;
+ uint32 bg0_ystride, bg1_ystride;
+ uint32 ppp_src_cfg_reg, unpack_pattern;
+ int v_slice, h_slice;
+
+ v_slice = h_slice = 1;
+ bg0_addr = (uint8 *) iBuf->buf;
+ bg1_addr = mdp_get_chroma_addr(iBuf);
+
+ bg0_ystride = iBuf->ibuf_width * iBuf->bpp;
+ bg1_ystride = iBuf->ibuf_width * iBuf->bpp;
+
+ switch (iBuf->ibuf_type) {
+ case MDP_BGR_565:
+ case MDP_RGB_565:
+ /* 888 = 3bytes
+ * RGB = 3Components
+ * RGB interleaved
+ */
+ ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS |
+ PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES |
+ PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+ PPP_SRC_UNPACK_ALIGN_LSB |
+ PPP_SRC_FETCH_PLANES_INTERLVD;
+
+ if (iBuf->ibuf_type == MDP_RGB_565)
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+ else
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
+ break;
+
+ case MDP_RGB_888:
+ /*
+ * 888 = 3bytes
+ * RGB = 3Components
+ * RGB interleaved
+ */
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES |
+ PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+ PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_INTERLVD;
+
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+ break;
+
+ case MDP_BGRA_8888:
+ case MDP_RGBA_8888:
+ case MDP_ARGB_8888:
+ case MDP_XRGB_8888:
+ case MDP_RGBX_8888:
+ /*
+ * 8888 = 4bytes
+ * ARGB = 4Components
+ * ARGB interleaved
+ */
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS | PPP_SRC_C3_ALPHA_EN |
+ PPP_SRC_BPP_INTERLVD_4BYTES | PPP_SRC_INTERLVD_4COMPONENTS |
+ PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB |
+ PPP_SRC_FETCH_PLANES_INTERLVD;
+
+ if (iBuf->ibuf_type == MDP_BGRA_8888)
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+ 8);
+ else if (iBuf->ibuf_type == MDP_RGBA_8888 ||
+ iBuf->ibuf_type == MDP_RGBX_8888)
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
+ 8);
+ else if (iBuf->ibuf_type == MDP_XRGB_8888)
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+ 8);
+ else
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+ 8);
+ break;
+
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+ PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS |
+ PPP_SRC_C3A_8BITS |
+ PPP_SRC_BPP_INTERLVD_2BYTES |
+ PPP_SRC_INTERLVD_2COMPONENTS |
+ PPP_SRC_UNPACK_TIGHT |
+ PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
+
+ if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+ else
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+ v_slice = h_slice = 2;
+ break;
+
+ case MDP_YCRYCB_H2V1:
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+ PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS |
+ PPP_SRC_C3A_8BITS |
+ PPP_SRC_BPP_INTERLVD_2BYTES |
+ PPP_SRC_INTERLVD_4COMPONENTS |
+ PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB;
+
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
+ h_slice = 2;
+ break;
+
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V1:
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+ PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS |
+ PPP_SRC_C3A_8BITS |
+ PPP_SRC_BPP_INTERLVD_2BYTES |
+ PPP_SRC_INTERLVD_2COMPONENTS |
+ PPP_SRC_UNPACK_TIGHT |
+ PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
+
+ if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+ else
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+ h_slice = 2;
+ break;
+
+ default:
+ return;
+ }
+
+ /* starting input address adjustment */
+ mdp_adjust_start_addr(&bg0_addr, &bg1_addr, v_slice, h_slice,
+ iBuf->roi.lcd_x, iBuf->roi.lcd_y,
+ iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp,
+ iBuf, 1);
+
+ /*
+ * 0x01c0: background plane 0 addr
+ * 0x01c4: background plane 1 addr
+ * 0x01c8: background plane 2 addr
+ * 0x01cc: bg y stride for plane 0 and 1
+ * 0x01d0: bg y stride for plane 2
+ * 0x01d4: bg src PPP config
+ * 0x01d8: unpack pattern
+ */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c0, bg0_addr);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c4, bg1_addr);
+
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01cc,
+ (bg1_ystride << 16) | bg0_ystride);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d4, ppp_src_cfg_reg);
+
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d8, unpack_pattern);
+}
+
+#define IS_PSEUDOPLNR(img) ((img == MDP_Y_CRCB_H2V2) | \
+ (img == MDP_Y_CBCR_H2V2) | \
+ (img == MDP_Y_CRCB_H2V1) | \
+ (img == MDP_Y_CBCR_H2V1))
#define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp)
#define Y_TO_CRCB_RATIO(format) \
((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CRCB_H2V2) ? 2 :\
- (format == MDP_Y_CBCR_H2V1 || format == MDP_Y_CRCB_H2V1) ? 1 : 1)
+ (format == MDP_Y_CBCR_H2V1 || format == MDP_Y_CRCB_H2V1) ? 1 : 1)
+#ifdef CONFIG_ANDROID_PMEM
static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp,
- uint32_t *len0, uint32_t *len1)
+ uint32_t *len0, uint32_t *len1)
{
*len0 = IMG_LEN(rect->h, img->width, rect->w, bpp);
if (IS_PSEUDOPLNR(img->format))
@@ -533,199 +555,1016 @@
*len1 = 0;
}
-static int valid_src_dst(unsigned long src_start, unsigned long src_len,
- unsigned long dst_start, unsigned long dst_len,
- struct mdp_blit_req *req, struct mdp_regs *regs)
+static void flush_imgs(struct mdp_blit_req *req, int src_bpp, int dst_bpp,
+ struct file *p_src_file, struct file *p_dst_file)
{
- unsigned long src_min_ok = src_start;
- unsigned long src_max_ok = src_start + src_len;
- unsigned long dst_min_ok = dst_start;
- unsigned long dst_max_ok = dst_start + dst_len;
- uint32_t src0_len, src1_len, dst0_len, dst1_len;
- get_len(&req->src, &req->src_rect, regs->src_bpp, &src0_len,
- &src1_len);
- get_len(&req->dst, &req->dst_rect, regs->dst_bpp, &dst0_len,
- &dst1_len);
+ uint32_t src0_len, src1_len;
- if (regs->src0 < src_min_ok || regs->src0 > src_max_ok ||
- regs->src0 + src0_len > src_max_ok) {
- DLOG("invalid_src %x %x %lx %lx\n", regs->src0,
- src0_len, src_min_ok, src_max_ok);
- return 0;
+ if (!(req->flags & MDP_BLIT_NON_CACHED)) {
+ /* flush src images to memory before dma to mdp */
+ get_len(&req->src, &req->src_rect, src_bpp,
+ &src0_len, &src1_len);
+
+ flush_pmem_file(p_src_file,
+ req->src.offset, src0_len);
+
+ if (IS_PSEUDOPLNR(req->src.format))
+ flush_pmem_file(p_src_file,
+ req->src.offset + src0_len, src1_len);
}
- if (regs->src_cfg & PPP_SRC_PLANE_PSEUDOPLNR) {
- if (regs->src1 < src_min_ok || regs->src1 > src_max_ok ||
- regs->src1 + src1_len > src_max_ok) {
- DLOG("invalid_src1");
- return 0;
+
+}
+#else
+static void flush_imgs(struct mdp_blit_req *req, int src_bpp, int dst_bpp,
+ struct file *p_src_file, struct file *p_dst_file) { }
+#endif
+
+static void mdp_start_ppp(struct msm_fb_data_type *mfd, MDPIBUF *iBuf,
+struct mdp_blit_req *req, struct file *p_src_file, struct file *p_dst_file)
+{
+ uint8 *src0, *src1;
+ uint8 *dest0, *dest1;
+ uint16 inpBpp;
+ uint32 dest0_ystride;
+ uint32 src_width;
+ uint32 src_height;
+ uint32 src0_ystride;
+ uint32 dst_roi_width;
+ uint32 dst_roi_height;
+ uint32 ppp_src_cfg_reg, ppp_operation_reg, ppp_dst_cfg_reg;
+ uint32 alpha, tpVal;
+ uint32 packPattern;
+ uint32 dst_packPattern;
+ boolean inputRGB, outputRGB, pseudoplanr_output;
+ int sv_slice, sh_slice;
+ int dv_slice, dh_slice;
+ boolean perPixelAlpha = FALSE;
+ boolean ppp_lookUp_enable = FALSE;
+
+ sv_slice = sh_slice = dv_slice = dh_slice = 1;
+ alpha = tpVal = 0;
+ src_width = iBuf->mdpImg.width;
+ src_height = iBuf->roi.y + iBuf->roi.height;
+ src1 = NULL;
+ dest1 = NULL;
+
+ inputRGB = outputRGB = TRUE;
+ pseudoplanr_output = FALSE;
+ ppp_operation_reg = 0;
+ ppp_dst_cfg_reg = 0;
+ ppp_src_cfg_reg = 0;
+
+ /* Wait for the pipe to clear */
+ do { } while (mdp_ppp_pipe_wait() <= 0);
+
+ /*
+ * destination config
+ */
+ switch (iBuf->ibuf_type) {
+ case MDP_RGB_888:
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+ ppp_dst_cfg_reg =
+ PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT | PPP_DST_C2R_8BIT |
+ PPP_DST_PACKET_CNT_INTERLVD_3ELEM | PPP_DST_PACK_TIGHT |
+ PPP_DST_PACK_ALIGN_LSB | PPP_DST_OUT_SEL_AXI |
+ PPP_DST_BPP_3BYTES | PPP_DST_PLANE_INTERLVD;
+ break;
+
+ case MDP_BGRA_8888:
+ case MDP_XRGB_8888:
+ case MDP_ARGB_8888:
+ case MDP_RGBA_8888:
+ case MDP_RGBX_8888:
+ if (iBuf->ibuf_type == MDP_BGRA_8888)
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+ 8);
+ else if (iBuf->ibuf_type == MDP_RGBA_8888 ||
+ iBuf->ibuf_type == MDP_RGBX_8888)
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
+ 8);
+ else if (iBuf->ibuf_type == MDP_XRGB_8888)
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+ 8);
+ else
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+ 8);
+
+ ppp_dst_cfg_reg = PPP_DST_C0G_8BIT |
+ PPP_DST_C1B_8BIT |
+ PPP_DST_C2R_8BIT |
+ PPP_DST_C3A_8BIT |
+ PPP_DST_C3ALPHA_EN |
+ PPP_DST_PACKET_CNT_INTERLVD_4ELEM |
+ PPP_DST_PACK_TIGHT |
+ PPP_DST_PACK_ALIGN_LSB |
+ PPP_DST_OUT_SEL_AXI |
+ PPP_DST_BPP_4BYTES | PPP_DST_PLANE_INTERLVD;
+ break;
+
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ if (iBuf->ibuf_type == MDP_Y_CBCR_H2V2)
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+ else
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+
+ ppp_dst_cfg_reg = PPP_DST_C2R_8BIT |
+ PPP_DST_C0G_8BIT |
+ PPP_DST_C1B_8BIT |
+ PPP_DST_C3A_8BIT |
+ PPP_DST_PACKET_CNT_INTERLVD_2ELEM |
+ PPP_DST_PACK_TIGHT |
+ PPP_DST_PACK_ALIGN_LSB |
+ PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES;
+
+ ppp_operation_reg |= PPP_OP_DST_CHROMA_420;
+ outputRGB = FALSE;
+ pseudoplanr_output = TRUE;
+ /*
+ * vertically (y direction) and horizontally (x direction)
+ * sample reduction by 2
+ */
+
+ /*
+ * H2V2(YUV420) Cosite
+ *
+ * Y Y Y Y
+ * CbCr CbCr
+ * Y Y Y Y
+ * Y Y Y Y
+ * CbCr CbCr
+ * Y Y Y Y
+ */
+ dv_slice = dh_slice = 2;
+
+ /* (x,y) and (width,height) must be even numbern */
+ iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
+ iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
+ iBuf->roi.x = (iBuf->roi.x / 2) * 2;
+ iBuf->roi.width = (iBuf->roi.width / 2) * 2;
+
+ iBuf->roi.lcd_y = (iBuf->roi.lcd_y / 2) * 2;
+ iBuf->roi.dst_height = (iBuf->roi.dst_height / 2) * 2;
+ iBuf->roi.y = (iBuf->roi.y / 2) * 2;
+ iBuf->roi.height = (iBuf->roi.height / 2) * 2;
+ break;
+
+ case MDP_YCRYCB_H2V1:
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
+ ppp_dst_cfg_reg =
+ PPP_DST_C2R_8BIT | PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT |
+ PPP_DST_C3A_8BIT | PPP_DST_PACKET_CNT_INTERLVD_4ELEM |
+ PPP_DST_PACK_TIGHT | PPP_DST_PACK_ALIGN_LSB |
+ PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES |
+ PPP_DST_PLANE_INTERLVD;
+
+ ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1;
+ outputRGB = FALSE;
+ /*
+ * horizontally (x direction) sample reduction by 2
+ *
+ * H2V1(YUV422) Cosite
+ *
+ * YCbCr Y YCbCr Y
+ * YCbCr Y YCbCr Y
+ * YCbCr Y YCbCr Y
+ * YCbCr Y YCbCr Y
+ */
+ dh_slice = 2;
+
+ /*
+ * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the
+ * preloaded gamma setting of 2.2 when the content is
+ * non-linear ppp_lookUp_enable = TRUE;
+ */
+
+ /* x and width must be even number */
+ iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
+ iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
+ iBuf->roi.x = (iBuf->roi.x / 2) * 2;
+ iBuf->roi.width = (iBuf->roi.width / 2) * 2;
+ break;
+
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V1:
+ if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+ else
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+
+ ppp_dst_cfg_reg = PPP_DST_C2R_8BIT |
+ PPP_DST_C0G_8BIT |
+ PPP_DST_C1B_8BIT |
+ PPP_DST_C3A_8BIT |
+ PPP_DST_PACKET_CNT_INTERLVD_2ELEM |
+ PPP_DST_PACK_TIGHT |
+ PPP_DST_PACK_ALIGN_LSB |
+ PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES;
+
+ ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1;
+ outputRGB = FALSE;
+ pseudoplanr_output = TRUE;
+ /* horizontally (x direction) sample reduction by 2 */
+ dh_slice = 2;
+
+ /* x and width must be even number */
+ iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
+ iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
+ iBuf->roi.x = (iBuf->roi.x / 2) * 2;
+ iBuf->roi.width = (iBuf->roi.width / 2) * 2;
+ break;
+
+ case MDP_BGR_565:
+ case MDP_RGB_565:
+ default:
+ if (iBuf->ibuf_type == MDP_RGB_565)
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+ else
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
+
+ ppp_dst_cfg_reg = PPP_DST_C0G_6BIT |
+ PPP_DST_C1B_5BIT |
+ PPP_DST_C2R_5BIT |
+ PPP_DST_PACKET_CNT_INTERLVD_3ELEM |
+ PPP_DST_PACK_TIGHT |
+ PPP_DST_PACK_ALIGN_LSB |
+ PPP_DST_OUT_SEL_AXI |
+ PPP_DST_BPP_2BYTES | PPP_DST_PLANE_INTERLVD;
+ break;
+ }
+
+ /* source config */
+ switch (iBuf->mdpImg.imgType) {
+ case MDP_RGB_888:
+ inpBpp = 3;
+ /*
+ * 565 = 2bytes
+ * RGB = 3Components
+ * RGB interleaved
+ */
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES |
+ PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+ PPP_SRC_UNPACK_ALIGN_LSB |
+ PPP_SRC_FETCH_PLANES_INTERLVD;
+
+ packPattern = MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+
+ ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
+ PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
+ break;
+
+ case MDP_BGRA_8888:
+ case MDP_RGBA_8888:
+ case MDP_ARGB_8888:
+ perPixelAlpha = TRUE;
+ case MDP_XRGB_8888:
+ case MDP_RGBX_8888:
+ inpBpp = 4;
+ /*
+ * 8888 = 4bytes
+ * ARGB = 4Components
+ * ARGB interleaved
+ */
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS |
+ PPP_SRC_C3_ALPHA_EN | PPP_SRC_BPP_INTERLVD_4BYTES |
+ PPP_SRC_INTERLVD_4COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+ PPP_SRC_UNPACK_ALIGN_LSB |
+ PPP_SRC_FETCH_PLANES_INTERLVD;
+
+ if (iBuf->mdpImg.imgType == MDP_BGRA_8888)
+ packPattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+ 8);
+ else if (iBuf->mdpImg.imgType == MDP_RGBA_8888 ||
+ iBuf->mdpImg.imgType == MDP_RGBX_8888)
+ packPattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
+ 8);
+ else if (iBuf->ibuf_type == MDP_XRGB_8888)
+ packPattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+ 8);
+ else
+ packPattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+ 8);
+
+ ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
+ PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
+ break;
+
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ inpBpp = 1;
+ src1 = (uint8 *) iBuf->mdpImg.cbcr_addr;
+
+ /*
+ * CbCr = 2bytes
+ * CbCr = 2Components
+ * Y+CbCr
+ */
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_2BYTES |
+ PPP_SRC_INTERLVD_2COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+ PPP_SRC_UNPACK_ALIGN_LSB |
+ PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
+
+ if (iBuf->mdpImg.imgType == MDP_Y_CRCB_H2V2)
+ packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+ else
+ packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+
+ ppp_operation_reg |= PPP_OP_COLOR_SPACE_YCBCR |
+ PPP_OP_SRC_CHROMA_420 |
+ PPP_OP_SRC_CHROMA_COSITE |
+ PPP_OP_DST_CHROMA_RGB | PPP_OP_DST_CHROMA_COSITE;
+
+ inputRGB = FALSE;
+ sh_slice = sv_slice = 2;
+ break;
+
+ case MDP_YCRYCB_H2V1:
+ inpBpp = 2;
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+ PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS |
+ PPP_SRC_C3A_8BITS |
+ PPP_SRC_BPP_INTERLVD_2BYTES |
+ PPP_SRC_INTERLVD_4COMPONENTS |
+ PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB;
+
+ packPattern =
+ MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
+
+ ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 |
+ PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE;
+
+ /*
+ * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the
+ * preloaded inverse gamma setting of 2.2 since they're
+ * symetric when the content is non-linear
+ * ppp_lookUp_enable = TRUE;
+ */
+
+ /* x and width must be even number */
+ iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
+ iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
+ iBuf->roi.x = (iBuf->roi.x / 2) * 2;
+ iBuf->roi.width = (iBuf->roi.width / 2) * 2;
+
+ inputRGB = FALSE;
+ sh_slice = 2;
+ break;
+
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V1:
+ inpBpp = 1;
+ src1 = (uint8 *) iBuf->mdpImg.cbcr_addr;
+
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+ PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS |
+ PPP_SRC_C3A_8BITS |
+ PPP_SRC_BPP_INTERLVD_2BYTES |
+ PPP_SRC_INTERLVD_2COMPONENTS |
+ PPP_SRC_UNPACK_TIGHT |
+ PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
+
+ if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V1)
+ packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+ else
+ packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+
+ ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 |
+ PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE;
+ inputRGB = FALSE;
+ sh_slice = 2;
+ break;
+
+ case MDP_BGR_565:
+ case MDP_RGB_565:
+ default:
+ inpBpp = 2;
+ /*
+ * 565 = 2bytes
+ * RGB = 3Components
+ * RGB interleaved
+ */
+ ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS |
+ PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES |
+ PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+ PPP_SRC_UNPACK_ALIGN_LSB |
+ PPP_SRC_FETCH_PLANES_INTERLVD;
+
+ if (iBuf->mdpImg.imgType == MDP_RGB_565)
+ packPattern =
+ MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+ else
+ packPattern =
+ MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
+
+ ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
+ PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
+ break;
+
+ }
+
+ if (pseudoplanr_output)
+ ppp_dst_cfg_reg |= PPP_DST_PLANE_PSEUDOPLN;
+
+ /* YCbCr to RGB color conversion flag */
+ if ((!inputRGB) && (outputRGB)) {
+ ppp_operation_reg |= PPP_OP_CONVERT_YCBCR2RGB |
+ PPP_OP_CONVERT_ON;
+
+ /*
+ * primary/secondary is sort of misleading term...but
+ * in mdp2.2/3.0 we only use primary matrix (forward/rev)
+ * in mdp3.1 we use set1(prim) and set2(secd)
+ */
+#ifdef CONFIG_FB_MSM_MDP31
+ ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_SECONDARY |
+ PPP_OP_DST_RGB;
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0);
+#endif
+
+ if (ppp_lookUp_enable) {
+ ppp_operation_reg |= PPP_OP_LUT_C0_ON |
+ PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON;
}
}
- if (regs->dst0 < dst_min_ok || regs->dst0 > dst_max_ok ||
- regs->dst0 + dst0_len > dst_max_ok) {
- DLOG("invalid_dst");
- return 0;
- }
- if (regs->dst_cfg & PPP_SRC_PLANE_PSEUDOPLNR) {
- if (regs->dst1 < dst_min_ok || regs->dst1 > dst_max_ok ||
- regs->dst1 + dst1_len > dst_max_ok) {
- DLOG("invalid_dst1");
- return 0;
+ /* RGB to YCbCr color conversion flag */
+ if ((inputRGB) && (!outputRGB)) {
+ ppp_operation_reg |= PPP_OP_CONVERT_RGB2YCBCR |
+ PPP_OP_CONVERT_ON;
+
+#ifdef CONFIG_FB_MSM_MDP31
+ ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_PRIMARY |
+ PPP_OP_DST_YCBCR;
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0x1e);
+#endif
+
+ if (ppp_lookUp_enable) {
+ ppp_operation_reg |= PPP_OP_LUT_C0_ON |
+ PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON;
}
}
- return 1;
+ /* YCbCr to YCbCr color conversion flag */
+ if ((!inputRGB) && (!outputRGB)) {
+ if ((ppp_lookUp_enable) &&
+ (iBuf->mdpImg.imgType != iBuf->ibuf_type)) {
+ ppp_operation_reg |= PPP_OP_LUT_C0_ON;
+ }
+ }
+
+ ppp_src_cfg_reg |= (iBuf->roi.x % 2) ? PPP_SRC_BPP_ROI_ODD_X : 0;
+ ppp_src_cfg_reg |= (iBuf->roi.y % 2) ? PPP_SRC_BPP_ROI_ODD_Y : 0;
+
+ if (req->flags & MDP_DEINTERLACE)
+ ppp_operation_reg |= PPP_OP_DEINT_EN;
+
+ /* Dither at DMA side only since iBuf format is RGB888 */
+ if (iBuf->mdpImg.mdpOp & MDPOP_DITHER)
+ ppp_operation_reg |= PPP_OP_DITHER_EN;
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_ROTATION) {
+ ppp_operation_reg |= PPP_OP_ROT_ON;
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
+ ppp_operation_reg |= PPP_OP_ROT_90;
+ }
+ if (iBuf->mdpImg.mdpOp & MDPOP_LR) {
+ ppp_operation_reg |= PPP_OP_FLIP_LR;
+ }
+ if (iBuf->mdpImg.mdpOp & MDPOP_UD) {
+ ppp_operation_reg |= PPP_OP_FLIP_UD;
+ }
+ }
+
+ src0_ystride = src_width * inpBpp;
+ dest0_ystride = iBuf->ibuf_width * iBuf->bpp;
+
+ /* no need to care about rotation since it's the real-XY. */
+ dst_roi_width = iBuf->roi.dst_width;
+ dst_roi_height = iBuf->roi.dst_height;
+
+ src0 = (uint8 *) iBuf->mdpImg.bmy_addr;
+ dest0 = (uint8 *) iBuf->buf;
+
+ /* Jumping from Y-Plane to Chroma Plane */
+ dest1 = mdp_get_chroma_addr(iBuf);
+
+ /* first pixel addr calculation */
+ mdp_adjust_start_addr(&src0, &src1, sv_slice, sh_slice, iBuf->roi.x,
+ iBuf->roi.y, src_width, src_height, inpBpp, iBuf,
+ 0);
+ mdp_adjust_start_addr(&dest0, &dest1, dv_slice, dh_slice,
+ iBuf->roi.lcd_x, iBuf->roi.lcd_y,
+ iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp,
+ iBuf, 2);
+
+ /* set scale operation */
+ mdp_set_scale(iBuf, dst_roi_width, dst_roi_height,
+ inputRGB, outputRGB, &ppp_operation_reg);
+
+ /*
+ * setting background source for blending
+ */
+ mdp_set_blend_attr(iBuf, &alpha, &tpVal, perPixelAlpha,
+ &ppp_operation_reg);
+
+ if (ppp_operation_reg & PPP_OP_BLEND_ON) {
+ mdp_ppp_setbg(iBuf);
+
+ if (iBuf->ibuf_type == MDP_YCRYCB_H2V1) {
+ ppp_operation_reg |= PPP_OP_BG_CHROMA_H2V1;
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) {
+ tpVal = mdp_conv_matx_rgb2yuv(tpVal,
+ (uint16 *) &
+ mdp_ccs_rgb2yuv,
+ &mdp_plv[0], NULL);
+ }
+ }
+ }
+
+ /*
+ * 0x0004: enable dbg bus
+ * 0x0100: "don't care" Edge Condit until scaling is on
+ * 0x0104: xrc tile x&y size u7.6 format = 7bit.6bit
+ * 0x0108: src pixel size
+ * 0x010c: component plane 0 starting address
+ * 0x011c: component plane 0 ystride
+ * 0x0124: PPP source config register
+ * 0x0128: unpacked pattern from lsb to msb (eg. RGB->BGR)
+ */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0108, (iBuf->roi.height << 16 |
+ iBuf->roi.width));
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x010c, src0); /* comp.plane 0 */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0110, src1); /* comp.plane 1 */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x011c,
+ (src0_ystride << 16 | src0_ystride));
+
+ /* setup for rgb 565 */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0124, ppp_src_cfg_reg);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0128, packPattern);
+ /*
+ * 0x0138: PPP destination operation register
+ * 0x014c: constant_alpha|transparent_color
+ * 0x0150: PPP destination config register
+ * 0x0154: PPP packing pattern
+ */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0138, ppp_operation_reg);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x014c, alpha << 24 | (tpVal &
+ 0xffffff));
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0150, ppp_dst_cfg_reg);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0154, dst_packPattern);
+
+ /*
+ * 0x0164: ROI height and width
+ * 0x0168: Component Plane 0 starting addr
+ * 0x016c: Component Plane 1 starting addr
+ * 0x0178: Component Plane 1/0 y stride
+ */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0164,
+ (dst_roi_height << 16 | dst_roi_width));
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0168, dest0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x016c, dest1);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0178,
+ (dest0_ystride << 16 | dest0_ystride));
+
+ flush_imgs(req, inpBpp, iBuf->bpp, p_src_file, p_dst_file);
+#ifdef CONFIG_FB_MSM_MDP31
+ MDP_OUTP(MDP_BASE + 0x00100, 0xFF00);
+#endif
+ mdp_pipe_kickoff(MDP_PPP_TERM, mfd);
}
-
-static void flush_imgs(struct mdp_blit_req *req, struct mdp_regs *regs,
- struct file *src_file, struct file *dst_file)
+static int mdp_ppp_verify_req(struct mdp_blit_req *req)
{
-}
+ u32 src_width, src_height, dst_width, dst_height;
-static void get_chroma_addr(struct mdp_img *img, struct mdp_rect *rect,
- uint32_t base, uint32_t bpp, uint32_t cfg,
- uint32_t *addr, uint32_t *ystride)
-{
- uint32_t compress_v = Y_TO_CRCB_RATIO(img->format);
- uint32_t compress_h = 2;
- uint32_t offset;
+ if (req == NULL) {
+ printk(KERN_ERR "\n%s(): Error in Line %u", __func__,
+ __LINE__);
+ return -1;
+ }
- if (IS_PSEUDOPLNR(img->format)) {
- offset = (rect->x / compress_h) * compress_h;
- offset += rect->y == 0 ? 0 :
- ((rect->y + 1) / compress_v) * img->width;
- *addr = base + (img->width * img->height * bpp);
- *addr += offset * bpp;
- *ystride |= *ystride << 16;
+ if (MDP_IS_IMGTYPE_BAD(req->src.format) ||
+ MDP_IS_IMGTYPE_BAD(req->dst.format)) {
+ printk(KERN_ERR "\n%s(): Error in Line %u", __func__,
+ __LINE__);
+ return -1;
+ }
+
+ if ((req->src.width == 0) || (req->src.height == 0) ||
+ (req->src_rect.w == 0) || (req->src_rect.h == 0) ||
+ (req->dst.width == 0) || (req->dst.height == 0) ||
+ (req->dst_rect.w == 0) || (req->dst_rect.h == 0)) {
+ printk(KERN_ERR "\n%s(): Error in Line %u", __func__,
+ __LINE__);
+
+ return -1;
+ }
+
+ if (((req->src_rect.x + req->src_rect.w) > req->src.width) ||
+ ((req->src_rect.y + req->src_rect.h) > req->src.height)) {
+ printk(KERN_ERR "\n%s(): Error in Line %u", __func__,
+ __LINE__);
+ return -1;
+ }
+
+ if (((req->dst_rect.x + req->dst_rect.w) > req->dst.width) ||
+ ((req->dst_rect.y + req->dst_rect.h) > req->dst.height)) {
+ printk(KERN_ERR "\n%s(): Error in Line %u", __func__,
+ __LINE__);
+ return -1;
+ }
+
+ /*
+ * scaling range check
+ */
+ src_width = req->src_rect.w;
+ src_height = req->src_rect.h;
+
+ if (req->flags & MDP_ROT_90) {
+ dst_width = req->dst_rect.h;
+ dst_height = req->dst_rect.w;
} else {
- *addr = 0;
+ dst_width = req->dst_rect.w;
+ dst_height = req->dst_rect.h;
}
-}
-static int send_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
- struct mdp_regs *regs, struct file *src_file,
- struct file *dst_file)
-{
- mdp_writel(mdp, 1, 0x060);
- mdp_writel(mdp, regs->src_rect, PPP_ADDR_SRC_ROI);
- mdp_writel(mdp, regs->src0, PPP_ADDR_SRC0);
- mdp_writel(mdp, regs->src1, PPP_ADDR_SRC1);
- mdp_writel(mdp, regs->src_ystride, PPP_ADDR_SRC_YSTRIDE);
- mdp_writel(mdp, regs->src_cfg, PPP_ADDR_SRC_CFG);
- mdp_writel(mdp, regs->src_pack, PPP_ADDR_SRC_PACK_PATTERN);
+ switch (req->dst.format) {
+ case MDP_Y_CRCB_H2V2:
+ case MDP_Y_CBCR_H2V2:
+ src_width = (src_width / 2) * 2;
+ src_height = (src_height / 2) * 2;
+ dst_width = (src_width / 2) * 2;
+ dst_height = (src_height / 2) * 2;
+ break;
- mdp_writel(mdp, regs->op, PPP_ADDR_OPERATION);
- mdp_writel(mdp, regs->phasex_init, PPP_ADDR_PHASEX_INIT);
- mdp_writel(mdp, regs->phasey_init, PPP_ADDR_PHASEY_INIT);
- mdp_writel(mdp, regs->phasex_step, PPP_ADDR_PHASEX_STEP);
- mdp_writel(mdp, regs->phasey_step, PPP_ADDR_PHASEY_STEP);
+ case MDP_Y_CRCB_H2V1:
+ case MDP_Y_CBCR_H2V1:
+ case MDP_YCRYCB_H2V1:
+ src_width = (src_width / 2) * 2;
+ dst_width = (src_width / 2) * 2;
+ break;
- mdp_writel(mdp, (req->alpha << 24) | (req->transp_mask & 0xffffff),
- PPP_ADDR_ALPHA_TRANSP);
-
- mdp_writel(mdp, regs->dst_cfg, PPP_ADDR_DST_CFG);
- mdp_writel(mdp, regs->dst_pack, PPP_ADDR_DST_PACK_PATTERN);
- mdp_writel(mdp, regs->dst_rect, PPP_ADDR_DST_ROI);
- mdp_writel(mdp, regs->dst0, PPP_ADDR_DST0);
- mdp_writel(mdp, regs->dst1, PPP_ADDR_DST1);
- mdp_writel(mdp, regs->dst_ystride, PPP_ADDR_DST_YSTRIDE);
-
- mdp_writel(mdp, regs->edge, PPP_ADDR_EDGE);
- if (regs->op & PPP_OP_BLEND_ON) {
- mdp_writel(mdp, regs->dst0, PPP_ADDR_BG0);
- mdp_writel(mdp, regs->dst1, PPP_ADDR_BG1);
- mdp_writel(mdp, regs->dst_ystride, PPP_ADDR_BG_YSTRIDE);
- mdp_writel(mdp, src_img_cfg[req->dst.format], PPP_ADDR_BG_CFG);
- mdp_writel(mdp, pack_pattern[req->dst.format],
- PPP_ADDR_BG_PACK_PATTERN);
+ default:
+ break;
}
- flush_imgs(req, regs, src_file, dst_file);
- mdp_writel(mdp, 0x1000, MDP_DISPLAY0_START);
+
+ if (((MDP_SCALE_Q_FACTOR * dst_width) / src_width >
+ MDP_MAX_X_SCALE_FACTOR)
+ || ((MDP_SCALE_Q_FACTOR * dst_width) / src_width <
+ MDP_MIN_X_SCALE_FACTOR)) {
+ printk(KERN_ERR "\n%s(): Error in Line %u", __func__,
+ __LINE__);
+ return -1;
+ }
+
+ if (((MDP_SCALE_Q_FACTOR * dst_height) / src_height >
+ MDP_MAX_Y_SCALE_FACTOR)
+ || ((MDP_SCALE_Q_FACTOR * dst_height) / src_height <
+ MDP_MIN_Y_SCALE_FACTOR)) {
+ printk(KERN_ERR "\n%s(): Error in Line %u", __func__,
+ __LINE__);
+ return -1;
+ }
return 0;
}
-int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
- struct file *src_file, unsigned long src_start, unsigned long src_len,
- struct file *dst_file, unsigned long dst_start, unsigned long dst_len)
+int get_gem_img(struct mdp_img *img, unsigned long *start, unsigned long *len)
{
- struct mdp_regs regs = {0};
+ /* Set len to zero to appropriately error out if
+ kgsl_gem_obj_addr fails */
- if (unlikely(req->src.format >= MDP_IMGTYPE_LIMIT ||
- req->dst.format >= MDP_IMGTYPE_LIMIT)) {
- printk(KERN_ERR "mpd_ppp: img is of wrong format\n");
- return -EINVAL;
+ *len = 0;
+ return kgsl_gem_obj_addr(img->memory_id, (int) img->priv, start, len);
+}
+
+int get_img(struct mdp_img *img, struct fb_info *info, unsigned long *start,
+ unsigned long *len, struct file **pp_file)
+{
+ int put_needed, ret = 0;
+ struct file *file;
+#ifdef CONFIG_ANDROID_PMEM
+ unsigned long vstart;
+#endif
+
+#ifdef CONFIG_ANDROID_PMEM
+ if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file))
+ return 0;
+#endif
+ file = fget_light(img->memory_id, &put_needed);
+ if (file == NULL)
+ return -1;
+
+ if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
+ *start = info->fix.smem_start;
+ *len = info->fix.smem_len;
+ *pp_file = file;
+ } else {
+ ret = -1;
+ fput_light(file, put_needed);
+ }
+ return ret;
+}
+
+
+void put_img(struct file *p_src_file)
+{
+#ifdef CONFIG_ANDROID_PMEM
+ if (p_src_file)
+ put_pmem_file(p_src_file);
+#endif
+}
+
+
+int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req)
+{
+ unsigned long src_start, dst_start;
+ unsigned long src_len = 0;
+ unsigned long dst_len = 0;
+ MDPIBUF iBuf;
+ u32 dst_width, dst_height;
+ struct file *p_src_file = 0 , *p_dst_file = 0;
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ if (req->dst.format == MDP_FB_FORMAT)
+ req->dst.format = mfd->fb_imgType;
+ if (req->src.format == MDP_FB_FORMAT)
+ req->src.format = mfd->fb_imgType;
+ if (req->flags & MDP_BLIT_SRC_GEM)
+ get_gem_img(&req->src, &src_start, &src_len);
+ else
+ get_img(&req->src, info, &src_start, &src_len, &p_src_file);
+ if (src_len == 0) {
+ printk(KERN_ERR "mdp_ppp: could not retrieve image from "
+ "memory\n");
+ return -1;
+ }
+ if (req->flags & MDP_BLIT_DST_GEM)
+ get_gem_img(&req->dst, &dst_start, &dst_len);
+ else
+ get_img(&req->dst, info, &dst_start, &dst_len, &p_dst_file);
+ if (dst_len == 0) {
+ put_img(p_src_file);
+ printk(KERN_ERR "mdp_ppp: could not retrieve image from "
+ "memory\n");
+ return -1;
+ }
+ if (mdp_ppp_verify_req(req)) {
+ printk(KERN_ERR "mdp_ppp: invalid image!\n");
+ put_img(p_src_file);
+ put_img(p_dst_file);
+ return -1;
}
- if (unlikely(req->src_rect.x > req->src.width ||
- req->src_rect.y > req->src.height ||
- req->dst_rect.x > req->dst.width ||
- req->dst_rect.y > req->dst.height)) {
- printk(KERN_ERR "mpd_ppp: img rect is outside of img!\n");
- return -EINVAL;
+ iBuf.ibuf_width = req->dst.width;
+ iBuf.ibuf_height = req->dst.height;
+ iBuf.bpp = bytes_per_pixel[req->dst.format];
+
+ iBuf.ibuf_type = req->dst.format;
+ iBuf.buf = (uint8 *) dst_start;
+ iBuf.buf += req->dst.offset;
+
+ iBuf.roi.lcd_x = req->dst_rect.x;
+ iBuf.roi.lcd_y = req->dst_rect.y;
+ iBuf.roi.dst_width = req->dst_rect.w;
+ iBuf.roi.dst_height = req->dst_rect.h;
+
+ iBuf.roi.x = req->src_rect.x;
+ iBuf.roi.width = req->src_rect.w;
+ iBuf.roi.y = req->src_rect.y;
+ iBuf.roi.height = req->src_rect.h;
+
+ iBuf.mdpImg.width = req->src.width;
+ iBuf.mdpImg.imgType = req->src.format;
+
+ iBuf.mdpImg.bmy_addr = (uint32 *) (src_start + req->src.offset);
+ iBuf.mdpImg.cbcr_addr =
+ (uint32 *) ((uint32) iBuf.mdpImg.bmy_addr +
+ req->src.width * req->src.height);
+
+ iBuf.mdpImg.mdpOp = MDPOP_NOP;
+
+ /* blending check */
+ if (req->transp_mask != MDP_TRANSP_NOP) {
+ iBuf.mdpImg.mdpOp |= MDPOP_TRANSP;
+ iBuf.mdpImg.tpVal = req->transp_mask;
+ iBuf.mdpImg.tpVal = mdp_calc_tpval(&iBuf.mdpImg);
+ } else {
+ iBuf.mdpImg.tpVal = 0;
}
- /* set the src image configuration */
- regs.src_cfg = src_img_cfg[req->src.format];
- regs.src_cfg |= (req->src_rect.x & 0x1) ? PPP_SRC_BPP_ROI_ODD_X : 0;
- regs.src_cfg |= (req->src_rect.y & 0x1) ? PPP_SRC_BPP_ROI_ODD_Y : 0;
- regs.src_rect = (req->src_rect.h << 16) | req->src_rect.w;
- regs.src_pack = pack_pattern[req->src.format];
-
- /* set the dest image configuration */
- regs.dst_cfg = dst_img_cfg[req->dst.format] | PPP_DST_OUT_SEL_AXI;
- regs.dst_rect = (req->dst_rect.h << 16) | req->dst_rect.w;
- regs.dst_pack = pack_pattern[req->dst.format];
-
- /* set src, bpp, start pixel and ystride */
- regs.src_bpp = bytes_per_pixel[req->src.format];
- regs.src0 = src_start + req->src.offset;
- regs.src_ystride = req->src.width * regs.src_bpp;
- get_chroma_addr(&req->src, &req->src_rect, regs.src0, regs.src_bpp,
- regs.src_cfg, ®s.src1, ®s.src_ystride);
- regs.src0 += (req->src_rect.x + (req->src_rect.y * req->src.width)) *
- regs.src_bpp;
-
- /* set dst, bpp, start pixel and ystride */
- regs.dst_bpp = bytes_per_pixel[req->dst.format];
- regs.dst0 = dst_start + req->dst.offset;
- regs.dst_ystride = req->dst.width * regs.dst_bpp;
- get_chroma_addr(&req->dst, &req->dst_rect, regs.dst0, regs.dst_bpp,
- regs.dst_cfg, ®s.dst1, ®s.dst_ystride);
- regs.dst0 += (req->dst_rect.x + (req->dst_rect.y * req->dst.width)) *
- regs.dst_bpp;
-
- if (!valid_src_dst(src_start, src_len, dst_start, dst_len, req,
- ®s)) {
- printk(KERN_ERR "mpd_ppp: final src or dst location is "
- "invalid, are you trying to make an image too large "
- "or to place it outside the screen?\n");
- return -EINVAL;
+ req->alpha &= 0xff;
+ if (req->alpha < MDP_ALPHA_NOP) {
+ iBuf.mdpImg.mdpOp |= MDPOP_ALPHAB;
+ iBuf.mdpImg.alpha = req->alpha;
+ } else {
+ iBuf.mdpImg.alpha = 0xff;
}
- /* set up operation register */
- regs.op = 0;
- blit_rotate(req, ®s);
- blit_convert(req, ®s);
+ /* rotation check */
+ if (req->flags & MDP_FLIP_LR)
+ iBuf.mdpImg.mdpOp |= MDPOP_LR;
+ if (req->flags & MDP_FLIP_UD)
+ iBuf.mdpImg.mdpOp |= MDPOP_UD;
+ if (req->flags & MDP_ROT_90)
+ iBuf.mdpImg.mdpOp |= MDPOP_ROT90;
if (req->flags & MDP_DITHER)
- regs.op |= PPP_OP_DITHER_EN;
- blit_blend(req, ®s);
- if (blit_scale(mdp, req, ®s)) {
- printk(KERN_ERR "mpd_ppp: error computing scale for img.\n");
- return -EINVAL;
- }
- blit_blur(mdp, req, ®s);
- regs.op |= dst_op_chroma[req->dst.format] |
- src_op_chroma[req->src.format];
+ iBuf.mdpImg.mdpOp |= MDPOP_DITHER;
- /* if the image is YCRYCB, the x and w must be even */
- if (unlikely(req->src.format == MDP_YCRYCB_H2V1)) {
- req->src_rect.x = req->src_rect.x & (~0x1);
- req->src_rect.w = req->src_rect.w & (~0x1);
- req->dst_rect.x = req->dst_rect.x & (~0x1);
- req->dst_rect.w = req->dst_rect.w & (~0x1);
- }
- if (get_edge_cond(req, ®s))
+ if (req->flags & MDP_BLEND_FG_PREMULT) {
+#ifdef CONFIG_FB_MSM_MDP31
+ iBuf.mdpImg.mdpOp |= MDPOP_FG_PM_ALPHA;
+#else
+ put_img(p_src_file);
+ put_img(p_dst_file);
return -EINVAL;
+#endif
+ }
- send_blit(mdp, req, ®s, src_file, dst_file);
+ if (req->flags & MDP_DEINTERLACE) {
+#ifdef CONFIG_FB_MSM_MDP31
+ if ((req->src.format != MDP_Y_CBCR_H2V2) &&
+ (req->src.format != MDP_Y_CRCB_H2V2)) {
+#endif
+ put_img(p_src_file);
+ put_img(p_dst_file);
+ return -EINVAL;
+#ifdef CONFIG_FB_MSM_MDP31
+ }
+#endif
+ }
+
+ /* scale check */
+ if (req->flags & MDP_ROT_90) {
+ dst_width = req->dst_rect.h;
+ dst_height = req->dst_rect.w;
+ } else {
+ dst_width = req->dst_rect.w;
+ dst_height = req->dst_rect.h;
+ }
+
+ if ((iBuf.roi.width != dst_width) || (iBuf.roi.height != dst_height))
+ iBuf.mdpImg.mdpOp |= MDPOP_ASCALE;
+
+ if (req->flags & MDP_BLUR) {
+#ifdef CONFIG_FB_MSM_MDP31
+ if (req->flags & MDP_SHARPENING)
+ printk(KERN_WARNING
+ "mdp: MDP_SHARPENING is set with MDP_BLUR!\n");
+ req->flags |= MDP_SHARPENING;
+ req->sharpening_strength = -127;
+#else
+ iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_BLUR;
+
+#endif
+ }
+
+ if (req->flags & MDP_SHARPENING) {
+#ifdef CONFIG_FB_MSM_MDP31
+ if ((req->sharpening_strength > 127) ||
+ (req->sharpening_strength < -127)) {
+ printk(KERN_ERR
+ "%s: sharpening strength out of range\n",
+ __func__);
+ put_img(p_src_file);
+ put_img(p_dst_file);
+ return -EINVAL;
+ }
+
+ iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_SHARPENING;
+ iBuf.mdpImg.sp_value = req->sharpening_strength & 0xff;
+#else
+ put_img(p_src_file);
+ put_img(p_dst_file);
+ return -EINVAL;
+#endif
+ }
+
+ down(&mdp_ppp_mutex);
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+#ifndef CONFIG_FB_MSM_MDP22
+ mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
+#else
+ /* bg tile fetching HW workaround */
+ if (((iBuf.mdpImg.mdpOp & (MDPOP_TRANSP | MDPOP_ALPHAB)) ||
+ (req->src.format == MDP_ARGB_8888) ||
+ (req->src.format == MDP_BGRA_8888) ||
+ (req->src.format == MDP_RGBA_8888)) &&
+ (iBuf.mdpImg.mdpOp & MDPOP_ROT90) && (req->dst_rect.w <= 16)) {
+ int dst_h, src_w, i;
+ uint32 mdpOp = iBuf.mdpImg.mdpOp;
+
+ src_w = req->src_rect.w;
+ dst_h = iBuf.roi.dst_height;
+
+ for (i = 0; i < (req->dst_rect.h / 16); i++) {
+ /* this tile size */
+ iBuf.roi.dst_height = 16;
+ iBuf.roi.width =
+ (16 * req->src_rect.w) / req->dst_rect.h;
+
+ /* if it's out of scale range... */
+ if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR)
+ iBuf.roi.width =
+ (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ MDP_MAX_X_SCALE_FACTOR;
+ else if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR)
+ iBuf.roi.width =
+ (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ MDP_MIN_X_SCALE_FACTOR;
+
+ mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
+
+ /* next tile location */
+ iBuf.roi.lcd_y += 16;
+ iBuf.roi.x += iBuf.roi.width;
+
+ /* this is for a remainder update */
+ dst_h -= 16;
+ src_w -= iBuf.roi.width;
+ /* restore mdpOp since MDPOP_ASCALE have been cleared */
+ iBuf.mdpImg.mdpOp = mdpOp;
+ }
+
+ if ((dst_h < 0) || (src_w < 0))
+ printk
+ ("msm_fb: mdp_blt_ex() unexpected result! line:%d\n",
+ __LINE__);
+
+ /* remainder update */
+ if ((dst_h > 0) && (src_w > 0)) {
+ u32 tmp_v;
+
+ iBuf.roi.dst_height = dst_h;
+ iBuf.roi.width = src_w;
+
+ if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR) {
+ tmp_v =
+ (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ MDP_MAX_X_SCALE_FACTOR +
+ (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) %
+ MDP_MAX_X_SCALE_FACTOR ? 1 : 0;
+
+ /* move x location as roi width gets bigger */
+ iBuf.roi.x -= tmp_v - iBuf.roi.width;
+ iBuf.roi.width = tmp_v;
+ } else
+ if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR) {
+ tmp_v =
+ (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ MDP_MIN_X_SCALE_FACTOR +
+ (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) %
+ MDP_MIN_X_SCALE_FACTOR ? 1 : 0;
+
+ /*
+ * we don't move x location for continuity of
+ * source image
+ */
+ iBuf.roi.width = tmp_v;
+ }
+
+ mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
+ }
+ } else {
+ mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
+ }
+#endif
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ up(&mdp_ppp_mutex);
+
+ put_img(p_src_file);
+ put_img(p_dst_file);
return 0;
}
diff --git a/drivers/video/msm/mdp_ppp.h b/drivers/video/msm/mdp_ppp.h
new file mode 100644
index 0000000..e045643
--- /dev/null
+++ b/drivers/video/msm/mdp_ppp.h
@@ -0,0 +1,82 @@
+/* drivers/video/msm/mdp_ppp.h
+ *
+ * Copyright (C) 2009 Google Incorporated
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#ifndef _VIDEO_MSM_MDP_PPP_H_
+#define _VIDEO_MSM_MDP_PPP_H_
+
+#include <linux/types.h>
+
+struct ppp_regs {
+ uint32_t src0;
+ uint32_t src1;
+ uint32_t dst0;
+ uint32_t dst1;
+ uint32_t src_cfg;
+ uint32_t dst_cfg;
+ uint32_t src_pack;
+ uint32_t dst_pack;
+ uint32_t src_rect;
+ uint32_t dst_rect;
+ uint32_t src_ystride;
+ uint32_t dst_ystride;
+ uint32_t op;
+ uint32_t src_bpp;
+ uint32_t dst_bpp;
+ uint32_t edge;
+ uint32_t phasex_init;
+ uint32_t phasey_init;
+ uint32_t phasex_step;
+ uint32_t phasey_step;
+
+ uint32_t bg0;
+ uint32_t bg1;
+ uint32_t bg_cfg;
+ uint32_t bg_bpp;
+ uint32_t bg_pack;
+ uint32_t bg_ystride;
+
+#ifdef CONFIG_MSM_MDP31
+ uint32_t src_xy;
+ uint32_t src_img_sz;
+ uint32_t dst_xy;
+ uint32_t bg_xy;
+ uint32_t bg_img_sz;
+ uint32_t bg_alpha_sel;
+
+ uint32_t scale_cfg;
+ uint32_t csc_cfg;
+#endif
+};
+
+struct mdp_info;
+struct mdp_rect;
+struct mdp_blit_req;
+
+void mdp_ppp_init_scale(const struct mdp_info *mdp);
+int mdp_ppp_cfg_scale(const struct mdp_info *mdp, struct ppp_regs *regs,
+ struct mdp_rect *src_rect, struct mdp_rect *dst_rect,
+ uint32_t src_format, uint32_t dst_format);
+int mdp_ppp_load_blur(const struct mdp_info *mdp);
+
+#ifndef CONFIG_MSM_MDP31
+int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req, struct ppp_regs *regs);
+#else
+static inline int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req,
+ struct ppp_regs *regs)
+{
+ return 0;
+}
+#endif
+
+#endif /* _VIDEO_MSM_MDP_PPP_H_ */
diff --git a/drivers/video/msm/mdp_ppp22.c b/drivers/video/msm/mdp_ppp22.c
new file mode 100644
index 0000000..9016f0a
--- /dev/null
+++ b/drivers/video/msm/mdp_ppp22.c
@@ -0,0 +1,1091 @@
+/* drivers/video/msm/mdp_ppp22.c
+ *
+ * Copyright (C) 2007 Code Aurora Forum. All rights reserved.
+ * Copyright (C) 2007 Google Incorporated
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <linux/msm_mdp.h>
+
+#include "mdp_hw.h"
+#include "mdp_ppp.h"
+
+struct mdp_table_entry {
+ uint32_t reg;
+ uint32_t val;
+};
+
+enum {
+ MDP_DOWNSCALE_PT2TOPT4,
+ MDP_DOWNSCALE_PT4TOPT6,
+ MDP_DOWNSCALE_PT6TOPT8,
+ MDP_DOWNSCALE_PT8TO1,
+ MDP_DOWNSCALE_MAX,
+
+ /* not technically in the downscale table list */
+ MDP_DOWNSCALE_BLUR,
+};
+
+static int downscale_x_table;
+static int downscale_y_table;
+
+static struct mdp_table_entry mdp_upscale_table[] = {
+ { 0x5fffc, 0x0 },
+ { 0x50200, 0x7fc00000 },
+ { 0x5fffc, 0xff80000d },
+ { 0x50204, 0x7ec003f9 },
+ { 0x5fffc, 0xfec0001c },
+ { 0x50208, 0x7d4003f3 },
+ { 0x5fffc, 0xfe40002b },
+ { 0x5020c, 0x7b8003ed },
+ { 0x5fffc, 0xfd80003c },
+ { 0x50210, 0x794003e8 },
+ { 0x5fffc, 0xfcc0004d },
+ { 0x50214, 0x76c003e4 },
+ { 0x5fffc, 0xfc40005f },
+ { 0x50218, 0x73c003e0 },
+ { 0x5fffc, 0xfb800071 },
+ { 0x5021c, 0x708003de },
+ { 0x5fffc, 0xfac00085 },
+ { 0x50220, 0x6d0003db },
+ { 0x5fffc, 0xfa000098 },
+ { 0x50224, 0x698003d9 },
+ { 0x5fffc, 0xf98000ac },
+ { 0x50228, 0x654003d8 },
+ { 0x5fffc, 0xf8c000c1 },
+ { 0x5022c, 0x610003d7 },
+ { 0x5fffc, 0xf84000d5 },
+ { 0x50230, 0x5c8003d7 },
+ { 0x5fffc, 0xf7c000e9 },
+ { 0x50234, 0x580003d7 },
+ { 0x5fffc, 0xf74000fd },
+ { 0x50238, 0x534003d8 },
+ { 0x5fffc, 0xf6c00112 },
+ { 0x5023c, 0x4e8003d8 },
+ { 0x5fffc, 0xf6800126 },
+ { 0x50240, 0x494003da },
+ { 0x5fffc, 0xf600013a },
+ { 0x50244, 0x448003db },
+ { 0x5fffc, 0xf600014d },
+ { 0x50248, 0x3f4003dd },
+ { 0x5fffc, 0xf5c00160 },
+ { 0x5024c, 0x3a4003df },
+ { 0x5fffc, 0xf5c00172 },
+ { 0x50250, 0x354003e1 },
+ { 0x5fffc, 0xf5c00184 },
+ { 0x50254, 0x304003e3 },
+ { 0x5fffc, 0xf6000195 },
+ { 0x50258, 0x2b0003e6 },
+ { 0x5fffc, 0xf64001a6 },
+ { 0x5025c, 0x260003e8 },
+ { 0x5fffc, 0xf6c001b4 },
+ { 0x50260, 0x214003eb },
+ { 0x5fffc, 0xf78001c2 },
+ { 0x50264, 0x1c4003ee },
+ { 0x5fffc, 0xf80001cf },
+ { 0x50268, 0x17c003f1 },
+ { 0x5fffc, 0xf90001db },
+ { 0x5026c, 0x134003f3 },
+ { 0x5fffc, 0xfa0001e5 },
+ { 0x50270, 0xf0003f6 },
+ { 0x5fffc, 0xfb4001ee },
+ { 0x50274, 0xac003f9 },
+ { 0x5fffc, 0xfcc001f5 },
+ { 0x50278, 0x70003fb },
+ { 0x5fffc, 0xfe4001fb },
+ { 0x5027c, 0x34003fe },
+};
+
+static struct mdp_table_entry mdp_downscale_x_table_PT2TOPT4[] = {
+ { 0x5fffc, 0x740008c },
+ { 0x50280, 0x33800088 },
+ { 0x5fffc, 0x800008e },
+ { 0x50284, 0x33400084 },
+ { 0x5fffc, 0x8400092 },
+ { 0x50288, 0x33000080 },
+ { 0x5fffc, 0x9000094 },
+ { 0x5028c, 0x3300007b },
+ { 0x5fffc, 0x9c00098 },
+ { 0x50290, 0x32400077 },
+ { 0x5fffc, 0xa40009b },
+ { 0x50294, 0x32000073 },
+ { 0x5fffc, 0xb00009d },
+ { 0x50298, 0x31c0006f },
+ { 0x5fffc, 0xbc000a0 },
+ { 0x5029c, 0x3140006b },
+ { 0x5fffc, 0xc8000a2 },
+ { 0x502a0, 0x31000067 },
+ { 0x5fffc, 0xd8000a5 },
+ { 0x502a4, 0x30800062 },
+ { 0x5fffc, 0xe4000a8 },
+ { 0x502a8, 0x2fc0005f },
+ { 0x5fffc, 0xec000aa },
+ { 0x502ac, 0x2fc0005b },
+ { 0x5fffc, 0xf8000ad },
+ { 0x502b0, 0x2f400057 },
+ { 0x5fffc, 0x108000b0 },
+ { 0x502b4, 0x2e400054 },
+ { 0x5fffc, 0x114000b2 },
+ { 0x502b8, 0x2e000050 },
+ { 0x5fffc, 0x124000b4 },
+ { 0x502bc, 0x2d80004c },
+ { 0x5fffc, 0x130000b6 },
+ { 0x502c0, 0x2d000049 },
+ { 0x5fffc, 0x140000b8 },
+ { 0x502c4, 0x2c800045 },
+ { 0x5fffc, 0x150000b9 },
+ { 0x502c8, 0x2c000042 },
+ { 0x5fffc, 0x15c000bd },
+ { 0x502cc, 0x2b40003e },
+ { 0x5fffc, 0x16c000bf },
+ { 0x502d0, 0x2a80003b },
+ { 0x5fffc, 0x17c000bf },
+ { 0x502d4, 0x2a000039 },
+ { 0x5fffc, 0x188000c2 },
+ { 0x502d8, 0x29400036 },
+ { 0x5fffc, 0x19c000c4 },
+ { 0x502dc, 0x28800032 },
+ { 0x5fffc, 0x1ac000c5 },
+ { 0x502e0, 0x2800002f },
+ { 0x5fffc, 0x1bc000c7 },
+ { 0x502e4, 0x2740002c },
+ { 0x5fffc, 0x1cc000c8 },
+ { 0x502e8, 0x26c00029 },
+ { 0x5fffc, 0x1dc000c9 },
+ { 0x502ec, 0x26000027 },
+ { 0x5fffc, 0x1ec000cc },
+ { 0x502f0, 0x25000024 },
+ { 0x5fffc, 0x200000cc },
+ { 0x502f4, 0x24800021 },
+ { 0x5fffc, 0x210000cd },
+ { 0x502f8, 0x23800020 },
+ { 0x5fffc, 0x220000ce },
+ { 0x502fc, 0x2300001d },
+};
+
+static struct mdp_table_entry mdp_downscale_x_table_PT4TOPT6[] = {
+ { 0x5fffc, 0x740008c },
+ { 0x50280, 0x33800088 },
+ { 0x5fffc, 0x800008e },
+ { 0x50284, 0x33400084 },
+ { 0x5fffc, 0x8400092 },
+ { 0x50288, 0x33000080 },
+ { 0x5fffc, 0x9000094 },
+ { 0x5028c, 0x3300007b },
+ { 0x5fffc, 0x9c00098 },
+ { 0x50290, 0x32400077 },
+ { 0x5fffc, 0xa40009b },
+ { 0x50294, 0x32000073 },
+ { 0x5fffc, 0xb00009d },
+ { 0x50298, 0x31c0006f },
+ { 0x5fffc, 0xbc000a0 },
+ { 0x5029c, 0x3140006b },
+ { 0x5fffc, 0xc8000a2 },
+ { 0x502a0, 0x31000067 },
+ { 0x5fffc, 0xd8000a5 },
+ { 0x502a4, 0x30800062 },
+ { 0x5fffc, 0xe4000a8 },
+ { 0x502a8, 0x2fc0005f },
+ { 0x5fffc, 0xec000aa },
+ { 0x502ac, 0x2fc0005b },
+ { 0x5fffc, 0xf8000ad },
+ { 0x502b0, 0x2f400057 },
+ { 0x5fffc, 0x108000b0 },
+ { 0x502b4, 0x2e400054 },
+ { 0x5fffc, 0x114000b2 },
+ { 0x502b8, 0x2e000050 },
+ { 0x5fffc, 0x124000b4 },
+ { 0x502bc, 0x2d80004c },
+ { 0x5fffc, 0x130000b6 },
+ { 0x502c0, 0x2d000049 },
+ { 0x5fffc, 0x140000b8 },
+ { 0x502c4, 0x2c800045 },
+ { 0x5fffc, 0x150000b9 },
+ { 0x502c8, 0x2c000042 },
+ { 0x5fffc, 0x15c000bd },
+ { 0x502cc, 0x2b40003e },
+ { 0x5fffc, 0x16c000bf },
+ { 0x502d0, 0x2a80003b },
+ { 0x5fffc, 0x17c000bf },
+ { 0x502d4, 0x2a000039 },
+ { 0x5fffc, 0x188000c2 },
+ { 0x502d8, 0x29400036 },
+ { 0x5fffc, 0x19c000c4 },
+ { 0x502dc, 0x28800032 },
+ { 0x5fffc, 0x1ac000c5 },
+ { 0x502e0, 0x2800002f },
+ { 0x5fffc, 0x1bc000c7 },
+ { 0x502e4, 0x2740002c },
+ { 0x5fffc, 0x1cc000c8 },
+ { 0x502e8, 0x26c00029 },
+ { 0x5fffc, 0x1dc000c9 },
+ { 0x502ec, 0x26000027 },
+ { 0x5fffc, 0x1ec000cc },
+ { 0x502f0, 0x25000024 },
+ { 0x5fffc, 0x200000cc },
+ { 0x502f4, 0x24800021 },
+ { 0x5fffc, 0x210000cd },
+ { 0x502f8, 0x23800020 },
+ { 0x5fffc, 0x220000ce },
+ { 0x502fc, 0x2300001d },
+};
+
+static struct mdp_table_entry mdp_downscale_x_table_PT6TOPT8[] = {
+ { 0x5fffc, 0xfe000070 },
+ { 0x50280, 0x4bc00068 },
+ { 0x5fffc, 0xfe000078 },
+ { 0x50284, 0x4bc00060 },
+ { 0x5fffc, 0xfe000080 },
+ { 0x50288, 0x4b800059 },
+ { 0x5fffc, 0xfe000089 },
+ { 0x5028c, 0x4b000052 },
+ { 0x5fffc, 0xfe400091 },
+ { 0x50290, 0x4a80004b },
+ { 0x5fffc, 0xfe40009a },
+ { 0x50294, 0x4a000044 },
+ { 0x5fffc, 0xfe8000a3 },
+ { 0x50298, 0x4940003d },
+ { 0x5fffc, 0xfec000ac },
+ { 0x5029c, 0x48400037 },
+ { 0x5fffc, 0xff0000b4 },
+ { 0x502a0, 0x47800031 },
+ { 0x5fffc, 0xff8000bd },
+ { 0x502a4, 0x4640002b },
+ { 0x5fffc, 0xc5 },
+ { 0x502a8, 0x45000026 },
+ { 0x5fffc, 0x8000ce },
+ { 0x502ac, 0x43800021 },
+ { 0x5fffc, 0x10000d6 },
+ { 0x502b0, 0x4240001c },
+ { 0x5fffc, 0x18000df },
+ { 0x502b4, 0x40800018 },
+ { 0x5fffc, 0x24000e6 },
+ { 0x502b8, 0x3f000014 },
+ { 0x5fffc, 0x30000ee },
+ { 0x502bc, 0x3d400010 },
+ { 0x5fffc, 0x40000f5 },
+ { 0x502c0, 0x3b80000c },
+ { 0x5fffc, 0x50000fc },
+ { 0x502c4, 0x39800009 },
+ { 0x5fffc, 0x6000102 },
+ { 0x502c8, 0x37c00006 },
+ { 0x5fffc, 0x7000109 },
+ { 0x502cc, 0x35800004 },
+ { 0x5fffc, 0x840010e },
+ { 0x502d0, 0x33800002 },
+ { 0x5fffc, 0x9800114 },
+ { 0x502d4, 0x31400000 },
+ { 0x5fffc, 0xac00119 },
+ { 0x502d8, 0x2f4003fe },
+ { 0x5fffc, 0xc40011e },
+ { 0x502dc, 0x2d0003fc },
+ { 0x5fffc, 0xdc00121 },
+ { 0x502e0, 0x2b0003fb },
+ { 0x5fffc, 0xf400125 },
+ { 0x502e4, 0x28c003fa },
+ { 0x5fffc, 0x11000128 },
+ { 0x502e8, 0x268003f9 },
+ { 0x5fffc, 0x12c0012a },
+ { 0x502ec, 0x244003f9 },
+ { 0x5fffc, 0x1480012c },
+ { 0x502f0, 0x224003f8 },
+ { 0x5fffc, 0x1640012e },
+ { 0x502f4, 0x200003f8 },
+ { 0x5fffc, 0x1800012f },
+ { 0x502f8, 0x1e0003f8 },
+ { 0x5fffc, 0x1a00012f },
+ { 0x502fc, 0x1c0003f8 },
+};
+
+static struct mdp_table_entry mdp_downscale_x_table_PT8TO1[] = {
+ { 0x5fffc, 0x0 },
+ { 0x50280, 0x7fc00000 },
+ { 0x5fffc, 0xff80000d },
+ { 0x50284, 0x7ec003f9 },
+ { 0x5fffc, 0xfec0001c },
+ { 0x50288, 0x7d4003f3 },
+ { 0x5fffc, 0xfe40002b },
+ { 0x5028c, 0x7b8003ed },
+ { 0x5fffc, 0xfd80003c },
+ { 0x50290, 0x794003e8 },
+ { 0x5fffc, 0xfcc0004d },
+ { 0x50294, 0x76c003e4 },
+ { 0x5fffc, 0xfc40005f },
+ { 0x50298, 0x73c003e0 },
+ { 0x5fffc, 0xfb800071 },
+ { 0x5029c, 0x708003de },
+ { 0x5fffc, 0xfac00085 },
+ { 0x502a0, 0x6d0003db },
+ { 0x5fffc, 0xfa000098 },
+ { 0x502a4, 0x698003d9 },
+ { 0x5fffc, 0xf98000ac },
+ { 0x502a8, 0x654003d8 },
+ { 0x5fffc, 0xf8c000c1 },
+ { 0x502ac, 0x610003d7 },
+ { 0x5fffc, 0xf84000d5 },
+ { 0x502b0, 0x5c8003d7 },
+ { 0x5fffc, 0xf7c000e9 },
+ { 0x502b4, 0x580003d7 },
+ { 0x5fffc, 0xf74000fd },
+ { 0x502b8, 0x534003d8 },
+ { 0x5fffc, 0xf6c00112 },
+ { 0x502bc, 0x4e8003d8 },
+ { 0x5fffc, 0xf6800126 },
+ { 0x502c0, 0x494003da },
+ { 0x5fffc, 0xf600013a },
+ { 0x502c4, 0x448003db },
+ { 0x5fffc, 0xf600014d },
+ { 0x502c8, 0x3f4003dd },
+ { 0x5fffc, 0xf5c00160 },
+ { 0x502cc, 0x3a4003df },
+ { 0x5fffc, 0xf5c00172 },
+ { 0x502d0, 0x354003e1 },
+ { 0x5fffc, 0xf5c00184 },
+ { 0x502d4, 0x304003e3 },
+ { 0x5fffc, 0xf6000195 },
+ { 0x502d8, 0x2b0003e6 },
+ { 0x5fffc, 0xf64001a6 },
+ { 0x502dc, 0x260003e8 },
+ { 0x5fffc, 0xf6c001b4 },
+ { 0x502e0, 0x214003eb },
+ { 0x5fffc, 0xf78001c2 },
+ { 0x502e4, 0x1c4003ee },
+ { 0x5fffc, 0xf80001cf },
+ { 0x502e8, 0x17c003f1 },
+ { 0x5fffc, 0xf90001db },
+ { 0x502ec, 0x134003f3 },
+ { 0x5fffc, 0xfa0001e5 },
+ { 0x502f0, 0xf0003f6 },
+ { 0x5fffc, 0xfb4001ee },
+ { 0x502f4, 0xac003f9 },
+ { 0x5fffc, 0xfcc001f5 },
+ { 0x502f8, 0x70003fb },
+ { 0x5fffc, 0xfe4001fb },
+ { 0x502fc, 0x34003fe },
+};
+
+struct mdp_table_entry *mdp_downscale_x_table[MDP_DOWNSCALE_MAX] = {
+ [MDP_DOWNSCALE_PT2TOPT4] = mdp_downscale_x_table_PT2TOPT4,
+ [MDP_DOWNSCALE_PT4TOPT6] = mdp_downscale_x_table_PT4TOPT6,
+ [MDP_DOWNSCALE_PT6TOPT8] = mdp_downscale_x_table_PT6TOPT8,
+ [MDP_DOWNSCALE_PT8TO1] = mdp_downscale_x_table_PT8TO1,
+};
+
+static struct mdp_table_entry mdp_downscale_y_table_PT2TOPT4[] = {
+ { 0x5fffc, 0x740008c },
+ { 0x50300, 0x33800088 },
+ { 0x5fffc, 0x800008e },
+ { 0x50304, 0x33400084 },
+ { 0x5fffc, 0x8400092 },
+ { 0x50308, 0x33000080 },
+ { 0x5fffc, 0x9000094 },
+ { 0x5030c, 0x3300007b },
+ { 0x5fffc, 0x9c00098 },
+ { 0x50310, 0x32400077 },
+ { 0x5fffc, 0xa40009b },
+ { 0x50314, 0x32000073 },
+ { 0x5fffc, 0xb00009d },
+ { 0x50318, 0x31c0006f },
+ { 0x5fffc, 0xbc000a0 },
+ { 0x5031c, 0x3140006b },
+ { 0x5fffc, 0xc8000a2 },
+ { 0x50320, 0x31000067 },
+ { 0x5fffc, 0xd8000a5 },
+ { 0x50324, 0x30800062 },
+ { 0x5fffc, 0xe4000a8 },
+ { 0x50328, 0x2fc0005f },
+ { 0x5fffc, 0xec000aa },
+ { 0x5032c, 0x2fc0005b },
+ { 0x5fffc, 0xf8000ad },
+ { 0x50330, 0x2f400057 },
+ { 0x5fffc, 0x108000b0 },
+ { 0x50334, 0x2e400054 },
+ { 0x5fffc, 0x114000b2 },
+ { 0x50338, 0x2e000050 },
+ { 0x5fffc, 0x124000b4 },
+ { 0x5033c, 0x2d80004c },
+ { 0x5fffc, 0x130000b6 },
+ { 0x50340, 0x2d000049 },
+ { 0x5fffc, 0x140000b8 },
+ { 0x50344, 0x2c800045 },
+ { 0x5fffc, 0x150000b9 },
+ { 0x50348, 0x2c000042 },
+ { 0x5fffc, 0x15c000bd },
+ { 0x5034c, 0x2b40003e },
+ { 0x5fffc, 0x16c000bf },
+ { 0x50350, 0x2a80003b },
+ { 0x5fffc, 0x17c000bf },
+ { 0x50354, 0x2a000039 },
+ { 0x5fffc, 0x188000c2 },
+ { 0x50358, 0x29400036 },
+ { 0x5fffc, 0x19c000c4 },
+ { 0x5035c, 0x28800032 },
+ { 0x5fffc, 0x1ac000c5 },
+ { 0x50360, 0x2800002f },
+ { 0x5fffc, 0x1bc000c7 },
+ { 0x50364, 0x2740002c },
+ { 0x5fffc, 0x1cc000c8 },
+ { 0x50368, 0x26c00029 },
+ { 0x5fffc, 0x1dc000c9 },
+ { 0x5036c, 0x26000027 },
+ { 0x5fffc, 0x1ec000cc },
+ { 0x50370, 0x25000024 },
+ { 0x5fffc, 0x200000cc },
+ { 0x50374, 0x24800021 },
+ { 0x5fffc, 0x210000cd },
+ { 0x50378, 0x23800020 },
+ { 0x5fffc, 0x220000ce },
+ { 0x5037c, 0x2300001d },
+};
+
+static struct mdp_table_entry mdp_downscale_y_table_PT4TOPT6[] = {
+ { 0x5fffc, 0x740008c },
+ { 0x50300, 0x33800088 },
+ { 0x5fffc, 0x800008e },
+ { 0x50304, 0x33400084 },
+ { 0x5fffc, 0x8400092 },
+ { 0x50308, 0x33000080 },
+ { 0x5fffc, 0x9000094 },
+ { 0x5030c, 0x3300007b },
+ { 0x5fffc, 0x9c00098 },
+ { 0x50310, 0x32400077 },
+ { 0x5fffc, 0xa40009b },
+ { 0x50314, 0x32000073 },
+ { 0x5fffc, 0xb00009d },
+ { 0x50318, 0x31c0006f },
+ { 0x5fffc, 0xbc000a0 },
+ { 0x5031c, 0x3140006b },
+ { 0x5fffc, 0xc8000a2 },
+ { 0x50320, 0x31000067 },
+ { 0x5fffc, 0xd8000a5 },
+ { 0x50324, 0x30800062 },
+ { 0x5fffc, 0xe4000a8 },
+ { 0x50328, 0x2fc0005f },
+ { 0x5fffc, 0xec000aa },
+ { 0x5032c, 0x2fc0005b },
+ { 0x5fffc, 0xf8000ad },
+ { 0x50330, 0x2f400057 },
+ { 0x5fffc, 0x108000b0 },
+ { 0x50334, 0x2e400054 },
+ { 0x5fffc, 0x114000b2 },
+ { 0x50338, 0x2e000050 },
+ { 0x5fffc, 0x124000b4 },
+ { 0x5033c, 0x2d80004c },
+ { 0x5fffc, 0x130000b6 },
+ { 0x50340, 0x2d000049 },
+ { 0x5fffc, 0x140000b8 },
+ { 0x50344, 0x2c800045 },
+ { 0x5fffc, 0x150000b9 },
+ { 0x50348, 0x2c000042 },
+ { 0x5fffc, 0x15c000bd },
+ { 0x5034c, 0x2b40003e },
+ { 0x5fffc, 0x16c000bf },
+ { 0x50350, 0x2a80003b },
+ { 0x5fffc, 0x17c000bf },
+ { 0x50354, 0x2a000039 },
+ { 0x5fffc, 0x188000c2 },
+ { 0x50358, 0x29400036 },
+ { 0x5fffc, 0x19c000c4 },
+ { 0x5035c, 0x28800032 },
+ { 0x5fffc, 0x1ac000c5 },
+ { 0x50360, 0x2800002f },
+ { 0x5fffc, 0x1bc000c7 },
+ { 0x50364, 0x2740002c },
+ { 0x5fffc, 0x1cc000c8 },
+ { 0x50368, 0x26c00029 },
+ { 0x5fffc, 0x1dc000c9 },
+ { 0x5036c, 0x26000027 },
+ { 0x5fffc, 0x1ec000cc },
+ { 0x50370, 0x25000024 },
+ { 0x5fffc, 0x200000cc },
+ { 0x50374, 0x24800021 },
+ { 0x5fffc, 0x210000cd },
+ { 0x50378, 0x23800020 },
+ { 0x5fffc, 0x220000ce },
+ { 0x5037c, 0x2300001d },
+};
+
+static struct mdp_table_entry mdp_downscale_y_table_PT6TOPT8[] = {
+ { 0x5fffc, 0xfe000070 },
+ { 0x50300, 0x4bc00068 },
+ { 0x5fffc, 0xfe000078 },
+ { 0x50304, 0x4bc00060 },
+ { 0x5fffc, 0xfe000080 },
+ { 0x50308, 0x4b800059 },
+ { 0x5fffc, 0xfe000089 },
+ { 0x5030c, 0x4b000052 },
+ { 0x5fffc, 0xfe400091 },
+ { 0x50310, 0x4a80004b },
+ { 0x5fffc, 0xfe40009a },
+ { 0x50314, 0x4a000044 },
+ { 0x5fffc, 0xfe8000a3 },
+ { 0x50318, 0x4940003d },
+ { 0x5fffc, 0xfec000ac },
+ { 0x5031c, 0x48400037 },
+ { 0x5fffc, 0xff0000b4 },
+ { 0x50320, 0x47800031 },
+ { 0x5fffc, 0xff8000bd },
+ { 0x50324, 0x4640002b },
+ { 0x5fffc, 0xc5 },
+ { 0x50328, 0x45000026 },
+ { 0x5fffc, 0x8000ce },
+ { 0x5032c, 0x43800021 },
+ { 0x5fffc, 0x10000d6 },
+ { 0x50330, 0x4240001c },
+ { 0x5fffc, 0x18000df },
+ { 0x50334, 0x40800018 },
+ { 0x5fffc, 0x24000e6 },
+ { 0x50338, 0x3f000014 },
+ { 0x5fffc, 0x30000ee },
+ { 0x5033c, 0x3d400010 },
+ { 0x5fffc, 0x40000f5 },
+ { 0x50340, 0x3b80000c },
+ { 0x5fffc, 0x50000fc },
+ { 0x50344, 0x39800009 },
+ { 0x5fffc, 0x6000102 },
+ { 0x50348, 0x37c00006 },
+ { 0x5fffc, 0x7000109 },
+ { 0x5034c, 0x35800004 },
+ { 0x5fffc, 0x840010e },
+ { 0x50350, 0x33800002 },
+ { 0x5fffc, 0x9800114 },
+ { 0x50354, 0x31400000 },
+ { 0x5fffc, 0xac00119 },
+ { 0x50358, 0x2f4003fe },
+ { 0x5fffc, 0xc40011e },
+ { 0x5035c, 0x2d0003fc },
+ { 0x5fffc, 0xdc00121 },
+ { 0x50360, 0x2b0003fb },
+ { 0x5fffc, 0xf400125 },
+ { 0x50364, 0x28c003fa },
+ { 0x5fffc, 0x11000128 },
+ { 0x50368, 0x268003f9 },
+ { 0x5fffc, 0x12c0012a },
+ { 0x5036c, 0x244003f9 },
+ { 0x5fffc, 0x1480012c },
+ { 0x50370, 0x224003f8 },
+ { 0x5fffc, 0x1640012e },
+ { 0x50374, 0x200003f8 },
+ { 0x5fffc, 0x1800012f },
+ { 0x50378, 0x1e0003f8 },
+ { 0x5fffc, 0x1a00012f },
+ { 0x5037c, 0x1c0003f8 },
+};
+
+static struct mdp_table_entry mdp_downscale_y_table_PT8TO1[] = {
+ { 0x5fffc, 0x0 },
+ { 0x50300, 0x7fc00000 },
+ { 0x5fffc, 0xff80000d },
+ { 0x50304, 0x7ec003f9 },
+ { 0x5fffc, 0xfec0001c },
+ { 0x50308, 0x7d4003f3 },
+ { 0x5fffc, 0xfe40002b },
+ { 0x5030c, 0x7b8003ed },
+ { 0x5fffc, 0xfd80003c },
+ { 0x50310, 0x794003e8 },
+ { 0x5fffc, 0xfcc0004d },
+ { 0x50314, 0x76c003e4 },
+ { 0x5fffc, 0xfc40005f },
+ { 0x50318, 0x73c003e0 },
+ { 0x5fffc, 0xfb800071 },
+ { 0x5031c, 0x708003de },
+ { 0x5fffc, 0xfac00085 },
+ { 0x50320, 0x6d0003db },
+ { 0x5fffc, 0xfa000098 },
+ { 0x50324, 0x698003d9 },
+ { 0x5fffc, 0xf98000ac },
+ { 0x50328, 0x654003d8 },
+ { 0x5fffc, 0xf8c000c1 },
+ { 0x5032c, 0x610003d7 },
+ { 0x5fffc, 0xf84000d5 },
+ { 0x50330, 0x5c8003d7 },
+ { 0x5fffc, 0xf7c000e9 },
+ { 0x50334, 0x580003d7 },
+ { 0x5fffc, 0xf74000fd },
+ { 0x50338, 0x534003d8 },
+ { 0x5fffc, 0xf6c00112 },
+ { 0x5033c, 0x4e8003d8 },
+ { 0x5fffc, 0xf6800126 },
+ { 0x50340, 0x494003da },
+ { 0x5fffc, 0xf600013a },
+ { 0x50344, 0x448003db },
+ { 0x5fffc, 0xf600014d },
+ { 0x50348, 0x3f4003dd },
+ { 0x5fffc, 0xf5c00160 },
+ { 0x5034c, 0x3a4003df },
+ { 0x5fffc, 0xf5c00172 },
+ { 0x50350, 0x354003e1 },
+ { 0x5fffc, 0xf5c00184 },
+ { 0x50354, 0x304003e3 },
+ { 0x5fffc, 0xf6000195 },
+ { 0x50358, 0x2b0003e6 },
+ { 0x5fffc, 0xf64001a6 },
+ { 0x5035c, 0x260003e8 },
+ { 0x5fffc, 0xf6c001b4 },
+ { 0x50360, 0x214003eb },
+ { 0x5fffc, 0xf78001c2 },
+ { 0x50364, 0x1c4003ee },
+ { 0x5fffc, 0xf80001cf },
+ { 0x50368, 0x17c003f1 },
+ { 0x5fffc, 0xf90001db },
+ { 0x5036c, 0x134003f3 },
+ { 0x5fffc, 0xfa0001e5 },
+ { 0x50370, 0xf0003f6 },
+ { 0x5fffc, 0xfb4001ee },
+ { 0x50374, 0xac003f9 },
+ { 0x5fffc, 0xfcc001f5 },
+ { 0x50378, 0x70003fb },
+ { 0x5fffc, 0xfe4001fb },
+ { 0x5037c, 0x34003fe },
+};
+
+struct mdp_table_entry *mdp_downscale_y_table[MDP_DOWNSCALE_MAX] = {
+ [MDP_DOWNSCALE_PT2TOPT4] = mdp_downscale_y_table_PT2TOPT4,
+ [MDP_DOWNSCALE_PT4TOPT6] = mdp_downscale_y_table_PT4TOPT6,
+ [MDP_DOWNSCALE_PT6TOPT8] = mdp_downscale_y_table_PT6TOPT8,
+ [MDP_DOWNSCALE_PT8TO1] = mdp_downscale_y_table_PT8TO1,
+};
+
+struct mdp_table_entry mdp_gaussian_blur_table[] = {
+ /* max variance */
+ { 0x5fffc, 0x20000080 },
+ { 0x50280, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50284, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50288, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5028c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50290, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50294, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50298, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5029c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502a0, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502a4, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502a8, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502ac, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502b0, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502b4, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502b8, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502bc, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502c0, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502c4, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502c8, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502cc, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502d0, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502d4, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502d8, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502dc, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502e0, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502e4, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502e8, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502ec, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502f0, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502f4, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502f8, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502fc, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50300, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50304, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50308, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5030c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50310, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50314, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50318, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5031c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50320, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50324, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50328, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5032c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50330, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50334, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50338, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5033c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50340, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50344, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50348, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5034c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50350, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50354, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50358, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5035c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50360, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50364, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50368, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5036c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50370, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50374, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50378, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5037c, 0x20000080 },
+};
+
+static void load_table(const struct mdp_info *mdp,
+ struct mdp_table_entry *table, int len)
+{
+ int i;
+ for (i = 0; i < len; i++)
+ mdp_writel(mdp, table[i].val, table[i].reg);
+}
+
+enum {
+ IMG_LEFT,
+ IMG_RIGHT,
+ IMG_TOP,
+ IMG_BOTTOM,
+};
+
+static void get_edge_info(uint32_t src, uint32_t src_coord, uint32_t dst,
+ uint32_t *interp1, uint32_t *interp2,
+ uint32_t *repeat1, uint32_t *repeat2) {
+ if (src > 3 * dst) {
+ *interp1 = 0;
+ *interp2 = src - 1;
+ *repeat1 = 0;
+ *repeat2 = 0;
+ } else if (src == 3 * dst) {
+ *interp1 = 0;
+ *interp2 = src;
+ *repeat1 = 0;
+ *repeat2 = 1;
+ } else if (src > dst && src < 3 * dst) {
+ *interp1 = -1;
+ *interp2 = src;
+ *repeat1 = 1;
+ *repeat2 = 1;
+ } else if (src == dst) {
+ *interp1 = -1;
+ *interp2 = src + 1;
+ *repeat1 = 1;
+ *repeat2 = 2;
+ } else {
+ *interp1 = -2;
+ *interp2 = src + 1;
+ *repeat1 = 2;
+ *repeat2 = 2;
+ }
+ *interp1 += src_coord;
+ *interp2 += src_coord;
+}
+
+int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req, struct ppp_regs *regs)
+{
+ int32_t luma_interp[4];
+ int32_t luma_repeat[4];
+ int32_t chroma_interp[4];
+ int32_t chroma_bound[4];
+ int32_t chroma_repeat[4];
+ uint32_t dst_w, dst_h;
+
+ memset(&luma_interp, 0, sizeof(int32_t) * 4);
+ memset(&luma_repeat, 0, sizeof(int32_t) * 4);
+ memset(&chroma_interp, 0, sizeof(int32_t) * 4);
+ memset(&chroma_bound, 0, sizeof(int32_t) * 4);
+ memset(&chroma_repeat, 0, sizeof(int32_t) * 4);
+ regs->edge = 0;
+
+ if (req->flags & MDP_ROT_90) {
+ dst_w = req->dst_rect.h;
+ dst_h = req->dst_rect.w;
+ } else {
+ dst_w = req->dst_rect.w;
+ dst_h = req->dst_rect.h;
+ }
+
+ if (regs->op & (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON)) {
+ get_edge_info(req->src_rect.h, req->src_rect.y, dst_h,
+ &luma_interp[IMG_TOP], &luma_interp[IMG_BOTTOM],
+ &luma_repeat[IMG_TOP], &luma_repeat[IMG_BOTTOM]);
+ get_edge_info(req->src_rect.w, req->src_rect.x, dst_w,
+ &luma_interp[IMG_LEFT], &luma_interp[IMG_RIGHT],
+ &luma_repeat[IMG_LEFT], &luma_repeat[IMG_RIGHT]);
+ } else {
+ luma_interp[IMG_LEFT] = req->src_rect.x;
+ luma_interp[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1;
+ luma_interp[IMG_TOP] = req->src_rect.y;
+ luma_interp[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1;
+ luma_repeat[IMG_LEFT] = 0;
+ luma_repeat[IMG_TOP] = 0;
+ luma_repeat[IMG_RIGHT] = 0;
+ luma_repeat[IMG_BOTTOM] = 0;
+ }
+
+ chroma_interp[IMG_LEFT] = luma_interp[IMG_LEFT];
+ chroma_interp[IMG_RIGHT] = luma_interp[IMG_RIGHT];
+ chroma_interp[IMG_TOP] = luma_interp[IMG_TOP];
+ chroma_interp[IMG_BOTTOM] = luma_interp[IMG_BOTTOM];
+
+ chroma_bound[IMG_LEFT] = req->src_rect.x;
+ chroma_bound[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1;
+ chroma_bound[IMG_TOP] = req->src_rect.y;
+ chroma_bound[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1;
+
+ if (IS_YCRCB(req->src.format)) {
+ chroma_interp[IMG_LEFT] = chroma_interp[IMG_LEFT] >> 1;
+ chroma_interp[IMG_RIGHT] = (chroma_interp[IMG_RIGHT] + 1) >> 1;
+
+ chroma_bound[IMG_LEFT] = chroma_bound[IMG_LEFT] >> 1;
+ chroma_bound[IMG_RIGHT] = chroma_bound[IMG_RIGHT] >> 1;
+ }
+
+ if (req->src.format == MDP_Y_CBCR_H2V2 ||
+ req->src.format == MDP_Y_CRCB_H2V2) {
+ chroma_interp[IMG_TOP] = (chroma_interp[IMG_TOP] - 1) >> 1;
+ chroma_interp[IMG_BOTTOM] = (chroma_interp[IMG_BOTTOM] + 1)
+ >> 1;
+ chroma_bound[IMG_TOP] = (chroma_bound[IMG_TOP] + 1) >> 1;
+ chroma_bound[IMG_BOTTOM] = chroma_bound[IMG_BOTTOM] >> 1;
+ }
+
+ chroma_repeat[IMG_LEFT] = chroma_bound[IMG_LEFT] -
+ chroma_interp[IMG_LEFT];
+ chroma_repeat[IMG_RIGHT] = chroma_interp[IMG_RIGHT] -
+ chroma_bound[IMG_RIGHT];
+ chroma_repeat[IMG_TOP] = chroma_bound[IMG_TOP] -
+ chroma_interp[IMG_TOP];
+ chroma_repeat[IMG_BOTTOM] = chroma_interp[IMG_BOTTOM] -
+ chroma_bound[IMG_BOTTOM];
+
+ if (chroma_repeat[IMG_LEFT] < 0 || chroma_repeat[IMG_LEFT] > 3 ||
+ chroma_repeat[IMG_RIGHT] < 0 || chroma_repeat[IMG_RIGHT] > 3 ||
+ chroma_repeat[IMG_TOP] < 0 || chroma_repeat[IMG_TOP] > 3 ||
+ chroma_repeat[IMG_BOTTOM] < 0 || chroma_repeat[IMG_BOTTOM] > 3 ||
+ luma_repeat[IMG_LEFT] < 0 || luma_repeat[IMG_LEFT] > 3 ||
+ luma_repeat[IMG_RIGHT] < 0 || luma_repeat[IMG_RIGHT] > 3 ||
+ luma_repeat[IMG_TOP] < 0 || luma_repeat[IMG_TOP] > 3 ||
+ luma_repeat[IMG_BOTTOM] < 0 || luma_repeat[IMG_BOTTOM] > 3)
+ return -1;
+
+ regs->edge |= (chroma_repeat[IMG_LEFT] & 3) << MDP_LEFT_CHROMA;
+ regs->edge |= (chroma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_CHROMA;
+ regs->edge |= (chroma_repeat[IMG_TOP] & 3) << MDP_TOP_CHROMA;
+ regs->edge |= (chroma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_CHROMA;
+ regs->edge |= (luma_repeat[IMG_LEFT] & 3) << MDP_LEFT_LUMA;
+ regs->edge |= (luma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_LUMA;
+ regs->edge |= (luma_repeat[IMG_TOP] & 3) << MDP_TOP_LUMA;
+ regs->edge |= (luma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_LUMA;
+ return 0;
+}
+
+#define ONE_HALF (1LL << 32)
+#define ONE (1LL << 33)
+#define TWO (2LL << 33)
+#define THREE (3LL << 33)
+#define FRAC_MASK (ONE - 1)
+#define INT_MASK (~FRAC_MASK)
+
+static int scale_params(uint32_t dim_in, uint32_t dim_out, uint32_t origin,
+ uint32_t *phase_init, uint32_t *phase_step)
+{
+ /* to improve precicsion calculations are done in U31.33 and converted
+ * to U3.29 at the end */
+ int64_t k1, k2, k3, k4, tmp;
+ uint64_t n, d, os, os_p, od, od_p, oreq;
+ unsigned rpa = 0;
+ int64_t ip64, delta;
+
+ if (dim_out % 3 == 0)
+ rpa = !(dim_in % (dim_out / 3));
+
+ n = ((uint64_t)dim_out) << 34;
+ d = dim_in;
+ if (!d)
+ return -1;
+ do_div(n, d);
+ k3 = (n + 1) >> 1;
+ if ((k3 >> 4) < (1LL << 27) || (k3 >> 4) > (1LL << 31))
+ return -1;
+
+ n = ((uint64_t)dim_in) << 34;
+ d = (uint64_t)dim_out;
+ if (!d)
+ return -1;
+ do_div(n, d);
+ k1 = (n + 1) >> 1;
+ k2 = (k1 - ONE) >> 1;
+
+ *phase_init = (int)(k2 >> 4);
+ k4 = (k3 - ONE) >> 1;
+
+ if (rpa) {
+ os = ((uint64_t)origin << 33) - ONE_HALF;
+ tmp = (dim_out * os) + ONE_HALF;
+ if (!dim_in)
+ return -1;
+ do_div(tmp, dim_in);
+ od = tmp - ONE_HALF;
+ } else {
+ os = ((uint64_t)origin << 1) - 1;
+ od = (((k3 * os) >> 1) + k4);
+ }
+
+ od_p = od & INT_MASK;
+ if (od_p != od)
+ od_p += ONE;
+
+ if (rpa) {
+ tmp = (dim_in * od_p) + ONE_HALF;
+ if (!dim_in)
+ return -1;
+ do_div(tmp, dim_in);
+ os_p = tmp - ONE_HALF;
+ } else {
+ os_p = ((k1 * (od_p >> 33)) + k2);
+ }
+
+ oreq = (os_p & INT_MASK) - ONE;
+
+ ip64 = os_p - oreq;
+ delta = ((int64_t)(origin) << 33) - oreq;
+ ip64 -= delta;
+ /* limit to valid range before the left shift */
+ delta = (ip64 & (1LL << 63)) ? 4 : -4;
+ delta <<= 33;
+ while (abs((int)(ip64 >> 33)) > 4)
+ ip64 += delta;
+ *phase_init = (int)(ip64 >> 4);
+ *phase_step = (uint32_t)(k1 >> 4);
+ return 0;
+}
+
+int mdp_ppp_cfg_scale(const struct mdp_info *mdp, struct ppp_regs *regs,
+ struct mdp_rect *src_rect, struct mdp_rect *dst_rect,
+ uint32_t src_format, uint32_t dst_format)
+{
+ int downscale;
+ uint32_t phase_init_x, phase_init_y, phase_step_x, phase_step_y;
+ uint32_t scale_factor_x, scale_factor_y;
+
+ if (scale_params(src_rect->w, dst_rect->w, 1, &phase_init_x,
+ &phase_step_x) ||
+ scale_params(src_rect->h, dst_rect->h, 1, &phase_init_y,
+ &phase_step_y))
+ return -1;
+
+ regs->phasex_init = phase_init_x;
+ regs->phasey_init = phase_init_y;
+ regs->phasex_step = phase_step_x;
+ regs->phasey_step = phase_step_y;
+
+ scale_factor_x = (dst_rect->w * 10) / src_rect->w;
+ scale_factor_y = (dst_rect->h * 10) / src_rect->h;
+
+ if (scale_factor_x > 8)
+ downscale = MDP_DOWNSCALE_PT8TO1;
+ else if (scale_factor_x > 6)
+ downscale = MDP_DOWNSCALE_PT6TOPT8;
+ else if (scale_factor_x > 4)
+ downscale = MDP_DOWNSCALE_PT4TOPT6;
+ else
+ downscale = MDP_DOWNSCALE_PT2TOPT4;
+
+ if (downscale != downscale_x_table) {
+ load_table(mdp, mdp_downscale_x_table[downscale], 64);
+ downscale_x_table = downscale;
+ }
+
+ if (scale_factor_y > 8)
+ downscale = MDP_DOWNSCALE_PT8TO1;
+ else if (scale_factor_y > 6)
+ downscale = MDP_DOWNSCALE_PT6TOPT8;
+ else if (scale_factor_y > 4)
+ downscale = MDP_DOWNSCALE_PT4TOPT6;
+ else
+ downscale = MDP_DOWNSCALE_PT2TOPT4;
+
+ if (downscale != downscale_y_table) {
+ load_table(mdp, mdp_downscale_y_table[downscale], 64);
+ downscale_y_table = downscale;
+ }
+
+ return 0;
+}
+
+
+int mdp_ppp_load_blur(const struct mdp_info *mdp)
+{
+ if (!(downscale_x_table == MDP_DOWNSCALE_BLUR &&
+ downscale_y_table == MDP_DOWNSCALE_BLUR)) {
+ load_table(mdp, mdp_gaussian_blur_table, 128);
+ downscale_x_table = MDP_DOWNSCALE_BLUR;
+ downscale_y_table = MDP_DOWNSCALE_BLUR;
+ }
+
+ return 0;
+}
+
+void mdp_ppp_init_scale(const struct mdp_info *mdp)
+{
+ downscale_x_table = MDP_DOWNSCALE_MAX;
+ downscale_y_table = MDP_DOWNSCALE_MAX;
+
+ load_table(mdp, mdp_upscale_table, ARRAY_SIZE(mdp_upscale_table));
+}
diff --git a/drivers/video/msm/mdp_ppp31.c b/drivers/video/msm/mdp_ppp31.c
new file mode 100644
index 0000000..91764fe
--- /dev/null
+++ b/drivers/video/msm/mdp_ppp31.c
@@ -0,0 +1,332 @@
+/* drivers/video/msm/mdp_ppp31.c
+ *
+ * Copyright (C) 2009 Code Aurora Forum. All rights reserved.
+ * Copyright (C) 2009 Google Incorporated
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <linux/msm_mdp.h>
+
+#include "mdp_hw.h"
+#include "mdp_ppp.h"
+
+#define NUM_COEFFS 32
+
+struct mdp_scale_coeffs {
+ uint16_t c[4][NUM_COEFFS];
+};
+
+struct mdp_scale_tbl_info {
+ uint16_t offset;
+ uint32_t set:2;
+ int use_pr;
+ struct mdp_scale_coeffs coeffs;
+};
+
+enum {
+ MDP_SCALE_PT2TOPT4,
+ MDP_SCALE_PT4TOPT6,
+ MDP_SCALE_PT6TOPT8,
+ MDP_SCALE_PT8TO8,
+ MDP_SCALE_MAX,
+};
+
+static struct mdp_scale_coeffs mdp_scale_pr_coeffs = {
+ .c = {
+ [0] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+ [1] = {
+ 511, 511, 511, 511, 511, 511, 511, 511,
+ 511, 511, 511, 511, 511, 511, 511, 511,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+ [2] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 511, 511, 511, 511, 511, 511, 511, 511,
+ 511, 511, 511, 511, 511, 511, 511, 511,
+ },
+ [3] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+ },
+};
+
+static struct mdp_scale_tbl_info mdp_scale_tbl[MDP_SCALE_MAX] = {
+ [ MDP_SCALE_PT2TOPT4 ] = {
+ .offset = 0,
+ .set = MDP_PPP_SCALE_COEFF_D0_SET,
+ .use_pr = -1,
+ .coeffs.c = {
+ [0] = {
+ 131, 131, 130, 129, 128, 127, 127, 126,
+ 125, 125, 124, 123, 123, 121, 120, 119,
+ 119, 118, 117, 117, 116, 115, 115, 114,
+ 113, 112, 111, 110, 109, 109, 108, 107,
+ },
+ [1] = {
+ 141, 140, 140, 140, 140, 139, 138, 138,
+ 138, 137, 137, 137, 136, 137, 137, 137,
+ 136, 136, 136, 135, 135, 135, 134, 134,
+ 134, 134, 134, 133, 133, 132, 132, 132,
+ },
+ [2] = {
+ 132, 132, 132, 133, 133, 134, 134, 134,
+ 134, 134, 135, 135, 135, 136, 136, 136,
+ 137, 137, 137, 136, 137, 137, 137, 138,
+ 138, 138, 139, 140, 140, 140, 140, 141,
+ },
+ [3] = {
+ 107, 108, 109, 109, 110, 111, 112, 113,
+ 114, 115, 115, 116, 117, 117, 118, 119,
+ 119, 120, 121, 123, 123, 124, 125, 125,
+ 126, 127, 127, 128, 129, 130, 131, 131,
+ }
+ },
+ },
+ [ MDP_SCALE_PT4TOPT6 ] = {
+ .offset = 32,
+ .set = MDP_PPP_SCALE_COEFF_D1_SET,
+ .use_pr = -1,
+ .coeffs.c = {
+ [0] = {
+ 136, 132, 128, 123, 119, 115, 111, 107,
+ 103, 98, 95, 91, 87, 84, 80, 76,
+ 73, 69, 66, 62, 59, 57, 54, 50,
+ 47, 44, 41, 39, 36, 33, 32, 29,
+ },
+ [1] = {
+ 206, 205, 204, 204, 201, 200, 199, 197,
+ 196, 194, 191, 191, 189, 185, 184, 182,
+ 180, 178, 176, 173, 170, 168, 165, 162,
+ 160, 157, 155, 152, 148, 146, 142, 140,
+ },
+ [2] = {
+ 140, 142, 146, 148, 152, 155, 157, 160,
+ 162, 165, 168, 170, 173, 176, 178, 180,
+ 182, 184, 185, 189, 191, 191, 194, 196,
+ 197, 199, 200, 201, 204, 204, 205, 206,
+ },
+ [3] = {
+ 29, 32, 33, 36, 39, 41, 44, 47,
+ 50, 54, 57, 59, 62, 66, 69, 73,
+ 76, 80, 84, 87, 91, 95, 98, 103,
+ 107, 111, 115, 119, 123, 128, 132, 136,
+ },
+ },
+ },
+ [ MDP_SCALE_PT6TOPT8 ] = {
+ .offset = 64,
+ .set = MDP_PPP_SCALE_COEFF_D2_SET,
+ .use_pr = -1,
+ .coeffs.c = {
+ [0] = {
+ 104, 96, 89, 82, 75, 68, 61, 55,
+ 49, 43, 38, 33, 28, 24, 20, 16,
+ 12, 9, 6, 4, 2, 0, -2, -4,
+ -5, -6, -7, -7, -8, -8, -8, -8,
+ },
+ [1] = {
+ 303, 303, 302, 300, 298, 296, 293, 289,
+ 286, 281, 276, 270, 265, 258, 252, 245,
+ 238, 230, 223, 214, 206, 197, 189, 180,
+ 172, 163, 154, 145, 137, 128, 120, 112,
+ },
+ [2] = {
+ 112, 120, 128, 137, 145, 154, 163, 172,
+ 180, 189, 197, 206, 214, 223, 230, 238,
+ 245, 252, 258, 265, 270, 276, 281, 286,
+ 289, 293, 296, 298, 300, 302, 303, 303,
+ },
+ [3] = {
+ -8, -8, -8, -8, -7, -7, -6, -5,
+ -4, -2, 0, 2, 4, 6, 9, 12,
+ 16, 20, 24, 28, 33, 38, 43, 49,
+ 55, 61, 68, 75, 82, 89, 96, 104,
+ },
+ },
+ },
+ [ MDP_SCALE_PT8TO8 ] = {
+ .offset = 96,
+ .set = MDP_PPP_SCALE_COEFF_U1_SET,
+ .use_pr = -1,
+ .coeffs.c = {
+ [0] = {
+ 0, -7, -13, -19, -24, -28, -32, -34,
+ -37, -39, -40, -41, -41, -41, -40, -40,
+ -38, -37, -35, -33, -31, -29, -26, -24,
+ -21, -18, -15, -13, -10, -7, -5, -2,
+ },
+ [1] = {
+ 511, 507, 501, 494, 485, 475, 463, 450,
+ 436, 422, 405, 388, 370, 352, 333, 314,
+ 293, 274, 253, 233, 213, 193, 172, 152,
+ 133, 113, 95, 77, 60, 43, 28, 13,
+ },
+ [2] = {
+ 0, 13, 28, 43, 60, 77, 95, 113,
+ 133, 152, 172, 193, 213, 233, 253, 274,
+ 294, 314, 333, 352, 370, 388, 405, 422,
+ 436, 450, 463, 475, 485, 494, 501, 507,
+ },
+ [3] = {
+ 0, -2, -5, -7, -10, -13, -15, -18,
+ -21, -24, -26, -29, -31, -33, -35, -37,
+ -38, -40, -40, -41, -41, -41, -40, -39,
+ -37, -34, -32, -28, -24, -19, -13, -7,
+ },
+ },
+ },
+};
+
+static void load_table(const struct mdp_info *mdp, int scale, int use_pr)
+{
+ int i;
+ uint32_t val;
+ struct mdp_scale_coeffs *coeffs;
+ struct mdp_scale_tbl_info *tbl = &mdp_scale_tbl[scale];
+
+ if (use_pr == tbl->use_pr)
+ return;
+
+ tbl->use_pr = use_pr;
+ if (!use_pr)
+ coeffs = &tbl->coeffs;
+ else
+ coeffs = &mdp_scale_pr_coeffs;
+
+ for (i = 0; i < NUM_COEFFS; ++i) {
+ val = ((coeffs->c[1][i] & 0x3ff) << 16) |
+ (coeffs->c[0][i] & 0x3ff);
+ mdp_writel(mdp, val, MDP_PPP_SCALE_COEFF_LSBn(tbl->offset + i));
+
+ val = ((coeffs->c[3][i] & 0x3ff) << 16) |
+ (coeffs->c[2][i] & 0x3ff);
+ mdp_writel(mdp, val, MDP_PPP_SCALE_COEFF_MSBn(tbl->offset + i));
+ }
+}
+
+#define SCALER_PHASE_BITS 29
+static void scale_params(uint32_t dim_in, uint32_t dim_out, uint32_t scaler,
+ uint32_t *phase_init, uint32_t *phase_step)
+{
+ uint64_t src = dim_in;
+ uint64_t dst = dim_out;
+ uint64_t numer;
+ uint64_t denom;
+
+ *phase_init = 0;
+
+ if (dst == 1) {
+ /* if destination is 1 pixel wide, the value of phase_step
+ * is unimportant. */
+ *phase_step = (uint32_t) (src << SCALER_PHASE_BITS);
+ if (scaler == MDP_PPP_SCALER_FIR)
+ *phase_init =
+ (uint32_t) ((src - 1) << SCALER_PHASE_BITS);
+ return;
+ }
+
+ if (scaler == MDP_PPP_SCALER_FIR) {
+ numer = (src - 1) << SCALER_PHASE_BITS;
+ denom = dst - 1;
+ /* we want to round up the result*/
+ numer += denom - 1;
+ } else {
+ numer = src << SCALER_PHASE_BITS;
+ denom = dst;
+ }
+
+ do_div(numer, denom);
+ *phase_step = (uint32_t) numer;
+}
+
+static int scale_idx(int factor)
+{
+ int idx;
+
+ if (factor > 80)
+ idx = MDP_SCALE_PT8TO8;
+ else if (factor > 60)
+ idx = MDP_SCALE_PT6TOPT8;
+ else if (factor > 40)
+ idx = MDP_SCALE_PT4TOPT6;
+ else
+ idx = MDP_SCALE_PT2TOPT4;
+
+ return idx;
+}
+
+int mdp_ppp_cfg_scale(const struct mdp_info *mdp, struct ppp_regs *regs,
+ struct mdp_rect *src_rect, struct mdp_rect *dst_rect,
+ uint32_t src_format, uint32_t dst_format)
+{
+ uint32_t x_fac;
+ uint32_t y_fac;
+ uint32_t scaler_x = MDP_PPP_SCALER_FIR;
+ uint32_t scaler_y = MDP_PPP_SCALER_FIR;
+ // Don't use pixel repeat mode, it looks bad
+ int use_pr = 0;
+ int x_idx;
+ int y_idx;
+
+ if (unlikely(src_rect->w > 2048 || src_rect->h > 2048))
+ return -ENOTSUPP;
+
+ x_fac = (dst_rect->w * 100) / src_rect->w;
+ y_fac = (dst_rect->h * 100) / src_rect->h;
+
+ /* if down-scaling by a factor smaller than 1/4, use M/N */
+ scaler_x = x_fac <= 25 ? MDP_PPP_SCALER_MN : MDP_PPP_SCALER_FIR;
+ scaler_y = y_fac <= 25 ? MDP_PPP_SCALER_MN : MDP_PPP_SCALER_FIR;
+ scale_params(src_rect->w, dst_rect->w, scaler_x, ®s->phasex_init,
+ ®s->phasex_step);
+ scale_params(src_rect->h, dst_rect->h, scaler_y, ®s->phasey_init,
+ ®s->phasey_step);
+
+ x_idx = scale_idx(x_fac);
+ y_idx = scale_idx(y_fac);
+ load_table(mdp, x_idx, use_pr);
+ load_table(mdp, y_idx, use_pr);
+
+ regs->scale_cfg = 0;
+ // Enable SVI when source or destination is YUV
+ if (!IS_RGB(src_format) && !IS_RGB(dst_format))
+ regs->scale_cfg |= (1 << 6);
+ regs->scale_cfg |= (mdp_scale_tbl[x_idx].set << 2) |
+ (mdp_scale_tbl[x_idx].set << 4);
+ regs->scale_cfg |= (scaler_x << 0) | (scaler_y << 1);
+
+ return 0;
+}
+
+int mdp_ppp_load_blur(const struct mdp_info *mdp)
+{
+ return -ENOTSUPP;
+}
+
+void mdp_ppp_init_scale(const struct mdp_info *mdp)
+{
+ int scale;
+ for (scale = 0; scale < MDP_SCALE_MAX; ++scale)
+ load_table(mdp, scale, 0);
+}
diff --git a/drivers/video/msm/mdp_ppp_v20.c b/drivers/video/msm/mdp_ppp_v20.c
new file mode 100644
index 0000000..8828a8f
--- /dev/null
+++ b/drivers/video/msm/mdp_ppp_v20.c
@@ -0,0 +1,2483 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include "linux/proc_fs.h"
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <asm/div64.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+static MDP_SCALE_MODE mdp_curr_up_scale_xy;
+static MDP_SCALE_MODE mdp_curr_down_scale_x;
+static MDP_SCALE_MODE mdp_curr_down_scale_y;
+
+static long long mdp_do_div(long long num, long long den)
+{
+ do_div(num, den);
+ return num;
+}
+
+struct mdp_table_entry mdp_gaussian_blur_table[] = {
+ /* max variance */
+ { 0x5fffc, 0x20000080 },
+ { 0x50280, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50284, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50288, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5028c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50290, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50294, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50298, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5029c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502a0, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502a4, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502a8, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502ac, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502b0, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502b4, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502b8, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502bc, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502c0, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502c4, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502c8, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502cc, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502d0, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502d4, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502d8, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502dc, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502e0, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502e4, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502e8, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502ec, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502f0, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502f4, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502f8, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502fc, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50300, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50304, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50308, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5030c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50310, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50314, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50318, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5031c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50320, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50324, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50328, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5032c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50330, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50334, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50338, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5033c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50340, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50344, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50348, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5034c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50350, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50354, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50358, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5035c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50360, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50364, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50368, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5036c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50370, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50374, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50378, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5037c, 0x20000080 },
+};
+
+static void load_scale_table(
+ struct mdp_table_entry *table, int len)
+{
+ int i;
+ for (i = 0; i < len; i++)
+ MDP_OUTP(MDP_BASE + table[i].reg, table[i].val);
+}
+
+static void mdp_load_pr_upscale_table(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50200, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50204, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50208, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5020c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50210, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50214, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50218, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5021c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50220, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50224, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50228, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5022c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50230, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50234, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50238, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5023c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50240, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50244, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50248, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5024c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50250, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50254, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50258, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5025c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50260, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50264, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50268, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5026c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50270, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50274, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50278, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5027c, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_x_point2TOpoint4(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_y_point2TOpoint4(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50340, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50344, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50348, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50350, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50354, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50358, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50360, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50364, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50368, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50370, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50374, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50378, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_x_point4TOpoint6(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_y_point4TOpoint6(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50340, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50344, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50348, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50350, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50354, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50358, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50360, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50364, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50368, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50370, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50374, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50378, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_x_point6TOpoint8(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_y_point6TOpoint8(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50340, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50344, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50348, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50350, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50354, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50358, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50360, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50364, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50368, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50370, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50374, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50378, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_x_point8TO1(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_y_point8TO1(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50340, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50344, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50348, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50350, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50354, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50358, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50360, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50364, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50368, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50370, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50374, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50378, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
+}
+
+static void mdp_load_bc_upscale_table(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50200, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d);
+ MDP_OUTP(MDP_BASE + 0x50204, 0x7ec003f9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c);
+ MDP_OUTP(MDP_BASE + 0x50208, 0x7d4003f3);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b);
+ MDP_OUTP(MDP_BASE + 0x5020c, 0x7b8003ed);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c);
+ MDP_OUTP(MDP_BASE + 0x50210, 0x794003e8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d);
+ MDP_OUTP(MDP_BASE + 0x50214, 0x76c003e4);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f);
+ MDP_OUTP(MDP_BASE + 0x50218, 0x73c003e0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071);
+ MDP_OUTP(MDP_BASE + 0x5021c, 0x708003de);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085);
+ MDP_OUTP(MDP_BASE + 0x50220, 0x6d0003db);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098);
+ MDP_OUTP(MDP_BASE + 0x50224, 0x698003d9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac);
+ MDP_OUTP(MDP_BASE + 0x50228, 0x654003d8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1);
+ MDP_OUTP(MDP_BASE + 0x5022c, 0x610003d7);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5);
+ MDP_OUTP(MDP_BASE + 0x50230, 0x5c8003d7);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9);
+ MDP_OUTP(MDP_BASE + 0x50234, 0x580003d7);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd);
+ MDP_OUTP(MDP_BASE + 0x50238, 0x534003d8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112);
+ MDP_OUTP(MDP_BASE + 0x5023c, 0x4e8003d8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126);
+ MDP_OUTP(MDP_BASE + 0x50240, 0x494003da);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a);
+ MDP_OUTP(MDP_BASE + 0x50244, 0x448003db);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d);
+ MDP_OUTP(MDP_BASE + 0x50248, 0x3f4003dd);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160);
+ MDP_OUTP(MDP_BASE + 0x5024c, 0x3a4003df);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172);
+ MDP_OUTP(MDP_BASE + 0x50250, 0x354003e1);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184);
+ MDP_OUTP(MDP_BASE + 0x50254, 0x304003e3);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195);
+ MDP_OUTP(MDP_BASE + 0x50258, 0x2b0003e6);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6);
+ MDP_OUTP(MDP_BASE + 0x5025c, 0x260003e8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4);
+ MDP_OUTP(MDP_BASE + 0x50260, 0x214003eb);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2);
+ MDP_OUTP(MDP_BASE + 0x50264, 0x1c4003ee);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf);
+ MDP_OUTP(MDP_BASE + 0x50268, 0x17c003f1);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db);
+ MDP_OUTP(MDP_BASE + 0x5026c, 0x134003f3);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5);
+ MDP_OUTP(MDP_BASE + 0x50270, 0xf0003f6);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee);
+ MDP_OUTP(MDP_BASE + 0x50274, 0xac003f9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5);
+ MDP_OUTP(MDP_BASE + 0x50278, 0x70003fb);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb);
+ MDP_OUTP(MDP_BASE + 0x5027c, 0x34003fe);
+}
+
+static void mdp_load_bc_downscale_table_x_point2TOpoint4(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac00084);
+ MDP_OUTP(MDP_BASE + 0x50280, 0x23400083);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b000084);
+ MDP_OUTP(MDP_BASE + 0x50284, 0x23000083);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400084);
+ MDP_OUTP(MDP_BASE + 0x50288, 0x23000082);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400085);
+ MDP_OUTP(MDP_BASE + 0x5028c, 0x23000081);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b800085);
+ MDP_OUTP(MDP_BASE + 0x50290, 0x23000080);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc00086);
+ MDP_OUTP(MDP_BASE + 0x50294, 0x22c0007f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c000086);
+ MDP_OUTP(MDP_BASE + 0x50298, 0x2280007f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c400086);
+ MDP_OUTP(MDP_BASE + 0x5029c, 0x2280007e);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c800086);
+ MDP_OUTP(MDP_BASE + 0x502a0, 0x2280007d);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00086);
+ MDP_OUTP(MDP_BASE + 0x502a4, 0x2240007d);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00087);
+ MDP_OUTP(MDP_BASE + 0x502a8, 0x2240007c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d000087);
+ MDP_OUTP(MDP_BASE + 0x502ac, 0x2240007b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400087);
+ MDP_OUTP(MDP_BASE + 0x502b0, 0x2200007b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400088);
+ MDP_OUTP(MDP_BASE + 0x502b4, 0x22400079);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d800088);
+ MDP_OUTP(MDP_BASE + 0x502b8, 0x22400078);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00088);
+ MDP_OUTP(MDP_BASE + 0x502bc, 0x22400077);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00089);
+ MDP_OUTP(MDP_BASE + 0x502c0, 0x22000077);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e000089);
+ MDP_OUTP(MDP_BASE + 0x502c4, 0x22000076);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e400089);
+ MDP_OUTP(MDP_BASE + 0x502c8, 0x22000075);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00088);
+ MDP_OUTP(MDP_BASE + 0x502cc, 0x21c00075);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00089);
+ MDP_OUTP(MDP_BASE + 0x502d0, 0x21c00074);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f000089);
+ MDP_OUTP(MDP_BASE + 0x502d4, 0x21c00073);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f400089);
+ MDP_OUTP(MDP_BASE + 0x502d8, 0x21800073);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f40008a);
+ MDP_OUTP(MDP_BASE + 0x502dc, 0x21800072);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f80008a);
+ MDP_OUTP(MDP_BASE + 0x502e0, 0x21800071);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008a);
+ MDP_OUTP(MDP_BASE + 0x502e4, 0x21800070);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008b);
+ MDP_OUTP(MDP_BASE + 0x502e8, 0x2180006f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x2000008c);
+ MDP_OUTP(MDP_BASE + 0x502ec, 0x2140006e);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x2040008c);
+ MDP_OUTP(MDP_BASE + 0x502f0, 0x2140006d);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x2080008c);
+ MDP_OUTP(MDP_BASE + 0x502f4, 0x2100006d);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008c);
+ MDP_OUTP(MDP_BASE + 0x502f8, 0x2100006c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008d);
+ MDP_OUTP(MDP_BASE + 0x502fc, 0x2100006b);
+}
+
+static void mdp_load_bc_downscale_table_y_point2TOpoint4(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac00084);
+ MDP_OUTP(MDP_BASE + 0x50300, 0x23400083);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b000084);
+ MDP_OUTP(MDP_BASE + 0x50304, 0x23000083);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400084);
+ MDP_OUTP(MDP_BASE + 0x50308, 0x23000082);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400085);
+ MDP_OUTP(MDP_BASE + 0x5030c, 0x23000081);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b800085);
+ MDP_OUTP(MDP_BASE + 0x50310, 0x23000080);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc00086);
+ MDP_OUTP(MDP_BASE + 0x50314, 0x22c0007f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c000086);
+ MDP_OUTP(MDP_BASE + 0x50318, 0x2280007f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c400086);
+ MDP_OUTP(MDP_BASE + 0x5031c, 0x2280007e);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c800086);
+ MDP_OUTP(MDP_BASE + 0x50320, 0x2280007d);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00086);
+ MDP_OUTP(MDP_BASE + 0x50324, 0x2240007d);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00087);
+ MDP_OUTP(MDP_BASE + 0x50328, 0x2240007c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d000087);
+ MDP_OUTP(MDP_BASE + 0x5032c, 0x2240007b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400087);
+ MDP_OUTP(MDP_BASE + 0x50330, 0x2200007b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400088);
+ MDP_OUTP(MDP_BASE + 0x50334, 0x22400079);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d800088);
+ MDP_OUTP(MDP_BASE + 0x50338, 0x22400078);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00088);
+ MDP_OUTP(MDP_BASE + 0x5033c, 0x22400077);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00089);
+ MDP_OUTP(MDP_BASE + 0x50340, 0x22000077);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e000089);
+ MDP_OUTP(MDP_BASE + 0x50344, 0x22000076);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e400089);
+ MDP_OUTP(MDP_BASE + 0x50348, 0x22000075);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00088);
+ MDP_OUTP(MDP_BASE + 0x5034c, 0x21c00075);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00089);
+ MDP_OUTP(MDP_BASE + 0x50350, 0x21c00074);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f000089);
+ MDP_OUTP(MDP_BASE + 0x50354, 0x21c00073);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f400089);
+ MDP_OUTP(MDP_BASE + 0x50358, 0x21800073);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f40008a);
+ MDP_OUTP(MDP_BASE + 0x5035c, 0x21800072);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f80008a);
+ MDP_OUTP(MDP_BASE + 0x50360, 0x21800071);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008a);
+ MDP_OUTP(MDP_BASE + 0x50364, 0x21800070);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008b);
+ MDP_OUTP(MDP_BASE + 0x50368, 0x2180006f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x2000008c);
+ MDP_OUTP(MDP_BASE + 0x5036c, 0x2140006e);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x2040008c);
+ MDP_OUTP(MDP_BASE + 0x50370, 0x2140006d);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x2080008c);
+ MDP_OUTP(MDP_BASE + 0x50374, 0x2100006d);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008c);
+ MDP_OUTP(MDP_BASE + 0x50378, 0x2100006c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008d);
+ MDP_OUTP(MDP_BASE + 0x5037c, 0x2100006b);
+}
+
+static void mdp_load_bc_downscale_table_x_point4TOpoint6(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x740008c);
+ MDP_OUTP(MDP_BASE + 0x50280, 0x33800088);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x800008e);
+ MDP_OUTP(MDP_BASE + 0x50284, 0x33400084);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x8400092);
+ MDP_OUTP(MDP_BASE + 0x50288, 0x33000080);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x9000094);
+ MDP_OUTP(MDP_BASE + 0x5028c, 0x3300007b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x9c00098);
+ MDP_OUTP(MDP_BASE + 0x50290, 0x32400077);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xa40009b);
+ MDP_OUTP(MDP_BASE + 0x50294, 0x32000073);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xb00009d);
+ MDP_OUTP(MDP_BASE + 0x50298, 0x31c0006f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xbc000a0);
+ MDP_OUTP(MDP_BASE + 0x5029c, 0x3140006b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xc8000a2);
+ MDP_OUTP(MDP_BASE + 0x502a0, 0x31000067);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xd8000a5);
+ MDP_OUTP(MDP_BASE + 0x502a4, 0x30800062);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xe4000a8);
+ MDP_OUTP(MDP_BASE + 0x502a8, 0x2fc0005f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xec000aa);
+ MDP_OUTP(MDP_BASE + 0x502ac, 0x2fc0005b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8000ad);
+ MDP_OUTP(MDP_BASE + 0x502b0, 0x2f400057);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x108000b0);
+ MDP_OUTP(MDP_BASE + 0x502b4, 0x2e400054);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x114000b2);
+ MDP_OUTP(MDP_BASE + 0x502b8, 0x2e000050);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x124000b4);
+ MDP_OUTP(MDP_BASE + 0x502bc, 0x2d80004c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x130000b6);
+ MDP_OUTP(MDP_BASE + 0x502c0, 0x2d000049);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x140000b8);
+ MDP_OUTP(MDP_BASE + 0x502c4, 0x2c800045);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x150000b9);
+ MDP_OUTP(MDP_BASE + 0x502c8, 0x2c000042);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x15c000bd);
+ MDP_OUTP(MDP_BASE + 0x502cc, 0x2b40003e);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x16c000bf);
+ MDP_OUTP(MDP_BASE + 0x502d0, 0x2a80003b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x17c000bf);
+ MDP_OUTP(MDP_BASE + 0x502d4, 0x2a000039);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x188000c2);
+ MDP_OUTP(MDP_BASE + 0x502d8, 0x29400036);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x19c000c4);
+ MDP_OUTP(MDP_BASE + 0x502dc, 0x28800032);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac000c5);
+ MDP_OUTP(MDP_BASE + 0x502e0, 0x2800002f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc000c7);
+ MDP_OUTP(MDP_BASE + 0x502e4, 0x2740002c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc000c8);
+ MDP_OUTP(MDP_BASE + 0x502e8, 0x26c00029);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc000c9);
+ MDP_OUTP(MDP_BASE + 0x502ec, 0x26000027);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec000cc);
+ MDP_OUTP(MDP_BASE + 0x502f0, 0x25000024);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x200000cc);
+ MDP_OUTP(MDP_BASE + 0x502f4, 0x24800021);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x210000cd);
+ MDP_OUTP(MDP_BASE + 0x502f8, 0x23800020);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x220000ce);
+ MDP_OUTP(MDP_BASE + 0x502fc, 0x2300001d);
+}
+
+static void mdp_load_bc_downscale_table_y_point4TOpoint6(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x740008c);
+ MDP_OUTP(MDP_BASE + 0x50300, 0x33800088);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x800008e);
+ MDP_OUTP(MDP_BASE + 0x50304, 0x33400084);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x8400092);
+ MDP_OUTP(MDP_BASE + 0x50308, 0x33000080);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x9000094);
+ MDP_OUTP(MDP_BASE + 0x5030c, 0x3300007b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x9c00098);
+ MDP_OUTP(MDP_BASE + 0x50310, 0x32400077);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xa40009b);
+ MDP_OUTP(MDP_BASE + 0x50314, 0x32000073);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xb00009d);
+ MDP_OUTP(MDP_BASE + 0x50318, 0x31c0006f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xbc000a0);
+ MDP_OUTP(MDP_BASE + 0x5031c, 0x3140006b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xc8000a2);
+ MDP_OUTP(MDP_BASE + 0x50320, 0x31000067);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xd8000a5);
+ MDP_OUTP(MDP_BASE + 0x50324, 0x30800062);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xe4000a8);
+ MDP_OUTP(MDP_BASE + 0x50328, 0x2fc0005f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xec000aa);
+ MDP_OUTP(MDP_BASE + 0x5032c, 0x2fc0005b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8000ad);
+ MDP_OUTP(MDP_BASE + 0x50330, 0x2f400057);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x108000b0);
+ MDP_OUTP(MDP_BASE + 0x50334, 0x2e400054);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x114000b2);
+ MDP_OUTP(MDP_BASE + 0x50338, 0x2e000050);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x124000b4);
+ MDP_OUTP(MDP_BASE + 0x5033c, 0x2d80004c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x130000b6);
+ MDP_OUTP(MDP_BASE + 0x50340, 0x2d000049);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x140000b8);
+ MDP_OUTP(MDP_BASE + 0x50344, 0x2c800045);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x150000b9);
+ MDP_OUTP(MDP_BASE + 0x50348, 0x2c000042);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x15c000bd);
+ MDP_OUTP(MDP_BASE + 0x5034c, 0x2b40003e);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x16c000bf);
+ MDP_OUTP(MDP_BASE + 0x50350, 0x2a80003b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x17c000bf);
+ MDP_OUTP(MDP_BASE + 0x50354, 0x2a000039);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x188000c2);
+ MDP_OUTP(MDP_BASE + 0x50358, 0x29400036);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x19c000c4);
+ MDP_OUTP(MDP_BASE + 0x5035c, 0x28800032);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac000c5);
+ MDP_OUTP(MDP_BASE + 0x50360, 0x2800002f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc000c7);
+ MDP_OUTP(MDP_BASE + 0x50364, 0x2740002c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc000c8);
+ MDP_OUTP(MDP_BASE + 0x50368, 0x26c00029);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc000c9);
+ MDP_OUTP(MDP_BASE + 0x5036c, 0x26000027);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec000cc);
+ MDP_OUTP(MDP_BASE + 0x50370, 0x25000024);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x200000cc);
+ MDP_OUTP(MDP_BASE + 0x50374, 0x24800021);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x210000cd);
+ MDP_OUTP(MDP_BASE + 0x50378, 0x23800020);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x220000ce);
+ MDP_OUTP(MDP_BASE + 0x5037c, 0x2300001d);
+}
+
+static void mdp_load_bc_downscale_table_x_point6TOpoint8(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000070);
+ MDP_OUTP(MDP_BASE + 0x50280, 0x4bc00068);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000078);
+ MDP_OUTP(MDP_BASE + 0x50284, 0x4bc00060);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000080);
+ MDP_OUTP(MDP_BASE + 0x50288, 0x4b800059);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000089);
+ MDP_OUTP(MDP_BASE + 0x5028c, 0x4b000052);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe400091);
+ MDP_OUTP(MDP_BASE + 0x50290, 0x4a80004b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40009a);
+ MDP_OUTP(MDP_BASE + 0x50294, 0x4a000044);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe8000a3);
+ MDP_OUTP(MDP_BASE + 0x50298, 0x4940003d);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec000ac);
+ MDP_OUTP(MDP_BASE + 0x5029c, 0x48400037);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xff0000b4);
+ MDP_OUTP(MDP_BASE + 0x502a0, 0x47800031);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xff8000bd);
+ MDP_OUTP(MDP_BASE + 0x502a4, 0x4640002b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xc5);
+ MDP_OUTP(MDP_BASE + 0x502a8, 0x45000026);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x8000ce);
+ MDP_OUTP(MDP_BASE + 0x502ac, 0x43800021);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x10000d6);
+ MDP_OUTP(MDP_BASE + 0x502b0, 0x4240001c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x18000df);
+ MDP_OUTP(MDP_BASE + 0x502b4, 0x40800018);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x24000e6);
+ MDP_OUTP(MDP_BASE + 0x502b8, 0x3f000014);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x30000ee);
+ MDP_OUTP(MDP_BASE + 0x502bc, 0x3d400010);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x40000f5);
+ MDP_OUTP(MDP_BASE + 0x502c0, 0x3b80000c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x50000fc);
+ MDP_OUTP(MDP_BASE + 0x502c4, 0x39800009);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x6000102);
+ MDP_OUTP(MDP_BASE + 0x502c8, 0x37c00006);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x7000109);
+ MDP_OUTP(MDP_BASE + 0x502cc, 0x35800004);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x840010e);
+ MDP_OUTP(MDP_BASE + 0x502d0, 0x33800002);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x9800114);
+ MDP_OUTP(MDP_BASE + 0x502d4, 0x31400000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xac00119);
+ MDP_OUTP(MDP_BASE + 0x502d8, 0x2f4003fe);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xc40011e);
+ MDP_OUTP(MDP_BASE + 0x502dc, 0x2d0003fc);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xdc00121);
+ MDP_OUTP(MDP_BASE + 0x502e0, 0x2b0003fb);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf400125);
+ MDP_OUTP(MDP_BASE + 0x502e4, 0x28c003fa);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x11000128);
+ MDP_OUTP(MDP_BASE + 0x502e8, 0x268003f9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x12c0012a);
+ MDP_OUTP(MDP_BASE + 0x502ec, 0x244003f9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1480012c);
+ MDP_OUTP(MDP_BASE + 0x502f0, 0x224003f8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1640012e);
+ MDP_OUTP(MDP_BASE + 0x502f4, 0x200003f8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1800012f);
+ MDP_OUTP(MDP_BASE + 0x502f8, 0x1e0003f8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1a00012f);
+ MDP_OUTP(MDP_BASE + 0x502fc, 0x1c0003f8);
+}
+
+static void mdp_load_bc_downscale_table_y_point6TOpoint8(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000070);
+ MDP_OUTP(MDP_BASE + 0x50300, 0x4bc00068);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000078);
+ MDP_OUTP(MDP_BASE + 0x50304, 0x4bc00060);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000080);
+ MDP_OUTP(MDP_BASE + 0x50308, 0x4b800059);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000089);
+ MDP_OUTP(MDP_BASE + 0x5030c, 0x4b000052);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe400091);
+ MDP_OUTP(MDP_BASE + 0x50310, 0x4a80004b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40009a);
+ MDP_OUTP(MDP_BASE + 0x50314, 0x4a000044);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe8000a3);
+ MDP_OUTP(MDP_BASE + 0x50318, 0x4940003d);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec000ac);
+ MDP_OUTP(MDP_BASE + 0x5031c, 0x48400037);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xff0000b4);
+ MDP_OUTP(MDP_BASE + 0x50320, 0x47800031);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xff8000bd);
+ MDP_OUTP(MDP_BASE + 0x50324, 0x4640002b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xc5);
+ MDP_OUTP(MDP_BASE + 0x50328, 0x45000026);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x8000ce);
+ MDP_OUTP(MDP_BASE + 0x5032c, 0x43800021);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x10000d6);
+ MDP_OUTP(MDP_BASE + 0x50330, 0x4240001c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x18000df);
+ MDP_OUTP(MDP_BASE + 0x50334, 0x40800018);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x24000e6);
+ MDP_OUTP(MDP_BASE + 0x50338, 0x3f000014);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x30000ee);
+ MDP_OUTP(MDP_BASE + 0x5033c, 0x3d400010);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x40000f5);
+ MDP_OUTP(MDP_BASE + 0x50340, 0x3b80000c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x50000fc);
+ MDP_OUTP(MDP_BASE + 0x50344, 0x39800009);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x6000102);
+ MDP_OUTP(MDP_BASE + 0x50348, 0x37c00006);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x7000109);
+ MDP_OUTP(MDP_BASE + 0x5034c, 0x35800004);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x840010e);
+ MDP_OUTP(MDP_BASE + 0x50350, 0x33800002);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x9800114);
+ MDP_OUTP(MDP_BASE + 0x50354, 0x31400000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xac00119);
+ MDP_OUTP(MDP_BASE + 0x50358, 0x2f4003fe);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xc40011e);
+ MDP_OUTP(MDP_BASE + 0x5035c, 0x2d0003fc);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xdc00121);
+ MDP_OUTP(MDP_BASE + 0x50360, 0x2b0003fb);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf400125);
+ MDP_OUTP(MDP_BASE + 0x50364, 0x28c003fa);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x11000128);
+ MDP_OUTP(MDP_BASE + 0x50368, 0x268003f9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x12c0012a);
+ MDP_OUTP(MDP_BASE + 0x5036c, 0x244003f9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1480012c);
+ MDP_OUTP(MDP_BASE + 0x50370, 0x224003f8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1640012e);
+ MDP_OUTP(MDP_BASE + 0x50374, 0x200003f8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1800012f);
+ MDP_OUTP(MDP_BASE + 0x50378, 0x1e0003f8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1a00012f);
+ MDP_OUTP(MDP_BASE + 0x5037c, 0x1c0003f8);
+}
+
+static void mdp_load_bc_downscale_table_x_point8TO1(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d);
+ MDP_OUTP(MDP_BASE + 0x50284, 0x7ec003f9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c);
+ MDP_OUTP(MDP_BASE + 0x50288, 0x7d4003f3);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b);
+ MDP_OUTP(MDP_BASE + 0x5028c, 0x7b8003ed);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c);
+ MDP_OUTP(MDP_BASE + 0x50290, 0x794003e8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d);
+ MDP_OUTP(MDP_BASE + 0x50294, 0x76c003e4);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f);
+ MDP_OUTP(MDP_BASE + 0x50298, 0x73c003e0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071);
+ MDP_OUTP(MDP_BASE + 0x5029c, 0x708003de);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085);
+ MDP_OUTP(MDP_BASE + 0x502a0, 0x6d0003db);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098);
+ MDP_OUTP(MDP_BASE + 0x502a4, 0x698003d9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac);
+ MDP_OUTP(MDP_BASE + 0x502a8, 0x654003d8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1);
+ MDP_OUTP(MDP_BASE + 0x502ac, 0x610003d7);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5);
+ MDP_OUTP(MDP_BASE + 0x502b0, 0x5c8003d7);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9);
+ MDP_OUTP(MDP_BASE + 0x502b4, 0x580003d7);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd);
+ MDP_OUTP(MDP_BASE + 0x502b8, 0x534003d8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112);
+ MDP_OUTP(MDP_BASE + 0x502bc, 0x4e8003d8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126);
+ MDP_OUTP(MDP_BASE + 0x502c0, 0x494003da);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a);
+ MDP_OUTP(MDP_BASE + 0x502c4, 0x448003db);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d);
+ MDP_OUTP(MDP_BASE + 0x502c8, 0x3f4003dd);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160);
+ MDP_OUTP(MDP_BASE + 0x502cc, 0x3a4003df);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172);
+ MDP_OUTP(MDP_BASE + 0x502d0, 0x354003e1);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184);
+ MDP_OUTP(MDP_BASE + 0x502d4, 0x304003e3);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195);
+ MDP_OUTP(MDP_BASE + 0x502d8, 0x2b0003e6);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6);
+ MDP_OUTP(MDP_BASE + 0x502dc, 0x260003e8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4);
+ MDP_OUTP(MDP_BASE + 0x502e0, 0x214003eb);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2);
+ MDP_OUTP(MDP_BASE + 0x502e4, 0x1c4003ee);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf);
+ MDP_OUTP(MDP_BASE + 0x502e8, 0x17c003f1);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db);
+ MDP_OUTP(MDP_BASE + 0x502ec, 0x134003f3);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5);
+ MDP_OUTP(MDP_BASE + 0x502f0, 0xf0003f6);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee);
+ MDP_OUTP(MDP_BASE + 0x502f4, 0xac003f9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5);
+ MDP_OUTP(MDP_BASE + 0x502f8, 0x70003fb);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb);
+ MDP_OUTP(MDP_BASE + 0x502fc, 0x34003fe);
+}
+
+static void mdp_load_bc_downscale_table_y_point8TO1(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d);
+ MDP_OUTP(MDP_BASE + 0x50304, 0x7ec003f9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c);
+ MDP_OUTP(MDP_BASE + 0x50308, 0x7d4003f3);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b);
+ MDP_OUTP(MDP_BASE + 0x5030c, 0x7b8003ed);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c);
+ MDP_OUTP(MDP_BASE + 0x50310, 0x794003e8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d);
+ MDP_OUTP(MDP_BASE + 0x50314, 0x76c003e4);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f);
+ MDP_OUTP(MDP_BASE + 0x50318, 0x73c003e0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071);
+ MDP_OUTP(MDP_BASE + 0x5031c, 0x708003de);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085);
+ MDP_OUTP(MDP_BASE + 0x50320, 0x6d0003db);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098);
+ MDP_OUTP(MDP_BASE + 0x50324, 0x698003d9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac);
+ MDP_OUTP(MDP_BASE + 0x50328, 0x654003d8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1);
+ MDP_OUTP(MDP_BASE + 0x5032c, 0x610003d7);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5);
+ MDP_OUTP(MDP_BASE + 0x50330, 0x5c8003d7);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9);
+ MDP_OUTP(MDP_BASE + 0x50334, 0x580003d7);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd);
+ MDP_OUTP(MDP_BASE + 0x50338, 0x534003d8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112);
+ MDP_OUTP(MDP_BASE + 0x5033c, 0x4e8003d8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126);
+ MDP_OUTP(MDP_BASE + 0x50340, 0x494003da);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a);
+ MDP_OUTP(MDP_BASE + 0x50344, 0x448003db);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d);
+ MDP_OUTP(MDP_BASE + 0x50348, 0x3f4003dd);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160);
+ MDP_OUTP(MDP_BASE + 0x5034c, 0x3a4003df);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172);
+ MDP_OUTP(MDP_BASE + 0x50350, 0x354003e1);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184);
+ MDP_OUTP(MDP_BASE + 0x50354, 0x304003e3);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195);
+ MDP_OUTP(MDP_BASE + 0x50358, 0x2b0003e6);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6);
+ MDP_OUTP(MDP_BASE + 0x5035c, 0x260003e8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4);
+ MDP_OUTP(MDP_BASE + 0x50360, 0x214003eb);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2);
+ MDP_OUTP(MDP_BASE + 0x50364, 0x1c4003ee);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf);
+ MDP_OUTP(MDP_BASE + 0x50368, 0x17c003f1);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db);
+ MDP_OUTP(MDP_BASE + 0x5036c, 0x134003f3);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5);
+ MDP_OUTP(MDP_BASE + 0x50370, 0xf0003f6);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee);
+ MDP_OUTP(MDP_BASE + 0x50374, 0xac003f9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5);
+ MDP_OUTP(MDP_BASE + 0x50378, 0x70003fb);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb);
+ MDP_OUTP(MDP_BASE + 0x5037c, 0x34003fe);
+}
+
+static int mdp_get_edge_cond(MDPIBUF *iBuf, uint32 *dup, uint32 *dup2)
+{
+ uint32 reg;
+ uint32 dst_roi_width; /* Dimensions of DST ROI. */
+ uint32 dst_roi_height; /* Used to calculate scaling ratios. */
+
+ /*
+ * positions of the luma pixel(relative to the image ) required for
+ * scaling the ROI
+ */
+ int32 luma_interp_point_left = 0; /* left-most luma pixel needed */
+ int32 luma_interp_point_right = 0; /* right-most luma pixel needed */
+ int32 luma_interp_point_top = 0; /* top-most luma pixel needed */
+ int32 luma_interp_point_bottom = 0; /* bottom-most luma pixel needed */
+
+ /*
+ * positions of the chroma pixel(relative to the image ) required for
+ * interpolating a chroma value at all required luma positions
+ */
+ /* left-most chroma pixel needed */
+ int32 chroma_interp_point_left = 0;
+ /* right-most chroma pixel needed */
+ int32 chroma_interp_point_right = 0;
+ /* top-most chroma pixel needed */
+ int32 chroma_interp_point_top = 0;
+ /* bottom-most chroma pixel needed */
+ int32 chroma_interp_point_bottom = 0;
+
+ /*
+ * a rectangular region within the chroma plane of the "image".
+ * Chroma pixels falling inside of this rectangle belongs to the ROI
+ */
+ int32 chroma_bound_left = 0;
+ int32 chroma_bound_right = 0;
+ int32 chroma_bound_top = 0;
+ int32 chroma_bound_bottom = 0;
+
+ /*
+ * number of chroma pixels to replicate on the left, right,
+ * top and bottom edge of the ROI.
+ */
+ int32 chroma_repeat_left = 0;
+ int32 chroma_repeat_right = 0;
+ int32 chroma_repeat_top = 0;
+ int32 chroma_repeat_bottom = 0;
+
+ /*
+ * number of luma pixels to replicate on the left, right,
+ * top and bottom edge of the ROI.
+ */
+ int32 luma_repeat_left = 0;
+ int32 luma_repeat_right = 0;
+ int32 luma_repeat_top = 0;
+ int32 luma_repeat_bottom = 0;
+
+ boolean chroma_edge_enable;
+
+ uint32 _is_scale_enabled = 0;
+ uint32 _is_yuv_offsite_vertical = 0;
+
+ /* fg edge duplicate */
+ reg = 0x0;
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) { /* if scaling enabled */
+
+ _is_scale_enabled = 1;
+
+ /*
+ * if rotation mode involves a 90 deg rotation, flip
+ * dst_roi_width with dst_roi_height.
+ * Scaling ratios is based on source ROI dimensions, and
+ * dst ROI dimensions before rotation.
+ */
+ if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
+ dst_roi_width = iBuf->roi.dst_height;
+ dst_roi_height = iBuf->roi.dst_width;
+ } else {
+ dst_roi_width = iBuf->roi.dst_width;
+ dst_roi_height = iBuf->roi.dst_height;
+ }
+
+ /*
+ * Find out the luma pixels needed for scaling in the
+ * x direction (LEFT and RIGHT). Locations of pixels are
+ * relative to the ROI. Upper-left corner of ROI corresponds
+ * to coordinates (0,0). Also set the number of luma pixel
+ * to repeat.
+ */
+ if (iBuf->roi.width > 3 * dst_roi_width) {
+ /* scale factor < 1/3 */
+ luma_interp_point_left = 0;
+ luma_interp_point_right = (iBuf->roi.width - 1);
+ luma_repeat_left = 0;
+ luma_repeat_right = 0;
+ } else if (iBuf->roi.width == 3 * dst_roi_width) {
+ /* scale factor == 1/3 */
+ luma_interp_point_left = 0;
+ luma_interp_point_right = (iBuf->roi.width - 1) + 1;
+ luma_repeat_left = 0;
+ luma_repeat_right = 1;
+ } else if ((iBuf->roi.width > dst_roi_width) &&
+ (iBuf->roi.width < 3 * dst_roi_width)) {
+ /* 1/3 < scale factor < 1 */
+ luma_interp_point_left = -1;
+ luma_interp_point_right = (iBuf->roi.width - 1) + 1;
+ luma_repeat_left = 1;
+ luma_repeat_right = 1;
+ }
+
+ else if (iBuf->roi.width == dst_roi_width) {
+ /* scale factor == 1 */
+ luma_interp_point_left = -1;
+ luma_interp_point_right = (iBuf->roi.width - 1) + 2;
+ luma_repeat_left = 1;
+ luma_repeat_right = 2;
+ } else { /* (iBuf->roi.width < dst_roi_width) */
+ /* scale factor > 1 */
+ luma_interp_point_left = -2;
+ luma_interp_point_right = (iBuf->roi.width - 1) + 2;
+ luma_repeat_left = 2;
+ luma_repeat_right = 2;
+ }
+
+ /*
+ * Find out the number of pixels needed for scaling in the
+ * y direction (TOP and BOTTOM). Locations of pixels are
+ * relative to the ROI. Upper-left corner of ROI corresponds
+ * to coordinates (0,0). Also set the number of luma pixel
+ * to repeat.
+ */
+ if (iBuf->roi.height > 3 * dst_roi_height) {
+ /* scale factor < 1/3 */
+ luma_interp_point_top = 0;
+ luma_interp_point_bottom = (iBuf->roi.height - 1);
+ luma_repeat_top = 0;
+ luma_repeat_bottom = 0;
+ } else if (iBuf->roi.height == 3 * dst_roi_height) {
+ /* scale factor == 1/3 */
+ luma_interp_point_top = 0;
+ luma_interp_point_bottom = (iBuf->roi.height - 1) + 1;
+ luma_repeat_top = 0;
+ luma_repeat_bottom = 1;
+ } else if ((iBuf->roi.height > dst_roi_height) &&
+ (iBuf->roi.height < 3 * dst_roi_height)) {
+ /* 1/3 < scale factor < 1 */
+ luma_interp_point_top = -1;
+ luma_interp_point_bottom = (iBuf->roi.height - 1) + 1;
+ luma_repeat_top = 1;
+ luma_repeat_bottom = 1;
+ } else if (iBuf->roi.height == dst_roi_height) {
+ /* scale factor == 1 */
+ luma_interp_point_top = -1;
+ luma_interp_point_bottom = (iBuf->roi.height - 1) + 2;
+ luma_repeat_top = 1;
+ luma_repeat_bottom = 2;
+ } else { /* (iBuf->roi.height < dst_roi_height) */
+ /* scale factor > 1 */
+ luma_interp_point_top = -2;
+ luma_interp_point_bottom = (iBuf->roi.height - 1) + 2;
+ luma_repeat_top = 2;
+ luma_repeat_bottom = 2;
+ }
+ } /* if (iBuf->scale.scale_flag) */
+ else { /* scaling disabled */
+ /*
+ * Since no scaling needed, Tile Fetch does not require any
+ * more luma pixel than what the ROI contains.
+ */
+ luma_interp_point_left = (int32) 0;
+ luma_interp_point_right = (int32) (iBuf->roi.width - 1);
+ luma_interp_point_top = (int32) 0;
+ luma_interp_point_bottom = (int32) (iBuf->roi.height - 1);
+
+ luma_repeat_left = 0;
+ luma_repeat_right = 0;
+ luma_repeat_top = 0;
+ luma_repeat_bottom = 0;
+ }
+
+ /* After adding the ROI offsets, we have locations of
+ * luma_interp_points relative to the image.
+ */
+ luma_interp_point_left += (int32) (iBuf->roi.x);
+ luma_interp_point_right += (int32) (iBuf->roi.x);
+ luma_interp_point_top += (int32) (iBuf->roi.y);
+ luma_interp_point_bottom += (int32) (iBuf->roi.y);
+
+ /*
+ * After adding the ROI offsets, we have locations of
+ * chroma_interp_points relative to the image.
+ */
+ chroma_interp_point_left = luma_interp_point_left;
+ chroma_interp_point_right = luma_interp_point_right;
+ chroma_interp_point_top = luma_interp_point_top;
+ chroma_interp_point_bottom = luma_interp_point_bottom;
+
+ chroma_edge_enable = TRUE;
+ /* find out which chroma pixels are needed for chroma upsampling. */
+ switch (iBuf->mdpImg.imgType) {
+ /*
+ * cosite in horizontal axis
+ * fully sampled in vertical axis
+ */
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V1:
+ case MDP_YCRYCB_H2V1:
+ /* floor( luma_interp_point_left / 2 ); */
+ chroma_interp_point_left = luma_interp_point_left >> 1;
+ /* floor( ( luma_interp_point_right + 1 ) / 2 ); */
+ chroma_interp_point_right = (luma_interp_point_right + 1) >> 1;
+
+ chroma_interp_point_top = luma_interp_point_top;
+ chroma_interp_point_bottom = luma_interp_point_bottom;
+ break;
+
+ /*
+ * cosite in horizontal axis
+ * offsite in vertical axis
+ */
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ /* floor( luma_interp_point_left / 2) */
+ chroma_interp_point_left = luma_interp_point_left >> 1;
+
+ /* floor( ( luma_interp_point_right + 1 )/ 2 ) */
+ chroma_interp_point_right = (luma_interp_point_right + 1) >> 1;
+
+ /* floor( (luma_interp_point_top - 1 ) / 2 ) */
+ chroma_interp_point_top = (luma_interp_point_top - 1) >> 1;
+
+ /* floor( ( luma_interp_point_bottom + 1 ) / 2 ) */
+ chroma_interp_point_bottom =
+ (luma_interp_point_bottom + 1) >> 1;
+
+ _is_yuv_offsite_vertical = 1;
+ break;
+
+ default:
+ chroma_edge_enable = FALSE;
+ chroma_interp_point_left = luma_interp_point_left;
+ chroma_interp_point_right = luma_interp_point_right;
+ chroma_interp_point_top = luma_interp_point_top;
+ chroma_interp_point_bottom = luma_interp_point_bottom;
+
+ break;
+ }
+
+ /* only if the image type is in YUV domain, we calculate chroma edge */
+ if (chroma_edge_enable) {
+ /* Defines which chroma pixels belongs to the roi */
+ switch (iBuf->mdpImg.imgType) {
+ /*
+ * Cosite in horizontal direction, and fully sampled
+ * in vertical direction.
+ */
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V1:
+ case MDP_YCRYCB_H2V1:
+ /*
+ * width of chroma ROI is 1/2 of size of luma ROI
+ * height of chroma ROI same as size of luma ROI
+ */
+ chroma_bound_left = iBuf->roi.x / 2;
+
+ /* there are half as many chroma pixel as luma pixels */
+ chroma_bound_right =
+ (iBuf->roi.width + iBuf->roi.x - 1) / 2;
+ chroma_bound_top = iBuf->roi.y;
+ chroma_bound_bottom =
+ (iBuf->roi.height + iBuf->roi.y - 1);
+ break;
+
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ /*
+ * cosite in horizontal dir, and offsite in vertical dir
+ * width of chroma ROI is 1/2 of size of luma ROI
+ * height of chroma ROI is 1/2 of size of luma ROI
+ */
+
+ chroma_bound_left = iBuf->roi.x / 2;
+ chroma_bound_right =
+ (iBuf->roi.width + iBuf->roi.x - 1) / 2;
+ chroma_bound_top = iBuf->roi.y / 2;
+ chroma_bound_bottom =
+ (iBuf->roi.height + iBuf->roi.y - 1) / 2;
+ break;
+
+ default:
+ /*
+ * If no valid chroma sub-sampling format specified,
+ * assume 4:4:4 ( i.e. fully sampled). Set ROI
+ * boundaries for chroma same as ROI boundaries for
+ * luma.
+ */
+ chroma_bound_left = iBuf->roi.x;
+ chroma_bound_right = iBuf->roi.width + iBuf->roi.x - 1;
+ chroma_bound_top = iBuf->roi.y;
+ chroma_bound_bottom =
+ (iBuf->roi.height + iBuf->roi.y - 1);
+ break;
+ }
+
+ /*
+ * Knowing which chroma pixels are needed, and which chroma
+ * pixels belong to the ROI (i.e. available for fetching ),
+ * calculate how many chroma pixels Tile Fetch needs to
+ * duplicate. If any required chroma pixels falls outside
+ * of the ROI, Tile Fetch must obtain them by replicating
+ * pixels.
+ */
+ if (chroma_bound_left > chroma_interp_point_left)
+ chroma_repeat_left =
+ chroma_bound_left - chroma_interp_point_left;
+ else
+ chroma_repeat_left = 0;
+
+ if (chroma_interp_point_right > chroma_bound_right)
+ chroma_repeat_right =
+ chroma_interp_point_right - chroma_bound_right;
+ else
+ chroma_repeat_right = 0;
+
+ if (chroma_bound_top > chroma_interp_point_top)
+ chroma_repeat_top =
+ chroma_bound_top - chroma_interp_point_top;
+ else
+ chroma_repeat_top = 0;
+
+ if (chroma_interp_point_bottom > chroma_bound_bottom)
+ chroma_repeat_bottom =
+ chroma_interp_point_bottom - chroma_bound_bottom;
+ else
+ chroma_repeat_bottom = 0;
+
+ if (_is_scale_enabled && (iBuf->roi.height == 1)
+ && _is_yuv_offsite_vertical) {
+ chroma_repeat_bottom = 3;
+ chroma_repeat_top = 0;
+ }
+ }
+ /* make sure chroma repeats are non-negative */
+ if ((chroma_repeat_left < 0) || (chroma_repeat_right < 0) ||
+ (chroma_repeat_top < 0) || (chroma_repeat_bottom < 0))
+ return -1;
+
+ /* make sure chroma repeats are no larger than 3 pixels */
+ if ((chroma_repeat_left > 3) || (chroma_repeat_right > 3) ||
+ (chroma_repeat_top > 3) || (chroma_repeat_bottom > 3))
+ return -1;
+
+ /* make sure luma repeats are non-negative */
+ if ((luma_repeat_left < 0) || (luma_repeat_right < 0) ||
+ (luma_repeat_top < 0) || (luma_repeat_bottom < 0))
+ return -1;
+
+ /* make sure luma repeats are no larger than 3 pixels */
+ if ((luma_repeat_left > 3) || (luma_repeat_right > 3) ||
+ (luma_repeat_top > 3) || (luma_repeat_bottom > 3))
+ return -1;
+
+ /* write chroma_repeat_left to register */
+ reg |= (chroma_repeat_left & 3) << MDP_LEFT_CHROMA;
+
+ /* write chroma_repeat_right to register */
+ reg |= (chroma_repeat_right & 3) << MDP_RIGHT_CHROMA;
+
+ /* write chroma_repeat_top to register */
+ reg |= (chroma_repeat_top & 3) << MDP_TOP_CHROMA;
+
+ /* write chroma_repeat_bottom to register */
+ reg |= (chroma_repeat_bottom & 3) << MDP_BOTTOM_CHROMA;
+
+ /* write luma_repeat_left to register */
+ reg |= (luma_repeat_left & 3) << MDP_LEFT_LUMA;
+
+ /* write luma_repeat_right to register */
+ reg |= (luma_repeat_right & 3) << MDP_RIGHT_LUMA;
+
+ /* write luma_repeat_top to register */
+ reg |= (luma_repeat_top & 3) << MDP_TOP_LUMA;
+
+ /* write luma_repeat_bottom to register */
+ reg |= (luma_repeat_bottom & 3) << MDP_BOTTOM_LUMA;
+
+ /* done with reg */
+ *dup = reg;
+
+ /* bg edge duplicate */
+ reg = 0x0;
+
+ switch (iBuf->ibuf_type) {
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ /*
+ * Edge condition for MDP_Y_CRCB/CBCR_H2V2 cosite only.
+ * For 420 cosite, 1 chroma replicated on all sides except
+ * left, so reg 101b8 should be 0x0209. For 420 offsite,
+ * 1 chroma replicated all sides.
+ */
+ if (iBuf->roi.lcd_y == 0) {
+ reg |= BIT(MDP_TOP_CHROMA);
+ }
+
+ if ((iBuf->roi.lcd_y + iBuf->roi.dst_height) ==
+ iBuf->ibuf_height) {
+ reg |= BIT(MDP_BOTTOM_CHROMA);
+ }
+
+ if (((iBuf->roi.lcd_x + iBuf->roi.dst_width) ==
+ iBuf->ibuf_width) && ((iBuf->roi.dst_width % 2) == 0)) {
+ reg |= BIT(MDP_RIGHT_CHROMA);
+ }
+
+ break;
+
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V1:
+ case MDP_YCRYCB_H2V1:
+ if (((iBuf->roi.lcd_x + iBuf->roi.dst_width) ==
+ iBuf->ibuf_width) && ((iBuf->roi.dst_width % 2) == 0)) {
+ reg |= BIT(MDP_RIGHT_CHROMA);
+ }
+ break;
+ default:
+ break;
+ }
+
+ *dup2 = reg;
+
+ return 0;
+}
+
+#define ADJUST_IP /* for 1/3 scale factor fix */
+
+static int mdp_calc_scale_params(
+/* ROI origin coordinate for the dimension */
+ uint32 org,
+/* src ROI dimension */
+ uint32 dim_in,
+/* scaled ROI dimension*/
+ uint32 dim_out,
+/* is this ROI width dimension? */
+ boolean is_W,
+/* initial phase location address */
+ int32 *phase_init_ptr,
+/* phase increment location address */
+ uint32 *phase_step_ptr,
+/* ROI start over-fetch location address */
+ uint32 *num_repl_beg_ptr,
+/* ROI end over-fetch location address */
+ uint32 *num_repl_end_ptr)
+{
+ boolean rpa_on = FALSE;
+ int init_phase = 0;
+ uint32 beg_of = 0;
+ uint32 end_of = 0;
+ uint64 numer = 0;
+ uint64 denom = 0;
+ /*uint64 inverter = 1; */
+ int64 point5 = 1;
+ int64 one = 1;
+ int64 k1, k2, k3, k4; /* linear equation coefficients */
+ uint64 int_mask;
+ uint64 fract_mask;
+ uint64 Os;
+ int64 Osprime;
+ int64 Od;
+ int64 Odprime;
+ int64 Oreq;
+ uint64 Es;
+ uint64 Ed;
+ uint64 Ereq;
+#ifdef ADJUST_IP
+ int64 IP64;
+ int64 delta;
+#endif
+ uint32 mult;
+
+ /*
+ * The phase accumulator should really be rational for all cases in a
+ * general purpose polyphase scaler for a tiled architecture with
+ * non-zero * origin capability because there is no way to represent
+ * certain scale factors in fixed point regardless of precision.
+ * The error incurred in attempting to use fixed point is most
+ * eggregious for SF where 1/SF is an integral multiple of 1/3.
+ *
+ * However, since the MDP2 has already been committed to HW, we
+ * only use the rational phase accumulator (RPA) when 1/SF is an
+ * integral multiple of 1/3. This will help minimize regressions in
+ * matching the HW to the C-Sim.
+ */
+ /*
+ * Set the RPA flag for this dimension.
+ *
+ * In order for 1/SF (dim_in/dim_out) to be an integral multiple of
+ * 1/3, dim_out must be an integral multiple of 3.
+ */
+ if (!(dim_out % 3)) {
+ mult = dim_out / 3;
+ rpa_on = (!(dim_in % mult));
+ }
+
+ numer = dim_out;
+ denom = dim_in;
+
+ /*
+ * convert to U30.34 before division
+ *
+ * The K vectors carry 4 extra bits of precision
+ * and are rounded.
+ *
+ * We initially go 5 bits over then round by adding
+ * 1 and right shifting by 1
+ * so final result is U31.33
+ */
+ numer <<= PQF_PLUS_5;
+
+ /* now calculate the scale factor (aka k3) */
+ k3 = ((mdp_do_div(numer, denom) + 1) >> 1);
+
+ /* check scale factor for legal range [0.25 - 4.0] */
+ if (((k3 >> 4) < (1LL << PQF_MINUS_2)) ||
+ ((k3 >> 4) > (1LL << PQF_PLUS_2))) {
+ return -1;
+ }
+
+ /* calculate inverse scale factor (aka k1) for phase init */
+ numer = dim_in;
+ denom = dim_out;
+ numer <<= PQF_PLUS_5;
+ k1 = ((mdp_do_div(numer, denom) + 1) >> 1);
+
+ /*
+ * calculate initial phase and ROI overfetch
+ */
+ /* convert point5 & one to S39.24 (will always be positive) */
+ point5 <<= (PQF_PLUS_4 - 1);
+ one <<= PQF_PLUS_4;
+ k2 = ((k1 - one) >> 1);
+ init_phase = (int)(k2 >> 4);
+ k4 = ((k3 - one) >> 1);
+ if (k3 == one) {
+ /* the simple case; SF = 1.0 */
+ beg_of = 1;
+ end_of = 2;
+ } else {
+ /* calculate the masks */
+ fract_mask = one - 1;
+ int_mask = ~fract_mask;
+
+ if (!rpa_on) {
+ /*
+ * FIXED POINT IMPLEMENTATION
+ */
+ if (!org) {
+ /* A fairly simple case; ROI origin = 0 */
+ if (k1 < one) {
+ /* upscaling */
+ beg_of = end_of = 2;
+ }
+ /* 0.33 <= SF < 1.0 */
+ else if (k1 < (3LL << PQF_PLUS_4))
+ beg_of = end_of = 1;
+ /* 0.33 == SF */
+ else if (k1 == (3LL << PQF_PLUS_4)) {
+ beg_of = 0;
+ end_of = 1;
+ }
+ /* 0.25 <= SF < 0.33 */
+ else
+ beg_of = end_of = 0;
+ } else {
+ /*
+ * The complicated case; ROI origin != 0
+ * init_phase needs to be adjusted
+ * OF is also position dependent
+ */
+
+ /* map (org - .5) into destination space */
+ Os = ((uint64) org << 1) - 1;
+ Od = ((k3 * Os) >> 1) + k4;
+
+ /* take the ceiling */
+ Odprime = (Od & int_mask);
+ if (Odprime != Od)
+ Odprime += one;
+
+ /* now map that back to source space */
+ Osprime = (k1 * (Odprime >> PQF_PLUS_4)) + k2;
+
+ /* then floor & decrement to calculate the required
+ starting coordinate */
+ Oreq = (Osprime & int_mask) - one;
+
+ /* calculate end coord in destination space then map to
+ source space */
+ Ed = Odprime +
+ ((uint64) dim_out << PQF_PLUS_4) - one;
+ Es = (k1 * (Ed >> PQF_PLUS_4)) + k2;
+
+ /* now floor & increment by 2 to calculate the required
+ ending coordinate */
+ Ereq = (Es & int_mask) + (one << 1);
+
+ /* calculate initial phase */
+#ifdef ADJUST_IP
+
+ IP64 = Osprime - Oreq;
+ delta = ((int64) (org) << PQF_PLUS_4) - Oreq;
+ IP64 -= delta;
+
+ /* limit to valid range before the left shift */
+ delta = (IP64 & (1LL << 63)) ? 4 : -4;
+ delta <<= PQF_PLUS_4;
+ while (abs((int)(IP64 >> PQF_PLUS_4)) > 4)
+ IP64 += delta;
+
+ /* right shift to account for extra bits of precision */
+ init_phase = (int)(IP64 >> 4);
+
+#else /* ADJUST_IP */
+
+ /* just calculate the real initial phase */
+ init_phase = (int)((Osprime - Oreq) >> 4);
+
+#endif /* ADJUST_IP */
+
+ /* calculate the overfetch */
+ beg_of = org - (uint32) (Oreq >> PQF_PLUS_4);
+ end_of =
+ (uint32) (Ereq >> PQF_PLUS_4) - (org +
+ dim_in -
+ 1);
+ }
+ } else {
+ /*
+ * RPA IMPLEMENTATION
+ *
+ * init_phase needs to be calculated in all RPA_on cases
+ * because it's a numerator, not a fixed point value.
+ */
+
+ /* map (org - .5) into destination space */
+ Os = ((uint64) org << PQF_PLUS_4) - point5;
+ Od = mdp_do_div((dim_out * (Os + point5)),
+ dim_in) - point5;
+
+ /* take the ceiling */
+ Odprime = (Od & int_mask);
+ if (Odprime != Od)
+ Odprime += one;
+
+ /* now map that back to source space */
+ Osprime =
+ mdp_do_div((dim_in * (Odprime + point5)),
+ dim_out) - point5;
+
+ /* then floor & decrement to calculate the required
+ starting coordinate */
+ Oreq = (Osprime & int_mask) - one;
+
+ /* calculate end coord in destination space then map to
+ source space */
+ Ed = Odprime + ((uint64) dim_out << PQF_PLUS_4) - one;
+ Es = mdp_do_div((dim_in * (Ed + point5)),
+ dim_out) - point5;
+
+ /* now floor & increment by 2 to calculate the required
+ ending coordinate */
+ Ereq = (Es & int_mask) + (one << 1);
+
+ /* calculate initial phase */
+
+#ifdef ADJUST_IP
+
+ IP64 = Osprime - Oreq;
+ delta = ((int64) (org) << PQF_PLUS_4) - Oreq;
+ IP64 -= delta;
+
+ /* limit to valid range before the left shift */
+ delta = (IP64 & (1LL << 63)) ? 4 : -4;
+ delta <<= PQF_PLUS_4;
+ while (abs((int)(IP64 >> PQF_PLUS_4)) > 4)
+ IP64 += delta;
+
+ /* right shift to account for extra bits of precision */
+ init_phase = (int)(IP64 >> 4);
+
+#else /* ADJUST_IP */
+
+ /* just calculate the real initial phase */
+ init_phase = (int)((Osprime - Oreq) >> 4);
+
+#endif /* ADJUST_IP */
+
+ /* calculate the overfetch */
+ beg_of = org - (uint32) (Oreq >> PQF_PLUS_4);
+ end_of =
+ (uint32) (Ereq >> PQF_PLUS_4) - (org + dim_in - 1);
+ }
+ }
+
+ /* return the scale parameters */
+ *phase_init_ptr = init_phase;
+ *phase_step_ptr = (uint32) (k1 >> 4);
+ *num_repl_beg_ptr = beg_of;
+ *num_repl_end_ptr = end_of;
+
+ return 0;
+}
+
+static uint8 *mdp_adjust_rot_addr(MDPIBUF *iBuf, uint8 *addr, uint32 uv)
+{
+ uint32 dest_ystride = iBuf->ibuf_width * iBuf->bpp;
+ uint32 h_slice = 1;
+
+ if (uv && ((iBuf->ibuf_type == MDP_Y_CBCR_H2V2) ||
+ (iBuf->ibuf_type == MDP_Y_CRCB_H2V2)))
+ h_slice = 2;
+
+ if (MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_ROT90) ^
+ MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_LR)) {
+ addr =
+ addr + (iBuf->roi.dst_width -
+ MIN(16, iBuf->roi.dst_width)) * iBuf->bpp;
+ }
+ if (MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_UD)) {
+ addr =
+ addr + ((iBuf->roi.dst_height -
+ MIN(16, iBuf->roi.dst_height))/h_slice) * dest_ystride;
+ }
+
+ return addr;
+}
+
+void mdp_set_scale(MDPIBUF *iBuf,
+ uint32 dst_roi_width,
+ uint32 dst_roi_height,
+ boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr)
+{
+ uint32 dst_roi_width_scale;
+ uint32 dst_roi_height_scale;
+ boolean use_pr;
+ uint32 phasex_step = 0;
+ uint32 phasey_step = 0;
+ int32 phasex_init = 0;
+ int32 phasey_init = 0;
+ uint32 lines_dup = 0;
+ uint32 lines_dup_bg = 0;
+ uint32 dummy;
+ uint32 mdp_blur = 0;
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) {
+ if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
+ dst_roi_width_scale = dst_roi_height;
+ dst_roi_height_scale = dst_roi_width;
+ } else {
+ dst_roi_width_scale = dst_roi_width;
+ dst_roi_height_scale = dst_roi_height;
+ }
+
+ mdp_blur = iBuf->mdpImg.mdpOp & MDPOP_BLUR;
+
+ if ((dst_roi_width_scale != iBuf->roi.width) ||
+ (dst_roi_height_scale != iBuf->roi.height) ||
+ mdp_blur) {
+ *pppop_reg_ptr |=
+ (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
+
+ /* let's use SHIM logic to calculate the partial ROI scaling */
+#if 0
+ phasex_step =
+ (uint32) mdp_do_div(0x20000000 * iBuf->roi.width,
+ dst_roi_width_scale);
+ phasey_step =
+ (uint32) mdp_do_div(0x20000000 * iBuf->roi.height,
+ dst_roi_height_scale);
+
+/*
+ phasex_step= ((long long) iBuf->roi.width * 0x20000000)/dst_roi_width_scale;
+ phasey_step= ((long long)iBuf->roi.height * 0x20000000)/dst_roi_height_scale;
+*/
+
+ phasex_init =
+ (((long long)phasex_step - 0x20000000) >> 1);
+ phasey_init =
+ (((long long)phasey_step - 0x20000000) >> 1);
+
+#else
+ mdp_calc_scale_params(iBuf->roi.x, iBuf->roi.width,
+ dst_roi_width_scale, 1,
+ &phasex_init, &phasex_step,
+ &dummy, &dummy);
+ mdp_calc_scale_params(iBuf->roi.y, iBuf->roi.height,
+ dst_roi_height_scale, 0,
+ &phasey_init, &phasey_step,
+ &dummy, &dummy);
+#endif
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x013c,
+ phasex_init);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0140,
+ phasey_init);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0144,
+ phasex_step);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0148,
+ phasey_step);
+
+ /* disable the pixel repeat option for scaling */
+ use_pr = false;
+
+ if ((dst_roi_width_scale > iBuf->roi.width) ||
+ (dst_roi_height_scale > iBuf->roi.height)) {
+ if ((use_pr)
+ && (mdp_curr_up_scale_xy !=
+ MDP_PR_SCALE_UP)) {
+ mdp_load_pr_upscale_table();
+ mdp_curr_up_scale_xy = MDP_PR_SCALE_UP;
+ } else if ((!use_pr)
+ && (mdp_curr_up_scale_xy !=
+ MDP_BC_SCALE_UP)) {
+ mdp_load_bc_upscale_table();
+ mdp_curr_up_scale_xy = MDP_BC_SCALE_UP;
+ }
+ }
+
+ if (mdp_blur) {
+ load_scale_table(mdp_gaussian_blur_table,
+ ARRAY_SIZE(mdp_gaussian_blur_table));
+ mdp_curr_down_scale_x = MDP_SCALE_BLUR;
+ mdp_curr_down_scale_y = MDP_SCALE_BLUR;
+ }
+
+ /* 0.2 < x <= 1 scaling factor */
+ if ((dst_roi_width_scale <= iBuf->roi.width) &&
+ !mdp_blur) {
+ if (((dst_roi_width_scale * 10) /
+ iBuf->roi.width) > 8) {
+ if ((use_pr)
+ && (mdp_curr_down_scale_x !=
+ MDP_PR_SCALE_POINT8_1)) {
+ mdp_load_pr_downscale_table_x_point8TO1
+ ();
+ mdp_curr_down_scale_x =
+ MDP_PR_SCALE_POINT8_1;
+ } else if ((!use_pr)
+ && (mdp_curr_down_scale_x !=
+ MDP_BC_SCALE_POINT8_1)) {
+ mdp_load_bc_downscale_table_x_point8TO1
+ ();
+ mdp_curr_down_scale_x =
+ MDP_BC_SCALE_POINT8_1;
+ }
+ } else
+ if (((dst_roi_width_scale * 10) /
+ iBuf->roi.width) > 6) {
+ if ((use_pr)
+ && (mdp_curr_down_scale_x !=
+ MDP_PR_SCALE_POINT6_POINT8)) {
+ mdp_load_pr_downscale_table_x_point6TOpoint8
+ ();
+ mdp_curr_down_scale_x =
+ MDP_PR_SCALE_POINT6_POINT8;
+ } else if ((!use_pr)
+ && (mdp_curr_down_scale_x !=
+ MDP_BC_SCALE_POINT6_POINT8))
+ {
+ mdp_load_bc_downscale_table_x_point6TOpoint8
+ ();
+ mdp_curr_down_scale_x =
+ MDP_BC_SCALE_POINT6_POINT8;
+ }
+ } else
+ if (((dst_roi_width_scale * 10) /
+ iBuf->roi.width) > 4) {
+ if ((use_pr)
+ && (mdp_curr_down_scale_x !=
+ MDP_PR_SCALE_POINT4_POINT6)) {
+ mdp_load_pr_downscale_table_x_point4TOpoint6
+ ();
+ mdp_curr_down_scale_x =
+ MDP_PR_SCALE_POINT4_POINT6;
+ } else if ((!use_pr)
+ && (mdp_curr_down_scale_x !=
+ MDP_BC_SCALE_POINT4_POINT6))
+ {
+ mdp_load_bc_downscale_table_x_point4TOpoint6
+ ();
+ mdp_curr_down_scale_x =
+ MDP_BC_SCALE_POINT4_POINT6;
+ }
+ } else {
+ if ((use_pr)
+ && (mdp_curr_down_scale_x !=
+ MDP_PR_SCALE_POINT2_POINT4)) {
+ mdp_load_pr_downscale_table_x_point2TOpoint4
+ ();
+ mdp_curr_down_scale_x =
+ MDP_PR_SCALE_POINT2_POINT4;
+ } else if ((!use_pr)
+ && (mdp_curr_down_scale_x !=
+ MDP_BC_SCALE_POINT2_POINT4))
+ {
+ mdp_load_bc_downscale_table_x_point2TOpoint4
+ ();
+ mdp_curr_down_scale_x =
+ MDP_BC_SCALE_POINT2_POINT4;
+ }
+ }
+ }
+ /* 0.2 < y <= 1 scaling factor */
+ if ((dst_roi_height_scale <= iBuf->roi.height) &&
+ !mdp_blur) {
+ if (((dst_roi_height_scale * 10) /
+ iBuf->roi.height) > 8) {
+ if ((use_pr)
+ && (mdp_curr_down_scale_y !=
+ MDP_PR_SCALE_POINT8_1)) {
+ mdp_load_pr_downscale_table_y_point8TO1
+ ();
+ mdp_curr_down_scale_y =
+ MDP_PR_SCALE_POINT8_1;
+ } else if ((!use_pr)
+ && (mdp_curr_down_scale_y !=
+ MDP_BC_SCALE_POINT8_1)) {
+ mdp_load_bc_downscale_table_y_point8TO1
+ ();
+ mdp_curr_down_scale_y =
+ MDP_BC_SCALE_POINT8_1;
+ }
+ } else
+ if (((dst_roi_height_scale * 10) /
+ iBuf->roi.height) > 6) {
+ if ((use_pr)
+ && (mdp_curr_down_scale_y !=
+ MDP_PR_SCALE_POINT6_POINT8)) {
+ mdp_load_pr_downscale_table_y_point6TOpoint8
+ ();
+ mdp_curr_down_scale_y =
+ MDP_PR_SCALE_POINT6_POINT8;
+ } else if ((!use_pr)
+ && (mdp_curr_down_scale_y !=
+ MDP_BC_SCALE_POINT6_POINT8))
+ {
+ mdp_load_bc_downscale_table_y_point6TOpoint8
+ ();
+ mdp_curr_down_scale_y =
+ MDP_BC_SCALE_POINT6_POINT8;
+ }
+ } else
+ if (((dst_roi_height_scale * 10) /
+ iBuf->roi.height) > 4) {
+ if ((use_pr)
+ && (mdp_curr_down_scale_y !=
+ MDP_PR_SCALE_POINT4_POINT6)) {
+ mdp_load_pr_downscale_table_y_point4TOpoint6
+ ();
+ mdp_curr_down_scale_y =
+ MDP_PR_SCALE_POINT4_POINT6;
+ } else if ((!use_pr)
+ && (mdp_curr_down_scale_y !=
+ MDP_BC_SCALE_POINT4_POINT6))
+ {
+ mdp_load_bc_downscale_table_y_point4TOpoint6
+ ();
+ mdp_curr_down_scale_y =
+ MDP_BC_SCALE_POINT4_POINT6;
+ }
+ } else {
+ if ((use_pr)
+ && (mdp_curr_down_scale_y !=
+ MDP_PR_SCALE_POINT2_POINT4)) {
+ mdp_load_pr_downscale_table_y_point2TOpoint4
+ ();
+ mdp_curr_down_scale_y =
+ MDP_PR_SCALE_POINT2_POINT4;
+ } else if ((!use_pr)
+ && (mdp_curr_down_scale_y !=
+ MDP_BC_SCALE_POINT2_POINT4))
+ {
+ mdp_load_bc_downscale_table_y_point2TOpoint4
+ ();
+ mdp_curr_down_scale_y =
+ MDP_BC_SCALE_POINT2_POINT4;
+ }
+ }
+ }
+ } else {
+ iBuf->mdpImg.mdpOp &= ~(MDPOP_ASCALE);
+ }
+ }
+ /* setting edge condition here after scaling check */
+ if (mdp_get_edge_cond(iBuf, &lines_dup, &lines_dup_bg))
+ printk(KERN_ERR "msm_fb: mdp_get_edge_cond() error!\n");
+
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01b8, lines_dup);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01bc, lines_dup_bg);
+}
+
+void mdp_init_scale_table(void)
+{
+ mdp_curr_up_scale_xy = MDP_INIT_SCALE;
+ mdp_curr_down_scale_x = MDP_INIT_SCALE;
+ mdp_curr_down_scale_y = MDP_INIT_SCALE;
+}
+
+void mdp_adjust_start_addr(uint8 **src0,
+ uint8 **src1,
+ int v_slice,
+ int h_slice,
+ int x,
+ int y,
+ uint32 width,
+ uint32 height, int bpp, MDPIBUF *iBuf, int layer)
+{
+ *src0 += (x + y * width) * bpp;
+
+ /* if it's dest/bg buffer, we need to adjust it for rotation */
+ if (layer != 0)
+ *src0 = mdp_adjust_rot_addr(iBuf, *src0, 0);
+
+ if (*src1) {
+ /*
+ * MDP_Y_CBCR_H2V2/MDP_Y_CRCB_H2V2 cosite for now
+ * we need to shift x direction same as y dir for offsite
+ */
+ *src1 +=
+ ((x / h_slice) * h_slice +
+ ((y == 0) ? 0 : ((y + 1) / v_slice - 1) * width)) * bpp;
+
+ /* if it's dest/bg buffer, we need to adjust it for rotation */
+ if (layer != 0)
+ *src1 = mdp_adjust_rot_addr(iBuf, *src1, 1);
+ }
+}
+
+void mdp_set_blend_attr(MDPIBUF *iBuf,
+ uint32 *alpha,
+ uint32 *tpVal,
+ uint32 perPixelAlpha, uint32 *pppop_reg_ptr)
+{
+ if (perPixelAlpha) {
+ *pppop_reg_ptr |= PPP_OP_ROT_ON |
+ PPP_OP_BLEND_ON | PPP_OP_BLEND_SRCPIXEL_ALPHA;
+ } else {
+ if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+ && (iBuf->mdpImg.alpha == 0xff)) {
+ iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB);
+ }
+
+ if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+ && (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
+ *pppop_reg_ptr |=
+ PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
+ PPP_OP_BLEND_CONSTANT_ALPHA |
+ PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
+ PPP_BLEND_CALPHA_TRNASP;
+
+ *alpha = iBuf->mdpImg.alpha;
+ *tpVal = iBuf->mdpImg.tpVal;
+ } else {
+ if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) {
+ *pppop_reg_ptr |= PPP_OP_ROT_ON |
+ PPP_OP_BLEND_ON |
+ PPP_OP_BLEND_SRCPIXEL_TRANSP;
+ *tpVal = iBuf->mdpImg.tpVal;
+ } else if (iBuf->mdpImg.mdpOp & MDPOP_ALPHAB) {
+ *pppop_reg_ptr |= PPP_OP_ROT_ON |
+ PPP_OP_BLEND_ON |
+ PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
+ PPP_OP_BLEND_CONSTANT_ALPHA;
+ *alpha = iBuf->mdpImg.alpha;
+ }
+ }
+ }
+}
diff --git a/drivers/video/msm/mdp_ppp_v31.c b/drivers/video/msm/mdp_ppp_v31.c
new file mode 100644
index 0000000..ee6af53
--- /dev/null
+++ b/drivers/video/msm/mdp_ppp_v31.c
@@ -0,0 +1,844 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include "linux/proc_fs.h"
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <asm/div64.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+#define MDP_SCALE_COEFF_NUM 32
+#define MDP_SCALE_0P2_TO_0P4_INDEX 0
+#define MDP_SCALE_0P4_TO_0P6_INDEX 32
+#define MDP_SCALE_0P6_TO_0P8_INDEX 64
+#define MDP_SCALE_0P8_TO_8P0_INDEX 96
+#define MDP_SCALE_COEFF_MASK 0x3ff
+
+#define MDP_SCALE_PR 0
+#define MDP_SCALE_FIR 1
+
+static uint32 mdp_scale_0p8_to_8p0_mode;
+static uint32 mdp_scale_0p6_to_0p8_mode;
+static uint32 mdp_scale_0p4_to_0p6_mode;
+static uint32 mdp_scale_0p2_to_0p4_mode;
+
+/* -------- All scaling range, "pixel repeat" -------- */
+static int16 mdp_scale_pixel_repeat_C0[MDP_SCALE_COEFF_NUM] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static int16 mdp_scale_pixel_repeat_C1[MDP_SCALE_COEFF_NUM] = {
+ 511, 511, 511, 511, 511, 511, 511, 511,
+ 511, 511, 511, 511, 511, 511, 511, 511,
+ 511, 511, 511, 511, 511, 511, 511, 511,
+ 511, 511, 511, 511, 511, 511, 511, 511
+};
+
+static int16 mdp_scale_pixel_repeat_C2[MDP_SCALE_COEFF_NUM] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static int16 mdp_scale_pixel_repeat_C3[MDP_SCALE_COEFF_NUM] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* --------------------------- FIR ------------------------------------- */
+/* -------- Downscale, ranging from 0.8x to 8.0x of original size -------- */
+
+static int16 mdp_scale_0p8_to_8p0_C0[MDP_SCALE_COEFF_NUM] = {
+ 0, -7, -13, -19, -24, -28, -32, -34, -37, -39,
+ -40, -41, -41, -41, -40, -40, -38, -37, -35, -33,
+ -31, -29, -26, -24, -21, -18, -15, -13, -10, -7,
+ -5, -2
+};
+
+static int16 mdp_scale_0p8_to_8p0_C1[MDP_SCALE_COEFF_NUM] = {
+ 511, 507, 501, 494, 485, 475, 463, 450, 436, 422,
+ 405, 388, 370, 352, 333, 314, 293, 274, 253, 233,
+ 213, 193, 172, 152, 133, 113, 95, 77, 60, 43,
+ 28, 13
+};
+
+static int16 mdp_scale_0p8_to_8p0_C2[MDP_SCALE_COEFF_NUM] = {
+ 0, 13, 28, 43, 60, 77, 95, 113, 133, 152,
+ 172, 193, 213, 233, 253, 274, 294, 314, 333, 352,
+ 370, 388, 405, 422, 436, 450, 463, 475, 485, 494,
+ 501, 507,
+};
+
+static int16 mdp_scale_0p8_to_8p0_C3[MDP_SCALE_COEFF_NUM] = {
+ 0, -2, -5, -7, -10, -13, -15, -18, -21, -24,
+ -26, -29, -31, -33, -35, -37, -38, -40, -40, -41,
+ -41, -41, -40, -39, -37, -34, -32, -28, -24, -19,
+ -13, -7
+};
+
+/* -------- Downscale, ranging from 0.6x to 0.8x of original size -------- */
+
+static int16 mdp_scale_0p6_to_0p8_C0[MDP_SCALE_COEFF_NUM] = {
+ 104, 96, 89, 82, 75, 68, 61, 55, 49, 43,
+ 38, 33, 28, 24, 20, 16, 12, 9, 6, 4,
+ 2, 0, -2, -4, -5, -6, -7, -7, -8, -8,
+ -8, -8
+};
+
+static int16 mdp_scale_0p6_to_0p8_C1[MDP_SCALE_COEFF_NUM] = {
+ 303, 303, 302, 300, 298, 296, 293, 289, 286, 281,
+ 276, 270, 265, 258, 252, 245, 238, 230, 223, 214,
+ 206, 197, 189, 180, 172, 163, 154, 145, 137, 128,
+ 120, 112
+};
+
+static int16 mdp_scale_0p6_to_0p8_C2[MDP_SCALE_COEFF_NUM] = {
+ 112, 120, 128, 137, 145, 154, 163, 172, 180, 189,
+ 197, 206, 214, 223, 230, 238, 245, 252, 258, 265,
+ 270, 276, 281, 286, 289, 293, 296, 298, 300, 302,
+ 303, 303
+};
+
+static int16 mdp_scale_0p6_to_0p8_C3[MDP_SCALE_COEFF_NUM] = {
+ -8, -8, -8, -8, -7, -7, -6, -5, -4, -2,
+ 0, 2, 4, 6, 9, 12, 16, 20, 24, 28,
+ 33, 38, 43, 49, 55, 61, 68, 75, 82, 89,
+ 96, 104
+};
+
+/* -------- Downscale, ranging from 0.4x to 0.6x of original size -------- */
+
+static int16 mdp_scale_0p4_to_0p6_C0[MDP_SCALE_COEFF_NUM] = {
+ 136, 132, 128, 123, 119, 115, 111, 107, 103, 98,
+ 95, 91, 87, 84, 80, 76, 73, 69, 66, 62,
+ 59, 57, 54, 50, 47, 44, 41, 39, 36, 33,
+ 32, 29
+};
+
+static int16 mdp_scale_0p4_to_0p6_C1[MDP_SCALE_COEFF_NUM] = {
+ 206, 205, 204, 204, 201, 200, 199, 197, 196, 194,
+ 191, 191, 189, 185, 184, 182, 180, 178, 176, 173,
+ 170, 168, 165, 162, 160, 157, 155, 152, 148, 146,
+ 142, 140
+};
+
+static int16 mdp_scale_0p4_to_0p6_C2[MDP_SCALE_COEFF_NUM] = {
+ 140, 142, 146, 148, 152, 155, 157, 160, 162, 165,
+ 168, 170, 173, 176, 178, 180, 182, 184, 185, 189,
+ 191, 191, 194, 196, 197, 199, 200, 201, 204, 204,
+ 205, 206
+};
+
+static int16 mdp_scale_0p4_to_0p6_C3[MDP_SCALE_COEFF_NUM] = {
+ 29, 32, 33, 36, 39, 41, 44, 47, 50, 54,
+ 57, 59, 62, 66, 69, 73, 76, 80, 84, 87,
+ 91, 95, 98, 103, 107, 111, 115, 119, 123, 128,
+ 132, 136
+};
+
+/* -------- Downscale, ranging from 0.2x to 0.4x of original size -------- */
+
+static int16 mdp_scale_0p2_to_0p4_C0[MDP_SCALE_COEFF_NUM] = {
+ 131, 131, 130, 129, 128, 127, 127, 126, 125, 125,
+ 124, 123, 123, 121, 120, 119, 119, 118, 117, 117,
+ 116, 115, 115, 114, 113, 112, 111, 110, 109, 109,
+ 108, 107
+};
+
+static int16 mdp_scale_0p2_to_0p4_C1[MDP_SCALE_COEFF_NUM] = {
+ 141, 140, 140, 140, 140, 139, 138, 138, 138, 137,
+ 137, 137, 136, 137, 137, 137, 136, 136, 136, 135,
+ 135, 135, 134, 134, 134, 134, 134, 133, 133, 132,
+ 132, 132
+};
+
+static int16 mdp_scale_0p2_to_0p4_C2[MDP_SCALE_COEFF_NUM] = {
+ 132, 132, 132, 133, 133, 134, 134, 134, 134, 134,
+ 135, 135, 135, 136, 136, 136, 137, 137, 137, 136,
+ 137, 137, 137, 138, 138, 138, 139, 140, 140, 140,
+ 140, 141
+};
+
+static int16 mdp_scale_0p2_to_0p4_C3[MDP_SCALE_COEFF_NUM] = {
+ 107, 108, 109, 109, 110, 111, 112, 113, 114, 115,
+ 115, 116, 117, 117, 118, 119, 119, 120, 121, 123,
+ 123, 124, 125, 125, 126, 127, 127, 128, 129, 130,
+ 131, 131
+};
+
+static void mdp_update_scale_table(int index, int16 *c0, int16 *c1,
+ int16 *c2, int16 *c3)
+{
+ int i, val;
+
+ for (i = 0; i < MDP_SCALE_COEFF_NUM; i++) {
+ val =
+ ((MDP_SCALE_COEFF_MASK & c1[i]) << 16) |
+ (MDP_SCALE_COEFF_MASK & c0[i]);
+ writel(val, MDP_PPP_SCALE_COEFF_LSBn(index));
+ val =
+ ((MDP_SCALE_COEFF_MASK & c3[i]) << 16) |
+ (MDP_SCALE_COEFF_MASK & c2[i]);
+ writel(val, MDP_PPP_SCALE_COEFF_MSBn(index));
+ index++;
+ }
+}
+
+void mdp_init_scale_table(void)
+{
+ mdp_scale_0p2_to_0p4_mode = MDP_SCALE_FIR;
+ mdp_update_scale_table(MDP_SCALE_0P2_TO_0P4_INDEX,
+ mdp_scale_0p2_to_0p4_C0,
+ mdp_scale_0p2_to_0p4_C1,
+ mdp_scale_0p2_to_0p4_C2,
+ mdp_scale_0p2_to_0p4_C3);
+
+ mdp_scale_0p4_to_0p6_mode = MDP_SCALE_FIR;
+ mdp_update_scale_table(MDP_SCALE_0P4_TO_0P6_INDEX,
+ mdp_scale_0p4_to_0p6_C0,
+ mdp_scale_0p4_to_0p6_C1,
+ mdp_scale_0p4_to_0p6_C2,
+ mdp_scale_0p4_to_0p6_C3);
+
+ mdp_scale_0p6_to_0p8_mode = MDP_SCALE_FIR;
+ mdp_update_scale_table(MDP_SCALE_0P6_TO_0P8_INDEX,
+ mdp_scale_0p6_to_0p8_C0,
+ mdp_scale_0p6_to_0p8_C1,
+ mdp_scale_0p6_to_0p8_C2,
+ mdp_scale_0p6_to_0p8_C3);
+
+ mdp_scale_0p8_to_8p0_mode = MDP_SCALE_FIR;
+ mdp_update_scale_table(MDP_SCALE_0P8_TO_8P0_INDEX,
+ mdp_scale_0p8_to_8p0_C0,
+ mdp_scale_0p8_to_8p0_C1,
+ mdp_scale_0p8_to_8p0_C2,
+ mdp_scale_0p8_to_8p0_C3);
+}
+
+static long long mdp_do_div(long long num, long long den)
+{
+ do_div(num, den);
+ return num;
+}
+
+#define SCALER_PHASE_BITS 29
+#define HAL_MDP_PHASE_STEP_2P50 0x50000000
+#define HAL_MDP_PHASE_STEP_1P66 0x35555555
+#define HAL_MDP_PHASE_STEP_1P25 0x28000000
+
+struct phase_val {
+ int phase_init_x;
+ int phase_init_y;
+ int phase_step_x;
+ int phase_step_y;
+};
+
+static void mdp_calc_scaleInitPhase_3p1(uint32 in_w,
+ uint32 in_h,
+ uint32 out_w,
+ uint32 out_h,
+ boolean is_rotate,
+ boolean is_pp_x,
+ boolean is_pp_y, struct phase_val *pval)
+{
+ uint64 dst_ROI_width;
+ uint64 dst_ROI_height;
+ uint64 src_ROI_width;
+ uint64 src_ROI_height;
+
+ /*
+ * phase_step_x, phase_step_y, phase_init_x and phase_init_y
+ * are represented in fixed-point, unsigned 3.29 format
+ */
+ uint32 phase_step_x = 0;
+ uint32 phase_step_y = 0;
+ uint32 phase_init_x = 0;
+ uint32 phase_init_y = 0;
+ uint32 yscale_filter_sel, xscale_filter_sel;
+ uint32 scale_unit_sel_x, scale_unit_sel_y;
+
+ uint64 numerator, denominator;
+ uint64 temp_dim;
+
+ src_ROI_width = in_w;
+ src_ROI_height = in_h;
+ dst_ROI_width = out_w;
+ dst_ROI_height = out_h;
+
+ /* if there is a 90 degree rotation */
+ if (is_rotate) {
+ /* decide whether to use FIR or M/N for scaling */
+
+ /* if down-scaling by a factor smaller than 1/4 */
+ if ((dst_ROI_height == 1 && src_ROI_width < 4) ||
+ (src_ROI_width < 4 * dst_ROI_height - 3))
+ scale_unit_sel_x = 0;/* use FIR scalar */
+ else
+ scale_unit_sel_x = 1;/* use M/N scalar */
+
+ /* if down-scaling by a factor smaller than 1/4 */
+ if ((dst_ROI_width == 1 && src_ROI_height < 4) ||
+ (src_ROI_height < 4 * dst_ROI_width - 3))
+ scale_unit_sel_y = 0;/* use FIR scalar */
+ else
+ scale_unit_sel_y = 1;/* use M/N scalar */
+ } else {
+ /* decide whether to use FIR or M/N for scaling */
+ if ((dst_ROI_width == 1 && src_ROI_width < 4) ||
+ (src_ROI_width < 4 * dst_ROI_width - 3))
+ scale_unit_sel_x = 0;/* use FIR scalar */
+ else
+ scale_unit_sel_x = 1;/* use M/N scalar */
+
+ if ((dst_ROI_height == 1 && src_ROI_height < 4) ||
+ (src_ROI_height < 4 * dst_ROI_height - 3))
+ scale_unit_sel_y = 0;/* use FIR scalar */
+ else
+ scale_unit_sel_y = 1;/* use M/N scalar */
+ }
+
+ /* if there is a 90 degree rotation */
+ if (is_rotate) {
+ /* swap the width and height of dst ROI */
+ temp_dim = dst_ROI_width;
+ dst_ROI_width = dst_ROI_height;
+ dst_ROI_height = temp_dim;
+ }
+
+ /* calculate phase step for the x direction */
+
+ /* if destination is only 1 pixel wide, the value of phase_step_x
+ is unimportant. Assigning phase_step_x to src ROI width
+ as an arbitrary value. */
+ if (dst_ROI_width == 1)
+ phase_step_x = (uint32) ((src_ROI_width) << SCALER_PHASE_BITS);
+
+ /* if using FIR scalar */
+ else if (scale_unit_sel_x == 0) {
+
+ /* Calculate the quotient ( src_ROI_width - 1 ) / ( dst_ROI_width - 1)
+ with u3.29 precision. Quotient is rounded up to the larger
+ 29th decimal point. */
+ numerator = (src_ROI_width - 1) << SCALER_PHASE_BITS;
+ denominator = (dst_ROI_width - 1); /* never equals to 0 because of the "( dst_ROI_width == 1 ) case" */
+ phase_step_x = (uint32) mdp_do_div((numerator + denominator - 1), denominator); /* divide and round up to the larger 29th decimal point. */
+
+ }
+
+ /* if M/N scalar */
+ else if (scale_unit_sel_x == 1) {
+ /* Calculate the quotient ( src_ROI_width ) / ( dst_ROI_width)
+ with u3.29 precision. Quotient is rounded down to the
+ smaller 29th decimal point. */
+ numerator = (src_ROI_width) << SCALER_PHASE_BITS;
+ denominator = (dst_ROI_width);
+ phase_step_x = (uint32) mdp_do_div(numerator, denominator);
+ }
+ /* calculate phase step for the y direction */
+
+ /* if destination is only 1 pixel wide, the value of
+ phase_step_x is unimportant. Assigning phase_step_x
+ to src ROI width as an arbitrary value. */
+ if (dst_ROI_height == 1)
+ phase_step_y = (uint32) ((src_ROI_height) << SCALER_PHASE_BITS);
+
+ /* if FIR scalar */
+ else if (scale_unit_sel_y == 0) {
+ /* Calculate the quotient ( src_ROI_height - 1 ) / ( dst_ROI_height - 1)
+ with u3.29 precision. Quotient is rounded up to the larger
+ 29th decimal point. */
+ numerator = (src_ROI_height - 1) << SCALER_PHASE_BITS;
+ denominator = (dst_ROI_height - 1); /* never equals to 0 because of the "( dst_ROI_height == 1 )" case */
+ phase_step_y = (uint32) mdp_do_div((numerator + denominator - 1), denominator); /* Quotient is rounded up to the larger 29th decimal point. */
+
+ }
+
+ /* if M/N scalar */
+ else if (scale_unit_sel_y == 1) {
+ /* Calculate the quotient ( src_ROI_height ) / ( dst_ROI_height)
+ with u3.29 precision. Quotient is rounded down to the smaller
+ 29th decimal point. */
+ numerator = (src_ROI_height) << SCALER_PHASE_BITS;
+ denominator = (dst_ROI_height);
+ phase_step_y = (uint32) mdp_do_div(numerator, denominator);
+ }
+
+ /* decide which set of FIR coefficients to use */
+ if (phase_step_x > HAL_MDP_PHASE_STEP_2P50)
+ xscale_filter_sel = 0;
+ else if (phase_step_x > HAL_MDP_PHASE_STEP_1P66)
+ xscale_filter_sel = 1;
+ else if (phase_step_x > HAL_MDP_PHASE_STEP_1P25)
+ xscale_filter_sel = 2;
+ else
+ xscale_filter_sel = 3;
+
+ if (phase_step_y > HAL_MDP_PHASE_STEP_2P50)
+ yscale_filter_sel = 0;
+ else if (phase_step_y > HAL_MDP_PHASE_STEP_1P66)
+ yscale_filter_sel = 1;
+ else if (phase_step_y > HAL_MDP_PHASE_STEP_1P25)
+ yscale_filter_sel = 2;
+ else
+ yscale_filter_sel = 3;
+
+ /* calculate phase init for the x direction */
+
+ /* if using FIR scalar */
+ if (scale_unit_sel_x == 0) {
+ if (dst_ROI_width == 1)
+ phase_init_x =
+ (uint32) ((src_ROI_width - 1) << SCALER_PHASE_BITS);
+ else
+ phase_init_x = 0;
+
+ }
+ /* M over N scalar */
+ else if (scale_unit_sel_x == 1)
+ phase_init_x = 0;
+
+ /* calculate phase init for the y direction
+ if using FIR scalar */
+ if (scale_unit_sel_y == 0) {
+ if (dst_ROI_height == 1)
+ phase_init_y =
+ (uint32) ((src_ROI_height -
+ 1) << SCALER_PHASE_BITS);
+ else
+ phase_init_y = 0;
+
+ }
+ /* M over N scalar */
+ else if (scale_unit_sel_y == 1)
+ phase_init_y = 0;
+
+ /* write registers */
+ pval->phase_step_x = (uint32) phase_step_x;
+ pval->phase_step_y = (uint32) phase_step_y;
+ pval->phase_init_x = (uint32) phase_init_x;
+ pval->phase_init_y = (uint32) phase_init_y;
+
+ return;
+}
+
+void mdp_set_scale(MDPIBUF *iBuf,
+ uint32 dst_roi_width,
+ uint32 dst_roi_height,
+ boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr)
+{
+ uint32 dst_roi_width_scale;
+ uint32 dst_roi_height_scale;
+ struct phase_val pval;
+ boolean use_pr;
+ uint32 ppp_scale_config = 0;
+
+ if (!inputRGB)
+ ppp_scale_config |= BIT(6);
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) {
+ if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
+ dst_roi_width_scale = dst_roi_height;
+ dst_roi_height_scale = dst_roi_width;
+ } else {
+ dst_roi_width_scale = dst_roi_width;
+ dst_roi_height_scale = dst_roi_height;
+ }
+
+ if ((dst_roi_width_scale != iBuf->roi.width) ||
+ (dst_roi_height_scale != iBuf->roi.height) ||
+ (iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) {
+ *pppop_reg_ptr |=
+ (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
+
+ mdp_calc_scaleInitPhase_3p1(iBuf->roi.width,
+ iBuf->roi.height,
+ dst_roi_width,
+ dst_roi_height,
+ iBuf->mdpImg.
+ mdpOp & MDPOP_ROT90, 1, 1,
+ &pval);
+
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x013c,
+ pval.phase_init_x);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0140,
+ pval.phase_init_y);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0144,
+ pval.phase_step_x);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0148,
+ pval.phase_step_y);
+
+ /* disable the pixel repeat option for scaling */
+ use_pr = false;
+
+ /* x-direction */
+ if ((dst_roi_width_scale == iBuf->roi.width) &&
+ !(iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) {
+ *pppop_reg_ptr &= ~PPP_OP_SCALE_X_ON;
+ } else
+ if (((dst_roi_width_scale * 10) / iBuf->roi.width) >
+ 8) {
+ if ((use_pr)
+ && (mdp_scale_0p8_to_8p0_mode !=
+ MDP_SCALE_PR)) {
+ mdp_scale_0p8_to_8p0_mode =
+ MDP_SCALE_PR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P8_TO_8P0_INDEX,
+ mdp_scale_pixel_repeat_C0,
+ mdp_scale_pixel_repeat_C1,
+ mdp_scale_pixel_repeat_C2,
+ mdp_scale_pixel_repeat_C3);
+ } else if ((!use_pr)
+ && (mdp_scale_0p8_to_8p0_mode !=
+ MDP_SCALE_FIR)) {
+ mdp_scale_0p8_to_8p0_mode =
+ MDP_SCALE_FIR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P8_TO_8P0_INDEX,
+ mdp_scale_0p8_to_8p0_C0,
+ mdp_scale_0p8_to_8p0_C1,
+ mdp_scale_0p8_to_8p0_C2,
+ mdp_scale_0p8_to_8p0_C3);
+ }
+ ppp_scale_config |= (SCALE_U1_SET << 2);
+ } else
+ if (((dst_roi_width_scale * 10) / iBuf->roi.width) >
+ 6) {
+ if ((use_pr)
+ && (mdp_scale_0p6_to_0p8_mode !=
+ MDP_SCALE_PR)) {
+ mdp_scale_0p6_to_0p8_mode =
+ MDP_SCALE_PR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P6_TO_0P8_INDEX,
+ mdp_scale_pixel_repeat_C0,
+ mdp_scale_pixel_repeat_C1,
+ mdp_scale_pixel_repeat_C2,
+ mdp_scale_pixel_repeat_C3);
+ } else if ((!use_pr)
+ && (mdp_scale_0p6_to_0p8_mode !=
+ MDP_SCALE_FIR)) {
+ mdp_scale_0p6_to_0p8_mode =
+ MDP_SCALE_FIR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P6_TO_0P8_INDEX,
+ mdp_scale_0p6_to_0p8_C0,
+ mdp_scale_0p6_to_0p8_C1,
+ mdp_scale_0p6_to_0p8_C2,
+ mdp_scale_0p6_to_0p8_C3);
+ }
+ ppp_scale_config |= (SCALE_D2_SET << 2);
+ } else
+ if (((dst_roi_width_scale * 10) / iBuf->roi.width) >
+ 4) {
+ if ((use_pr)
+ && (mdp_scale_0p4_to_0p6_mode !=
+ MDP_SCALE_PR)) {
+ mdp_scale_0p4_to_0p6_mode =
+ MDP_SCALE_PR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P4_TO_0P6_INDEX,
+ mdp_scale_pixel_repeat_C0,
+ mdp_scale_pixel_repeat_C1,
+ mdp_scale_pixel_repeat_C2,
+ mdp_scale_pixel_repeat_C3);
+ } else if ((!use_pr)
+ && (mdp_scale_0p4_to_0p6_mode !=
+ MDP_SCALE_FIR)) {
+ mdp_scale_0p4_to_0p6_mode =
+ MDP_SCALE_FIR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P4_TO_0P6_INDEX,
+ mdp_scale_0p4_to_0p6_C0,
+ mdp_scale_0p4_to_0p6_C1,
+ mdp_scale_0p4_to_0p6_C2,
+ mdp_scale_0p4_to_0p6_C3);
+ }
+ ppp_scale_config |= (SCALE_D1_SET << 2);
+ } else
+ if ((dst_roi_width_scale == 1 && iBuf->roi.width < 4) ||
+ (iBuf->roi.width < 4 * dst_roi_width_scale - 3)) {
+ if ((use_pr)
+ && (mdp_scale_0p2_to_0p4_mode !=
+ MDP_SCALE_PR)) {
+ mdp_scale_0p2_to_0p4_mode =
+ MDP_SCALE_PR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P2_TO_0P4_INDEX,
+ mdp_scale_pixel_repeat_C0,
+ mdp_scale_pixel_repeat_C1,
+ mdp_scale_pixel_repeat_C2,
+ mdp_scale_pixel_repeat_C3);
+ } else if ((!use_pr)
+ && (mdp_scale_0p2_to_0p4_mode !=
+ MDP_SCALE_FIR)) {
+ mdp_scale_0p2_to_0p4_mode =
+ MDP_SCALE_FIR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P2_TO_0P4_INDEX,
+ mdp_scale_0p2_to_0p4_C0,
+ mdp_scale_0p2_to_0p4_C1,
+ mdp_scale_0p2_to_0p4_C2,
+ mdp_scale_0p2_to_0p4_C3);
+ }
+ ppp_scale_config |= (SCALE_D0_SET << 2);
+ } else
+ ppp_scale_config |= BIT(0);
+
+ /* y-direction */
+ if ((dst_roi_height_scale == iBuf->roi.height) &&
+ !(iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) {
+ *pppop_reg_ptr &= ~PPP_OP_SCALE_Y_ON;
+ } else if (((dst_roi_height_scale * 10) /
+ iBuf->roi.height) > 8) {
+ if ((use_pr)
+ && (mdp_scale_0p8_to_8p0_mode !=
+ MDP_SCALE_PR)) {
+ mdp_scale_0p8_to_8p0_mode =
+ MDP_SCALE_PR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P8_TO_8P0_INDEX,
+ mdp_scale_pixel_repeat_C0,
+ mdp_scale_pixel_repeat_C1,
+ mdp_scale_pixel_repeat_C2,
+ mdp_scale_pixel_repeat_C3);
+ } else if ((!use_pr)
+ && (mdp_scale_0p8_to_8p0_mode !=
+ MDP_SCALE_FIR)) {
+ mdp_scale_0p8_to_8p0_mode =
+ MDP_SCALE_FIR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P8_TO_8P0_INDEX,
+ mdp_scale_0p8_to_8p0_C0,
+ mdp_scale_0p8_to_8p0_C1,
+ mdp_scale_0p8_to_8p0_C2,
+ mdp_scale_0p8_to_8p0_C3);
+ }
+ ppp_scale_config |= (SCALE_U1_SET << 4);
+ } else
+ if (((dst_roi_height_scale * 10) /
+ iBuf->roi.height) > 6) {
+ if ((use_pr)
+ && (mdp_scale_0p6_to_0p8_mode !=
+ MDP_SCALE_PR)) {
+ mdp_scale_0p6_to_0p8_mode =
+ MDP_SCALE_PR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P6_TO_0P8_INDEX,
+ mdp_scale_pixel_repeat_C0,
+ mdp_scale_pixel_repeat_C1,
+ mdp_scale_pixel_repeat_C2,
+ mdp_scale_pixel_repeat_C3);
+ } else if ((!use_pr)
+ && (mdp_scale_0p6_to_0p8_mode !=
+ MDP_SCALE_FIR)) {
+ mdp_scale_0p6_to_0p8_mode =
+ MDP_SCALE_FIR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P6_TO_0P8_INDEX,
+ mdp_scale_0p6_to_0p8_C0,
+ mdp_scale_0p6_to_0p8_C1,
+ mdp_scale_0p6_to_0p8_C2,
+ mdp_scale_0p6_to_0p8_C3);
+ }
+ ppp_scale_config |= (SCALE_D2_SET << 4);
+ } else
+ if (((dst_roi_height_scale * 10) /
+ iBuf->roi.height) > 4) {
+ if ((use_pr)
+ && (mdp_scale_0p4_to_0p6_mode !=
+ MDP_SCALE_PR)) {
+ mdp_scale_0p4_to_0p6_mode =
+ MDP_SCALE_PR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P4_TO_0P6_INDEX,
+ mdp_scale_pixel_repeat_C0,
+ mdp_scale_pixel_repeat_C1,
+ mdp_scale_pixel_repeat_C2,
+ mdp_scale_pixel_repeat_C3);
+ } else if ((!use_pr)
+ && (mdp_scale_0p4_to_0p6_mode !=
+ MDP_SCALE_FIR)) {
+ mdp_scale_0p4_to_0p6_mode =
+ MDP_SCALE_FIR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P4_TO_0P6_INDEX,
+ mdp_scale_0p4_to_0p6_C0,
+ mdp_scale_0p4_to_0p6_C1,
+ mdp_scale_0p4_to_0p6_C2,
+ mdp_scale_0p4_to_0p6_C3);
+ }
+ ppp_scale_config |= (SCALE_D1_SET << 4);
+ } else if ((dst_roi_height_scale == 1 &&
+ iBuf->roi.height < 4) ||
+ (iBuf->roi.height < 4 * dst_roi_height_scale - 3)) {
+ if ((use_pr)
+ && (mdp_scale_0p2_to_0p4_mode !=
+ MDP_SCALE_PR)) {
+ mdp_scale_0p2_to_0p4_mode =
+ MDP_SCALE_PR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P2_TO_0P4_INDEX,
+ mdp_scale_pixel_repeat_C0,
+ mdp_scale_pixel_repeat_C1,
+ mdp_scale_pixel_repeat_C2,
+ mdp_scale_pixel_repeat_C3);
+ } else if ((!use_pr)
+ && (mdp_scale_0p2_to_0p4_mode !=
+ MDP_SCALE_FIR)) {
+ mdp_scale_0p2_to_0p4_mode =
+ MDP_SCALE_FIR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P2_TO_0P4_INDEX,
+ mdp_scale_0p2_to_0p4_C0,
+ mdp_scale_0p2_to_0p4_C1,
+ mdp_scale_0p2_to_0p4_C2,
+ mdp_scale_0p2_to_0p4_C3);
+ }
+ ppp_scale_config |= (SCALE_D0_SET << 4);
+ } else
+ ppp_scale_config |= BIT(1);
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_SHARPENING) {
+ ppp_scale_config |= BIT(7);
+ MDP_OUTP(MDP_BASE + 0x50020,
+ iBuf->mdpImg.sp_value);
+ }
+
+ MDP_OUTP(MDP_BASE + 0x10230, ppp_scale_config);
+ } else {
+ iBuf->mdpImg.mdpOp &= ~(MDPOP_ASCALE);
+ }
+ }
+}
+
+void mdp_adjust_start_addr(uint8 **src0,
+ uint8 **src1,
+ int v_slice,
+ int h_slice,
+ int x,
+ int y,
+ uint32 width,
+ uint32 height, int bpp, MDPIBUF *iBuf, int layer)
+{
+ switch (layer) {
+ case 0:
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0200, (y << 16) | (x));
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0208,
+ (height << 16) | (width));
+ break;
+
+ case 1:
+ /* MDP 3.1 HW bug workaround */
+ if (iBuf->ibuf_type == MDP_YCRYCB_H2V1) {
+ *src0 += (x + y * width) * bpp;
+ x = y = 0;
+ width = iBuf->roi.dst_width;
+ height = iBuf->roi.dst_height;
+ }
+
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0204, (y << 16) | (x));
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x020c,
+ (height << 16) | (width));
+ break;
+
+ case 2:
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x019c, (y << 16) | (x));
+ break;
+ }
+}
+
+void mdp_set_blend_attr(MDPIBUF *iBuf,
+ uint32 *alpha,
+ uint32 *tpVal,
+ uint32 perPixelAlpha, uint32 *pppop_reg_ptr)
+{
+ int bg_alpha;
+
+ *alpha = iBuf->mdpImg.alpha;
+ *tpVal = iBuf->mdpImg.tpVal;
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_FG_PM_ALPHA) {
+ if (perPixelAlpha) {
+ *pppop_reg_ptr |= PPP_OP_ROT_ON |
+ PPP_OP_BLEND_ON | PPP_OP_BLEND_CONSTANT_ALPHA;
+ }
+ else {
+ if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+ && (iBuf->mdpImg.alpha == 0xff)) {
+ iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB);
+ }
+
+ if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+ || (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
+ *pppop_reg_ptr |=
+ PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
+ PPP_OP_BLEND_CONSTANT_ALPHA |
+ PPP_OP_BLEND_ALPHA_BLEND_NORMAL;
+ }
+ }
+
+ bg_alpha = PPP_BLEND_BG_USE_ALPHA_SEL |
+ PPP_BLEND_BG_ALPHA_REVERSE;
+
+ if (perPixelAlpha)
+ bg_alpha |= PPP_BLEND_BG_SRCPIXEL_ALPHA;
+ else {
+ bg_alpha |= PPP_BLEND_BG_CONSTANT_ALPHA;
+ bg_alpha |= iBuf->mdpImg.alpha << 24;
+ }
+ outpdw(MDP_BASE + 0x70010, bg_alpha);
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)
+ *pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP;
+ } else if (perPixelAlpha) {
+ *pppop_reg_ptr |= PPP_OP_ROT_ON |
+ PPP_OP_BLEND_ON | PPP_OP_BLEND_SRCPIXEL_ALPHA;
+ } else {
+ if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+ && (iBuf->mdpImg.alpha == 0xff)) {
+ iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB);
+ }
+
+ if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+ || (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
+ *pppop_reg_ptr |=
+ PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
+ PPP_OP_BLEND_CONSTANT_ALPHA |
+ PPP_OP_BLEND_ALPHA_BLEND_NORMAL;
+ }
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)
+ *pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP;
+ }
+}
diff --git a/drivers/video/msm/mdp_vsync.c b/drivers/video/msm/mdp_vsync.c
new file mode 100644
index 0000000..4108c89
--- /dev/null
+++ b/drivers/video/msm/mdp_vsync.c
@@ -0,0 +1,488 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/vmalloc.h>
+#include <linux/clk.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <mach/gpio.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mddihost.h"
+
+#ifdef CONFIG_FB_MSM_MDP40
+#include "mdp4.h"
+
+#define MDP_SYNC_CFG_0 0x100
+#define MDP_SYNC_STATUS_0 0x10c
+#define MDP_SYNC_CFG_1 0x104
+#define MDP_SYNC_STATUS_1 0x110
+#define MDP_PRIM_VSYNC_OUT_CTRL 0x118
+#define MDP_SEC_VSYNC_OUT_CTRL 0x11C
+#define MDP_VSYNC_SEL 0x124
+#define MDP_PRIM_VSYNC_INIT_VAL 0x128
+#define MDP_SEC_VSYNC_INIT_VAL 0x12C
+#else
+#define MDP_SYNC_CFG_0 0x300
+#define MDP_SYNC_STATUS_0 0x30c
+#define MDP_PRIM_VSYNC_OUT_CTRL 0x318
+#define MDP_PRIM_VSYNC_INIT_VAL 0x328
+#endif
+
+extern mddi_lcd_type mddi_lcd_idx;
+extern spinlock_t mdp_spin_lock;
+extern struct workqueue_struct *mdp_vsync_wq;
+extern int lcdc_mode;
+extern int vsync_mode;
+
+#ifdef MDP_HW_VSYNC
+int vsync_above_th = 4;
+int vsync_start_th = 1;
+int vsync_load_cnt;
+int vsync_clk_status;
+DEFINE_MUTEX(vsync_clk_lock);
+DEFINE_MUTEX(vsync_timer_lock);
+
+static struct clk *mdp_vsync_clk;
+static struct msm_fb_data_type *vsync_mfd;
+static unsigned char timer_shutdown_flag;
+
+void mdp_hw_vsync_clk_enable(struct msm_fb_data_type *mfd)
+{
+ if (vsync_clk_status == 1)
+ return;
+ mutex_lock(&vsync_clk_lock);
+ if (mfd->use_mdp_vsync) {
+ clk_enable(mdp_vsync_clk);
+ vsync_clk_status = 1;
+ }
+ mutex_unlock(&vsync_clk_lock);
+}
+
+void mdp_hw_vsync_clk_disable(struct msm_fb_data_type *mfd)
+{
+ if (vsync_clk_status == 0)
+ return;
+ mutex_lock(&vsync_clk_lock);
+ if (mfd->use_mdp_vsync) {
+ clk_disable(mdp_vsync_clk);
+ vsync_clk_status = 0;
+ }
+ mutex_unlock(&vsync_clk_lock);
+}
+
+static void mdp_set_vsync(unsigned long data);
+void mdp_vsync_clk_enable(void)
+{
+ if (vsync_mfd) {
+ mdp_hw_vsync_clk_enable(vsync_mfd);
+ if (!vsync_mfd->vsync_resync_timer.function) {
+ mdp_set_vsync((unsigned long) vsync_mfd);
+ }
+ }
+}
+
+void mdp_vsync_clk_disable(void)
+{
+ if (vsync_mfd) {
+ if (vsync_mfd->vsync_resync_timer.function) {
+ mutex_lock(&vsync_timer_lock);
+ timer_shutdown_flag = 1;
+ mutex_unlock(&vsync_timer_lock);
+ del_timer_sync(&vsync_mfd->vsync_resync_timer);
+ mutex_lock(&vsync_timer_lock);
+ timer_shutdown_flag = 0;
+ mutex_unlock(&vsync_timer_lock);
+ vsync_mfd->vsync_resync_timer.function = NULL;
+ }
+
+ mdp_hw_vsync_clk_disable(vsync_mfd);
+ }
+}
+#endif
+
+static void mdp_set_vsync(unsigned long data)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
+ struct msm_fb_panel_data *pdata = NULL;
+
+ pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+
+ vsync_mfd = mfd;
+ init_timer(&mfd->vsync_resync_timer);
+
+ if ((pdata) && (pdata->set_vsync_notifier == NULL))
+ return;
+
+ if ((mfd->panel_info.lcd.vsync_enable) && (mfd->panel_power_on)
+ && (!mfd->vsync_handler_pending)) {
+ mfd->vsync_handler_pending = TRUE;
+ if (!queue_work(mdp_vsync_wq, &mfd->vsync_resync_worker)) {
+ MSM_FB_INFO
+ ("mdp_set_vsync: can't queue_work! -> needs to increase vsync_resync_timer_duration\n");
+ }
+ } else {
+ MSM_FB_DEBUG
+ ("mdp_set_vsync failed! EN:%d PWR:%d PENDING:%d\n",
+ mfd->panel_info.lcd.vsync_enable, mfd->panel_power_on,
+ mfd->vsync_handler_pending);
+ }
+
+ mutex_lock(&vsync_timer_lock);
+ if (!timer_shutdown_flag) {
+ mfd->vsync_resync_timer.function = mdp_set_vsync;
+ mfd->vsync_resync_timer.data = data;
+ mfd->vsync_resync_timer.expires =
+ jiffies + mfd->panel_info.lcd.vsync_notifier_period;
+ add_timer(&mfd->vsync_resync_timer);
+ }
+ mutex_unlock(&vsync_timer_lock);
+}
+
+static void mdp_vsync_handler(void *data)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
+
+ if (vsync_clk_status == 0) {
+ pr_debug("Warning: vsync clk is disabled\n");
+ mfd->vsync_handler_pending = FALSE;
+ return;
+ }
+
+ if (mfd->use_mdp_vsync) {
+#ifdef MDP_HW_VSYNC
+ if (mfd->panel_power_on) {
+ MDP_OUTP(MDP_BASE + MDP_SYNC_STATUS_0, vsync_load_cnt);
+
+#ifdef CONFIG_FB_MSM_MDP40
+ if (mdp_hw_revision < MDP4_REVISION_V2_1)
+ MDP_OUTP(MDP_BASE + MDP_SYNC_STATUS_1,
+ vsync_load_cnt);
+#endif
+ }
+
+#endif
+ } else {
+ mfd->last_vsync_timetick = ktime_get_real();
+ }
+
+ mfd->vsync_handler_pending = FALSE;
+}
+
+irqreturn_t mdp_hw_vsync_handler_proxy(int irq, void *data)
+{
+ /*
+ * ToDo: tried enabling/disabling GPIO MDP HW VSYNC interrupt
+ * but getting inaccurate timing in mdp_vsync_handler()
+ * disable_irq(MDP_HW_VSYNC_IRQ);
+ */
+ mdp_vsync_handler(data);
+
+ return IRQ_HANDLED;
+}
+
+#ifdef MDP_HW_VSYNC
+static void mdp_set_sync_cfg_0(struct msm_fb_data_type *mfd, int vsync_cnt)
+{
+ unsigned long cfg;
+
+ cfg = mfd->total_lcd_lines - 1;
+ cfg <<= MDP_SYNCFG_HGT_LOC;
+ if (mfd->panel_info.lcd.hw_vsync_mode)
+ cfg |= MDP_SYNCFG_VSYNC_EXT_EN;
+ cfg |= (MDP_SYNCFG_VSYNC_INT_EN | vsync_cnt);
+
+ MDP_OUTP(MDP_BASE + MDP_SYNC_CFG_0, cfg);
+}
+
+#ifdef CONFIG_FB_MSM_MDP40
+static void mdp_set_sync_cfg_1(struct msm_fb_data_type *mfd, int vsync_cnt)
+{
+ unsigned long cfg;
+
+ cfg = mfd->total_lcd_lines - 1;
+ cfg <<= MDP_SYNCFG_HGT_LOC;
+ if (mfd->panel_info.lcd.hw_vsync_mode)
+ cfg |= MDP_SYNCFG_VSYNC_EXT_EN;
+ cfg |= (MDP_SYNCFG_VSYNC_INT_EN | vsync_cnt);
+
+ MDP_OUTP(MDP_BASE + MDP_SYNC_CFG_1, cfg);
+}
+#endif
+#endif
+
+void mdp_config_vsync(struct msm_fb_data_type *mfd)
+{
+ /* vsync on primary lcd only for now */
+ if ((mfd->dest != DISPLAY_LCD) || (mfd->panel_info.pdest != DISPLAY_1)
+ || (!vsync_mode)) {
+ goto err_handle;
+ }
+
+ vsync_clk_status = 0;
+ if (mfd->panel_info.lcd.vsync_enable) {
+ mfd->total_porch_lines = mfd->panel_info.lcd.v_back_porch +
+ mfd->panel_info.lcd.v_front_porch +
+ mfd->panel_info.lcd.v_pulse_width;
+ mfd->total_lcd_lines =
+ mfd->panel_info.yres + mfd->total_porch_lines;
+ mfd->lcd_ref_usec_time =
+ 100000000 / mfd->panel_info.lcd.refx100;
+ mfd->vsync_handler_pending = FALSE;
+
+ mfd->last_vsync_timetick.tv64 = 0;
+
+#ifdef MDP_HW_VSYNC
+ if (mdp_vsync_clk == NULL)
+ mdp_vsync_clk = clk_get(NULL, "mdp_vsync_clk");
+
+ if (IS_ERR(mdp_vsync_clk)) {
+ printk(KERN_ERR "error: can't get mdp_vsync_clk!\n");
+ mfd->use_mdp_vsync = 0;
+ } else
+ mfd->use_mdp_vsync = 1;
+
+ if (mfd->use_mdp_vsync) {
+ uint32 vsync_cnt_cfg, vsync_cnt_cfg_dem;
+ uint32 mdp_vsync_clk_speed_hz;
+
+ mdp_vsync_clk_speed_hz = clk_get_rate(mdp_vsync_clk);
+
+ if (mdp_vsync_clk_speed_hz == 0) {
+ mfd->use_mdp_vsync = 0;
+ } else {
+ /*
+ * Do this calculation in 2 steps for
+ * rounding uint32 properly.
+ */
+ vsync_cnt_cfg_dem =
+ (mfd->panel_info.lcd.refx100 *
+ mfd->total_lcd_lines) / 100;
+ vsync_cnt_cfg =
+ (mdp_vsync_clk_speed_hz) /
+ vsync_cnt_cfg_dem;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON,
+ FALSE);
+ mdp_hw_vsync_clk_enable(mfd);
+
+ mdp_set_sync_cfg_0(mfd, vsync_cnt_cfg);
+
+
+#ifdef CONFIG_FB_MSM_MDP40
+ if (mdp_hw_revision < MDP4_REVISION_V2_1)
+ mdp_set_sync_cfg_1(mfd, vsync_cnt_cfg);
+#endif
+
+ /*
+ * load the last line + 1 to be in the
+ * safety zone
+ */
+ vsync_load_cnt = mfd->panel_info.yres;
+
+ /* line counter init value at the next pulse */
+ MDP_OUTP(MDP_BASE + MDP_PRIM_VSYNC_INIT_VAL,
+ vsync_load_cnt);
+#ifdef CONFIG_FB_MSM_MDP40
+ if (mdp_hw_revision < MDP4_REVISION_V2_1) {
+ MDP_OUTP(MDP_BASE +
+ MDP_SEC_VSYNC_INIT_VAL, vsync_load_cnt);
+ }
+#endif
+
+ /*
+ * external vsync source pulse width and
+ * polarity flip
+ */
+ MDP_OUTP(MDP_BASE + MDP_PRIM_VSYNC_OUT_CTRL,
+ BIT(0));
+#ifdef CONFIG_FB_MSM_MDP40
+ if (mdp_hw_revision < MDP4_REVISION_V2_1) {
+ MDP_OUTP(MDP_BASE +
+ MDP_SEC_VSYNC_OUT_CTRL, BIT(0));
+ MDP_OUTP(MDP_BASE +
+ MDP_VSYNC_SEL, 0x20);
+ }
+#endif
+
+ /* threshold */
+ MDP_OUTP(MDP_BASE + 0x200,
+ (vsync_above_th << 16) |
+ (vsync_start_th));
+
+ mdp_hw_vsync_clk_disable(mfd);
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK,
+ MDP_BLOCK_POWER_OFF, FALSE);
+ }
+ }
+#else
+ mfd->use_mdp_vsync = 0;
+ hrtimer_init(&mfd->dma_hrtimer, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL);
+ mfd->dma_hrtimer.function = mdp_dma2_vsync_hrtimer_handler;
+ mfd->vsync_width_boundary = vmalloc(mfd->panel_info.xres * 4);
+#endif
+
+#ifdef CONFIG_FB_MSM_MDDI
+ mfd->channel_irq = 0;
+ if (mfd->panel_info.lcd.hw_vsync_mode) {
+ u32 vsync_gpio = mfd->vsync_gpio;
+ u32 ret;
+
+ if (vsync_gpio == -1) {
+ MSM_FB_INFO("vsync_gpio not defined!\n");
+ goto err_handle;
+ }
+
+ ret = gpio_tlmm_config(GPIO_CFG
+ (vsync_gpio,
+ (mfd->use_mdp_vsync) ? 1 : 0,
+ GPIO_CFG_INPUT,
+ GPIO_CFG_PULL_DOWN,
+ GPIO_CFG_2MA),
+ GPIO_CFG_ENABLE);
+ if (ret)
+ goto err_handle;
+
+ /*
+ * if use_mdp_vsync, then no interrupt need since
+ * mdp_vsync is feed directly to mdp to reset the
+ * write pointer counter. therefore no irq_handler
+ * need to reset write pointer counter.
+ */
+ if (!mfd->use_mdp_vsync) {
+ mfd->channel_irq = MSM_GPIO_TO_INT(vsync_gpio);
+ if (request_irq
+ (mfd->channel_irq,
+ &mdp_hw_vsync_handler_proxy,
+ IRQF_TRIGGER_FALLING, "VSYNC_GPIO",
+ (void *)mfd)) {
+ MSM_FB_INFO
+ ("irq=%d failed! vsync_gpio=%d\n",
+ mfd->channel_irq,
+ vsync_gpio);
+ goto err_handle;
+ }
+ }
+ }
+#endif
+ mdp_hw_vsync_clk_enable(mfd);
+ mdp_set_vsync((unsigned long)mfd);
+ }
+
+ return;
+
+err_handle:
+ if (mfd->vsync_width_boundary)
+ vfree(mfd->vsync_width_boundary);
+ mfd->panel_info.lcd.vsync_enable = FALSE;
+ printk(KERN_ERR "%s: failed!\n", __func__);
+}
+
+void mdp_vsync_resync_workqueue_handler(struct work_struct *work)
+{
+ struct msm_fb_data_type *mfd = NULL;
+ int vsync_fnc_enabled = FALSE;
+ struct msm_fb_panel_data *pdata = NULL;
+
+ mfd = container_of(work, struct msm_fb_data_type, vsync_resync_worker);
+
+ if (mfd) {
+ if (mfd->panel_power_on) {
+ pdata =
+ (struct msm_fb_panel_data *)mfd->pdev->dev.
+ platform_data;
+
+ if (pdata->set_vsync_notifier != NULL) {
+ if (pdata->clk_func && !pdata->clk_func(2)) {
+ mfd->vsync_handler_pending = FALSE;
+ return;
+ }
+
+ pdata->set_vsync_notifier(
+ mdp_vsync_handler,
+ (void *)mfd);
+ vsync_fnc_enabled = TRUE;
+ }
+ }
+ }
+
+ if ((mfd) && (!vsync_fnc_enabled))
+ mfd->vsync_handler_pending = FALSE;
+}
+
+boolean mdp_hw_vsync_set_handler(msm_fb_vsync_handler_type handler, void *data)
+{
+ /*
+ * ToDo: tried enabling/disabling GPIO MDP HW VSYNC interrupt
+ * but getting inaccurate timing in mdp_vsync_handler()
+ * enable_irq(MDP_HW_VSYNC_IRQ);
+ */
+
+ return TRUE;
+}
+
+uint32 mdp_get_lcd_line_counter(struct msm_fb_data_type *mfd)
+{
+ uint32 elapsed_usec_time;
+ uint32 lcd_line;
+ ktime_t last_vsync_timetick_local;
+ ktime_t curr_time;
+ unsigned long flag;
+
+ if ((!mfd->panel_info.lcd.vsync_enable) || (!vsync_mode))
+ return 0;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ last_vsync_timetick_local = mfd->last_vsync_timetick;
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+ curr_time = ktime_get_real();
+ elapsed_usec_time = ktime_to_us(ktime_sub(curr_time,
+ last_vsync_timetick_local));
+
+ elapsed_usec_time = elapsed_usec_time % mfd->lcd_ref_usec_time;
+
+ /* lcd line calculation referencing to line counter = 0 */
+ lcd_line =
+ (elapsed_usec_time * mfd->total_lcd_lines) / mfd->lcd_ref_usec_time;
+
+ /* lcd line adjusment referencing to the actual line counter at vsync */
+ lcd_line =
+ (mfd->total_lcd_lines - mfd->panel_info.lcd.v_back_porch +
+ lcd_line) % (mfd->total_lcd_lines + 1);
+
+ if (lcd_line > mfd->total_lcd_lines) {
+ MSM_FB_INFO
+ ("mdp_get_lcd_line_counter: mdp_lcd_rd_cnt >= mfd->total_lcd_lines error!\n");
+ }
+
+ return lcd_line;
+}
diff --git a/drivers/video/msm/mipi_dsi.c b/drivers/video/msm/mipi_dsi.c
new file mode 100644
index 0000000..61bb345
--- /dev/null
+++ b/drivers/video/msm/mipi_dsi.c
@@ -0,0 +1,548 @@
+/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/clk.h>
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mdp.h"
+#include "mdp4.h"
+
+u32 dsi_irq;
+
+static int mipi_dsi_probe(struct platform_device *pdev);
+static int mipi_dsi_remove(struct platform_device *pdev);
+
+static int mipi_dsi_off(struct platform_device *pdev);
+static int mipi_dsi_on(struct platform_device *pdev);
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+static struct mipi_dsi_platform_data *mipi_dsi_pdata;
+
+static int vsync_gpio = -1;
+
+static struct platform_driver mipi_dsi_driver = {
+ .probe = mipi_dsi_probe,
+ .remove = mipi_dsi_remove,
+ .shutdown = NULL,
+ .driver = {
+ .name = "mipi_dsi",
+ },
+};
+
+struct device dsi_dev;
+
+static int mipi_dsi_off(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct msm_fb_data_type *mfd;
+ struct msm_panel_info *pinfo;
+
+ mfd = platform_get_drvdata(pdev);
+ pinfo = &mfd->panel_info;
+
+ if (mdp_rev >= MDP_REV_41)
+ mutex_lock(&mfd->dma->ov_mutex);
+ else
+ down(&mfd->dma->mutex);
+
+ mdp4_overlay_dsi_state_set(ST_DSI_SUSPEND);
+
+ /*
+ * Description: dsi clock is need to perform shutdown.
+ * mdp4_dsi_cmd_dma_busy_wait() will enable dsi clock if disabled.
+ * also, wait until dma (overlay and dmap) finish.
+ */
+ if (mfd->panel_info.type == MIPI_CMD_PANEL) {
+ if (mdp_rev >= MDP_REV_41) {
+ mdp4_dsi_cmd_dma_busy_wait(mfd);
+ mdp4_dsi_blt_dmap_busy_wait(mfd);
+ } else {
+ mdp3_dsi_cmd_dma_busy_wait(mfd);
+ }
+ }
+
+ /*
+ * Desctiption: change to DSI_CMD_MODE since it needed to
+ * tx DCS dsiplay off comamnd to panel
+ */
+ mipi_dsi_op_mode_config(DSI_CMD_MODE);
+
+ if (mfd->panel_info.type == MIPI_CMD_PANEL) {
+ if (pinfo->lcd.vsync_enable) {
+ if (pinfo->lcd.hw_vsync_mode && vsync_gpio > 0)
+ gpio_free(vsync_gpio);
+
+ mipi_dsi_set_tear_off(mfd);
+ }
+ }
+
+ ret = panel_next_off(pdev);
+
+#ifdef CONFIG_MSM_BUS_SCALING
+ mdp_bus_scale_update_request(0);
+#endif
+ /* disbale dsi engine */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0000, 0);
+
+ mipi_dsi_phy_ctrl(0);
+
+ local_bh_disable();
+ mipi_dsi_clk_disable();
+ local_bh_enable();
+
+ if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save)
+ mipi_dsi_pdata->dsi_power_save(0);
+
+ if (mdp_rev >= MDP_REV_41)
+ mutex_unlock(&mfd->dma->ov_mutex);
+ else
+ up(&mfd->dma->mutex);
+
+ pr_debug("%s:\n", __func__);
+
+ return ret;
+}
+
+static int mipi_dsi_on(struct platform_device *pdev)
+{
+ int ret = 0;
+ u32 clk_rate;
+ struct msm_fb_data_type *mfd;
+ struct fb_info *fbi;
+ struct fb_var_screeninfo *var;
+ struct msm_panel_info *pinfo;
+ struct mipi_panel_info *mipi;
+ u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
+ u32 ystride, bpp, data;
+ u32 dummy_xres, dummy_yres;
+ int target_type = 0;
+
+ mfd = platform_get_drvdata(pdev);
+ fbi = mfd->fbi;
+ var = &fbi->var;
+ pinfo = &mfd->panel_info;
+
+ if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save)
+ mipi_dsi_pdata->dsi_power_save(1);
+
+ clk_rate = mfd->fbi->var.pixclock;
+ clk_rate = min(clk_rate, mfd->panel_info.clk_max);
+
+ local_bh_disable();
+ mipi_dsi_clk_enable();
+ local_bh_enable();
+
+#ifndef CONFIG_FB_MSM_MDP303
+ mdp4_overlay_dsi_state_set(ST_DSI_RESUME);
+#endif
+
+ MIPI_OUTP(MIPI_DSI_BASE + 0x114, 1);
+ MIPI_OUTP(MIPI_DSI_BASE + 0x114, 0);
+
+ hbp = var->left_margin;
+ hfp = var->right_margin;
+ vbp = var->upper_margin;
+ vfp = var->lower_margin;
+ hspw = var->hsync_len;
+ vspw = var->vsync_len;
+ width = mfd->panel_info.xres;
+ height = mfd->panel_info.yres;
+
+ mipi_dsi_phy_ctrl(1);
+
+ if (mdp_rev == MDP_REV_42 && mipi_dsi_pdata)
+ target_type = mipi_dsi_pdata->target_type;
+
+ mipi_dsi_phy_init(0, &(mfd->panel_info), target_type);
+
+ mipi = &mfd->panel_info.mipi;
+ if (mfd->panel_info.type == MIPI_VIDEO_PANEL) {
+ dummy_xres = mfd->panel_info.mipi.xres_pad;
+ dummy_yres = mfd->panel_info.mipi.yres_pad;
+
+ if (mdp_rev >= MDP_REV_41) {
+ MIPI_OUTP(MIPI_DSI_BASE + 0x20,
+ ((hspw + hbp + width + dummy_xres) << 16 |
+ (hspw + hbp)));
+ MIPI_OUTP(MIPI_DSI_BASE + 0x24,
+ ((vspw + vbp + height + dummy_yres) << 16 |
+ (vspw + vbp)));
+ MIPI_OUTP(MIPI_DSI_BASE + 0x28,
+ (vspw + vbp + height + dummy_yres +
+ vfp - 1) << 16 | (hspw + hbp +
+ width + dummy_xres + hfp - 1));
+ } else {
+ /* DSI_LAN_SWAP_CTRL */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x00ac, mipi->dlane_swap);
+
+ MIPI_OUTP(MIPI_DSI_BASE + 0x20,
+ ((hbp + width + dummy_xres) << 16 | (hbp)));
+ MIPI_OUTP(MIPI_DSI_BASE + 0x24,
+ ((vbp + height + dummy_yres) << 16 | (vbp)));
+ MIPI_OUTP(MIPI_DSI_BASE + 0x28,
+ (vbp + height + dummy_yres + vfp) << 16 |
+ (hbp + width + dummy_xres + hfp));
+ }
+
+ MIPI_OUTP(MIPI_DSI_BASE + 0x2c, (hspw << 16));
+ MIPI_OUTP(MIPI_DSI_BASE + 0x30, 0);
+ MIPI_OUTP(MIPI_DSI_BASE + 0x34, (vspw << 16));
+
+ } else { /* command mode */
+ if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
+ bpp = 3;
+ else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB666)
+ bpp = 3;
+ else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565)
+ bpp = 2;
+ else
+ bpp = 3; /* Default format set to RGB888 */
+
+ ystride = width * bpp + 1;
+
+ /* DSI_COMMAND_MODE_MDP_STREAM_CTRL */
+ data = (ystride << 16) | (mipi->vc << 8) | DTYPE_DCS_LWRITE;
+ MIPI_OUTP(MIPI_DSI_BASE + 0x5c, data);
+ MIPI_OUTP(MIPI_DSI_BASE + 0x54, data);
+
+ /* DSI_COMMAND_MODE_MDP_STREAM_TOTAL */
+ data = height << 16 | width;
+ MIPI_OUTP(MIPI_DSI_BASE + 0x60, data);
+ MIPI_OUTP(MIPI_DSI_BASE + 0x58, data);
+ }
+
+ mipi_dsi_host_init(mipi);
+ mipi_dsi_cmd_bta_sw_trigger(); /* clean up ack_err_status */
+
+ ret = panel_next_on(pdev);
+
+ mipi_dsi_op_mode_config(mipi->mode);
+
+ if (mfd->panel_info.type == MIPI_CMD_PANEL) {
+ if (pinfo->lcd.vsync_enable) {
+ if (pinfo->lcd.hw_vsync_mode && vsync_gpio > 0) {
+ if (gpio_request(vsync_gpio, "MDP_VSYNC") == 0)
+ gpio_direction_input(vsync_gpio);
+ else
+ pr_err("%s: unable to request gpio=%d\n",
+ __func__, vsync_gpio);
+ }
+ mipi_dsi_set_tear_on(mfd);
+ }
+ }
+
+#ifdef CONFIG_MSM_BUS_SCALING
+ mdp_bus_scale_update_request(2);
+#endif
+ return ret;
+}
+
+
+static int mipi_dsi_resource_initialized;
+
+static int mipi_dsi_probe(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct fb_info *fbi;
+ struct msm_panel_info *pinfo;
+ struct mipi_panel_info *mipi;
+ struct platform_device *mdp_dev = NULL;
+ struct msm_fb_panel_data *pdata = NULL;
+ int rc;
+ uint8 lanes = 0, bpp;
+ uint32 h_period, v_period, dsi_pclk_rate;
+
+ resource_size_t size ;
+
+ if ((pdev->id == 1) && (pdev->num_resources >= 0)) {
+ mipi_dsi_pdata = pdev->dev.platform_data;
+
+ size = resource_size(&pdev->resource[0]);
+ mipi_dsi_base = ioremap(pdev->resource[0].start, size);
+
+ MSM_FB_INFO("mipi_dsi base phy_addr = 0x%x virt = 0x%x\n",
+ pdev->resource[0].start, (int) mipi_dsi_base);
+
+ if (!mipi_dsi_base)
+ return -ENOMEM;
+
+ if (mdp_rev >= MDP_REV_41) {
+ mmss_sfpb_base = ioremap(MMSS_SFPB_BASE_PHY, 0x100);
+ MSM_FB_INFO("mmss_sfpb base phy_addr = 0x%x,"
+ "virt = 0x%x\n", MMSS_SFPB_BASE_PHY,
+ (int) mmss_sfpb_base);
+
+ if (!mmss_sfpb_base)
+ return -ENOMEM;
+ }
+
+ dsi_irq = platform_get_irq(pdev, 0);
+ if (dsi_irq < 0) {
+ pr_err("mipi_dsi: can not get mdp irq\n");
+ return -ENOMEM;
+ }
+
+ rc = request_irq(dsi_irq, mipi_dsi_isr, IRQF_DISABLED,
+ "MIPI_DSI", 0);
+ if (rc) {
+ pr_err("mipi_dsi_host request_irq() failed!\n");
+ return rc;
+ }
+
+ disable_irq(dsi_irq);
+
+ if (mdp_rev == MDP_REV_42 && mipi_dsi_pdata &&
+ mipi_dsi_pdata->target_type == 1) {
+ /* Target type is 1 for device with (De)serializer
+ * 0x4f00000 is the base for TV Encoder.
+ * Unused Offset 0x1000 is used for
+ * (de)serializer on emulation platform
+ */
+ periph_base = ioremap(MMSS_SERDES_BASE_PHY, 0x100);
+
+ if (periph_base) {
+ pr_debug("periph_base %p\n", periph_base);
+ writel(0x4, periph_base + 0x28);
+ writel(0xc, periph_base + 0x28);
+ } else {
+ pr_err("periph_base is NULL\n");
+ free_irq(dsi_irq, 0);
+ return -ENOMEM;
+ }
+ }
+
+ if (mipi_dsi_pdata) {
+ vsync_gpio = mipi_dsi_pdata->vsync_gpio;
+ pr_debug("%s: vsync_gpio=%d\n", __func__, vsync_gpio);
+
+ if (mdp_rev == MDP_REV_303 &&
+ mipi_dsi_pdata->dsi_client_reset) {
+ if (mipi_dsi_pdata->dsi_client_reset())
+ pr_err("%s: DSI Client Reset failed!\n",
+ __func__);
+ else
+ pr_debug("%s: DSI Client Reset success\n",
+ __func__);
+ }
+ }
+
+ mipi_dsi_resource_initialized = 1;
+
+ return 0;
+ }
+
+ mipi_dsi_clk_init(&pdev->dev);
+
+ if (!mipi_dsi_resource_initialized)
+ return -EPERM;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+ return -ENOMEM;
+
+
+ mdp_dev = platform_device_alloc("mdp", pdev->id);
+ if (!mdp_dev)
+ return -ENOMEM;
+
+ /*
+ * link to the latest pdev
+ */
+ mfd->pdev = mdp_dev;
+ mfd->dest = DISPLAY_LCD;
+
+ /*
+ * alloc panel device data
+ */
+ if (platform_device_add_data
+ (mdp_dev, pdev->dev.platform_data,
+ sizeof(struct msm_fb_panel_data))) {
+ pr_err("mipi_dsi_probe: platform_device_add_data failed!\n");
+ platform_device_put(mdp_dev);
+ return -ENOMEM;
+ }
+ /*
+ * data chain
+ */
+ pdata = mdp_dev->dev.platform_data;
+ pdata->on = mipi_dsi_on;
+ pdata->off = mipi_dsi_off;
+ pdata->next = pdev;
+
+ /*
+ * get/set panel specific fb info
+ */
+ mfd->panel_info = pdata->panel_info;
+ pinfo = &mfd->panel_info;
+
+ if (mdp_rev == MDP_REV_303 &&
+ mipi_dsi_pdata->get_lane_config) {
+ if (mipi_dsi_pdata->get_lane_config() != 2) {
+ pr_info("Changing to DSI Single Mode Configuration\n");
+#ifdef CONFIG_FB_MSM_MDP303
+ update_lane_config(pinfo);
+#endif
+ }
+ }
+
+ if (mfd->index == 0)
+ mfd->fb_imgType = MSMFB_DEFAULT_TYPE;
+ else
+ mfd->fb_imgType = MDP_RGB_565;
+
+ fbi = mfd->fbi;
+ fbi->var.pixclock = mfd->panel_info.clk_rate;
+ fbi->var.left_margin = mfd->panel_info.lcdc.h_back_porch;
+ fbi->var.right_margin = mfd->panel_info.lcdc.h_front_porch;
+ fbi->var.upper_margin = mfd->panel_info.lcdc.v_back_porch;
+ fbi->var.lower_margin = mfd->panel_info.lcdc.v_front_porch;
+ fbi->var.hsync_len = mfd->panel_info.lcdc.h_pulse_width;
+ fbi->var.vsync_len = mfd->panel_info.lcdc.v_pulse_width;
+
+ h_period = ((mfd->panel_info.lcdc.h_pulse_width)
+ + (mfd->panel_info.lcdc.h_back_porch)
+ + (mfd->panel_info.xres)
+ + (mfd->panel_info.lcdc.h_front_porch));
+
+ v_period = ((mfd->panel_info.lcdc.v_pulse_width)
+ + (mfd->panel_info.lcdc.v_back_porch)
+ + (mfd->panel_info.yres)
+ + (mfd->panel_info.lcdc.v_front_porch));
+
+ mipi = &mfd->panel_info.mipi;
+
+ if (mipi->data_lane3)
+ lanes += 1;
+ if (mipi->data_lane2)
+ lanes += 1;
+ if (mipi->data_lane1)
+ lanes += 1;
+ if (mipi->data_lane0)
+ lanes += 1;
+
+ if ((mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
+ || (mipi->dst_format == DSI_VIDEO_DST_FORMAT_RGB888)
+ || (mipi->dst_format == DSI_VIDEO_DST_FORMAT_RGB666_LOOSE))
+ bpp = 3;
+ else if ((mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565)
+ || (mipi->dst_format == DSI_VIDEO_DST_FORMAT_RGB565))
+ bpp = 2;
+ else
+ bpp = 3; /* Default format set to RGB888 */
+
+ if (mfd->panel_info.type == MIPI_VIDEO_PANEL &&
+ !mfd->panel_info.clk_rate) {
+ h_period += mfd->panel_info.mipi.xres_pad;
+ v_period += mfd->panel_info.mipi.yres_pad;
+
+ if (lanes > 0) {
+ mfd->panel_info.clk_rate =
+ ((h_period * v_period * (mipi->frame_rate) * bpp * 8)
+ / lanes);
+ } else {
+ pr_err("%s: forcing mipi_dsi lanes to 1\n", __func__);
+ mfd->panel_info.clk_rate =
+ (h_period * v_period
+ * (mipi->frame_rate) * bpp * 8);
+ }
+ }
+ pll_divider_config.clk_rate = mfd->panel_info.clk_rate;
+
+ rc = mipi_dsi_clk_div_config(bpp, lanes, &dsi_pclk_rate);
+ if (rc)
+ goto mipi_dsi_probe_err;
+
+ if ((dsi_pclk_rate < 3300000) || (dsi_pclk_rate > 103300000))
+ dsi_pclk_rate = 35000000;
+ mipi->dsi_pclk_rate = dsi_pclk_rate;
+
+ /*
+ * set driver data
+ */
+ platform_set_drvdata(mdp_dev, mfd);
+
+ /*
+ * register in mdp driver
+ */
+ rc = platform_device_add(mdp_dev);
+ if (rc)
+ goto mipi_dsi_probe_err;
+
+ pdev_list[pdev_list_cnt++] = pdev;
+
+return 0;
+
+mipi_dsi_probe_err:
+ platform_device_put(mdp_dev);
+ return rc;
+}
+
+static int mipi_dsi_remove(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+
+ mfd = platform_get_drvdata(pdev);
+ iounmap(mipi_dsi_base);
+ return 0;
+}
+
+static int mipi_dsi_register_driver(void)
+{
+ return platform_driver_register(&mipi_dsi_driver);
+}
+
+static int __init mipi_dsi_driver_init(void)
+{
+ int ret;
+
+ mipi_dsi_init();
+
+ ret = mipi_dsi_register_driver();
+
+ device_initialize(&dsi_dev);
+
+ if (ret) {
+ pr_err("mipi_dsi_register_driver() failed!\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+module_init(mipi_dsi_driver_init);
diff --git a/drivers/video/msm/mipi_dsi.h b/drivers/video/msm/mipi_dsi.h
new file mode 100644
index 0000000..2ed0596
--- /dev/null
+++ b/drivers/video/msm/mipi_dsi.h
@@ -0,0 +1,285 @@
+/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MIPI_DSI_H
+#define MIPI_DSI_H
+
+#include <mach/scm-io.h>
+#include <linux/list.h>
+
+#ifdef BIT
+#undef BIT
+#endif
+
+#define BIT(x) (1<<(x))
+
+#define MMSS_CC_BASE_PHY 0x04000000 /* mmss clcok control */
+#define MMSS_SFPB_BASE_PHY 0x05700000 /* mmss SFPB CFG */
+#define MMSS_SERDES_BASE_PHY 0x04f01000 /* mmss (De)Serializer CFG */
+
+#define MIPI_DSI_BASE mipi_dsi_base
+
+#define MIPI_OUTP(addr, data) writel((data), (addr))
+#define MIPI_INP(addr) readl(addr)
+
+#ifdef CONFIG_MSM_SECURE_IO
+#define MIPI_OUTP_SECURE(addr, data) secure_writel((data), (addr))
+#define MIPI_INP_SECURE(addr) secure_readl(addr)
+#else
+#define MIPI_OUTP_SECURE(addr, data) writel((data), (addr))
+#define MIPI_INP_SECURE(addr) readl(addr)
+#endif
+
+#define MIPI_DSI_PRIM 1
+#define MIPI_DSI_SECD 2
+
+#define MIPI_DSI_PANEL_VGA 0
+#define MIPI_DSI_PANEL_WVGA 1
+#define MIPI_DSI_PANEL_WVGA_PT 2
+#define MIPI_DSI_PANEL_FWVGA_PT 3
+#define DSI_PANEL_MAX 3
+
+enum { /* mipi dsi panel */
+ DSI_VIDEO_MODE,
+ DSI_CMD_MODE,
+};
+
+enum {
+ ST_DSI_CLK_OFF,
+ ST_DSI_SUSPEND,
+ ST_DSI_RESUME,
+ ST_DSI_PLAYING,
+ ST_DSI_NUM
+};
+
+enum {
+ EV_DSI_UPDATE,
+ EV_DSI_DONE,
+ EV_DSI_TOUT,
+ EV_DSI_NUM
+};
+
+enum {
+ LANDSCAPE = 1,
+ PORTRAIT = 2,
+};
+
+#define DSI_NON_BURST_SYNCH_PULSE 0
+#define DSI_NON_BURST_SYNCH_EVENT 1
+#define DSI_BURST_MODE 2
+
+
+#define DSI_RGB_SWAP_RGB 0
+#define DSI_RGB_SWAP_RBG 1
+#define DSI_RGB_SWAP_BGR 2
+#define DSI_RGB_SWAP_BRG 3
+#define DSI_RGB_SWAP_GRB 4
+#define DSI_RGB_SWAP_GBR 5
+
+#define DSI_VIDEO_DST_FORMAT_RGB565 0
+#define DSI_VIDEO_DST_FORMAT_RGB666 1
+#define DSI_VIDEO_DST_FORMAT_RGB666_LOOSE 2
+#define DSI_VIDEO_DST_FORMAT_RGB888 3
+
+#define DSI_CMD_DST_FORMAT_RGB111 0
+#define DSI_CMD_DST_FORMAT_RGB332 3
+#define DSI_CMD_DST_FORMAT_RGB444 4
+#define DSI_CMD_DST_FORMAT_RGB565 6
+#define DSI_CMD_DST_FORMAT_RGB666 7
+#define DSI_CMD_DST_FORMAT_RGB888 8
+
+#define DSI_INTR_ERROR_MASK BIT(25)
+#define DSI_INTR_ERROR BIT(24)
+#define DSI_INTR_VIDEO_DONE_MASK BIT(17)
+#define DSI_INTR_VIDEO_DONE BIT(16)
+#define DSI_INTR_CMD_MDP_DONE_MASK BIT(9)
+#define DSI_INTR_CMD_MDP_DONE BIT(8)
+#define DSI_INTR_CMD_DMA_DONE_MASK BIT(1)
+#define DSI_INTR_CMD_DMA_DONE BIT(0)
+
+#define DSI_CMD_TRIGGER_NONE 0x0 /* mdp trigger */
+#define DSI_CMD_TRIGGER_TE 0x02
+#define DSI_CMD_TRIGGER_SW 0x04
+#define DSI_CMD_TRIGGER_SW_SEOF 0x05 /* cmd dma only */
+#define DSI_CMD_TRIGGER_SW_TE 0x06
+
+extern struct device dsi_dev;
+extern int mipi_dsi_clk_on;
+extern u32 dsi_irq;
+
+extern void __iomem *periph_base;
+extern char *mmss_cc_base; /* mutimedia sub system clock control */
+extern char *mmss_sfpb_base; /* mutimedia sub system sfpb */
+
+struct dsiphy_pll_divider_config {
+ u32 clk_rate;
+ u32 fb_divider;
+ u32 ref_divider_ratio;
+ u32 bit_clk_divider; /* oCLK1 */
+ u32 byte_clk_divider; /* oCLK2 */
+ u32 dsi_clk_divider; /* oCLK3 */
+};
+
+extern struct dsiphy_pll_divider_config pll_divider_config;
+
+struct dsi_clk_mnd_table {
+ uint8 lanes;
+ uint8 bpp;
+ uint8 dsiclk_div;
+ uint8 dsiclk_m;
+ uint8 dsiclk_n;
+ uint8 dsiclk_d;
+ uint8 pclk_m;
+ uint8 pclk_n;
+ uint8 pclk_d;
+};
+
+static const struct dsi_clk_mnd_table mnd_table[] = {
+ { 1, 2, 8, 1, 1, 0, 1, 2, 1},
+ { 1, 3, 8, 1, 1, 0, 1, 3, 2},
+ { 2, 2, 4, 1, 1, 0, 1, 2, 1},
+ { 2, 3, 4, 1, 1, 0, 1, 3, 2},
+ { 3, 2, 1, 3, 8, 4, 3, 16, 8},
+ { 3, 3, 1, 3, 8, 4, 1, 8, 4},
+ { 4, 2, 2, 1, 1, 0, 1, 2, 1},
+ { 4, 3, 2, 1, 1, 0, 1, 3, 2},
+};
+
+struct dsi_clk_desc {
+ uint32 src;
+ uint32 m;
+ uint32 n;
+ uint32 d;
+ uint32 mnd_mode;
+ uint32 pre_div_func;
+};
+
+#define DSI_HOST_HDR_SIZE 4
+#define DSI_HDR_LAST BIT(31)
+#define DSI_HDR_LONG_PKT BIT(30)
+#define DSI_HDR_BTA BIT(29)
+#define DSI_HDR_VC(vc) (((vc) & 0x03) << 22)
+#define DSI_HDR_DTYPE(dtype) (((dtype) & 0x03f) << 16)
+#define DSI_HDR_DATA2(data) (((data) & 0x0ff) << 8)
+#define DSI_HDR_DATA1(data) ((data) & 0x0ff)
+#define DSI_HDR_WC(wc) ((wc) & 0x0ffff)
+
+#define DSI_BUF_SIZE 1024
+#define MIPI_DSI_MRPS 0x04 /* Maximum Return Packet Size */
+
+#define MIPI_DSI_LEN 8 /* 4 x 4 - 6 - 2, bytes dcs header+crc-align */
+
+struct dsi_buf {
+ uint32 *hdr; /* dsi host header */
+ char *start; /* buffer start addr */
+ char *end; /* buffer end addr */
+ int size; /* size of buffer */
+ char *data; /* buffer */
+ int len; /* data length */
+ dma_addr_t dmap; /* mapped dma addr */
+};
+
+/* dcs read/write */
+#define DTYPE_DCS_WRITE 0x05 /* short write, 0 parameter */
+#define DTYPE_DCS_WRITE1 0x15 /* short write, 1 parameter */
+#define DTYPE_DCS_READ 0x06 /* read */
+#define DTYPE_DCS_LWRITE 0x39 /* long write */
+
+/* generic read/write */
+#define DTYPE_GEN_WRITE 0x03 /* short write, 0 parameter */
+#define DTYPE_GEN_WRITE1 0x13 /* short write, 1 parameter */
+#define DTYPE_GEN_WRITE2 0x23 /* short write, 2 parameter */
+#define DTYPE_GEN_LWRITE 0x29 /* long write */
+#define DTYPE_GEN_READ 0x04 /* long read, 0 parameter */
+#define DTYPE_GEN_READ1 0x14 /* long read, 1 parameter */
+#define DTYPE_GEN_READ2 0x24 /* long read, 2 parameter */
+
+#define DTYPE_TEAR_ON 0x35 /* set tear on */
+#define DTYPE_MAX_PKTSIZE 0x37 /* set max packet size */
+#define DTYPE_NULL_PKT 0x09 /* null packet, no data */
+#define DTYPE_BLANK_PKT 0x19 /* blankiing packet, no data */
+
+#define DTYPE_CM_ON 0x02 /* color mode off */
+#define DTYPE_CM_OFF 0x12 /* color mode on */
+#define DTYPE_PERIPHERAL_OFF 0x22
+#define DTYPE_PERIPHERAL_ON 0x32
+
+
+struct dsi_cmd_desc {
+ int dtype;
+ int last;
+ int vc;
+ int ack; /* ask ACK from peripheral */
+ int wait;
+ int dlen;
+ char *payload;
+};
+
+
+typedef void (*kickoff_act)(void *);
+
+struct dsi_kickoff_action {
+ struct list_head act_entry;
+ kickoff_act action;
+ void *data;
+};
+
+
+char *mipi_dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen);
+char *mipi_dsi_buf_init(struct dsi_buf *dp);
+void mipi_dsi_init(void);
+int mipi_dsi_buf_alloc(struct dsi_buf *, int size);
+int mipi_dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm);
+int mipi_dsi_cmds_tx(struct msm_fb_data_type *mfd,
+ struct dsi_buf *dp, struct dsi_cmd_desc *cmds, int cnt);
+
+int mipi_dsi_cmd_dma_tx(struct dsi_buf *dp);
+int mipi_dsi_cmd_reg_tx(uint32 data);
+int mipi_dsi_cmds_rx(struct msm_fb_data_type *mfd,
+ struct dsi_buf *tp, struct dsi_buf *rp,
+ struct dsi_cmd_desc *cmds, int len);
+int mipi_dsi_cmd_dma_rx(struct dsi_buf *tp, int rlen);
+void mipi_dsi_host_init(struct mipi_panel_info *pinfo);
+void mipi_dsi_op_mode_config(int mode);
+void mipi_dsi_cmd_mode_ctrl(int enable);
+void mdp4_dsi_cmd_trigger(void);
+void mipi_dsi_cmd_mdp_sw_trigger(void);
+void mipi_dsi_cmd_bta_sw_trigger(void);
+void mipi_dsi_ack_err_status(void);
+void mipi_dsi_set_tear_on(struct msm_fb_data_type *mfd);
+void mipi_dsi_set_tear_off(struct msm_fb_data_type *mfd);
+void mipi_dsi_clk_enable(void);
+void mipi_dsi_clk_disable(void);
+void mipi_dsi_pre_kickoff_action(void);
+void mipi_dsi_post_kickoff_action(void);
+void mipi_dsi_pre_kickoff_add(struct dsi_kickoff_action *act);
+void mipi_dsi_post_kickoff_add(struct dsi_kickoff_action *act);
+void mipi_dsi_pre_kickoff_del(struct dsi_kickoff_action *act);
+void mipi_dsi_post_kickoff_del(struct dsi_kickoff_action *act);
+
+irqreturn_t mipi_dsi_isr(int irq, void *ptr);
+
+void mipi_set_tx_power_mode(int mode);
+void mipi_dsi_phy_ctrl(int on);
+void mipi_dsi_phy_init(int panel_ndx, struct msm_panel_info const *panel_info,
+ int target_type);
+int mipi_dsi_clk_div_config(uint8 bpp, uint8 lanes,
+ uint32 *expected_dsi_pclk);
+void mipi_dsi_clk_init(struct device *dev);
+void mipi_dsi_clk_deinit(struct device *dev);
+
+#ifdef CONFIG_FB_MSM_MDP303
+void update_lane_config(struct msm_panel_info *pinfo);
+#endif
+
+#endif /* MIPI_DSI_H */
diff --git a/drivers/video/msm/mipi_dsi_host.c b/drivers/video/msm/mipi_dsi_host.c
new file mode 100644
index 0000000..6607e4c
--- /dev/null
+++ b/drivers/video/msm/mipi_dsi_host.c
@@ -0,0 +1,1248 @@
+
+/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/clk.h>
+#include <mach/dma.h>
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mdp.h"
+#include "mdp4.h"
+
+static struct completion dsi_dma_comp;
+static struct dsi_buf dsi_tx_buf;
+static int dsi_irq_enabled;
+static spinlock_t dsi_lock;
+
+static struct list_head pre_kickoff_list;
+static struct list_head post_kickoff_list;
+
+void mipi_dsi_init(void)
+{
+ init_completion(&dsi_dma_comp);
+ mipi_dsi_buf_alloc(&dsi_tx_buf, DSI_BUF_SIZE);
+ spin_lock_init(&dsi_lock);
+
+ INIT_LIST_HEAD(&pre_kickoff_list);
+ INIT_LIST_HEAD(&post_kickoff_list);
+}
+
+void mipi_dsi_enable_irq(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dsi_lock, flags);
+ if (dsi_irq_enabled) {
+ pr_debug("%s: IRQ aleady enabled\n", __func__);
+ spin_unlock_irqrestore(&dsi_lock, flags);
+ return;
+ }
+ dsi_irq_enabled = 1;
+ enable_irq(dsi_irq);
+ spin_unlock_irqrestore(&dsi_lock, flags);
+}
+
+void mipi_dsi_disable_irq(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dsi_lock, flags);
+ if (dsi_irq_enabled == 0) {
+ pr_debug("%s: IRQ already disabled\n", __func__);
+ spin_unlock_irqrestore(&dsi_lock, flags);
+ return;
+ }
+
+ dsi_irq_enabled = 0;
+ disable_irq(dsi_irq);
+ spin_unlock_irqrestore(&dsi_lock, flags);
+}
+
+/*
+ * mipi_dsi_disale_irq_nosync() should be called
+ * from interrupt context
+ */
+ void mipi_dsi_disable_irq_nosync(void)
+{
+ spin_lock(&dsi_lock);
+ if (dsi_irq_enabled == 0) {
+ pr_debug("%s: IRQ cannot be disabled\n", __func__);
+ return;
+ }
+
+ dsi_irq_enabled = 0;
+ disable_irq_nosync(dsi_irq);
+ spin_unlock(&dsi_lock);
+}
+
+static void mipi_dsi_action(struct list_head *act_list)
+{
+ struct list_head *lp;
+ struct dsi_kickoff_action *act;
+
+ list_for_each(lp, act_list) {
+ act = list_entry(lp, struct dsi_kickoff_action, act_entry);
+ if (act && act->action)
+ act->action(act->data);
+ }
+}
+
+void mipi_dsi_pre_kickoff_action(void)
+{
+ mipi_dsi_action(&pre_kickoff_list);
+}
+
+void mipi_dsi_post_kickoff_action(void)
+{
+ mipi_dsi_action(&post_kickoff_list);
+}
+
+/*
+ * mipi_dsi_pre_kickoff_add:
+ * ov_mutex need to be acquired before call this function.
+ */
+void mipi_dsi_pre_kickoff_add(struct dsi_kickoff_action *act)
+{
+ if (act)
+ list_add_tail(&act->act_entry, &pre_kickoff_list);
+}
+
+/*
+ * mipi_dsi_pre_kickoff_add:
+ * ov_mutex need to be acquired before call this function.
+ */
+void mipi_dsi_post_kickoff_add(struct dsi_kickoff_action *act)
+{
+ if (act)
+ list_add_tail(&act->act_entry, &post_kickoff_list);
+}
+
+/*
+ * mipi_dsi_pre_kickoff_add:
+ * ov_mutex need to be acquired before call this function.
+ */
+void mipi_dsi_pre_kickoff_del(struct dsi_kickoff_action *act)
+{
+ if (!list_empty(&pre_kickoff_list) && act)
+ list_del(&act->act_entry);
+}
+
+/*
+ * mipi_dsi_pre_kickoff_add:
+ * ov_mutex need to be acquired before call this function.
+ */
+void mipi_dsi_post_kickoff_del(struct dsi_kickoff_action *act)
+{
+ if (!list_empty(&post_kickoff_list) && act)
+ list_del(&act->act_entry);
+}
+
+/*
+ * mipi dsi buf mechanism
+ */
+char *mipi_dsi_buf_reserve(struct dsi_buf *dp, int len)
+{
+ dp->data += len;
+ return dp->data;
+}
+
+char *mipi_dsi_buf_unreserve(struct dsi_buf *dp, int len)
+{
+ dp->data -= len;
+ return dp->data;
+}
+
+char *mipi_dsi_buf_push(struct dsi_buf *dp, int len)
+{
+ dp->data -= len;
+ dp->len += len;
+ return dp->data;
+}
+
+char *mipi_dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen)
+{
+ dp->hdr = (uint32 *)dp->data;
+ return mipi_dsi_buf_reserve(dp, hlen);
+}
+
+char *mipi_dsi_buf_init(struct dsi_buf *dp)
+{
+ int off;
+
+ dp->data = dp->start;
+ off = (int)dp->data;
+ /* 8 byte align */
+ off &= 0x07;
+ if (off)
+ off = 8 - off;
+ dp->data += off;
+ dp->len = 0;
+ return dp->data;
+}
+
+int mipi_dsi_buf_alloc(struct dsi_buf *dp, int size)
+{
+
+ dp->start = kmalloc(size, GFP_KERNEL);
+ if (dp->start == NULL) {
+ pr_err("%s:%u\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
+
+ dp->end = dp->start + size;
+ dp->size = size;
+
+ if ((int)dp->start & 0x07)
+ pr_err("%s: buf NOT 8 bytes aligned\n", __func__);
+
+ dp->data = dp->start;
+ dp->len = 0;
+ return size;
+}
+
+/*
+ * mipi dsi gerneric long write
+ */
+static int mipi_dsi_generic_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ char *bp;
+ uint32 *hp;
+ int i, len;
+
+ bp = mipi_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+
+ /* fill up payload */
+ if (cm->payload) {
+ len = cm->dlen;
+ len += 3;
+ len &= ~0x03; /* multipled by 4 */
+ for (i = 0; i < cm->dlen; i++)
+ *bp++ = cm->payload[i];
+
+ /* append 0xff to the end */
+ for (; i < len; i++)
+ *bp++ = 0xff;
+
+ dp->len += len;
+ }
+
+ /* fill up header */
+ hp = dp->hdr;
+ *hp = 0;
+ *hp = DSI_HDR_WC(cm->dlen);
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_LONG_PKT;
+ *hp |= DSI_HDR_DTYPE(DTYPE_GEN_LWRITE);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ mipi_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len;
+}
+
+/*
+ * mipi dsi gerneric short write with 0, 1 2 parameters
+ */
+static int mipi_dsi_generic_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ uint32 *hp;
+ int len;
+
+ if (cm->dlen && cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return 0;
+ }
+
+ mipi_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(cm->vc);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+
+ len = (cm->dlen > 2) ? 2 : cm->dlen;
+
+ if (len == 1) {
+ *hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE1);
+ *hp |= DSI_HDR_DATA1(cm->payload[0]);
+ *hp |= DSI_HDR_DATA2(0);
+ } else if (len == 2) {
+ *hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE2);
+ *hp |= DSI_HDR_DATA1(cm->payload[0]);
+ *hp |= DSI_HDR_DATA2(cm->payload[1]);
+ } else {
+ *hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE);
+ *hp |= DSI_HDR_DATA1(0);
+ *hp |= DSI_HDR_DATA2(0);
+ }
+
+ mipi_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+/*
+ * mipi dsi gerneric read with 0, 1 2 parameters
+ */
+static int mipi_dsi_generic_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ uint32 *hp;
+ int len;
+
+ if (cm->dlen && cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return 0;
+ }
+
+ mipi_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_BTA;
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ len = (cm->dlen > 2) ? 2 : cm->dlen;
+
+ if (len == 1) {
+ *hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ1);
+ *hp |= DSI_HDR_DATA1(cm->payload[0]);
+ *hp |= DSI_HDR_DATA2(0);
+ } else if (len == 2) {
+ *hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ2);
+ *hp |= DSI_HDR_DATA1(cm->payload[0]);
+ *hp |= DSI_HDR_DATA2(cm->payload[1]);
+ } else {
+ *hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ);
+ *hp |= DSI_HDR_DATA1(0);
+ *hp |= DSI_HDR_DATA2(0);
+ }
+
+ mipi_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+ return dp->len; /* 4 bytes */
+}
+
+/*
+ * mipi dsi dcs long write
+ */
+static int mipi_dsi_dcs_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ char *bp;
+ uint32 *hp;
+ int i, len;
+
+ bp = mipi_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+
+ /*
+ * fill up payload
+ * dcs command byte (first byte) followed by payload
+ */
+ if (cm->payload) {
+ len = cm->dlen;
+ len += 3;
+ len &= ~0x03; /* multipled by 4 */
+ for (i = 0; i < cm->dlen; i++)
+ *bp++ = cm->payload[i];
+
+ /* append 0xff to the end */
+ for (; i < len; i++)
+ *bp++ = 0xff;
+
+ dp->len += len;
+ }
+
+ /* fill up header */
+ hp = dp->hdr;
+ *hp = 0;
+ *hp = DSI_HDR_WC(cm->dlen);
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_LONG_PKT;
+ *hp |= DSI_HDR_DTYPE(DTYPE_DCS_LWRITE);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ mipi_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len;
+}
+
+/*
+ * mipi dsi dcs short write with 0 parameters
+ */
+static int mipi_dsi_dcs_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ uint32 *hp;
+ int len;
+
+ if (cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return -EINVAL;
+ }
+
+ mipi_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(cm->vc);
+ if (cm->ack) /* ask ACK trigger msg from peripeheral */
+ *hp |= DSI_HDR_BTA;
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ len = (cm->dlen > 1) ? 1 : cm->dlen;
+
+ *hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE);
+ *hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs command byte */
+ *hp |= DSI_HDR_DATA2(0);
+
+ mipi_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+ return dp->len;
+}
+
+/*
+ * mipi dsi dcs short write with 1 parameters
+ */
+static int mipi_dsi_dcs_swrite1(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ uint32 *hp;
+
+ if (cm->dlen < 2 || cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return -EINVAL;
+ }
+
+ mipi_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(cm->vc);
+ if (cm->ack) /* ask ACK trigger msg from peripeheral */
+ *hp |= DSI_HDR_BTA;
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ *hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE1);
+ *hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs comamnd byte */
+ *hp |= DSI_HDR_DATA2(cm->payload[1]); /* parameter */
+
+ mipi_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len;
+}
+/*
+ * mipi dsi dcs read with 0 parameters
+ */
+
+static int mipi_dsi_dcs_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ uint32 *hp;
+
+ if (cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return -EINVAL;
+ }
+
+ mipi_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_BTA;
+ *hp |= DSI_HDR_DTYPE(DTYPE_DCS_READ);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ *hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs command byte */
+ *hp |= DSI_HDR_DATA2(0);
+
+ mipi_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+static int mipi_dsi_cm_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ uint32 *hp;
+
+ mipi_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_DTYPE(DTYPE_CM_ON);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ mipi_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+static int mipi_dsi_cm_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ uint32 *hp;
+
+ mipi_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_DTYPE(DTYPE_CM_OFF);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ mipi_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+static int mipi_dsi_peripheral_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ uint32 *hp;
+
+ mipi_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_ON);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ mipi_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+static int mipi_dsi_peripheral_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ uint32 *hp;
+
+ mipi_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_OFF);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ mipi_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+static int mipi_dsi_set_max_pktsize(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ uint32 *hp;
+
+ if (cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return 0;
+ }
+
+ mipi_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_DTYPE(DTYPE_MAX_PKTSIZE);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ *hp |= DSI_HDR_DATA1(cm->payload[0]);
+ *hp |= DSI_HDR_DATA2(cm->payload[1]);
+
+ mipi_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+static int mipi_dsi_null_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ uint32 *hp;
+
+ mipi_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp = DSI_HDR_WC(cm->dlen);
+ *hp |= DSI_HDR_LONG_PKT;
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_DTYPE(DTYPE_NULL_PKT);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ mipi_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+static int mipi_dsi_blank_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ uint32 *hp;
+
+ mipi_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp = DSI_HDR_WC(cm->dlen);
+ *hp |= DSI_HDR_LONG_PKT;
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_DTYPE(DTYPE_BLANK_PKT);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ mipi_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+/*
+ * prepare cmd buffer to be txed
+ */
+int mipi_dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ int len = 0;
+
+ switch (cm->dtype) {
+ case DTYPE_GEN_WRITE:
+ case DTYPE_GEN_WRITE1:
+ case DTYPE_GEN_WRITE2:
+ len = mipi_dsi_generic_swrite(dp, cm);
+ break;
+ case DTYPE_GEN_LWRITE:
+ len = mipi_dsi_generic_lwrite(dp, cm);
+ break;
+ case DTYPE_GEN_READ:
+ case DTYPE_GEN_READ1:
+ case DTYPE_GEN_READ2:
+ len = mipi_dsi_generic_read(dp, cm);
+ break;
+ case DTYPE_DCS_LWRITE:
+ len = mipi_dsi_dcs_lwrite(dp, cm);
+ break;
+ case DTYPE_DCS_WRITE:
+ len = mipi_dsi_dcs_swrite(dp, cm);
+ break;
+ case DTYPE_DCS_WRITE1:
+ len = mipi_dsi_dcs_swrite1(dp, cm);
+ break;
+ case DTYPE_DCS_READ:
+ len = mipi_dsi_dcs_read(dp, cm);
+ break;
+ case DTYPE_MAX_PKTSIZE:
+ len = mipi_dsi_set_max_pktsize(dp, cm);
+ break;
+ case DTYPE_NULL_PKT:
+ len = mipi_dsi_null_pkt(dp, cm);
+ break;
+ case DTYPE_BLANK_PKT:
+ len = mipi_dsi_blank_pkt(dp, cm);
+ break;
+ case DTYPE_CM_ON:
+ len = mipi_dsi_cm_on(dp, cm);
+ break;
+ case DTYPE_CM_OFF:
+ len = mipi_dsi_cm_off(dp, cm);
+ break;
+ case DTYPE_PERIPHERAL_ON:
+ len = mipi_dsi_peripheral_on(dp, cm);
+ break;
+ case DTYPE_PERIPHERAL_OFF:
+ len = mipi_dsi_peripheral_off(dp, cm);
+ break;
+ default:
+ pr_debug("%s: dtype=%x NOT supported\n",
+ __func__, cm->dtype);
+ break;
+
+ }
+
+ return len;
+}
+
+void mipi_dsi_host_init(struct mipi_panel_info *pinfo)
+{
+ uint32 dsi_ctrl, intr_ctrl;
+ uint32 data;
+
+ if (pinfo->mode == DSI_VIDEO_MODE) {
+ data = 0;
+ if (pinfo->pulse_mode_hsa_he)
+ data |= BIT(28);
+ if (pinfo->hfp_power_stop)
+ data |= BIT(24);
+ if (pinfo->hbp_power_stop)
+ data |= BIT(20);
+ if (pinfo->hsa_power_stop)
+ data |= BIT(16);
+ if (pinfo->eof_bllp_power_stop)
+ data |= BIT(15);
+ if (pinfo->bllp_power_stop)
+ data |= BIT(12);
+ data |= ((pinfo->traffic_mode & 0x03) << 8);
+ data |= ((pinfo->dst_format & 0x03) << 4); /* 2 bits */
+ data |= (pinfo->vc & 0x03);
+ MIPI_OUTP(MIPI_DSI_BASE + 0x000c, data);
+
+ data = 0;
+ data |= ((pinfo->rgb_swap & 0x07) << 12);
+ if (pinfo->b_sel)
+ data |= BIT(8);
+ if (pinfo->g_sel)
+ data |= BIT(4);
+ if (pinfo->r_sel)
+ data |= BIT(0);
+ MIPI_OUTP(MIPI_DSI_BASE + 0x001c, data);
+ } else if (pinfo->mode == DSI_CMD_MODE) {
+ data = 0;
+ data |= ((pinfo->interleave_max & 0x0f) << 20);
+ data |= ((pinfo->rgb_swap & 0x07) << 16);
+ if (pinfo->b_sel)
+ data |= BIT(12);
+ if (pinfo->g_sel)
+ data |= BIT(8);
+ if (pinfo->r_sel)
+ data |= BIT(4);
+ data |= (pinfo->dst_format & 0x0f); /* 4 bits */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x003c, data);
+
+ /* DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL */
+ data = pinfo->wr_mem_continue & 0x0ff;
+ data <<= 8;
+ data |= (pinfo->wr_mem_start & 0x0ff);
+ if (pinfo->insert_dcs_cmd)
+ data |= BIT(16);
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0040, data);
+ } else
+ pr_err("%s: Unknown DSI mode=%d\n", __func__, pinfo->mode);
+
+ dsi_ctrl = BIT(8) | BIT(2); /* clock enable & cmd mode */
+ intr_ctrl = 0;
+ intr_ctrl = (DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_CMD_MDP_DONE_MASK);
+
+ if (pinfo->crc_check)
+ dsi_ctrl |= BIT(24);
+ if (pinfo->ecc_check)
+ dsi_ctrl |= BIT(20);
+ if (pinfo->data_lane3)
+ dsi_ctrl |= BIT(7);
+ if (pinfo->data_lane2)
+ dsi_ctrl |= BIT(6);
+ if (pinfo->data_lane1)
+ dsi_ctrl |= BIT(5);
+ if (pinfo->data_lane0)
+ dsi_ctrl |= BIT(4);
+
+ /* from frame buffer, low power mode */
+ /* DSI_COMMAND_MODE_DMA_CTRL */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x38, 0x14000000);
+
+ data = 0;
+ if (pinfo->te_sel)
+ data |= BIT(31);
+ data |= pinfo->mdp_trigger << 4;/* cmd mdp trigger */
+ data |= pinfo->dma_trigger; /* cmd dma trigger */
+ data |= (pinfo->stream & 0x01) << 8;
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0080, data); /* DSI_TRIG_CTRL */
+
+ /* DSI_LAN_SWAP_CTRL */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x00ac, pinfo->dlane_swap);
+
+ /* clock out ctrl */
+ data = pinfo->t_clk_post & 0x3f; /* 6 bits */
+ data <<= 8;
+ data |= pinfo->t_clk_pre & 0x3f; /* 6 bits */
+ MIPI_OUTP(MIPI_DSI_BASE + 0xc0, data); /* DSI_CLKOUT_TIMING_CTRL */
+
+ data = 0;
+ if (pinfo->rx_eot_ignore)
+ data |= BIT(4);
+ if (pinfo->tx_eot_append)
+ data |= BIT(0);
+ MIPI_OUTP(MIPI_DSI_BASE + 0x00c8, data); /* DSI_EOT_PACKET_CTRL */
+
+
+ /* allow only ack-err-status to generate interrupt */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0108, 0x13ff3fe0); /* DSI_ERR_INT_MASK0 */
+
+ intr_ctrl |= DSI_INTR_ERROR_MASK;
+ MIPI_OUTP(MIPI_DSI_BASE + 0x010c, intr_ctrl); /* DSI_INTL_CTRL */
+
+ /* turn esc, byte, dsi, pclk, sclk, hclk on */
+ if (mdp_rev >= MDP_REV_41)
+ MIPI_OUTP(MIPI_DSI_BASE + 0x118, 0x23f); /* DSI_CLK_CTRL */
+ else
+ MIPI_OUTP(MIPI_DSI_BASE + 0x118, 0x33f); /* DSI_CLK_CTRL */
+
+ dsi_ctrl |= BIT(0); /* enable dsi */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0000, dsi_ctrl);
+
+ wmb();
+}
+
+void mipi_set_tx_power_mode(int mode)
+{
+ uint32 data = MIPI_INP(MIPI_DSI_BASE + 0x38);
+
+ if (mode == 0)
+ data &= ~BIT(26);
+ else
+ data |= BIT(26);
+
+ MIPI_OUTP(MIPI_DSI_BASE + 0x38, data);
+}
+
+void mipi_dsi_op_mode_config(int mode)
+{
+
+ uint32 dsi_ctrl, intr_ctrl;
+
+ dsi_ctrl = MIPI_INP(MIPI_DSI_BASE + 0x0000);
+ dsi_ctrl &= ~0x07;
+ if (mode == DSI_VIDEO_MODE) {
+ dsi_ctrl |= 0x03;
+ intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK;
+ } else { /* command mode */
+ dsi_ctrl |= 0x05;
+ intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_ERROR_MASK |
+ DSI_INTR_CMD_MDP_DONE_MASK;
+ }
+
+ pr_debug("%s: dsi_ctrl=%x intr=%x\n", __func__, dsi_ctrl, intr_ctrl);
+
+ MIPI_OUTP(MIPI_DSI_BASE + 0x010c, intr_ctrl); /* DSI_INTL_CTRL */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0000, dsi_ctrl);
+ wmb();
+}
+
+void mipi_dsi_cmd_mdp_sw_trigger(void)
+{
+ mipi_dsi_pre_kickoff_action();
+ mipi_dsi_enable_irq();
+ MIPI_OUTP(MIPI_DSI_BASE + 0x090, 0x01); /* trigger */
+ wmb();
+}
+
+
+void mipi_dsi_cmd_bta_sw_trigger(void)
+{
+ uint32 data;
+ int cnt = 0;
+
+ MIPI_OUTP(MIPI_DSI_BASE + 0x094, 0x01); /* trigger */
+ wmb();
+
+ while (cnt < 10000) {
+ data = MIPI_INP(MIPI_DSI_BASE + 0x0004);/* DSI_STATUS */
+ if ((data & 0x0010) == 0)
+ break;
+ cnt++;
+ }
+
+ mipi_dsi_ack_err_status();
+
+ pr_debug("%s: BTA done, cnt=%d\n", __func__, cnt);
+}
+
+static char set_tear_on[2] = {0x35, 0x00};
+static struct dsi_cmd_desc dsi_tear_on_cmd = {
+ DTYPE_DCS_WRITE1, 1, 0, 0, 0, sizeof(set_tear_on), set_tear_on};
+
+static char set_tear_off[2] = {0x34, 0x00};
+static struct dsi_cmd_desc dsi_tear_off_cmd = {
+ DTYPE_DCS_WRITE, 1, 0, 0, 0, sizeof(set_tear_off), set_tear_off};
+
+void mipi_dsi_set_tear_on(struct msm_fb_data_type *mfd)
+{
+ mipi_dsi_buf_init(&dsi_tx_buf);
+ mipi_dsi_cmds_tx(mfd, &dsi_tx_buf, &dsi_tear_on_cmd, 1);
+}
+
+void mipi_dsi_set_tear_off(struct msm_fb_data_type *mfd)
+{
+ mipi_dsi_buf_init(&dsi_tx_buf);
+ mipi_dsi_cmds_tx(mfd, &dsi_tx_buf, &dsi_tear_off_cmd, 1);
+}
+
+int mipi_dsi_cmd_reg_tx(uint32 data)
+{
+#ifdef DSI_HOST_DEBUG
+ int i;
+ char *bp;
+
+ bp = (char *)&data;
+ pr_debug("%s: ", __func__);
+ for (i = 0; i < 4; i++)
+ pr_debug("%x ", *bp++);
+
+ pr_debug("\n");
+#endif
+
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0080, 0x04);/* sw trigger */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0, 0x135);
+
+ wmb();
+
+ MIPI_OUTP(MIPI_DSI_BASE + 0x038, data);
+ wmb();
+ MIPI_OUTP(MIPI_DSI_BASE + 0x08c, 0x01); /* trigger */
+ wmb();
+
+ udelay(300);
+
+ return 4;
+}
+
+/*
+ * mipi_dsi_cmds_tx:
+ * ov_mutex need to be acquired before call this function.
+ */
+int mipi_dsi_cmds_tx(struct msm_fb_data_type *mfd,
+ struct dsi_buf *tp, struct dsi_cmd_desc *cmds, int cnt)
+{
+ struct dsi_cmd_desc *cm;
+ uint32 dsi_ctrl, ctrl;
+ int i, video_mode;
+
+ /* turn on cmd mode
+ * for video mode, do not send cmds more than
+ * one pixel line, since it only transmit it
+ * during BLLP.
+ */
+ dsi_ctrl = MIPI_INP(MIPI_DSI_BASE + 0x0000);
+ video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
+ if (video_mode) {
+ ctrl = dsi_ctrl | 0x04; /* CMD_MODE_EN */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0000, ctrl);
+ } else { /* cmd mode */
+ /*
+ * during boot up, cmd mode is configured
+ * even it is video mode panel.
+ */
+ /* make sure mdp dma is not txing pixel data */
+ if (mfd->panel_info.type == MIPI_CMD_PANEL) {
+#ifndef CONFIG_FB_MSM_MDP303
+ mdp4_dsi_cmd_dma_busy_wait(mfd);
+#else
+ mdp3_dsi_cmd_dma_busy_wait(mfd);
+#endif
+ }
+ }
+
+ mipi_dsi_enable_irq();
+ cm = cmds;
+ mipi_dsi_buf_init(tp);
+ for (i = 0; i < cnt; i++) {
+ mipi_dsi_buf_init(tp);
+ mipi_dsi_cmd_dma_add(tp, cm);
+ mipi_dsi_cmd_dma_tx(tp);
+ if (cm->wait)
+ msleep(cm->wait);
+ cm++;
+ }
+ mipi_dsi_disable_irq();
+
+ if (video_mode)
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0000, dsi_ctrl); /* restore */
+
+ return cnt;
+}
+
+/* MIPI_DSI_MRPS, Maximum Return Packet Size */
+static char max_pktsize[2] = {0x00, 0x00}; /* LSB tx first, 10 bytes */
+
+static struct dsi_cmd_desc pkt_size_cmd[] = {
+ {DTYPE_MAX_PKTSIZE, 1, 0, 0, 0,
+ sizeof(max_pktsize), max_pktsize}
+};
+
+/*
+ * DSI panel reply with MAX_RETURN_PACKET_SIZE bytes of data
+ * plus DCS header, ECC and CRC for DCS long read response
+ * mipi_dsi_controller only have 4x32 bits register ( 16 bytes) to
+ * hold data per transaction.
+ * MIPI_DSI_LEN equal to 8
+ * len should be either 4 or 8
+ * any return data more than MIPI_DSI_LEN need to be break down
+ * to multiple transactions.
+ *
+ * ov_mutex need to be acquired before call this function.
+ */
+int mipi_dsi_cmds_rx(struct msm_fb_data_type *mfd,
+ struct dsi_buf *tp, struct dsi_buf *rp,
+ struct dsi_cmd_desc *cmds, int len)
+{
+ int cnt, res;
+ static int pkt_size;
+
+ if (len <= 2)
+ cnt = 4; /* short read */
+ else {
+ if (len > MIPI_DSI_LEN)
+ len = MIPI_DSI_LEN; /* 8 bytes at most */
+
+ res = len & 0x03;
+ len += (4 - res); /* 4 bytes align */
+ /*
+ * add extra 2 bytes to len to have overall
+ * packet size is multipe by 4. This also make
+ * sure 4 bytes dcs headerlocates within a
+ * 32 bits register after shift in.
+ * after all, len should be either 6 or 10.
+ */
+ len += 2;
+ cnt = len + 6; /* 4 bytes header + 2 bytes crc */
+ }
+
+
+ if (mfd->panel_info.type == MIPI_CMD_PANEL) {
+ /* make sure mdp dma is not txing pixel data */
+#ifndef CONFIG_FB_MSM_MDP303
+ mdp4_dsi_cmd_dma_busy_wait(mfd);
+#else
+ mdp3_dsi_cmd_dma_busy_wait(mfd);
+#endif
+ }
+
+ mipi_dsi_enable_irq();
+ if (pkt_size != len) {
+ /* set new max pkt size */
+ pkt_size = len;
+ max_pktsize[0] = pkt_size;
+ mipi_dsi_buf_init(tp);
+ mipi_dsi_cmd_dma_add(tp, pkt_size_cmd);
+ mipi_dsi_cmd_dma_tx(tp);
+ }
+
+ mipi_dsi_buf_init(tp);
+ mipi_dsi_cmd_dma_add(tp, cmds);
+
+ /* transmit read comamnd to client */
+ mipi_dsi_cmd_dma_tx(tp);
+ /*
+ * once cmd_dma_done interrupt received,
+ * return data from client is ready and stored
+ * at RDBK_DATA register already
+ */
+ mipi_dsi_cmd_dma_rx(rp, cnt);
+
+ mipi_dsi_disable_irq();
+
+ /* strip off dcs header & crc */
+ if (cnt > 4) { /* long response */
+ rp->data += 4; /* skip dcs header */
+ rp->len -= 6; /* deduct 4 bytes header + 2 bytes crc */
+ rp->len -= 2; /* extra 2 bytes added */
+ } else {
+ rp->data += 1; /* skip dcs short header */
+ rp->len -= 2; /* deduct 1 byte header + 1 byte ecc */
+ }
+
+ return rp->len;
+}
+
+int mipi_dsi_cmd_dma_tx(struct dsi_buf *tp)
+{
+ int len;
+
+#ifdef DSI_HOST_DEBUG
+ int i;
+ char *bp;
+
+ bp = tp->data;
+
+ pr_debug("%s: ", __func__);
+ for (i = 0; i < tp->len; i++)
+ pr_debug("%x ", *bp++);
+
+ pr_debug("\n");
+#endif
+
+ len = tp->len;
+ len += 3;
+ len &= ~0x03; /* multipled by 4 */
+
+ tp->dmap = dma_map_single(&dsi_dev, tp->data, len, DMA_TO_DEVICE);
+ if (dma_mapping_error(&dsi_dev, tp->dmap))
+ pr_err("%s: dmap mapp failed\n", __func__);
+
+ INIT_COMPLETION(dsi_dma_comp);
+
+ MIPI_OUTP(MIPI_DSI_BASE + 0x044, tp->dmap);
+ MIPI_OUTP(MIPI_DSI_BASE + 0x048, len);
+ wmb();
+ MIPI_OUTP(MIPI_DSI_BASE + 0x08c, 0x01); /* trigger */
+ wmb();
+
+ wait_for_completion(&dsi_dma_comp);
+
+ dma_unmap_single(&dsi_dev, tp->dmap, len, DMA_TO_DEVICE);
+ tp->dmap = 0;
+ return tp->len;
+}
+
+int mipi_dsi_cmd_dma_rx(struct dsi_buf *rp, int rlen)
+{
+ uint32 *lp, data;
+ int i, off, cnt;
+
+ lp = (uint32 *)rp->data;
+ cnt = rlen;
+ cnt += 3;
+ cnt >>= 2;
+
+ if (cnt > 4)
+ cnt = 4; /* 4 x 32 bits registers only */
+
+ off = 0x068; /* DSI_RDBK_DATA0 */
+ off += ((cnt - 1) * 4);
+
+
+ for (i = 0; i < cnt; i++) {
+ data = (uint32)MIPI_INP(MIPI_DSI_BASE + off);
+ *lp++ = ntohl(data); /* to network byte order */
+ off -= 4;
+ rp->len += sizeof(*lp);
+ }
+
+ return rlen;
+}
+
+void mipi_dsi_irq_set(uint32 mask, uint32 irq)
+{
+ uint32 data;
+
+ data = MIPI_INP(MIPI_DSI_BASE + 0x010c);/* DSI_INTR_CTRL */
+ data &= ~mask;
+ data |= irq;
+ MIPI_OUTP(MIPI_DSI_BASE + 0x010c, data);
+}
+
+
+void mipi_dsi_ack_err_status(void)
+{
+ uint32 status;
+
+ status = MIPI_INP(MIPI_DSI_BASE + 0x0064);/* DSI_ACK_ERR_STATUS */
+
+ if (status) {
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0064, status);
+ pr_debug("%s: status=%x\n", __func__, status);
+ }
+}
+
+void mipi_dsi_timeout_status(void)
+{
+ uint32 status;
+
+ status = MIPI_INP(MIPI_DSI_BASE + 0x00bc);/* DSI_TIMEOUT_STATUS */
+ if (status & 0x0111) {
+ MIPI_OUTP(MIPI_DSI_BASE + 0x00bc, status);
+ pr_debug("%s: status=%x\n", __func__, status);
+ }
+}
+
+void mipi_dsi_dln0_phy_err(void)
+{
+ uint32 status;
+
+ status = MIPI_INP(MIPI_DSI_BASE + 0x00b0);/* DSI_DLN0_PHY_ERR */
+
+ if (status & 0x011111) {
+ MIPI_OUTP(MIPI_DSI_BASE + 0x00b0, status);
+ pr_debug("%s: status=%x\n", __func__, status);
+ }
+}
+
+void mipi_dsi_fifo_status(void)
+{
+ uint32 status;
+
+ status = MIPI_INP(MIPI_DSI_BASE + 0x0008);/* DSI_FIFO_STATUS */
+
+ if (status & 0x44444489) {
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0008, status);
+ pr_debug("%s: status=%x\n", __func__, status);
+ }
+}
+
+void mipi_dsi_status(void)
+{
+ uint32 status;
+
+ status = MIPI_INP(MIPI_DSI_BASE + 0x0004);/* DSI_STATUS */
+
+ if (status & 0x80000000) {
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0004, status);
+ pr_debug("%s: status=%x\n", __func__, status);
+ }
+}
+
+void mipi_dsi_error(void)
+{
+ /* DSI_ERR_INT_MASK0 */
+ mipi_dsi_ack_err_status(); /* mask0, 0x01f */
+ mipi_dsi_timeout_status(); /* mask0, 0x0e0 */
+ mipi_dsi_fifo_status(); /* mask0, 0x133d00 */
+ mipi_dsi_status(); /* mask0, 0xc0100 */
+ mipi_dsi_dln0_phy_err(); /* mask0, 0x3e00000 */
+}
+
+
+irqreturn_t mipi_dsi_isr(int irq, void *ptr)
+{
+ uint32 isr;
+
+ isr = MIPI_INP(MIPI_DSI_BASE + 0x010c);/* DSI_INTR_CTRL */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x010c, isr);
+
+#ifdef CONFIG_FB_MSM_MDP40
+ mdp4_stat.intr_dsi++;
+#endif
+
+ if (isr & DSI_INTR_ERROR) {
+ mipi_dsi_error();
+ }
+
+ if (isr & DSI_INTR_VIDEO_DONE) {
+ /*
+ * do something here
+ */
+ }
+
+ if (isr & DSI_INTR_CMD_DMA_DONE) {
+ complete(&dsi_dma_comp);
+ }
+
+ if (isr & DSI_INTR_CMD_MDP_DONE) {
+ mipi_dsi_disable_irq_nosync();
+ mipi_dsi_post_kickoff_action();
+ }
+
+
+ return IRQ_HANDLED;
+}
diff --git a/drivers/video/msm/mipi_novatek.c b/drivers/video/msm/mipi_novatek.c
new file mode 100644
index 0000000..27108f2
--- /dev/null
+++ b/drivers/video/msm/mipi_novatek.c
@@ -0,0 +1,463 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_novatek.h"
+#include "mdp4.h"
+
+
+static struct mipi_dsi_novatek_platform_data *mipi_novatek_pdata;
+
+static struct dsi_buf novatek_tx_buf;
+static struct dsi_buf novatek_rx_buf;
+
+
+/* novatek blue panel */
+
+#ifdef NOVETAK_COMMANDS_UNUSED
+static char display_config_cmd_mode1[] = {
+ /* TYPE_DCS_LWRITE */
+ 0x2A, 0x00, 0x00, 0x01,
+ 0x3F, 0xFF, 0xFF, 0xFF
+};
+
+static char display_config_cmd_mode2[] = {
+ /* DTYPE_DCS_LWRITE */
+ 0x2B, 0x00, 0x00, 0x01,
+ 0xDF, 0xFF, 0xFF, 0xFF
+};
+
+static char display_config_cmd_mode3_666[] = {
+ /* DTYPE_DCS_WRITE1 */
+ 0x3A, 0x66, 0x15, 0x80 /* 666 Packed (18-bits) */
+};
+
+static char display_config_cmd_mode3_565[] = {
+ /* DTYPE_DCS_WRITE1 */
+ 0x3A, 0x55, 0x15, 0x80 /* 565 mode */
+};
+
+static char display_config_321[] = {
+ /* DTYPE_DCS_WRITE1 */
+ 0x66, 0x2e, 0x15, 0x00 /* Reg 0x66 : 2E */
+};
+
+static char display_config_323[] = {
+ /* DTYPE_DCS_WRITE */
+ 0x13, 0x00, 0x05, 0x00 /* Reg 0x13 < Set for Normal Mode> */
+};
+
+static char display_config_2lan[] = {
+ /* DTYPE_DCS_WRITE */
+ 0x61, 0x01, 0x02, 0xff /* Reg 0x61 : 01,02 < Set for 2 Data Lane > */
+};
+
+static char display_config_exit_sleep[] = {
+ /* DTYPE_DCS_WRITE */
+ 0x11, 0x00, 0x05, 0x80 /* Reg 0x11 < exit sleep mode> */
+};
+
+static char display_config_TE_ON[] = {
+ /* DTYPE_DCS_WRITE1 */
+ 0x35, 0x00, 0x15, 0x80
+};
+
+static char display_config_39H[] = {
+ /* DTYPE_DCS_WRITE */
+ 0x39, 0x00, 0x05, 0x80
+};
+
+static char display_config_set_tear_scanline[] = {
+ /* DTYPE_DCS_LWRITE */
+ 0x44, 0x00, 0x00, 0xff
+};
+
+static char display_config_set_twolane[] = {
+ /* DTYPE_DCS_WRITE1 */
+ 0xae, 0x03, 0x15, 0x80
+};
+
+static char display_config_set_threelane[] = {
+ /* DTYPE_DCS_WRITE1 */
+ 0xae, 0x05, 0x15, 0x80
+};
+
+#else
+
+static char sw_reset[2] = {0x01, 0x00}; /* DTYPE_DCS_WRITE */
+static char enter_sleep[2] = {0x10, 0x00}; /* DTYPE_DCS_WRITE */
+static char exit_sleep[2] = {0x11, 0x00}; /* DTYPE_DCS_WRITE */
+static char display_off[2] = {0x28, 0x00}; /* DTYPE_DCS_WRITE */
+static char display_on[2] = {0x29, 0x00}; /* DTYPE_DCS_WRITE */
+
+
+
+static char rgb_888[2] = {0x3A, 0x77}; /* DTYPE_DCS_WRITE1 */
+
+#if defined(NOVATEK_TWO_LANE)
+static char set_num_of_lanes[2] = {0xae, 0x03}; /* DTYPE_DCS_WRITE1 */
+#else /* 1 lane */
+static char set_num_of_lanes[2] = {0xae, 0x01}; /* DTYPE_DCS_WRITE1 */
+#endif
+/* commands by Novatke */
+static char novatek_f4[2] = {0xf4, 0x55}; /* DTYPE_DCS_WRITE1 */
+static char novatek_8c[16] = { /* DTYPE_DCS_LWRITE */
+ 0x8C, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x08, 0x00, 0x30, 0xC0, 0xB7, 0x37};
+static char novatek_ff[2] = {0xff, 0x55 }; /* DTYPE_DCS_WRITE1 */
+
+static char set_width[5] = { /* DTYPE_DCS_LWRITE */
+ 0x2A, 0x00, 0x00, 0x02, 0x1B}; /* 540 - 1 */
+static char set_height[5] = { /* DTYPE_DCS_LWRITE */
+ 0x2B, 0x00, 0x00, 0x03, 0xBF}; /* 960 - 1 */
+#endif
+
+static char led_pwm1[2] = {0x51, 0x0}; /* DTYPE_DCS_WRITE1 */
+static char led_pwm2[2] = {0x53, 0x24}; /* DTYPE_DCS_WRITE1 */
+static char led_pwm3[2] = {0x55, 0x00}; /* DTYPE_DCS_WRITE1 */
+
+static struct dsi_cmd_desc novatek_cmd_backlight_cmds[] = {
+ {DTYPE_DCS_LWRITE, 1, 0, 0, 1, sizeof(led_pwm1), led_pwm1},
+};
+
+static struct dsi_cmd_desc novatek_video_on_cmds[] = {
+ {DTYPE_DCS_WRITE, 1, 0, 0, 50,
+ sizeof(sw_reset), sw_reset},
+ {DTYPE_DCS_WRITE, 1, 0, 0, 10,
+ sizeof(exit_sleep), exit_sleep},
+ {DTYPE_DCS_WRITE, 1, 0, 0, 10,
+ sizeof(display_on), display_on},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, 10,
+ sizeof(set_num_of_lanes), set_num_of_lanes},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, 10,
+ sizeof(rgb_888), rgb_888},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, 10,
+ sizeof(led_pwm2), led_pwm2},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, 10,
+ sizeof(led_pwm3), led_pwm3},
+};
+
+static struct dsi_cmd_desc novatek_cmd_on_cmds[] = {
+ {DTYPE_DCS_WRITE, 1, 0, 0, 50,
+ sizeof(sw_reset), sw_reset},
+ {DTYPE_DCS_WRITE, 1, 0, 0, 10,
+ sizeof(exit_sleep), exit_sleep},
+ {DTYPE_DCS_WRITE, 1, 0, 0, 10,
+ sizeof(display_on), display_on},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, 50,
+ sizeof(novatek_f4), novatek_f4},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, 50,
+ sizeof(novatek_8c), novatek_8c},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, 50,
+ sizeof(novatek_ff), novatek_ff},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, 10,
+ sizeof(set_num_of_lanes), set_num_of_lanes},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, 50,
+ sizeof(set_width), set_width},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, 50,
+ sizeof(set_height), set_height},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, 10,
+ sizeof(rgb_888), rgb_888},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, 1,
+ sizeof(led_pwm2), led_pwm2},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, 1,
+ sizeof(led_pwm3), led_pwm3},
+};
+
+static struct dsi_cmd_desc novatek_display_off_cmds[] = {
+ {DTYPE_DCS_WRITE, 1, 0, 0, 10,
+ sizeof(display_off), display_off},
+ {DTYPE_DCS_WRITE, 1, 0, 0, 120,
+ sizeof(enter_sleep), enter_sleep}
+};
+
+static char manufacture_id[2] = {0x04, 0x00}; /* DTYPE_DCS_READ */
+
+static struct dsi_cmd_desc novatek_manufacture_id_cmd = {
+ DTYPE_DCS_READ, 1, 0, 1, 5, sizeof(manufacture_id), manufacture_id};
+
+static uint32 mipi_novatek_manufacture_id(struct msm_fb_data_type *mfd)
+{
+ struct dsi_buf *rp, *tp;
+ struct dsi_cmd_desc *cmd;
+ uint32 *lp;
+
+ tp = &novatek_tx_buf;
+ rp = &novatek_rx_buf;
+ mipi_dsi_buf_init(rp);
+ mipi_dsi_buf_init(tp);
+
+ cmd = &novatek_manufacture_id_cmd;
+ mipi_dsi_cmds_rx(mfd, tp, rp, cmd, 3);
+ lp = (uint32 *)rp->data;
+ pr_info("%s: manufacture_id=%x", __func__, *lp);
+ return *lp;
+}
+
+static int fpga_addr;
+static bool support_3d;
+
+static void mipi_novatek_3d_init(int addr)
+{
+ fpga_addr = addr;
+}
+
+static void mipi_dsi_enable_3d_barrier(int mode)
+{
+ void __iomem *fpga_ptr;
+ uint32_t ptr_value = 0;
+
+ if (!fpga_addr && support_3d) {
+ pr_err("%s: fpga_addr not set. Failed to enable 3D barrier\n",
+ __func__);
+ return;
+ }
+
+ fpga_ptr = ioremap_nocache(fpga_addr, sizeof(uint32_t));
+ if (!fpga_ptr) {
+ pr_err("%s: FPGA ioremap failed. Failed to enable 3D barrier\n",
+ __func__);
+ return;
+ }
+
+ ptr_value = readl_relaxed(fpga_ptr);
+ if (mode == LANDSCAPE)
+ writel_relaxed(((0xFFFF0000 & ptr_value) | 1), fpga_ptr);
+ else if (mode == PORTRAIT)
+ writel_relaxed(((0xFFFF0000 & ptr_value) | 3), fpga_ptr);
+ else
+ writel_relaxed((0xFFFF0000 & ptr_value), fpga_ptr);
+
+ mb();
+ iounmap(fpga_ptr);
+}
+
+static int mipi_novatek_lcd_on(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct mipi_panel_info *mipi;
+ struct msm_panel_info *pinfo;
+
+ mfd = platform_get_drvdata(pdev);
+ if (!mfd)
+ return -ENODEV;
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ pinfo = &mfd->panel_info;
+ if (pinfo->is_3d_panel)
+ support_3d = TRUE;
+
+ mipi = &mfd->panel_info.mipi;
+
+ if (mipi->mode == DSI_VIDEO_MODE) {
+ mipi_dsi_cmds_tx(mfd, &novatek_tx_buf, novatek_video_on_cmds,
+ ARRAY_SIZE(novatek_video_on_cmds));
+ } else {
+ mipi_dsi_cmds_tx(mfd, &novatek_tx_buf, novatek_cmd_on_cmds,
+ ARRAY_SIZE(novatek_cmd_on_cmds));
+
+ mipi_dsi_cmd_bta_sw_trigger(); /* clean up ack_err_status */
+
+ mipi_novatek_manufacture_id(mfd);
+ }
+
+ return 0;
+}
+
+static int mipi_novatek_lcd_off(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ mipi_dsi_cmds_tx(mfd, &novatek_tx_buf, novatek_display_off_cmds,
+ ARRAY_SIZE(novatek_display_off_cmds));
+
+ return 0;
+}
+
+
+
+static void mipi_novatek_set_backlight(struct msm_fb_data_type *mfd)
+{
+ struct mipi_panel_info *mipi;
+ static int bl_level_old;
+
+ mipi = &mfd->panel_info.mipi;
+ if (bl_level_old == mfd->bl_level)
+ return;
+
+ mutex_lock(&mfd->dma->ov_mutex);
+ /* mdp4_dsi_cmd_busy_wait: will turn on dsi clock also */
+ mdp4_dsi_cmd_dma_busy_wait(mfd);
+ mdp4_dsi_blt_dmap_busy_wait(mfd);
+
+ led_pwm1[1] = (unsigned char)(mfd->bl_level);
+ mipi_dsi_cmds_tx(mfd, &novatek_tx_buf, novatek_cmd_backlight_cmds,
+ ARRAY_SIZE(novatek_cmd_backlight_cmds));
+ bl_level_old = mfd->bl_level;
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return;
+}
+
+static int mipi_dsi_3d_barrier_sysfs_register(struct device *dev);
+static int barrier_mode;
+
+static int __devinit mipi_novatek_lcd_probe(struct platform_device *pdev)
+{
+ if (pdev->id == 0) {
+ mipi_novatek_pdata = pdev->dev.platform_data;
+
+ if (mipi_novatek_pdata && mipi_novatek_pdata->fpga_3d_config_addr)
+ mipi_novatek_3d_init(mipi_novatek_pdata->fpga_3d_config_addr);
+
+ /* create sysfs to control 3D barrier for the Sharp panel */
+ if (mipi_dsi_3d_barrier_sysfs_register(&pdev->dev)) {
+ pr_err("%s: Failed to register 3d Barrier sysfs\n",
+ __func__);
+ return -ENODEV;
+ }
+ barrier_mode = 0;
+
+ return 0;
+ }
+
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = mipi_novatek_lcd_probe,
+ .driver = {
+ .name = "mipi_novatek",
+ },
+};
+
+static struct msm_fb_panel_data novatek_panel_data = {
+ .on = mipi_novatek_lcd_on,
+ .off = mipi_novatek_lcd_off,
+ .set_backlight = mipi_novatek_set_backlight,
+};
+
+static ssize_t mipi_dsi_3d_barrier_read(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf((char *)buf, sizeof(buf), "%u\n", barrier_mode);
+}
+
+static ssize_t mipi_dsi_3d_barrier_write(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ int ret = -1;
+ u32 data = 0;
+
+ if (sscanf((char *)buf, "%u", &data) != 1) {
+ dev_err(dev, "%s\n", __func__);
+ ret = -EINVAL;
+ } else {
+ barrier_mode = data;
+ if (data == 1)
+ mipi_dsi_enable_3d_barrier(LANDSCAPE);
+ else if (data == 2)
+ mipi_dsi_enable_3d_barrier(PORTRAIT);
+ else
+ mipi_dsi_enable_3d_barrier(0);
+ }
+
+ return count;
+}
+
+static struct device_attribute mipi_dsi_3d_barrier_attributes[] = {
+ __ATTR(enable_3d_barrier, 0666, mipi_dsi_3d_barrier_read,
+ mipi_dsi_3d_barrier_write),
+};
+
+static int mipi_dsi_3d_barrier_sysfs_register(struct device *dev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mipi_dsi_3d_barrier_attributes); i++)
+ if (device_create_file(dev, mipi_dsi_3d_barrier_attributes + i))
+ goto error;
+
+ return 0;
+
+error:
+ for (; i >= 0 ; i--)
+ device_remove_file(dev, mipi_dsi_3d_barrier_attributes + i);
+ pr_err("%s: Unable to create interface\n", __func__);
+
+ return -ENODEV;
+}
+
+static int ch_used[3];
+
+int mipi_novatek_device_register(struct msm_panel_info *pinfo,
+ u32 channel, u32 panel)
+{
+ struct platform_device *pdev = NULL;
+ int ret;
+
+ if ((channel >= 3) || ch_used[channel])
+ return -ENODEV;
+
+ ch_used[channel] = TRUE;
+
+ pdev = platform_device_alloc("mipi_novatek", (panel << 8)|channel);
+ if (!pdev)
+ return -ENOMEM;
+
+ novatek_panel_data.panel_info = *pinfo;
+
+ ret = platform_device_add_data(pdev, &novatek_panel_data,
+ sizeof(novatek_panel_data));
+ if (ret) {
+ printk(KERN_ERR
+ "%s: platform_device_add_data failed!\n", __func__);
+ goto err_device_put;
+ }
+
+ ret = platform_device_add(pdev);
+ if (ret) {
+ printk(KERN_ERR
+ "%s: platform_device_register failed!\n", __func__);
+ goto err_device_put;
+ }
+
+ return 0;
+
+err_device_put:
+ platform_device_put(pdev);
+ return ret;
+}
+
+static int __init mipi_novatek_lcd_init(void)
+{
+ mipi_dsi_buf_alloc(&novatek_tx_buf, DSI_BUF_SIZE);
+ mipi_dsi_buf_alloc(&novatek_rx_buf, DSI_BUF_SIZE);
+
+ return platform_driver_register(&this_driver);
+}
+
+module_init(mipi_novatek_lcd_init);
diff --git a/drivers/video/msm/mipi_novatek.h b/drivers/video/msm/mipi_novatek.h
new file mode 100644
index 0000000..f84de9a
--- /dev/null
+++ b/drivers/video/msm/mipi_novatek.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MIPI_NOVATEK_BLUE_H
+#define MIPI_NOVATEK_BLUE_H
+
+#define NOVATEK_TWO_LANE
+
+int mipi_novatek_device_register(struct msm_panel_info *pinfo,
+ u32 channel, u32 panel);
+
+#endif /* MIPI_NOVATEK_BLUE_H */
diff --git a/drivers/video/msm/mipi_novatek_cmd_qhd_pt.c b/drivers/video/msm/mipi_novatek_cmd_qhd_pt.c
new file mode 100644
index 0000000..b3bd6c8
--- /dev/null
+++ b/drivers/video/msm/mipi_novatek_cmd_qhd_pt.c
@@ -0,0 +1,99 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_novatek.h"
+
+static struct msm_panel_info pinfo;
+
+static struct mipi_dsi_phy_ctrl dsi_cmd_mode_phy_db = {
+/* DSI_BIT_CLK at 500MHz, 2 lane, RGB888 */
+ {0x03, 0x01, 0x01, 0x00}, /* regulator */
+ /* timing */
+ {0xB4, 0x8D, 0x1D, 0x00, 0x20, 0x94, 0x20,
+ 0x8F, 0x20, 0x03, 0x04},
+ {0x7f, 0x00, 0x00, 0x00}, /* phy ctrl */
+ {0xee, 0x02, 0x86, 0x00}, /* strength */
+ /* pll control */
+ {0x40, 0xf9, 0xb0, 0xda, 0x00, 0x50, 0x48, 0x63,
+#if defined(NOVATEK_TWO_LANE)
+ 0x30, 0x07, 0x03,
+#else /* default set to 1 lane */
+ 0x30, 0x07, 0x07,
+#endif
+ 0x05, 0x14, 0x03, 0x0, 0x0, 0x54, 0x06, 0x10, 0x04, 0x0},
+};
+
+static int __init mipi_cmd_novatek_blue_qhd_pt_init(void)
+{
+ int ret;
+
+#ifdef CONFIG_FB_MSM_MIPI_PANEL_DETECT
+ if (msm_fb_detect_client("mipi_cmd_novatek_qhd"))
+ return 0;
+#endif
+
+ pinfo.xres = 540;
+ pinfo.yres = 960;
+ pinfo.type = MIPI_CMD_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 24;
+ pinfo.lcdc.h_back_porch = 50;
+ pinfo.lcdc.h_front_porch = 50;
+ pinfo.lcdc.h_pulse_width = 20;
+ pinfo.lcdc.v_back_porch = 11;
+ pinfo.lcdc.v_front_porch = 10;
+ pinfo.lcdc.v_pulse_width = 5;
+ pinfo.lcdc.border_clr = 0; /* blk */
+ pinfo.lcdc.underflow_clr = 0xff; /* blue */
+ pinfo.lcdc.hsync_skew = 0;
+ pinfo.bl_max = 255;
+ pinfo.bl_min = 1;
+ pinfo.fb_num = 2;
+ pinfo.clk_rate = 454000000;
+ pinfo.is_3d_panel = FB_TYPE_3D_PANEL;
+ pinfo.lcd.vsync_enable = TRUE;
+ pinfo.lcd.hw_vsync_mode = TRUE;
+ pinfo.lcd.refx100 = 6000; /* adjust refx100 to prevent tearing */
+
+ pinfo.mipi.mode = DSI_CMD_MODE;
+ pinfo.mipi.dst_format = DSI_CMD_DST_FORMAT_RGB888;
+ pinfo.mipi.vc = 0;
+ pinfo.mipi.rgb_swap = DSI_RGB_SWAP_BGR;
+ pinfo.mipi.data_lane0 = TRUE;
+#if defined(NOVATEK_TWO_LANE)
+ pinfo.mipi.data_lane1 = TRUE;
+#endif
+ pinfo.mipi.t_clk_post = 0x22;
+ pinfo.mipi.t_clk_pre = 0x3f;
+ pinfo.mipi.stream = 0; /* dma_p */
+ pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.te_sel = 1; /* TE from vsycn gpio */
+ pinfo.mipi.interleave_max = 1;
+ pinfo.mipi.insert_dcs_cmd = TRUE;
+ pinfo.mipi.wr_mem_continue = 0x3c;
+ pinfo.mipi.wr_mem_start = 0x2c;
+ pinfo.mipi.dsi_phy_db = &dsi_cmd_mode_phy_db;
+
+ ret = mipi_novatek_device_register(&pinfo, MIPI_DSI_PRIM,
+ MIPI_DSI_PANEL_WVGA_PT);
+ if (ret)
+ pr_err("%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(mipi_cmd_novatek_blue_qhd_pt_init);
diff --git a/drivers/video/msm/mipi_novatek_video_qhd_pt.c b/drivers/video/msm/mipi_novatek_video_qhd_pt.c
new file mode 100644
index 0000000..635b66e
--- /dev/null
+++ b/drivers/video/msm/mipi_novatek_video_qhd_pt.c
@@ -0,0 +1,98 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_novatek.h"
+
+static struct msm_panel_info pinfo;
+
+static struct mipi_dsi_phy_ctrl dsi_video_mode_phy_db = {
+/* DSI_BIT_CLK at 500MHz, 2 lane, RGB888 */
+ {0x03, 0x01, 0x01, 0x00}, /* regulator */
+ /* timing */
+ {0x82, 0x31, 0x13, 0x0, 0x42, 0x4D, 0x18,
+ 0x35, 0x21, 0x03, 0x04},
+ {0x7f, 0x00, 0x00, 0x00}, /* phy ctrl */
+ {0xee, 0x02, 0x86, 0x00}, /* strength */
+ /* pll control */
+ {0x40, 0xf9, 0xb0, 0xda, 0x00, 0x50, 0x48, 0x63,
+#if defined(NOVATEK_TWO_LANE)
+ 0x30, 0x07, 0x03,
+#else /* default set to 1 lane */
+ 0x30, 0x07, 0x07,
+#endif
+ 0x05, 0x14, 0x03, 0x0, 0x0, 0x54, 0x06, 0x10, 0x04, 0x0},
+};
+
+static int __init mipi_video_novatek_qhd_pt_init(void)
+{
+ int ret;
+
+#ifdef CONFIG_FB_MSM_MIPI_PANEL_DETECT
+ if (msm_fb_detect_client("mipi_video_novatek_qhd"))
+ return 0;
+#endif
+
+ pinfo.xres = 540;
+ pinfo.yres = 960;
+ pinfo.type = MIPI_VIDEO_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 24;
+ pinfo.lcdc.h_back_porch = 80;
+ pinfo.lcdc.h_front_porch = 24;
+ pinfo.lcdc.h_pulse_width = 8;
+ pinfo.lcdc.v_back_porch = 16;
+ pinfo.lcdc.v_front_porch = 8;
+ pinfo.lcdc.v_pulse_width = 1;
+ pinfo.lcdc.border_clr = 0; /* blk */
+ pinfo.lcdc.underflow_clr = 0xff; /* blue */
+ pinfo.lcdc.hsync_skew = 0;
+ pinfo.bl_max = 15;
+ pinfo.bl_min = 1;
+ pinfo.fb_num = 2;
+
+ pinfo.mipi.mode = DSI_VIDEO_MODE;
+ pinfo.mipi.pulse_mode_hsa_he = TRUE;
+ pinfo.mipi.hfp_power_stop = FALSE;
+ pinfo.mipi.hbp_power_stop = FALSE;
+ pinfo.mipi.hsa_power_stop = FALSE;
+ pinfo.mipi.eof_bllp_power_stop = TRUE;
+ pinfo.mipi.bllp_power_stop = TRUE;
+ pinfo.mipi.traffic_mode = DSI_NON_BURST_SYNCH_PULSE;
+ pinfo.mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
+ pinfo.mipi.vc = 0;
+ pinfo.mipi.rgb_swap = DSI_RGB_SWAP_BGR;
+ pinfo.mipi.data_lane0 = TRUE;
+#if defined(NOVATEK_TWO_LANE)
+ pinfo.mipi.data_lane1 = TRUE;
+#endif
+ pinfo.mipi.tx_eot_append = TRUE;
+ pinfo.mipi.t_clk_post = 0x04;
+ pinfo.mipi.t_clk_pre = 0x1c;
+ pinfo.mipi.stream = 0; /* dma_p */
+ pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.frame_rate = 60;
+ pinfo.mipi.dsi_phy_db = &dsi_video_mode_phy_db;
+
+ ret = mipi_novatek_device_register(&pinfo, MIPI_DSI_PRIM,
+ MIPI_DSI_PANEL_WVGA_PT);
+ if (ret)
+ pr_err("%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(mipi_video_novatek_qhd_pt_init);
diff --git a/drivers/video/msm/mipi_renesas.c b/drivers/video/msm/mipi_renesas.c
new file mode 100644
index 0000000..652ca29
--- /dev/null
+++ b/drivers/video/msm/mipi_renesas.c
@@ -0,0 +1,1231 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_renesas.h"
+
+#define RENESAS_CMD_DELAY 0 /* 50 */
+#define RENESAS_SLEEP_OFF_DELAY 50
+static struct msm_panel_common_pdata *mipi_renesas_pdata;
+
+static struct dsi_buf renesas_tx_buf;
+static struct dsi_buf renesas_rx_buf;
+
+static char config_sleep_out[2] = {0x11, 0x00};
+static char config_CMD_MODE[2] = {0x40, 0x01};
+static char config_WRTXHT[7] = {0x92, 0x16, 0x08, 0x08, 0x00, 0x01, 0xe0};
+static char config_WRTXVT[7] = {0x8b, 0x02, 0x02, 0x02, 0x00, 0x03, 0x60};
+static char config_PLL2NR[2] = {0xa0, 0x24};
+static char config_PLL2NF1[2] = {0xa2, 0xd0};
+static char config_PLL2NF2[2] = {0xa4, 0x00};
+static char config_PLL2BWADJ1[2] = {0xa6, 0xd0};
+static char config_PLL2BWADJ2[2] = {0xa8, 0x00};
+static char config_PLL2CTL[2] = {0xaa, 0x00};
+static char config_DBICBR[2] = {0x48, 0x03};
+static char config_DBICTYPE[2] = {0x49, 0x00};
+static char config_DBICSET1[2] = {0x4a, 0x1c};
+static char config_DBICADD[2] = {0x4b, 0x00};
+static char config_DBICCTL[2] = {0x4e, 0x01};
+/* static char config_COLMOD_565[2] = {0x3a, 0x05}; */
+/* static char config_COLMOD_666PACK[2] = {0x3a, 0x06}; */
+static char config_COLMOD_888[2] = {0x3a, 0x07};
+static char config_MADCTL[2] = {0x36, 0x00};
+static char config_DBIOC[2] = {0x82, 0x40};
+static char config_CASET[7] = {0x2a, 0x00, 0x00, 0x00, 0x00, 0x01, 0xdf };
+static char config_PASET[7] = {0x2b, 0x00, 0x00, 0x00, 0x00, 0x03, 0x5f };
+static char config_TXON[2] = {0x81, 0x00};
+static char config_BLSET_TM[2] = {0xff, 0x6c};
+
+static char config_AGCPSCTL_TM[2] = {0x56, 0x08};
+
+static char config_DBICADD70[2] = {0x4b, 0x70};
+static char config_DBICSET_15[2] = {0x4a, 0x15};
+static char config_DBICADD72[2] = {0x4b, 0x72};
+
+static char config_Power_Ctrl_2a_cmd[3] = {0x4c, 0x40, 0x10};
+static char config_Auto_Sequencer_Setting_a_cmd[3] = {0x4c, 0x00, 0x00};
+static char Driver_Output_Ctrl_indx[3] = {0x4c, 0x00, 0x01};
+static char Driver_Output_Ctrl_cmd[3] = {0x4c, 0x03, 0x10};
+static char config_LCD_drive_AC_Ctrl_indx[3] = {0x4c, 0x00, 0x02};
+static char config_LCD_drive_AC_Ctrl_cmd[3] = {0x4c, 0x01, 0x00};
+static char config_Entry_Mode_indx[3] = {0x4c, 0x00, 0x03};
+static char config_Entry_Mode_cmd[3] = {0x4c, 0x00, 0x00};
+static char config_Display_Ctrl_1_indx[3] = {0x4c, 0x00, 0x07};
+static char config_Display_Ctrl_1_cmd[3] = {0x4c, 0x00, 0x00};
+static char config_Display_Ctrl_2_indx[3] = {0x4c, 0x00, 0x08};
+static char config_Display_Ctrl_2_cmd[3] = {0x4c, 0x00, 0x04};
+static char config_Display_Ctrl_3_indx[3] = {0x4c, 0x00, 0x09};
+static char config_Display_Ctrl_3_cmd[3] = {0x4c, 0x00, 0x0c};
+static char config_Display_IF_Ctrl_1_indx[3] = {0x4c, 0x00, 0x0c};
+static char config_Display_IF_Ctrl_1_cmd[3] = {0x4c, 0x40, 0x10};
+static char config_Display_IF_Ctrl_2_indx[3] = {0x4c, 0x00, 0x0e};
+static char config_Display_IF_Ctrl_2_cmd[3] = {0x4c, 0x00, 0x00};
+
+static char config_Panel_IF_Ctrl_1_indx[3] = {0x4c, 0x00, 0x20};
+static char config_Panel_IF_Ctrl_1_cmd[3] = {0x4c, 0x01, 0x3f};
+static char config_Panel_IF_Ctrl_3_indx[3] = {0x4c, 0x00, 0x22};
+static char config_Panel_IF_Ctrl_3_cmd[3] = {0x4c, 0x76, 0x00};
+static char config_Panel_IF_Ctrl_4_indx[3] = {0x4c, 0x00, 0x23};
+static char config_Panel_IF_Ctrl_4_cmd[3] = {0x4c, 0x1c, 0x0a};
+static char config_Panel_IF_Ctrl_5_indx[3] = {0x4c, 0x00, 0x24};
+static char config_Panel_IF_Ctrl_5_cmd[3] = {0x4c, 0x1c, 0x2c};
+static char config_Panel_IF_Ctrl_6_indx[3] = {0x4c, 0x00, 0x25};
+static char config_Panel_IF_Ctrl_6_cmd[3] = {0x4c, 0x1c, 0x4e};
+static char config_Panel_IF_Ctrl_8_indx[3] = {0x4c, 0x00, 0x27};
+static char config_Panel_IF_Ctrl_8_cmd[3] = {0x4c, 0x00, 0x00};
+static char config_Panel_IF_Ctrl_9_indx[3] = {0x4c, 0x00, 0x28};
+static char config_Panel_IF_Ctrl_9_cmd[3] = {0x4c, 0x76, 0x0c};
+
+
+static char config_gam_adjust_00_indx[3] = {0x4c, 0x03, 0x00};
+static char config_gam_adjust_00_cmd[3] = {0x4c, 0x00, 0x00};
+static char config_gam_adjust_01_indx[3] = {0x4c, 0x03, 0x01};
+static char config_gam_adjust_01_cmd[3] = {0x4c, 0x05, 0x02};
+static char config_gam_adjust_02_indx[3] = {0x4c, 0x03, 0x02};
+static char config_gam_adjust_02_cmd[3] = {0x4c, 0x07, 0x05};
+static char config_gam_adjust_03_indx[3] = {0x4c, 0x03, 0x03};
+static char config_gam_adjust_03_cmd[3] = {0x4c, 0x00, 0x00};
+static char config_gam_adjust_04_indx[3] = {0x4c, 0x03, 0x04};
+static char config_gam_adjust_04_cmd[3] = {0x4c, 0x02, 0x00};
+static char config_gam_adjust_05_indx[3] = {0x4c, 0x03, 0x05};
+static char config_gam_adjust_05_cmd[3] = {0x4c, 0x07, 0x07};
+static char config_gam_adjust_06_indx[3] = {0x4c, 0x03, 0x06};
+static char config_gam_adjust_06_cmd[3] = {0x4c, 0x10, 0x10};
+static char config_gam_adjust_07_indx[3] = {0x4c, 0x03, 0x07};
+static char config_gam_adjust_07_cmd[3] = {0x4c, 0x02, 0x02};
+static char config_gam_adjust_08_indx[3] = {0x4c, 0x03, 0x08};
+static char config_gam_adjust_08_cmd[3] = {0x4c, 0x07, 0x04};
+static char config_gam_adjust_09_indx[3] = {0x4c, 0x03, 0x09};
+static char config_gam_adjust_09_cmd[3] = {0x4c, 0x07, 0x07};
+static char config_gam_adjust_0A_indx[3] = {0x4c, 0x03, 0x0a};
+static char config_gam_adjust_0A_cmd[3] = {0x4c, 0x00, 0x00};
+static char config_gam_adjust_0B_indx[3] = {0x4c, 0x03, 0x0b};
+static char config_gam_adjust_0B_cmd[3] = {0x4c, 0x00, 0x00};
+static char config_gam_adjust_0C_indx[3] = {0x4c, 0x03, 0x0c};
+static char config_gam_adjust_0C_cmd[3] = {0x4c, 0x07, 0x07};
+static char config_gam_adjust_0D_indx[3] = {0x4c, 0x03, 0x0d};
+static char config_gam_adjust_0D_cmd[3] = {0x4c, 0x10, 0x10};
+static char config_gam_adjust_10_indx[3] = {0x4c, 0x03, 0x10};
+static char config_gam_adjust_10_cmd[3] = {0x4c, 0x01, 0x04};
+static char config_gam_adjust_11_indx[3] = {0x4c, 0x03, 0x11};
+static char config_gam_adjust_11_cmd[3] = {0x4c, 0x05, 0x03};
+static char config_gam_adjust_12_indx[3] = {0x4c, 0x03, 0x12};
+static char config_gam_adjust_12_cmd[3] = {0x4c, 0x03, 0x04};
+static char config_gam_adjust_15_indx[3] = {0x4c, 0x03, 0x15};
+static char config_gam_adjust_15_cmd[3] = {0x4c, 0x03, 0x04};
+static char config_gam_adjust_16_indx[3] = {0x4c, 0x03, 0x16};
+static char config_gam_adjust_16_cmd[3] = {0x4c, 0x03, 0x1c};
+static char config_gam_adjust_17_indx[3] = {0x4c, 0x03, 0x17};
+static char config_gam_adjust_17_cmd[3] = {0x4c, 0x02, 0x04};
+static char config_gam_adjust_18_indx[3] = {0x4c, 0x03, 0x18};
+static char config_gam_adjust_18_cmd[3] = {0x4c, 0x04, 0x02};
+static char config_gam_adjust_19_indx[3] = {0x4c, 0x03, 0x19};
+static char config_gam_adjust_19_cmd[3] = {0x4c, 0x03, 0x05};
+static char config_gam_adjust_1C_indx[3] = {0x4c, 0x03, 0x1c};
+static char config_gam_adjust_1C_cmd[3] = {0x4c, 0x07, 0x07};
+static char config_gam_adjust_1D_indx[3] = {0x4c, 0x03, 0x1D};
+static char config_gam_adjust_1D_cmd[3] = {0x4c, 0x02, 0x1f};
+static char config_gam_adjust_20_indx[3] = {0x4c, 0x03, 0x20};
+static char config_gam_adjust_20_cmd[3] = {0x4c, 0x05, 0x07};
+static char config_gam_adjust_21_indx[3] = {0x4c, 0x03, 0x21};
+static char config_gam_adjust_21_cmd[3] = {0x4c, 0x06, 0x04};
+static char config_gam_adjust_22_indx[3] = {0x4c, 0x03, 0x22};
+static char config_gam_adjust_22_cmd[3] = {0x4c, 0x04, 0x05};
+static char config_gam_adjust_27_indx[3] = {0x4c, 0x03, 0x27};
+static char config_gam_adjust_27_cmd[3] = {0x4c, 0x02, 0x03};
+static char config_gam_adjust_28_indx[3] = {0x4c, 0x03, 0x28};
+static char config_gam_adjust_28_cmd[3] = {0x4c, 0x03, 0x00};
+static char config_gam_adjust_29_indx[3] = {0x4c, 0x03, 0x29};
+static char config_gam_adjust_29_cmd[3] = {0x4c, 0x00, 0x02};
+
+static char config_Power_Ctrl_1_indx[3] = {0x4c, 0x01, 0x00};
+static char config_Power_Ctrl_1b_cmd[3] = {0x4c, 0x36, 0x3c};
+static char config_Power_Ctrl_2_indx[3] = {0x4c, 0x01, 0x01};
+static char config_Power_Ctrl_2b_cmd[3] = {0x4c, 0x40, 0x03};
+static char config_Power_Ctrl_3_indx[3] = {0x4c, 0x01, 0x02};
+static char config_Power_Ctrl_3a_cmd[3] = {0x4c, 0x00, 0x01};
+static char config_Power_Ctrl_4_indx[3] = {0x4c, 0x01, 0x03};
+static char config_Power_Ctrl_4a_cmd[3] = {0x4c, 0x3c, 0x58};
+static char config_Power_Ctrl_6_indx[3] = {0x4c, 0x01, 0x0c};
+static char config_Power_Ctrl_6a_cmd[3] = {0x4c, 0x01, 0x35};
+
+static char config_Auto_Sequencer_Setting_b_cmd[3] = {0x4c, 0x00, 0x02};
+
+static char config_Panel_IF_Ctrl_10_indx[3] = {0x4c, 0x00, 0x29};
+static char config_Panel_IF_Ctrl_10a_cmd[3] = {0x4c, 0x03, 0xbf};
+static char config_Auto_Sequencer_Setting_indx[3] = {0x4c, 0x01, 0x06};
+static char config_Auto_Sequencer_Setting_c_cmd[3] = {0x4c, 0x00, 0x03};
+static char config_Power_Ctrl_2c_cmd[3] = {0x4c, 0x40, 0x10};
+
+static char config_VIDEO[2] = {0x40, 0x00};
+
+static char config_Panel_IF_Ctrl_10_indx_off[3] = {0x4C, 0x00, 0x29};
+
+static char config_Panel_IF_Ctrl_10b_cmd_off[3] = {0x4C, 0x00, 0x02};
+
+static char config_Power_Ctrl_1a_cmd[3] = {0x4C, 0x30, 0x00};
+
+static struct dsi_cmd_desc renesas_sleep_off_cmds[] = {
+ {DTYPE_DCS_WRITE, 1, 0, 0, RENESAS_SLEEP_OFF_DELAY,
+ sizeof(config_sleep_out), config_sleep_out }
+};
+
+static struct dsi_cmd_desc renesas_display_off_cmds[] = {
+ /* Choosing Command Mode */
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_CMD_MODE), config_CMD_MODE },
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Auto_Sequencer_Setting_indx),
+ config_Auto_Sequencer_Setting_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Auto_Sequencer_Setting_b_cmd),
+ config_Auto_Sequencer_Setting_b_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY * 2,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ /* After waiting >= 5 frames, turn OFF RGB signals
+ This is done by on DSI/MDP (depends on Vid/Cmd Mode. */
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Auto_Sequencer_Setting_indx),
+ config_Auto_Sequencer_Setting_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Auto_Sequencer_Setting_a_cmd),
+ config_Auto_Sequencer_Setting_a_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Panel_IF_Ctrl_10_indx_off),
+ config_Panel_IF_Ctrl_10_indx_off},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Panel_IF_Ctrl_10b_cmd_off),
+ config_Panel_IF_Ctrl_10b_cmd_off},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Power_Ctrl_1_indx),
+ config_Power_Ctrl_1_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Power_Ctrl_1a_cmd),
+ config_Power_Ctrl_1a_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15}
+};
+
+static struct dsi_cmd_desc renesas_display_on_cmds[] = {
+ /* Choosing Command Mode */
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_CMD_MODE), config_CMD_MODE },
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_WRTXHT), config_WRTXHT },
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_WRTXVT), config_WRTXVT },
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_PLL2NR), config_PLL2NR },
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_PLL2NF1), config_PLL2NF1 },
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_PLL2NF2), config_PLL2NF2 },
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_PLL2BWADJ1), config_PLL2BWADJ1},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_PLL2BWADJ2), config_PLL2BWADJ2},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_PLL2CTL), config_PLL2CTL},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICBR), config_DBICBR},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICTYPE), config_DBICTYPE},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET1), config_DBICSET1},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD), config_DBICADD},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICCTL), config_DBICCTL},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_COLMOD_888), config_COLMOD_888},
+ /* Choose config_COLMOD_565 or config_COLMOD_666PACK for other modes */
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_MADCTL), config_MADCTL},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBIOC), config_DBIOC},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_CASET), config_CASET},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_PASET), config_PASET},
+ {DTYPE_DCS_WRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_TXON), config_TXON},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_BLSET_TM), config_BLSET_TM},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_AGCPSCTL_TM), config_AGCPSCTL_TM},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Power_Ctrl_1_indx), config_Power_Ctrl_1_indx },
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Power_Ctrl_1a_cmd), config_Power_Ctrl_1a_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Power_Ctrl_2_indx), config_Power_Ctrl_2_indx },
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Power_Ctrl_2a_cmd), config_Power_Ctrl_2a_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Auto_Sequencer_Setting_indx),
+ config_Auto_Sequencer_Setting_indx },
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Auto_Sequencer_Setting_a_cmd),
+ config_Auto_Sequencer_Setting_a_cmd },
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(Driver_Output_Ctrl_indx), Driver_Output_Ctrl_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(Driver_Output_Ctrl_cmd),
+ Driver_Output_Ctrl_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_LCD_drive_AC_Ctrl_indx),
+ config_LCD_drive_AC_Ctrl_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_LCD_drive_AC_Ctrl_cmd),
+ config_LCD_drive_AC_Ctrl_cmd },
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Entry_Mode_indx),
+ config_Entry_Mode_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Entry_Mode_cmd),
+ config_Entry_Mode_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Display_Ctrl_1_indx),
+ config_Display_Ctrl_1_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Display_Ctrl_1_cmd),
+ config_Display_Ctrl_1_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Display_Ctrl_2_indx),
+ config_Display_Ctrl_2_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Display_Ctrl_2_cmd),
+ config_Display_Ctrl_2_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Display_Ctrl_3_indx),
+ config_Display_Ctrl_3_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Display_Ctrl_3_cmd),
+ config_Display_Ctrl_3_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Display_IF_Ctrl_1_indx),
+ config_Display_IF_Ctrl_1_indx },
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Display_IF_Ctrl_1_cmd),
+ config_Display_IF_Ctrl_1_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Display_IF_Ctrl_2_indx),
+ config_Display_IF_Ctrl_2_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Display_IF_Ctrl_2_cmd),
+ config_Display_IF_Ctrl_2_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Panel_IF_Ctrl_1_indx),
+ config_Panel_IF_Ctrl_1_indx },
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Panel_IF_Ctrl_1_cmd),
+ config_Panel_IF_Ctrl_1_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Panel_IF_Ctrl_3_indx),
+ config_Panel_IF_Ctrl_3_indx },
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Panel_IF_Ctrl_3_cmd),
+ config_Panel_IF_Ctrl_3_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Panel_IF_Ctrl_4_indx),
+ config_Panel_IF_Ctrl_4_indx },
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Panel_IF_Ctrl_4_cmd),
+ config_Panel_IF_Ctrl_4_cmd },
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Panel_IF_Ctrl_5_indx),
+ config_Panel_IF_Ctrl_5_indx },
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Panel_IF_Ctrl_5_cmd),
+ config_Panel_IF_Ctrl_5_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Panel_IF_Ctrl_6_indx),
+ config_Panel_IF_Ctrl_6_indx },
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Panel_IF_Ctrl_6_cmd),
+ config_Panel_IF_Ctrl_6_cmd },
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Panel_IF_Ctrl_8_indx),
+ config_Panel_IF_Ctrl_8_indx },
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Panel_IF_Ctrl_8_cmd),
+ config_Panel_IF_Ctrl_8_cmd },
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Panel_IF_Ctrl_9_indx),
+ config_Panel_IF_Ctrl_9_indx },
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Panel_IF_Ctrl_9_cmd),
+ config_Panel_IF_Ctrl_9_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_00_indx),
+ config_gam_adjust_00_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_00_cmd),
+ config_gam_adjust_00_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_01_indx),
+ config_gam_adjust_01_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_01_cmd),
+ config_gam_adjust_01_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_02_indx),
+ config_gam_adjust_02_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_02_cmd),
+ config_gam_adjust_02_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_03_indx),
+ config_gam_adjust_03_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_03_cmd),
+ config_gam_adjust_03_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_04_indx), config_gam_adjust_04_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_04_cmd), config_gam_adjust_04_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_05_indx), config_gam_adjust_05_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_05_cmd), config_gam_adjust_05_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_06_indx), config_gam_adjust_06_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_06_cmd), config_gam_adjust_06_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_07_indx), config_gam_adjust_07_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_07_cmd), config_gam_adjust_07_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_08_indx), config_gam_adjust_08_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_08_cmd), config_gam_adjust_08_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_09_indx), config_gam_adjust_09_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_09_cmd), config_gam_adjust_09_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_0A_indx), config_gam_adjust_0A_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_0A_cmd), config_gam_adjust_0A_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_0B_indx), config_gam_adjust_0B_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_0B_cmd), config_gam_adjust_0B_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_0C_indx), config_gam_adjust_0C_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_0C_cmd), config_gam_adjust_0C_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_0D_indx), config_gam_adjust_0D_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_0D_cmd), config_gam_adjust_0D_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_10_indx), config_gam_adjust_10_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_10_cmd), config_gam_adjust_10_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_11_indx), config_gam_adjust_11_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_11_cmd), config_gam_adjust_11_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_12_indx), config_gam_adjust_12_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_12_cmd), config_gam_adjust_12_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_15_indx), config_gam_adjust_15_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_15_cmd), config_gam_adjust_15_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_16_indx), config_gam_adjust_16_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_16_cmd), config_gam_adjust_16_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_17_indx), config_gam_adjust_17_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_17_cmd), config_gam_adjust_17_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_18_indx), config_gam_adjust_18_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_18_cmd), config_gam_adjust_18_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_19_indx), config_gam_adjust_19_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_19_cmd), config_gam_adjust_19_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_1C_indx), config_gam_adjust_1C_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_1C_cmd), config_gam_adjust_1C_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_1D_indx), config_gam_adjust_1D_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_1D_cmd), config_gam_adjust_1D_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_20_indx), config_gam_adjust_20_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_20_cmd), config_gam_adjust_20_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_21_indx), config_gam_adjust_21_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_21_cmd), config_gam_adjust_21_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_22_indx), config_gam_adjust_22_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_22_cmd), config_gam_adjust_22_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_27_indx), config_gam_adjust_27_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_27_cmd), config_gam_adjust_27_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_28_indx), config_gam_adjust_28_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_28_cmd), config_gam_adjust_28_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_29_indx), config_gam_adjust_29_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_gam_adjust_29_cmd), config_gam_adjust_29_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Power_Ctrl_1_indx), config_Power_Ctrl_1_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Power_Ctrl_1b_cmd), config_Power_Ctrl_1b_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Power_Ctrl_2_indx), config_Power_Ctrl_2_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Power_Ctrl_2b_cmd), config_Power_Ctrl_2b_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Power_Ctrl_3_indx), config_Power_Ctrl_3_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Power_Ctrl_3a_cmd), config_Power_Ctrl_3a_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Power_Ctrl_4_indx), config_Power_Ctrl_4_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Power_Ctrl_4a_cmd), config_Power_Ctrl_4a_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Power_Ctrl_6_indx), config_Power_Ctrl_6_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Power_Ctrl_6a_cmd), config_Power_Ctrl_6a_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Auto_Sequencer_Setting_indx),
+ config_Auto_Sequencer_Setting_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Auto_Sequencer_Setting_b_cmd),
+ config_Auto_Sequencer_Setting_b_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Panel_IF_Ctrl_10_indx),
+ config_Panel_IF_Ctrl_10_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Panel_IF_Ctrl_10a_cmd),
+ config_Panel_IF_Ctrl_10a_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Auto_Sequencer_Setting_indx),
+ config_Auto_Sequencer_Setting_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Auto_Sequencer_Setting_c_cmd),
+ config_Auto_Sequencer_Setting_c_cmd},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD70), config_DBICADD70},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Power_Ctrl_2_indx),
+ config_Power_Ctrl_2_indx},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DBICADD72), config_DBICADD72},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_Power_Ctrl_2c_cmd),
+ config_Power_Ctrl_2c_cmd},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, 0/* RENESAS_CMD_DELAY */,
+ sizeof(config_DBICSET_15), config_DBICSET_15},
+
+};
+
+static struct dsi_cmd_desc renesas_video_on_cmds[] = {
+{DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_VIDEO), config_VIDEO}
+};
+
+static struct dsi_cmd_desc renesas_cmd_on_cmds[] = {
+{DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_CMD_MODE), config_CMD_MODE},
+};
+
+static int mipi_renesas_lcd_on(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct mipi_panel_info *mipi;
+
+ mfd = platform_get_drvdata(pdev);
+ mipi = &mfd->panel_info.mipi;
+
+ if (!mfd)
+ return -ENODEV;
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ mipi_dsi_cmds_tx(mfd, &renesas_tx_buf, renesas_sleep_off_cmds,
+ ARRAY_SIZE(renesas_sleep_off_cmds));
+
+ mipi_set_tx_power_mode(1);
+ mipi_dsi_cmds_tx(mfd, &renesas_tx_buf, renesas_display_on_cmds,
+ ARRAY_SIZE(renesas_display_on_cmds));
+
+ if (mipi->mode == DSI_VIDEO_MODE)
+ mipi_dsi_cmds_tx(mfd, &renesas_tx_buf, renesas_video_on_cmds,
+ ARRAY_SIZE(renesas_video_on_cmds));
+ else
+ mipi_dsi_cmds_tx(mfd, &renesas_tx_buf, renesas_cmd_on_cmds,
+ ARRAY_SIZE(renesas_cmd_on_cmds));
+ mipi_set_tx_power_mode(0);
+
+ return 0;
+}
+
+static int mipi_renesas_lcd_off(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ mipi_dsi_cmds_tx(mfd, &renesas_tx_buf, renesas_display_off_cmds,
+ ARRAY_SIZE(renesas_display_off_cmds));
+
+ return 0;
+}
+
+static int __devinit mipi_renesas_lcd_probe(struct platform_device *pdev)
+{
+ if (pdev->id == 0) {
+ mipi_renesas_pdata = pdev->dev.platform_data;
+ return 0;
+ }
+
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static void mipi_renesas_set_backlight(struct msm_fb_data_type *mfd)
+{
+ int ret = -EPERM;
+ int bl_level;
+
+ bl_level = mfd->bl_level;
+
+ if (mipi_renesas_pdata && mipi_renesas_pdata->pmic_backlight)
+ ret = mipi_renesas_pdata->pmic_backlight(bl_level);
+ else
+ pr_err("%s(): Backlight level set failed", __func__);
+}
+
+static struct platform_driver this_driver = {
+ .probe = mipi_renesas_lcd_probe,
+ .driver = {
+ .name = "mipi_renesas",
+ },
+};
+
+static struct msm_fb_panel_data renesas_panel_data = {
+ .on = mipi_renesas_lcd_on,
+ .off = mipi_renesas_lcd_off,
+ .set_backlight = mipi_renesas_set_backlight,
+};
+
+static int ch_used[3];
+
+int mipi_renesas_device_register(struct msm_panel_info *pinfo,
+ u32 channel, u32 panel)
+{
+ struct platform_device *pdev = NULL;
+ int ret;
+ if ((channel >= 3) || ch_used[channel])
+ return -ENODEV;
+
+ ch_used[channel] = TRUE;
+
+ pdev = platform_device_alloc("mipi_renesas", (panel << 8)|channel);
+ if (!pdev)
+ return -ENOMEM;
+
+ renesas_panel_data.panel_info = *pinfo;
+
+ ret = platform_device_add_data(pdev, &renesas_panel_data,
+ sizeof(renesas_panel_data));
+ if (ret) {
+ pr_err("%s: platform_device_add_data failed!\n", __func__);
+ goto err_device_put;
+ }
+
+ ret = platform_device_add(pdev);
+ if (ret) {
+ pr_err("%s: platform_device_register failed!\n", __func__);
+ goto err_device_put;
+ }
+
+ return 0;
+
+err_device_put:
+ platform_device_put(pdev);
+ return ret;
+}
+
+static int __init mipi_renesas_lcd_init(void)
+{
+ mipi_dsi_buf_alloc(&renesas_tx_buf, DSI_BUF_SIZE);
+ mipi_dsi_buf_alloc(&renesas_rx_buf, DSI_BUF_SIZE);
+
+ return platform_driver_register(&this_driver);
+}
+
+module_init(mipi_renesas_lcd_init);
diff --git a/drivers/video/msm/mipi_renesas.h b/drivers/video/msm/mipi_renesas.h
new file mode 100644
index 0000000..59ccfd0
--- /dev/null
+++ b/drivers/video/msm/mipi_renesas.h
@@ -0,0 +1,21 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MIPI_RENESAS_H
+#define MIPI_RENESAS_H
+
+#define RENESAS_FWVGA_TWO_LANE
+
+int mipi_renesas_device_register(struct msm_panel_info *pinfo,
+ u32 channel, u32 panel);
+
+#endif /* MIPI_RENESAS_H */
diff --git a/drivers/video/msm/mipi_renesas_cmd_fwvga_pt.c b/drivers/video/msm/mipi_renesas_cmd_fwvga_pt.c
new file mode 100644
index 0000000..ff573a3
--- /dev/null
+++ b/drivers/video/msm/mipi_renesas_cmd_fwvga_pt.c
@@ -0,0 +1,162 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_renesas.h"
+
+static struct msm_panel_info pinfo;
+
+static struct mipi_dsi_phy_ctrl dsi_cmd_mode_phy_db = {
+#ifdef CONFIG_FB_MSM_MDP303
+ /* DSI Bit Clock at 500 MHz, 2 lane, RGB888 */
+ /* regulator */
+ {0x03, 0x01, 0x01, 0x00},
+ /* timing */
+ {0xb9, 0x8e, 0x1f, 0x00, 0x98, 0x9c, 0x22, 0x90,
+ 0x18, 0x03, 0x04},
+ /* phy ctrl */
+ {0x7f, 0x00, 0x00, 0x00},
+ /* strength */
+ {0xbb, 0x02, 0x06, 0x00},
+ /* pll control */
+ {0x01, 0xec, 0x31, 0xd2, 0x00, 0x40, 0x37, 0x62,
+ 0x01, 0x0f, 0x07,
+ 0x05, 0x14, 0x03, 0x0, 0x0, 0x0, 0x20, 0x0, 0x02, 0x0},
+#else
+ /* DSI_BIT_CLK at 400MHz, 1 lane, RGB888 */
+ {0x03, 0x01, 0x01, 0x00}, /* regulator */
+ /* timing */
+ {0x22, 0x0c, 0x7, 0x00, 0x10, 0x20, 0x10,
+ 0xd, 0x8, 0x2, 0x3},
+ /* phy ctrl */
+ {0x7f, 0x00, 0x00, 0x00},
+ /* strength */
+ {0xee, 0x00, 0x6, 0x00},
+ /* pll control */
+ {0x40, 0x2f, 0xb1, 0xda, 0x00, 0x50, 0x48, 0x63,
+#if defined(RENESAS_FWVGA_TWO_LANE)
+ 0x33, 0x1f, 0x07,
+#else /* default set to 1 lane */
+ 0x30, 0x07, 0x07,
+#endif
+ 0x05, 0x14, 0x03, 0x0, 0x0, 0x54, 0x06, 0x10, 0x04, 0x0},
+#endif
+};
+
+static int __init mipi_cmd_renesas_fwvga_pt_init(void)
+{
+ int ret;
+
+#ifdef CONFIG_FB_MSM_MIPI_PANEL_DETECT
+ if (msm_fb_detect_client("mipi_cmd_renesas_fwvga"))
+ return 0;
+#endif
+
+ pinfo.xres = 480;
+ pinfo.yres = 864;
+ pinfo.type = MIPI_CMD_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 24;
+#ifdef CONFIG_FB_MSM_MDP303
+ pinfo.lcdc.h_back_porch = 100;
+ pinfo.lcdc.h_front_porch = 100;
+ pinfo.lcdc.h_pulse_width = 8;
+ pinfo.lcdc.v_back_porch = 20;
+ pinfo.lcdc.v_front_porch = 20;
+ pinfo.lcdc.v_pulse_width = 1;
+#else
+ pinfo.lcdc.h_front_porch = 50;
+#if defined(RENESAS_FWVGA_TWO_LANE)
+ pinfo.lcdc.h_back_porch = 400;
+ pinfo.lcdc.h_pulse_width = 5;
+ pinfo.lcdc.v_back_porch = 75;
+ pinfo.lcdc.v_front_porch = 5;
+ pinfo.lcdc.v_pulse_width = 1;
+#else
+ pinfo.lcdc.h_back_porch = 50;
+ pinfo.lcdc.h_pulse_width = 20;
+ pinfo.lcdc.v_back_porch = 10;
+ pinfo.lcdc.v_front_porch = 10;
+ pinfo.lcdc.v_pulse_width = 5;
+#endif
+
+#endif /* CONFIG_FB_MSM_MDP303 */
+ pinfo.lcdc.border_clr = 0; /* blk */
+ pinfo.lcdc.underflow_clr = 0xff; /* blue */
+ pinfo.lcdc.hsync_skew = 0;
+ pinfo.bl_max = 100;
+ pinfo.bl_min = 1;
+ pinfo.fb_num = 2;
+
+#ifdef CONFIG_FB_MSM_MDP303
+ pinfo.clk_rate = 499000000;
+#else
+ pinfo.clk_rate = 152000000;
+#endif
+
+#ifdef USE_HW_VSYNC
+ pinfo.lcd.vsync_enable = TRUE;
+ pinfo.lcd.hw_vsync_mode = TRUE;
+#endif
+ pinfo.lcd.refx100 = 6000; /* adjust refx100 to prevent tearing */
+
+ pinfo.mipi.mode = DSI_CMD_MODE;
+ pinfo.mipi.dst_format = DSI_CMD_DST_FORMAT_RGB888;
+ pinfo.mipi.vc = 0;
+ pinfo.mipi.rgb_swap = DSI_RGB_SWAP_RGB;
+ pinfo.mipi.data_lane0 = TRUE;
+#ifdef CONFIG_FB_MSM_MDP303
+ pinfo.mipi.data_lane1 = TRUE;
+ pinfo.mipi.t_clk_post = 0x20;
+ pinfo.mipi.t_clk_pre = 0x2F;
+ pinfo.mipi.stream = 0; /* dma_p */
+ pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.te_sel = 0; /* TE from vsync gpio */
+ pinfo.mipi.interleave_max = 1;
+ pinfo.mipi.insert_dcs_cmd = TRUE;
+ pinfo.mipi.wr_mem_continue = 0x3c;
+ pinfo.mipi.wr_mem_start = 0x2c;
+ pinfo.mipi.dsi_phy_db = &dsi_cmd_mode_phy_db;
+ pinfo.mipi.tx_eot_append = 0x01;
+ pinfo.mipi.rx_eot_ignore = 0;
+ pinfo.mipi.dlane_swap = 0x01;
+#else
+#if defined(RENESAS_FWVGA_TWO_LANE)
+ pinfo.mipi.data_lane1 = TRUE;
+#else
+ pinfo.mipi.data_lane1 = FALSE;
+#endif
+ pinfo.mipi.t_clk_post = 0x18;
+ pinfo.mipi.t_clk_pre = 0x14;
+ pinfo.mipi.stream = 0; /* dma_p */
+ pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.te_sel = 1; /* TE from vsycn gpio */
+ pinfo.mipi.interleave_max = 1;
+ pinfo.mipi.insert_dcs_cmd = TRUE;
+ pinfo.mipi.wr_mem_continue = 0x3c;
+ pinfo.mipi.wr_mem_start = 0x2c;
+ pinfo.mipi.dsi_phy_db = &dsi_cmd_mode_phy_db;
+#endif /* CONFIG_FB_MSM_MDP303 */
+
+ ret = mipi_renesas_device_register(&pinfo, MIPI_DSI_PRIM,
+ MIPI_DSI_PANEL_FWVGA_PT);
+ if (ret)
+ pr_err("%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(mipi_cmd_renesas_fwvga_pt_init);
diff --git a/drivers/video/msm/mipi_renesas_video_fwvga_pt.c b/drivers/video/msm/mipi_renesas_video_fwvga_pt.c
new file mode 100644
index 0000000..0e49011
--- /dev/null
+++ b/drivers/video/msm/mipi_renesas_video_fwvga_pt.c
@@ -0,0 +1,165 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_renesas.h"
+
+static struct msm_panel_info pinfo;
+
+static struct mipi_dsi_phy_ctrl dsi_video_mode_phy_db = {
+#ifdef CONFIG_FB_MSM_MDP303
+ /* DSI Bit Clock at 500 MHz, 2 lane, RGB888 */
+ /* regulator */
+ {0x03, 0x01, 0x01, 0x00},
+ /* timing */
+ {0xb9, 0x8e, 0x1f, 0x00, 0x98, 0x9c, 0x22, 0x90,
+ 0x18, 0x03, 0x04},
+ /* phy ctrl */
+ {0x7f, 0x00, 0x00, 0x00},
+ /* strength */
+ {0xbb, 0x02, 0x06, 0x00},
+ /* pll control */
+ {0x00, 0xec, 0x31, 0xd2, 0x00, 0x40, 0x37, 0x62,
+ 0x01, 0x0f, 0x07,
+ 0x05, 0x14, 0x03, 0x0, 0x0, 0x0, 0x20, 0x0, 0x02, 0x0},
+#else
+ /* DSI_BIT_CLK at 400MHz, 1 lane, RGB888 */
+ /* regulator */
+ {0x03, 0x01, 0x01, 0x00},
+ /* timing */
+ {0xaa, 0x3b, 0x1b, 0x00, 0x52, 0x58, 0x20, 0x3f,
+ 0x2e, 0x03, 0x04},
+ /* phy ctrl */
+ {0x7f, 0x00, 0x00, 0x00},
+ /* strength */
+ {0xee, 0x00, 0x86, 0x00},
+ /* pll control */
+ {0x40, 0xc7, 0xb0, 0xda, 0x00, 0x50, 0x48, 0x63,
+#if defined(RENESAS_FWVGA_TWO_LANE)
+ 0x30, 0x07, 0x03,
+#else
+ /* default set to 1 lane */
+ 0x30, 0x07, 0x07,
+#endif
+ 0x05, 0x14, 0x03, 0x0, 0x0, 0x54, 0x06, 0x10, 0x04, 0x0},
+#endif
+};
+
+static int __init mipi_video_renesas_fwvga_pt_init(void)
+{
+ int ret;
+
+#ifdef CONFIG_FB_MSM_MIPI_PANEL_DETECT
+ if (msm_fb_detect_client("mipi_video_renesas_fwvga"))
+ return 0;
+#endif
+
+ pinfo.xres = 480;
+ pinfo.yres = 864;
+ pinfo.type = MIPI_VIDEO_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 24;
+#ifdef CONFIG_FB_MSM_MDP303
+ pinfo.lcdc.h_back_porch = 100;
+ pinfo.lcdc.h_front_porch = 100;
+ pinfo.lcdc.h_pulse_width = 8;
+ pinfo.lcdc.v_back_porch = 20;
+ pinfo.lcdc.v_front_porch = 20;
+ pinfo.lcdc.v_pulse_width = 1;
+ pinfo.clk_rate = 499000000;
+#else
+
+#if defined(RENESAS_FWVGA_TWO_LANE)
+ pinfo.lcdc.h_back_porch = 400;
+#else
+ pinfo.lcdc.h_back_porch = 50;
+#endif
+ pinfo.lcdc.h_front_porch = 50;
+
+#if defined(RENESAS_FWVGA_TWO_LANE)
+ pinfo.lcdc.h_pulse_width = 5;
+#else
+ pinfo.lcdc.h_pulse_width = 20;
+#endif
+
+#if defined(RENESAS_FWVGA_TWO_LANE)
+ pinfo.lcdc.v_back_porch = 75;
+ pinfo.lcdc.v_front_porch = 5;
+ pinfo.lcdc.v_pulse_width = 1;
+#else
+ pinfo.lcdc.v_back_porch = 10;
+ pinfo.lcdc.v_front_porch = 10;
+ pinfo.lcdc.v_pulse_width = 5;
+#endif
+
+#endif
+ pinfo.lcdc.border_clr = 0; /* blk */
+ pinfo.lcdc.underflow_clr = 0xff; /* blue */
+ pinfo.lcdc.hsync_skew = 0;
+ pinfo.bl_max = 100;
+ pinfo.bl_min = 1;
+ pinfo.fb_num = 2;
+
+ pinfo.mipi.mode = DSI_VIDEO_MODE;
+ pinfo.mipi.pulse_mode_hsa_he = TRUE;
+ pinfo.mipi.hfp_power_stop = TRUE;
+ pinfo.mipi.hbp_power_stop = TRUE;
+ pinfo.mipi.hsa_power_stop = TRUE;
+ pinfo.mipi.eof_bllp_power_stop = TRUE;
+ pinfo.mipi.bllp_power_stop = TRUE;
+#ifdef CONFIG_FB_MSM_MDP303
+ pinfo.mipi.traffic_mode = DSI_BURST_MODE;
+ pinfo.mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
+ pinfo.mipi.vc = 0;
+ pinfo.mipi.rgb_swap = DSI_RGB_SWAP_RGB;
+ pinfo.mipi.data_lane0 = TRUE;
+ pinfo.mipi.data_lane1 = TRUE;
+ pinfo.mipi.t_clk_post = 0x20;
+ pinfo.mipi.t_clk_pre = 0x2F;
+ pinfo.mipi.stream = 0; /* dma_p */
+ pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_NONE;
+ pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.frame_rate = 60;
+ pinfo.mipi.dsi_phy_db = &dsi_video_mode_phy_db;
+ pinfo.mipi.dlane_swap = 0x01;
+ pinfo.mipi.tx_eot_append = 0x01;
+#else
+ pinfo.mipi.traffic_mode = DSI_NON_BURST_SYNCH_PULSE;
+ pinfo.mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
+ pinfo.mipi.vc = 0;
+ pinfo.mipi.rgb_swap = DSI_RGB_SWAP_BGR;
+ pinfo.mipi.data_lane0 = TRUE;
+#if defined(RENESAS_FWVGA_TWO_LANE)
+ pinfo.mipi.data_lane1 = TRUE;
+#else
+ pinfo.mipi.data_lane1 = FALSE;
+#endif
+ pinfo.mipi.t_clk_post = 0x03;
+ pinfo.mipi.t_clk_pre = 0x24;
+ pinfo.mipi.stream = 0; /* dma_p */
+ pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.frame_rate = 60;
+ pinfo.mipi.dsi_phy_db = &dsi_video_mode_phy_db;
+#endif
+
+ ret = mipi_renesas_device_register(&pinfo, MIPI_DSI_PRIM,
+ MIPI_DSI_PANEL_FWVGA_PT);
+ if (ret)
+ pr_err("%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(mipi_video_renesas_fwvga_pt_init);
diff --git a/drivers/video/msm/mipi_simulator.c b/drivers/video/msm/mipi_simulator.c
new file mode 100644
index 0000000..da697b5
--- /dev/null
+++ b/drivers/video/msm/mipi_simulator.c
@@ -0,0 +1,162 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_simulator.h"
+
+static struct dsi_buf simulator_tx_buf;
+static struct dsi_buf simulator_rx_buf;
+static struct msm_panel_common_pdata *mipi_simulator_pdata;
+
+static char display_on[2] = {0x00, 0x00};
+static char display_off[2] = {0x00, 0x00};
+
+static struct dsi_cmd_desc display_on_cmds[] = {
+ {DTYPE_PERIPHERAL_ON, 1, 0, 0, 0, sizeof(display_on),
+ display_on}
+};
+static struct dsi_cmd_desc display_off_cmds[] = {
+ {DTYPE_PERIPHERAL_OFF, 1, 0, 0, 0, sizeof(display_off),
+ display_off}
+};
+
+static int mipi_simulator_lcd_on(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct mipi_panel_info *mipi;
+
+ mfd = platform_get_drvdata(pdev);
+ mipi = &mfd->panel_info.mipi;
+
+ if (!mfd)
+ return -ENODEV;
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ pr_debug("%s:%d, debug info (mode) : %d", __func__, __LINE__,
+ mipi->mode);
+
+ if (mipi->mode == DSI_VIDEO_MODE) {
+ mipi_dsi_cmds_tx(mfd, &simulator_tx_buf, display_on_cmds,
+ ARRAY_SIZE(display_on_cmds));
+ } else {
+ pr_err("%s:%d, CMD MODE NOT SUPPORTED", __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int mipi_simulator_lcd_off(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct mipi_panel_info *mipi;
+
+ mfd = platform_get_drvdata(pdev);
+ mipi = &mfd->panel_info.mipi;
+
+ if (!mfd)
+ return -ENODEV;
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ pr_debug("%s:%d, debug info", __func__, __LINE__);
+
+ if (mipi->mode == DSI_VIDEO_MODE) {
+ mipi_dsi_cmds_tx(mfd, &simulator_tx_buf, display_off_cmds,
+ ARRAY_SIZE(display_off_cmds));
+ } else {
+ pr_debug("%s:%d, DONT REACH HERE", __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __devinit mipi_simulator_lcd_probe(struct platform_device *pdev)
+{
+ if (pdev->id == 0) {
+ mipi_simulator_pdata = pdev->dev.platform_data;
+ return 0;
+ }
+ pr_debug("%s:%d, debug info", __func__, __LINE__);
+
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = mipi_simulator_lcd_probe,
+ .driver = {
+ .name = "mipi_simulator",
+ },
+};
+
+static struct msm_fb_panel_data simulator_panel_data = {
+ .on = mipi_simulator_lcd_on,
+ .off = mipi_simulator_lcd_off,
+};
+
+static int ch_used[3];
+
+int mipi_simulator_device_register(struct msm_panel_info *pinfo,
+ u32 channel, u32 panel)
+{
+ struct platform_device *pdev = NULL;
+ int ret;
+
+ if ((channel >= 3) || ch_used[channel])
+ return -ENODEV;
+
+ ch_used[channel] = TRUE;
+
+ pr_debug("%s:%d, debug info", __func__, __LINE__);
+
+ pdev = platform_device_alloc("mipi_simulator", (panel << 8)|channel);
+ if (!pdev)
+ return -ENOMEM;
+
+ simulator_panel_data.panel_info = *pinfo;
+
+ ret = platform_device_add_data(pdev, &simulator_panel_data,
+ sizeof(simulator_panel_data));
+ if (ret) {
+ pr_err(KERN_ERR
+ "%s: platform_device_add_data failed!\n", __func__);
+ goto err_device_put;
+ }
+
+ ret = platform_device_add(pdev);
+ if (ret) {
+ pr_err(KERN_ERR
+ "%s: platform_device_register failed!\n", __func__);
+ goto err_device_put;
+ }
+
+ return 0;
+
+err_device_put:
+ platform_device_put(pdev);
+ return ret;
+}
+
+static int __init mipi_simulator_lcd_init(void)
+{
+ mipi_dsi_buf_alloc(&simulator_tx_buf, DSI_BUF_SIZE);
+ mipi_dsi_buf_alloc(&simulator_rx_buf, DSI_BUF_SIZE);
+
+ return platform_driver_register(&this_driver);
+}
+
+module_init(mipi_simulator_lcd_init);
diff --git a/drivers/video/msm/mipi_simulator.h b/drivers/video/msm/mipi_simulator.h
new file mode 100644
index 0000000..274ce8f
--- /dev/null
+++ b/drivers/video/msm/mipi_simulator.h
@@ -0,0 +1,19 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MIPI_SIMULATOR_H
+#define MIPI_SIMULATOR_H
+
+int mipi_simulator_device_register(struct msm_panel_info *pinfo,
+ u32 channel, u32 panel);
+
+#endif /* MIPI_SIMULATOR_H */
diff --git a/drivers/video/msm/mipi_simulator_video.c b/drivers/video/msm/mipi_simulator_video.c
new file mode 100644
index 0000000..8795554
--- /dev/null
+++ b/drivers/video/msm/mipi_simulator_video.c
@@ -0,0 +1,88 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_simulator.h"
+
+static struct msm_panel_info pinfo;
+
+static struct mipi_dsi_phy_ctrl dsi_video_mode_phy_db = {
+ {0x03, 0x01, 0x01, 0x00},
+ {0xaa, 0x3b, 0x1b, 0x00, 0x52, 0x58, 0x20, 0x3f,
+ 0x2e, 0x03, 0x04},
+ {0x7f, 0x00, 0x00, 0x00},
+ {0xee, 0x00, 0x86, 0x00},
+ {0x40, 0xc7, 0xb0, 0xda, 0x00, 0x50, 0x48, 0x63,
+ 0x30, 0x07, 0x03,
+ 0x05, 0x14, 0x03, 0x0, 0x0, 0x54, 0x06, 0x10, 0x04, 0x0},
+};
+
+static int __init mipi_video_simulator_init(void)
+{
+ int ret;
+
+#ifdef CONFIG_FB_MSM_MIPI_PANEL_DETECT
+ if (msm_fb_detect_client("mipi_video_simulator"))
+ return 0;
+#endif
+ pinfo.xres = 640;
+ pinfo.yres = 480;
+ pinfo.type = MIPI_VIDEO_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 24;
+
+ pinfo.lcdc.h_back_porch = 6;
+ pinfo.lcdc.h_front_porch = 6;
+ pinfo.lcdc.h_pulse_width = 2;
+ pinfo.lcdc.v_back_porch = 6;
+ pinfo.lcdc.v_front_porch = 6;
+ pinfo.lcdc.v_pulse_width = 2;
+
+ pinfo.lcdc.border_clr = 0; /* blk */
+ pinfo.lcdc.underflow_clr = 0xff; /* blue */
+ pinfo.lcdc.hsync_skew = 0;
+ pinfo.bl_max = 15;
+ pinfo.bl_min = 1;
+ pinfo.fb_num = 2;
+
+ pinfo.mipi.mode = DSI_VIDEO_MODE;
+ pinfo.mipi.pulse_mode_hsa_he = TRUE;
+ pinfo.mipi.hfp_power_stop = TRUE;
+ pinfo.mipi.hbp_power_stop = TRUE;
+ pinfo.mipi.hsa_power_stop = TRUE;
+ pinfo.mipi.eof_bllp_power_stop = TRUE;
+ pinfo.mipi.bllp_power_stop = TRUE;
+ pinfo.mipi.traffic_mode = DSI_NON_BURST_SYNCH_PULSE;
+ pinfo.mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
+ pinfo.mipi.vc = 0;
+ pinfo.mipi.rgb_swap = DSI_RGB_SWAP_RGB;
+ pinfo.mipi.data_lane0 = TRUE;
+ pinfo.mipi.data_lane1 = TRUE;
+ pinfo.mipi.t_clk_post = 0x03;
+ pinfo.mipi.t_clk_pre = 0x24;
+ pinfo.mipi.stream = 0; /* dma_p */
+ pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.frame_rate = 60;
+ pinfo.mipi.dsi_phy_db = &dsi_video_mode_phy_db;
+
+ ret = mipi_simulator_device_register(&pinfo, MIPI_DSI_PRIM,
+ MIPI_DSI_PANEL_FWVGA_PT);
+ if (ret)
+ pr_err("%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(mipi_video_simulator_init);
diff --git a/drivers/video/msm/mipi_toshiba.c b/drivers/video/msm/mipi_toshiba.c
new file mode 100644
index 0000000..09fbf24
--- /dev/null
+++ b/drivers/video/msm/mipi_toshiba.c
@@ -0,0 +1,292 @@
+/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_toshiba.h"
+
+static struct msm_panel_common_pdata *mipi_toshiba_pdata;
+
+static struct dsi_buf toshiba_tx_buf;
+static struct dsi_buf toshiba_rx_buf;
+
+#ifdef TOSHIBA_CMDS_UNUSED
+static char one_lane[3] = {0xEF, 0x60, 0x62};
+static char dmode_wqvga[2] = {0xB3, 0x01};
+static char intern_wr_clk1_wqvga[3] = {0xef, 0x2f, 0x22};
+static char intern_wr_clk2_wqvga[3] = {0xef, 0x6e, 0x33};
+static char hor_addr_2A_wqvga[5] = {0x2A, 0x00, 0x00, 0x00, 0xef};
+static char hor_addr_2B_wqvga[5] = {0x2B, 0x00, 0x00, 0x01, 0xaa};
+static char if_sel_cmd[2] = {0x53, 0x00};
+#endif
+
+static char exit_sleep[2] = {0x11, 0x00};
+static char display_on[2] = {0x29, 0x00};
+static char display_off[2] = {0x28, 0x00};
+static char enter_sleep[2] = {0x10, 0x00};
+
+#ifdef CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT_PANEL
+static char mcap_off[2] = {0xb2, 0x00};
+static char ena_test_reg[3] = {0xEF, 0x01, 0x01};
+static char two_lane[3] = {0xEF, 0x60, 0x63};
+static char non_burst_sync_pulse[3] = {0xef, 0x61, 0x09};
+static char dmode_wvga[2] = {0xB3, 0x00};
+static char intern_wr_clk1_wvga[3] = {0xef, 0x2f, 0xcc};
+static char intern_wr_clk2_wvga[3] = {0xef, 0x6e, 0xdd};
+static char hor_addr_2A_wvga[5] = {0x2A, 0x00, 0x00, 0x01, 0xdf};
+static char hor_addr_2B_wvga[5] = {0x2B, 0x00, 0x00, 0x03, 0x55};
+static char if_sel_video[2] = {0x53, 0x01};
+
+static struct dsi_cmd_desc toshiba_display_on_cmds[] = {
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(mcap_off), mcap_off},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(ena_test_reg), ena_test_reg},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(two_lane), two_lane},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(non_burst_sync_pulse),
+ non_burst_sync_pulse},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(dmode_wvga), dmode_wvga},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(intern_wr_clk1_wvga),
+ intern_wr_clk1_wvga},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(intern_wr_clk2_wvga),
+ intern_wr_clk2_wvga},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, 0, sizeof(hor_addr_2A_wvga),
+ hor_addr_2A_wvga},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, 0, sizeof(hor_addr_2B_wvga),
+ hor_addr_2B_wvga},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(if_sel_video), if_sel_video},
+ {DTYPE_DCS_WRITE, 1, 0, 0, 0, sizeof(exit_sleep), exit_sleep},
+ {DTYPE_DCS_WRITE, 1, 0, 0, 0, sizeof(display_on), display_on}
+};
+
+#endif
+
+#ifdef CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT_PANEL
+static char mcap_start[2] = {0xb0, 0x04};
+static char num_out_pixelform[3] = {0xb3, 0x00, 0x87};
+static char dsi_ctrl[3] = {0xb6, 0x30, 0x83};
+static char panel_driving[7] = {0xc0, 0x01, 0x00, 0x85, 0x00, 0x00, 0x00};
+static char dispV_timing[5] = {0xc1, 0x00, 0x10, 0x00, 0x01};
+static char dispCtrl[3] = {0xc3, 0x00, 0x19};
+static char test_mode_c4[2] = {0xc4, 0x03};
+static char dispH_timing[15] = {
+ /* TYPE_DCS_LWRITE */
+ 0xc5, 0x00, 0x01, 0x05,
+ 0x04, 0x5e, 0x00, 0x00,
+ 0x00, 0x00, 0x0b, 0x17,
+ 0x05, 0x00, 0x00
+};
+static char test_mode_c6[2] = {0xc6, 0x00};
+static char gamma_setA[13] = {
+ 0xc8, 0x0a, 0x15, 0x18,
+ 0x1b, 0x1c, 0x0d, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00
+};
+static char gamma_setB[13] = {
+ 0xc9, 0x0d, 0x1d, 0x1f,
+ 0x1f, 0x1f, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00
+};
+static char gamma_setC[13] = {
+ 0xca, 0x1e, 0x1f, 0x1e,
+ 0x1d, 0x1d, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00
+};
+static char powerSet_ChrgPmp[5] = {0xd0, 0x02, 0x00, 0xa3, 0xb8};
+static char testMode_d1[6] = {0xd1, 0x10, 0x14, 0x53, 0x64, 0x00};
+static char powerSet_SrcAmp[3] = {0xd2, 0xb3, 0x00};
+static char powerInt_PS[3] = {0xd3, 0x33, 0x03};
+static char vreg[2] = {0xd5, 0x00};
+static char test_mode_d6[2] = {0xd6, 0x01};
+static char timingCtrl_d7[9] = {
+ 0xd7, 0x09, 0x00, 0x84,
+ 0x81, 0x61, 0xbc, 0xb5,
+ 0x05
+};
+static char timingCtrl_d8[7] = {
+ 0xd8, 0x04, 0x25, 0x90,
+ 0x4c, 0x92, 0x00
+};
+static char timingCtrl_d9[4] = {0xd9, 0x5b, 0x7f, 0x05};
+static char white_balance[6] = {0xcb, 0x00, 0x00, 0x00, 0x1c, 0x00};
+static char vcs_settings[2] = {0xdd, 0x53};
+static char vcom_dc_settings[2] = {0xde, 0x43};
+static char testMode_e3[5] = {0xe3, 0x00, 0x00, 0x00, 0x00};
+static char testMode_e4[6] = {0xe4, 0x00, 0x00, 0x22, 0xaa, 0x00};
+static char testMode_e5[2] = {0xe5, 0x00};
+static char testMode_fa[4] = {0xfa, 0x00, 0x00, 0x00};
+static char testMode_fd[5] = {0xfd, 0x00, 0x00, 0x00, 0x00};
+static char testMode_fe[5] = {0xfe, 0x00, 0x00, 0x00, 0x00};
+static char mcap_end[2] = {0xb0, 0x03};
+static char set_add_mode[2] = {0x36, 0x0};
+static char set_pixel_format[2] = {0x3a, 0x70};
+
+
+static struct dsi_cmd_desc toshiba_display_on_cmds[] = {
+ {DTYPE_GEN_WRITE2, 1, 0, 0, 10, sizeof(mcap_start), mcap_start},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 10, sizeof(num_out_pixelform),
+ num_out_pixelform},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 10, sizeof(dsi_ctrl), dsi_ctrl},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(panel_driving), panel_driving},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(dispV_timing), dispV_timing},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(dispCtrl), dispCtrl},
+ {DTYPE_GEN_WRITE2, 1, 0, 0, 0, sizeof(test_mode_c4), test_mode_c4},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(dispH_timing), dispH_timing},
+ {DTYPE_GEN_WRITE2, 1, 0, 0, 0, sizeof(test_mode_c6), test_mode_c6},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(gamma_setA), gamma_setA},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(gamma_setB), gamma_setB},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(gamma_setC), gamma_setC},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(powerSet_ChrgPmp),
+ powerSet_ChrgPmp},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(testMode_d1), testMode_d1},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(powerSet_SrcAmp),
+ powerSet_SrcAmp},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(powerInt_PS), powerInt_PS},
+ {DTYPE_GEN_WRITE2, 1, 0, 0, 0, sizeof(vreg), vreg},
+ {DTYPE_GEN_WRITE2, 1, 0, 0, 0, sizeof(test_mode_d6), test_mode_d6},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(timingCtrl_d7), timingCtrl_d7},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(timingCtrl_d8), timingCtrl_d8},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(timingCtrl_d9), timingCtrl_d9},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(white_balance), white_balance},
+ {DTYPE_GEN_WRITE2, 1, 0, 0, 0, sizeof(vcs_settings), vcs_settings},
+ {DTYPE_GEN_WRITE2, 1, 0, 0, 0, sizeof(vcom_dc_settings),
+ vcom_dc_settings},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(testMode_e3), testMode_e3},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(testMode_e4), testMode_e4},
+ {DTYPE_GEN_WRITE2, 1, 0, 0, 0, sizeof(testMode_e5), testMode_e5},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(testMode_fa), testMode_fa},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(testMode_fd), testMode_fd},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(testMode_fe), testMode_fe},
+ {DTYPE_GEN_WRITE2, 1, 0, 0, 0, sizeof(mcap_end), mcap_end},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, 0, sizeof(set_add_mode), set_add_mode},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, 0, sizeof(set_pixel_format),
+ set_pixel_format},
+ {DTYPE_DCS_WRITE, 1, 0, 0, 120, sizeof(exit_sleep), exit_sleep},
+ {DTYPE_DCS_WRITE, 1, 0, 0, 50, sizeof(display_on), display_on}
+};
+#endif
+
+static struct dsi_cmd_desc toshiba_display_off_cmds[] = {
+ {DTYPE_DCS_WRITE, 1, 0, 0, 50, sizeof(display_off), display_off},
+ {DTYPE_DCS_WRITE, 1, 0, 0, 120, sizeof(enter_sleep), enter_sleep}
+};
+
+static int mipi_toshiba_lcd_on(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ mipi_dsi_cmds_tx(mfd, &toshiba_tx_buf, toshiba_display_on_cmds,
+ ARRAY_SIZE(toshiba_display_on_cmds));
+
+ return 0;
+}
+
+static int mipi_toshiba_lcd_off(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ mipi_dsi_cmds_tx(mfd, &toshiba_tx_buf, toshiba_display_off_cmds,
+ ARRAY_SIZE(toshiba_display_off_cmds));
+
+ return 0;
+}
+
+static int __devinit mipi_toshiba_lcd_probe(struct platform_device *pdev)
+{
+ if (pdev->id == 0) {
+ mipi_toshiba_pdata = pdev->dev.platform_data;
+ return 0;
+ }
+
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = mipi_toshiba_lcd_probe,
+ .driver = {
+ .name = "mipi_toshiba",
+ },
+};
+
+static struct msm_fb_panel_data toshiba_panel_data = {
+ .on = mipi_toshiba_lcd_on,
+ .off = mipi_toshiba_lcd_off,
+};
+
+static int ch_used[3];
+
+int mipi_toshiba_device_register(struct msm_panel_info *pinfo,
+ u32 channel, u32 panel)
+{
+ struct platform_device *pdev = NULL;
+ int ret;
+
+ if ((channel >= 3) || ch_used[channel])
+ return -ENODEV;
+
+ ch_used[channel] = TRUE;
+
+ pdev = platform_device_alloc("mipi_toshiba", (panel << 8)|channel);
+ if (!pdev)
+ return -ENOMEM;
+
+ toshiba_panel_data.panel_info = *pinfo;
+
+ ret = platform_device_add_data(pdev, &toshiba_panel_data,
+ sizeof(toshiba_panel_data));
+ if (ret) {
+ printk(KERN_ERR
+ "%s: platform_device_add_data failed!\n", __func__);
+ goto err_device_put;
+ }
+
+ ret = platform_device_add(pdev);
+ if (ret) {
+ printk(KERN_ERR
+ "%s: platform_device_register failed!\n", __func__);
+ goto err_device_put;
+ }
+
+ return 0;
+
+err_device_put:
+ platform_device_put(pdev);
+ return ret;
+}
+
+static int __init mipi_toshiba_lcd_init(void)
+{
+ mipi_dsi_buf_alloc(&toshiba_tx_buf, DSI_BUF_SIZE);
+ mipi_dsi_buf_alloc(&toshiba_rx_buf, DSI_BUF_SIZE);
+
+ return platform_driver_register(&this_driver);
+}
+
+module_init(mipi_toshiba_lcd_init);
diff --git a/drivers/video/msm/mipi_toshiba.h b/drivers/video/msm/mipi_toshiba.h
new file mode 100644
index 0000000..657636a
--- /dev/null
+++ b/drivers/video/msm/mipi_toshiba.h
@@ -0,0 +1,21 @@
+
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MIPI_TOSHIBA_H
+#define MIPI_TOSHIBA_H
+
+int mipi_toshiba_device_register(struct msm_panel_info *pinfo,
+ u32 channel, u32 panel);
+
+#endif /* MIPI_TOSHIBA_H */
diff --git a/drivers/video/msm/mipi_toshiba_video_wsvga_pt.c b/drivers/video/msm/mipi_toshiba_video_wsvga_pt.c
new file mode 100644
index 0000000..0477725
--- /dev/null
+++ b/drivers/video/msm/mipi_toshiba_video_wsvga_pt.c
@@ -0,0 +1,106 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_toshiba.h"
+
+static struct msm_panel_info pinfo;
+
+static struct mipi_dsi_phy_ctrl dsi_video_mode_phy_db = {
+ /* 600*1024, RGB888, 3 Lane 55 fps video mode */
+ /* regulator */
+ {0x03, 0x0a, 0x04, 0x00, 0x20},
+ /* timing */
+ {0xab, 0x8a, 0x18, 0x00, 0x92, 0x97, 0x1b, 0x8c,
+ 0x0c, 0x03, 0x04, 0xa0},
+ /* phy ctrl */
+ {0x5f, 0x00, 0x00, 0x10},
+ /* strength */
+ {0xff, 0x00, 0x06, 0x00},
+ /* pll control */
+ {0x0, 0x7f, 0x1, 0x1a, 0x00, 0x50, 0x48, 0x63,
+ 0x41, 0x0f, 0x01,
+ 0x00, 0x14, 0x03, 0x00, 0x02, 0x00, 0x20, 0x00, 0x01 },
+};
+
+static int __init mipi_video_toshiba_wsvga_pt_init(void)
+{
+ int ret;
+
+#ifdef CONFIG_FB_MSM_MIPI_PANEL_DETECT
+ if (msm_fb_detect_client("mipi_video_toshiba_wsvga"))
+ return 0;
+#endif
+
+ pinfo.xres = 600;
+ pinfo.yres = 1024;
+ /*
+ *
+ * Panel's Horizontal input timing requirement is to
+ * include dummy(pad) data of 200 clk in addition to
+ * width and porch/sync width values
+ */
+ pinfo.mipi.xres_pad = 200;
+ pinfo.mipi.yres_pad = 0;
+
+ pinfo.type = MIPI_VIDEO_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 24;
+ pinfo.lcdc.h_back_porch = 16;
+ pinfo.lcdc.h_front_porch = 23;
+ pinfo.lcdc.h_pulse_width = 8;
+ pinfo.lcdc.v_back_porch = 2;
+ pinfo.lcdc.v_front_porch = 7;
+ pinfo.lcdc.v_pulse_width = 2;
+ pinfo.lcdc.border_clr = 0; /* blk */
+ pinfo.lcdc.underflow_clr = 0xff; /* blue */
+ pinfo.lcdc.hsync_skew = 0;
+ pinfo.bl_max = 15;
+ pinfo.bl_min = 1;
+ pinfo.fb_num = 2;
+ pinfo.clk_rate = 384000000;
+
+ pinfo.mipi.mode = DSI_VIDEO_MODE;
+ pinfo.mipi.pulse_mode_hsa_he = FALSE;
+ pinfo.mipi.hfp_power_stop = FALSE;
+ pinfo.mipi.hbp_power_stop = FALSE;
+ pinfo.mipi.hsa_power_stop = FALSE;
+ pinfo.mipi.eof_bllp_power_stop = FALSE;
+ pinfo.mipi.bllp_power_stop = FALSE;
+ pinfo.mipi.traffic_mode = DSI_NON_BURST_SYNCH_EVENT;
+ pinfo.mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
+ pinfo.mipi.vc = 0;
+ pinfo.mipi.rgb_swap = DSI_RGB_SWAP_RGB;
+ pinfo.mipi.data_lane0 = TRUE;
+ pinfo.mipi.data_lane1 = TRUE;
+ pinfo.mipi.data_lane2 = TRUE;
+ pinfo.mipi.t_clk_post = 0x20;
+ pinfo.mipi.t_clk_pre = 0x2d;
+ pinfo.mipi.stream = 0; /* dma_p */
+ pinfo.mipi.mdp_trigger = 0;
+ pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.frame_rate = 55;
+ pinfo.mipi.dsi_phy_db = &dsi_video_mode_phy_db;
+ pinfo.mipi.tx_eot_append = TRUE;
+
+ ret = mipi_toshiba_device_register(&pinfo, MIPI_DSI_PRIM,
+ MIPI_DSI_PANEL_WVGA_PT);
+ if (ret)
+ printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(mipi_video_toshiba_wsvga_pt_init);
diff --git a/drivers/video/msm/mipi_toshiba_video_wvga_pt.c b/drivers/video/msm/mipi_toshiba_video_wvga_pt.c
new file mode 100644
index 0000000..1913513
--- /dev/null
+++ b/drivers/video/msm/mipi_toshiba_video_wvga_pt.c
@@ -0,0 +1,108 @@
+/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_toshiba.h"
+
+static struct msm_panel_info pinfo;
+
+static struct mipi_dsi_phy_ctrl dsi_video_mode_phy_db = {
+ /* 480*854, RGB888, 2 Lane 60 fps video mode */
+ {0x03, 0x01, 0x01, 0x00}, /* regulator */
+ /* timing */
+ {0x6a, 0x22, 0x0f, 0x00, 0x30, 0x38, 0x13, 0x26,
+ 0x1b, 0x03, 0x04},
+ {0x7f, 0x00, 0x00, 0x00}, /* phy ctrl */
+ {0xee, 0x03, 0x86, 0x03}, /* strength */
+ /* pll control */
+
+#define DSI_BIT_CLK_380MHZ
+
+#if defined(DSI_BIT_CLK_366MHZ)
+ {0x41, 0xdb, 0xb2, 0xf5, 0x00, 0x50, 0x48, 0x63,
+ 0x31, 0x0f, 0x07,
+ 0x05, 0x14, 0x03, 0x03, 0x03, 0x54, 0x06, 0x10, 0x04, 0x03 },
+#elif defined(DSI_BIT_CLK_380MHZ)
+ {0x41, 0xf7, 0xb2, 0xf5, 0x00, 0x50, 0x48, 0x63,
+ 0x31, 0x0f, 0x07,
+ 0x05, 0x14, 0x03, 0x03, 0x03, 0x54, 0x06, 0x10, 0x04, 0x03 },
+#elif defined(DSI_BIT_CLK_400MHZ)
+ {0x41, 0x8f, 0xb1, 0xda, 0x00, 0x50, 0x48, 0x63,
+ 0x31, 0x0f, 0x07,
+ 0x05, 0x14, 0x03, 0x03, 0x03, 0x54, 0x06, 0x10, 0x04, 0x03 },
+#else /* 200 mhz */
+ {0x41, 0x8f, 0xb1, 0xda, 0x00, 0x50, 0x48, 0x63,
+ 0x33, 0x1f, 0x0f,
+ 0x05, 0x14, 0x03, 0x03, 0x03, 0x54, 0x06, 0x10, 0x04, 0x03 },
+#endif
+};
+
+static int __init mipi_video_toshiba_wvga_pt_init(void)
+{
+ int ret;
+
+#ifdef CONFIG_FB_MSM_MIPI_PANEL_DETECT
+ if (msm_fb_detect_client("mipi_video_toshiba_wvga"))
+ return 0;
+#endif
+
+ pinfo.xres = 480;
+ pinfo.yres = 864; /* 856 for V1 surf */
+ pinfo.type = MIPI_VIDEO_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 24;
+ pinfo.lcdc.h_back_porch = 64;
+ pinfo.lcdc.h_front_porch = 64;
+ pinfo.lcdc.h_pulse_width = 16;
+ pinfo.lcdc.v_back_porch = 8;
+ pinfo.lcdc.v_front_porch = 4;
+ pinfo.lcdc.v_pulse_width = 1;
+ pinfo.lcdc.border_clr = 0; /* blk */
+ pinfo.lcdc.underflow_clr = 0xff; /* blue */
+ pinfo.lcdc.hsync_skew = 0;
+ pinfo.bl_max = 15;
+ pinfo.bl_min = 1;
+ pinfo.fb_num = 2;
+
+ pinfo.mipi.mode = DSI_VIDEO_MODE;
+ pinfo.mipi.pulse_mode_hsa_he = TRUE;
+ pinfo.mipi.hfp_power_stop = FALSE;
+ pinfo.mipi.hbp_power_stop = FALSE;
+ pinfo.mipi.hsa_power_stop = FALSE;
+ pinfo.mipi.eof_bllp_power_stop = TRUE;
+ pinfo.mipi.bllp_power_stop = TRUE;
+ pinfo.mipi.traffic_mode = DSI_NON_BURST_SYNCH_PULSE;
+ pinfo.mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
+ pinfo.mipi.vc = 0;
+ pinfo.mipi.rgb_swap = DSI_RGB_SWAP_BGR;
+ pinfo.mipi.data_lane0 = TRUE;
+ pinfo.mipi.data_lane1 = TRUE;
+ pinfo.mipi.t_clk_post = 0x04;
+ pinfo.mipi.t_clk_pre = 0x17;
+ pinfo.mipi.stream = 0; /* dma_p */
+ pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.frame_rate = 60;
+ pinfo.mipi.dsi_phy_db = &dsi_video_mode_phy_db;
+
+ ret = mipi_toshiba_device_register(&pinfo, MIPI_DSI_PRIM,
+ MIPI_DSI_PANEL_WVGA_PT);
+ if (ret)
+ printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(mipi_video_toshiba_wvga_pt_init);
diff --git a/drivers/video/msm/msm_dss_io_7x27a.c b/drivers/video/msm/msm_dss_io_7x27a.c
new file mode 100644
index 0000000..8e1959a
--- /dev/null
+++ b/drivers/video/msm/msm_dss_io_7x27a.c
@@ -0,0 +1,390 @@
+/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/clk.h>
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+
+/* multimedia sub system sfpb */
+char *mmss_sfpb_base;
+void __iomem *periph_base;
+
+int mipi_dsi_clk_on;
+static struct dsi_clk_desc dsicore_clk;
+static struct dsi_clk_desc dsi_pclk;
+
+static struct clk *dsi_byte_div_clk;
+static struct clk *dsi_esc_clk;
+static struct clk *dsi_pixel_clk;
+static struct clk *dsi_clk;
+static struct clk *dsi_ref_clk;
+static struct clk *mdp_dsi_pclk;
+static struct clk *ahb_m_clk;
+static struct clk *ahb_s_clk;
+
+void mipi_dsi_clk_init(struct device *dev)
+{
+ dsi_esc_clk = clk_get(NULL, "dsi_esc_clk");
+ if (IS_ERR(dsi_esc_clk)) {
+ printk(KERN_ERR "can't find dsi_esc_clk\n");
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_byte_div_clk = clk_get(NULL, "dsi_byte_clk");
+ if (IS_ERR(dsi_byte_div_clk)) {
+ pr_err("can't find dsi_byte_div_clk\n");
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_pixel_clk = clk_get(NULL, "dsi_pixel_clk");
+ if (IS_ERR(dsi_pixel_clk)) {
+ pr_err("can't find dsi_pixel_clk\n");
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_clk = clk_get(NULL, "dsi_clk");
+ if (IS_ERR(dsi_clk)) {
+ pr_err("can't find dsi_clk\n");
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_ref_clk = clk_get(NULL, "dsi_ref_clk");
+ if (IS_ERR(dsi_ref_clk)) {
+ pr_err("can't find dsi_ref_clk\n");
+ goto mipi_dsi_clk_err;
+ }
+
+ mdp_dsi_pclk = clk_get(NULL, "mdp_dsi_pclk");
+ if (IS_ERR(mdp_dsi_pclk)) {
+ pr_err("can't find mdp_dsi_pclk\n");
+ goto mipi_dsi_clk_err;
+ }
+
+ ahb_m_clk = clk_get(NULL, "ahb_m_clk");
+ if (IS_ERR(ahb_m_clk)) {
+ pr_err("can't find ahb_m_clk\n");
+ goto mipi_dsi_clk_err;
+ }
+
+ ahb_s_clk = clk_get(NULL, "ahb_s_clk");
+ if (IS_ERR(ahb_s_clk)) {
+ pr_err("can't find ahb_s_clk\n");
+ goto mipi_dsi_clk_err;
+ }
+
+ return;
+
+mipi_dsi_clk_err:
+ mipi_dsi_clk_deinit(NULL);
+
+}
+
+void mipi_dsi_clk_deinit(struct device *dev)
+{
+ clk_put(mdp_dsi_pclk);
+ clk_put(ahb_m_clk);
+ clk_put(ahb_s_clk);
+ clk_put(dsi_ref_clk);
+ clk_put(dsi_byte_div_clk);
+ clk_put(dsi_esc_clk);
+}
+
+static void mipi_dsi_clk_ctrl(struct dsi_clk_desc *clk, int clk_en)
+{
+ uint32 data;
+ if (clk_en) {
+ data = (clk->pre_div_func) << 24 |
+ (clk->m) << 16 | (clk->n) << 8 |
+ ((clk->d) * 2);
+ clk_set_rate(dsi_clk, data);
+ clk_enable(dsi_clk);
+ } else
+ clk_disable(dsi_clk);
+}
+
+static void mipi_dsi_pclk_ctrl(struct dsi_clk_desc *clk, int clk_en)
+{
+ uint32 data;
+
+ if (clk_en) {
+ data = (clk->pre_div_func) << 24 | (clk->m) << 16
+ | (clk->n) << 8 | ((clk->d) * 2);
+ if ((clk_set_rate(dsi_pixel_clk, data)) < 0)
+ pr_err("%s: pixel clk set rate failed\n", __func__);
+ if (clk_enable(dsi_pixel_clk))
+ pr_err("%s clk enable failed\n", __func__);
+ } else {
+ clk_disable(dsi_pixel_clk);
+ }
+}
+
+static void mipi_dsi_calibration(void)
+{
+ MIPI_OUTP(MIPI_DSI_BASE + 0xf8, 0x00a105a1); /* cal_hw_ctrl */
+}
+
+#define PREF_DIV_RATIO 19
+struct dsiphy_pll_divider_config pll_divider_config;
+
+int mipi_dsi_clk_div_config(uint8 bpp, uint8 lanes,
+ uint32 *expected_dsi_pclk)
+{
+ u32 fb_divider, rate, vco;
+ u32 div_ratio = 0;
+ struct dsi_clk_mnd_table const *mnd_entry = mnd_table;
+ if (pll_divider_config.clk_rate == 0)
+ pll_divider_config.clk_rate = 454000000;
+
+ rate = pll_divider_config.clk_rate / 1000000; /* In Mhz */
+
+ if (rate < 125) {
+ vco = rate * 8;
+ div_ratio = 8;
+ } else if (rate < 250) {
+ vco = rate * 4;
+ div_ratio = 4;
+ } else if (rate < 500) {
+ vco = rate * 2;
+ div_ratio = 2;
+ } else {
+ vco = rate * 1;
+ div_ratio = 1;
+ }
+
+ /* find the mnd settings from mnd_table entry */
+ for (; mnd_entry != mnd_table + ARRAY_SIZE(mnd_table); ++mnd_entry) {
+ if (((mnd_entry->lanes) == lanes) &&
+ ((mnd_entry->bpp) == bpp))
+ break;
+ }
+
+ if (mnd_entry == mnd_table + ARRAY_SIZE(mnd_table)) {
+ pr_err("%s: requested Lanes, %u & BPP, %u, not supported\n",
+ __func__, lanes, bpp);
+ return -EINVAL;
+ }
+ fb_divider = ((vco * PREF_DIV_RATIO) / 27);
+ pll_divider_config.fb_divider = fb_divider;
+ pll_divider_config.ref_divider_ratio = PREF_DIV_RATIO;
+ pll_divider_config.bit_clk_divider = div_ratio;
+ pll_divider_config.byte_clk_divider =
+ pll_divider_config.bit_clk_divider * 8;
+ pll_divider_config.dsi_clk_divider =
+ (mnd_entry->dsiclk_div) * div_ratio;
+
+ if ((mnd_entry->dsiclk_d == 0)
+ || (mnd_entry->dsiclk_m == 1)) {
+ dsicore_clk.mnd_mode = 0;
+ dsicore_clk.src = 0x3;
+ dsicore_clk.pre_div_func = (mnd_entry->dsiclk_n - 1);
+ } else {
+ dsicore_clk.mnd_mode = 2;
+ dsicore_clk.src = 0x3;
+ dsicore_clk.m = mnd_entry->dsiclk_m;
+ dsicore_clk.n = mnd_entry->dsiclk_n;
+ dsicore_clk.d = mnd_entry->dsiclk_d;
+ }
+
+ if ((mnd_entry->pclk_d == 0)
+ || (mnd_entry->pclk_m == 1)) {
+ dsi_pclk.mnd_mode = 0;
+ dsi_pclk.src = 0x3;
+ dsi_pclk.pre_div_func = (mnd_entry->pclk_n - 1);
+ *expected_dsi_pclk = ((vco * 1000000) /
+ ((pll_divider_config.dsi_clk_divider)
+ * (mnd_entry->pclk_n)));
+ } else {
+ dsi_pclk.mnd_mode = 2;
+ dsi_pclk.src = 0x3;
+ dsi_pclk.m = mnd_entry->pclk_m;
+ dsi_pclk.n = mnd_entry->pclk_n;
+ dsi_pclk.d = mnd_entry->pclk_d;
+ *expected_dsi_pclk = ((vco * 1000000 * dsi_pclk.m) /
+ ((pll_divider_config.dsi_clk_divider)
+ * (mnd_entry->pclk_n)));
+ }
+ dsicore_clk.m = 1;
+ dsicore_clk.n = 1;
+ dsicore_clk.d = 2;
+ dsicore_clk.pre_div_func = 0;
+
+ dsi_pclk.m = 1;
+ dsi_pclk.n = 3;
+ dsi_pclk.d = 2;
+ dsi_pclk.pre_div_func = 0;
+ return 0;
+}
+
+void mipi_dsi_phy_init(int panel_ndx, struct msm_panel_info const *panel_info,
+ int target_type)
+{
+ struct mipi_dsi_phy_ctrl *pd;
+ int i, off;
+
+ MIPI_OUTP(MIPI_DSI_BASE + 0x128, 0x0001);/* start phy sw reset */
+ msleep(100);
+ MIPI_OUTP(MIPI_DSI_BASE + 0x128, 0x0000);/* end phy w reset */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x2cc, 0x0003);/* regulator_ctrl_0 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x2d0, 0x0001);/* regulator_ctrl_1 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x2d4, 0x0001);/* regulator_ctrl_2 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x2d8, 0x0000);/* regulator_ctrl_3 */
+#ifdef DSI_POWER
+ MIPI_OUTP(MIPI_DSI_BASE + 0x2dc, 0x0100);/* regulator_ctrl_4 */
+#endif
+
+ pd = (panel_info->mipi).dsi_phy_db;
+
+ off = 0x02cc; /* regulator ctrl 0 */
+ for (i = 0; i < 4; i++) {
+ MIPI_OUTP(MIPI_DSI_BASE + off, pd->regulator[i]);
+ wmb();
+ off += 4;
+ }
+
+ off = 0x0260; /* phy timig ctrl 0 */
+ for (i = 0; i < 11; i++) {
+ MIPI_OUTP(MIPI_DSI_BASE + off, pd->timing[i]);
+ wmb();
+ off += 4;
+ }
+
+ off = 0x0290; /* ctrl 0 */
+ for (i = 0; i < 4; i++) {
+ MIPI_OUTP(MIPI_DSI_BASE + off, pd->ctrl[i]);
+ wmb();
+ off += 4;
+ }
+
+ off = 0x02a0; /* strength 0 */
+ for (i = 0; i < 4; i++) {
+ MIPI_OUTP(MIPI_DSI_BASE + off, pd->strength[i]);
+ wmb();
+ off += 4;
+ }
+
+ mipi_dsi_calibration();
+
+ off = 0x0204; /* pll ctrl 1, skip 0 */
+ for (i = 1; i < 21; i++) {
+ MIPI_OUTP(MIPI_DSI_BASE + off, pd->pll[i]);
+ wmb();
+ off += 4;
+ }
+
+ MIPI_OUTP(MIPI_DSI_BASE + 0x100, 0x67);
+
+ /* pll ctrl 0 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x200, pd->pll[0]);
+ wmb();
+ MIPI_OUTP(MIPI_DSI_BASE + 0x200, (pd->pll[0] | 0x01));
+}
+
+void mipi_dsi_clk_enable(void)
+{
+ unsigned data = 0;
+
+ if (mipi_dsi_clk_on) {
+ pr_err("%s: mipi_dsi_clk already ON\n", __func__);
+ return;
+ }
+
+ mipi_dsi_clk_on = 1;
+
+ clk_enable(dsi_ref_clk);
+ clk_set_rate(dsi_byte_div_clk, data);
+ clk_set_rate(dsi_esc_clk, data);
+ clk_enable(mdp_dsi_pclk);
+ clk_enable(ahb_m_clk);
+ clk_enable(ahb_s_clk);
+ clk_enable(dsi_byte_div_clk);
+ clk_enable(dsi_esc_clk);
+ mipi_dsi_pclk_ctrl(&dsi_pclk, 1);
+ mipi_dsi_clk_ctrl(&dsicore_clk, 1);
+}
+
+void mipi_dsi_clk_disable(void)
+{
+ if (mipi_dsi_clk_on == 0) {
+ pr_err("%s: mipi_dsi_clk already OFF\n", __func__);
+ return;
+ }
+
+ mipi_dsi_clk_on = 0;
+
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0118, 0);
+
+ mipi_dsi_pclk_ctrl(&dsi_pclk, 0);
+ mipi_dsi_clk_ctrl(&dsicore_clk, 0);
+ clk_disable(dsi_esc_clk);
+ clk_disable(dsi_byte_div_clk);
+ clk_disable(mdp_dsi_pclk);
+ clk_disable(ahb_m_clk);
+ clk_disable(ahb_s_clk);
+ clk_disable(dsi_ref_clk);
+}
+
+void mipi_dsi_phy_ctrl(int on)
+{
+ if (on) {
+ /* DSIPHY_PLL_CTRL_5 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0214, 0x050);
+
+ /* DSIPHY_TPA_CTRL_1 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0258, 0x00f);
+
+ /* DSIPHY_TPA_CTRL_2 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x025c, 0x000);
+ } else {
+ /* DSIPHY_PLL_CTRL_5 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0214, 0x05f);
+
+ /* DSIPHY_TPA_CTRL_1 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0258, 0x08f);
+
+ /* DSIPHY_TPA_CTRL_2 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x025c, 0x001);
+
+ /* DSIPHY_REGULATOR_CTRL_0 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x02cc, 0x02);
+
+ /* DSIPHY_CTRL_0 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0290, 0x00);
+
+ /* DSIPHY_CTRL_1 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0294, 0x7f);
+
+ /* DSIPHY_PLL_CTRL_0, disbale dsi pll */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0200, 0x40);
+
+ /* disbale dsi clk */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0118, 0);
+ }
+}
+
+#ifdef CONFIG_FB_MSM_MDP303
+void update_lane_config(struct msm_panel_info *pinfo)
+{
+ struct mipi_dsi_phy_ctrl *pd;
+
+ pd = (pinfo->mipi).dsi_phy_db;
+ pinfo->mipi.data_lane1 = FALSE;
+ pd->pll[10] |= 0x08;
+
+ pinfo->yres = 320;
+ pinfo->lcdc.h_back_porch = 15;
+ pinfo->lcdc.h_front_porch = 21;
+ pinfo->lcdc.h_pulse_width = 5;
+ pinfo->lcdc.v_back_porch = 50;
+ pinfo->lcdc.v_front_porch = 101;
+ pinfo->lcdc.v_pulse_width = 50;
+}
+#endif
diff --git a/drivers/video/msm/msm_dss_io_8960.c b/drivers/video/msm/msm_dss_io_8960.c
new file mode 100644
index 0000000..ce9fb28
--- /dev/null
+++ b/drivers/video/msm/msm_dss_io_8960.c
@@ -0,0 +1,715 @@
+/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/clk.h>
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "hdmi_msm.h"
+#include <mach/msm_iomap.h>
+
+/* HDMI PHY macros */
+#define HDMI_PHY_REG_0 (0x00000400)
+#define HDMI_PHY_REG_1 (0x00000404)
+#define HDMI_PHY_REG_2 (0x00000408)
+#define HDMI_PHY_REG_3 (0x0000040c)
+#define HDMI_PHY_REG_4 (0x00000410)
+#define HDMI_PHY_REG_5 (0x00000414)
+#define HDMI_PHY_REG_6 (0x00000418)
+#define HDMI_PHY_REG_7 (0x0000041c)
+#define HDMI_PHY_REG_8 (0x00000420)
+#define HDMI_PHY_REG_9 (0x00000424)
+#define HDMI_PHY_REG_10 (0x00000428)
+#define HDMI_PHY_REG_11 (0x0000042c)
+#define HDMI_PHY_REG_12 (0x00000430)
+#define HDMI_PHY_REG_BIST_CFG (0x00000434)
+#define HDMI_PHY_DEBUG_BUS_SEL (0x00000438)
+#define HDMI_PHY_REG_MISC0 (0x0000043c)
+#define HDMI_PHY_REG_13 (0x00000440)
+#define HDMI_PHY_REG_14 (0x00000444)
+#define HDMI_PHY_REG_15 (0x00000448)
+#define HDMI_PHY_CTRL (0x000002D4)
+
+/* HDMI PHY/PLL bit field macros */
+#define HDMI_PHY_PLL_STATUS0 (0x00000598)
+#define SW_RESET BIT(2)
+#define SW_RESET_PLL BIT(0)
+#define PWRDN_B BIT(7)
+
+/* multimedia sub system clock control */
+char *mmss_cc_base = MSM_MMSS_CLK_CTL_BASE;
+/* multimedia sub system sfpb */
+char *mmss_sfpb_base;
+void __iomem *periph_base;
+
+int mipi_dsi_clk_on;
+static struct dsi_clk_desc dsicore_clk;
+static struct dsi_clk_desc dsi_pclk;
+
+static struct clk *dsi_byte_div_clk;
+static struct clk *dsi_esc_clk;
+static struct clk *dsi_m_pclk;
+static struct clk *dsi_s_pclk;
+
+static struct clk *amp_pclk;
+
+void mipi_dsi_clk_init(struct device *dev)
+{
+ amp_pclk = clk_get(NULL, "amp_pclk");
+ if (IS_ERR(amp_pclk)) {
+ pr_err("can't find amp_pclk\n");
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_m_pclk = clk_get(dev, "dsi_m_pclk");
+ if (IS_ERR(dsi_m_pclk)) {
+ pr_err("can't find dsi_m_pclk\n");
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_s_pclk = clk_get(dev, "dsi_s_pclk");
+ if (IS_ERR(dsi_s_pclk)) {
+ pr_err("can't find dsi_s_pclk\n");
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_byte_div_clk = clk_get(dev, "dsi_byte_div_clk");
+ if (IS_ERR(dsi_byte_div_clk)) {
+ pr_err("can't find dsi_byte_div_clk\n");
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_esc_clk = clk_get(dev, "dsi_esc_clk");
+ if (IS_ERR(dsi_esc_clk)) {
+ printk(KERN_ERR "can't find dsi_esc_clk\n");
+ goto mipi_dsi_clk_err;
+ }
+
+ return;
+
+mipi_dsi_clk_err:
+ mipi_dsi_clk_deinit(NULL);
+}
+
+void mipi_dsi_clk_deinit(struct device *dev)
+{
+ clk_put(amp_pclk);
+ clk_put(dsi_m_pclk);
+ clk_put(dsi_s_pclk);
+ clk_put(dsi_byte_div_clk);
+ clk_put(dsi_esc_clk);
+}
+
+static void mipi_dsi_clk_ctrl(struct dsi_clk_desc *clk, int clk_en)
+{
+ char *cc, *ns, *md;
+ int pmxo_sel = 0;
+ char mnd_en = 1, root_en = 1;
+ uint32 data, val;
+
+ cc = mmss_cc_base + 0x004c;
+ md = mmss_cc_base + 0x0050;
+ ns = mmss_cc_base + 0x0054;
+
+ if (clk_en) {
+ if (clk->mnd_mode == 0) {
+ data = clk->pre_div_func << 14;
+ data |= clk->src;
+ MIPI_OUTP_SECURE(ns, data);
+ MIPI_OUTP_SECURE(cc, ((pmxo_sel << 8)
+ | (clk->mnd_mode << 6)
+ | (root_en << 2) | clk_en));
+ } else {
+ val = clk->d * 2;
+ data = (~val) & 0x0ff;
+ data |= clk->m << 8;
+ MIPI_OUTP_SECURE(md, data);
+
+ val = clk->n - clk->m;
+ data = (~val) & 0x0ff;
+ data <<= 24;
+ data |= clk->src;
+ MIPI_OUTP_SECURE(ns, data);
+
+ MIPI_OUTP_SECURE(cc, ((pmxo_sel << 8)
+ | (clk->mnd_mode << 6)
+ | (mnd_en << 5)
+ | (root_en << 2) | clk_en));
+ }
+ } else
+ MIPI_OUTP_SECURE(cc, 0);
+
+ wmb();
+}
+
+static void mipi_dsi_sfpb_cfg(void)
+{
+ char *sfpb;
+ int data;
+
+ sfpb = mmss_sfpb_base + 0x058;
+
+ data = MIPI_INP(sfpb);
+ data |= 0x01800;
+ MIPI_OUTP(sfpb, data);
+ wmb();
+}
+
+static void mipi_dsi_pclk_ctrl(struct dsi_clk_desc *clk, int clk_en)
+{
+ char *cc, *ns, *md;
+ char mnd_en = 1, root_en = 1;
+ uint32 data, val;
+
+ cc = mmss_cc_base + 0x0130;
+ md = mmss_cc_base + 0x0134;
+ ns = mmss_cc_base + 0x0138;
+
+ if (clk_en) {
+ if (clk->mnd_mode == 0) {
+ data = clk->pre_div_func << 12;
+ data |= clk->src;
+ MIPI_OUTP_SECURE(ns, data);
+ MIPI_OUTP_SECURE(cc, ((clk->mnd_mode << 6)
+ | (root_en << 2) | clk_en));
+ } else {
+ val = clk->d * 2;
+ data = (~val) & 0x0ff;
+ data |= clk->m << 8;
+ MIPI_OUTP_SECURE(md, data);
+
+ val = clk->n - clk->m;
+ data = (~val) & 0x0ff;
+ data <<= 24;
+ data |= clk->src;
+ MIPI_OUTP_SECURE(ns, data);
+
+ MIPI_OUTP_SECURE(cc, ((clk->mnd_mode << 6)
+ | (mnd_en << 5)
+ | (root_en << 2) | clk_en));
+ }
+ } else
+ MIPI_OUTP_SECURE(cc, 0);
+
+ wmb();
+}
+
+static void mipi_dsi_ahb_en(void)
+{
+ char *ahb;
+
+ ahb = mmss_cc_base + 0x08;
+
+ pr_debug("%s: ahb=%x %x\n",
+ __func__, (int) ahb, MIPI_INP_SECURE(ahb));
+}
+
+static void mipi_dsi_calibration(void)
+{
+ int i = 0;
+ uint32 term_cnt = 5000;
+ int cal_busy = MIPI_INP(MIPI_DSI_BASE + 0x550);
+
+ /* DSI1_DSIPHY_REGULATOR_CAL_PWR_CFG */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0518, 0x01);
+
+ /* DSI1_DSIPHY_CAL_SW_CFG2 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0534, 0x0);
+ /* DSI1_DSIPHY_CAL_HW_CFG1 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x053c, 0x5a);
+ /* DSI1_DSIPHY_CAL_HW_CFG3 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0544, 0x10);
+ /* DSI1_DSIPHY_CAL_HW_CFG4 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0548, 0x01);
+ /* DSI1_DSIPHY_CAL_HW_CFG0 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0538, 0x01);
+
+ /* DSI1_DSIPHY_CAL_HW_TRIGGER */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0528, 0x01);
+ usleep_range(5000, 5000);
+ /* DSI1_DSIPHY_CAL_HW_TRIGGER */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0528, 0x00);
+
+ cal_busy = MIPI_INP(MIPI_DSI_BASE + 0x550);
+ while (cal_busy & 0x10) {
+ i++;
+ if (i > term_cnt) {
+ pr_err("DSI1 PHY REGULATOR NOT READY,"
+ "exceeded polling TIMEOUT!\n");
+ break;
+ }
+ cal_busy = MIPI_INP(MIPI_DSI_BASE + 0x550);
+ }
+}
+
+void mipi_dsi_phy_rdy_poll(void)
+{
+ uint32 phy_pll_busy;
+ uint32 i = 0;
+ uint32 term_cnt = 0xFFFFFF;
+
+ phy_pll_busy = MIPI_INP(MIPI_DSI_BASE + 0x280);
+ while (!(phy_pll_busy & 0x1)) {
+ i++;
+ if (i > term_cnt) {
+ pr_err("DSI1 PHY NOT READY, exceeded polling TIMEOUT!\n");
+ break;
+ }
+ phy_pll_busy = MIPI_INP(MIPI_DSI_BASE + 0x280);
+ }
+}
+
+#define PREF_DIV_RATIO 27
+struct dsiphy_pll_divider_config pll_divider_config;
+
+int mipi_dsi_phy_pll_config(u32 clk_rate)
+{
+ struct dsiphy_pll_divider_config *dividers;
+ u32 fb_divider, tmp;
+ dividers = &pll_divider_config;
+
+ /* DSIPHY_PLL_CTRL_x: 1 2 3 8 9 10 */
+ /* masks 0xff 0x07 0x3f 0x0f 0xff 0xff */
+
+ /* DSIPHY_PLL_CTRL_1 */
+ fb_divider = ((dividers->fb_divider) / 2) - 1;
+ MIPI_OUTP(MIPI_DSI_BASE + 0x204, fb_divider & 0xff);
+
+ /* DSIPHY_PLL_CTRL_2 */
+ tmp = MIPI_INP(MIPI_DSI_BASE + 0x208);
+ tmp &= ~0x07;
+ tmp |= (fb_divider >> 8) & 0x07;
+ MIPI_OUTP(MIPI_DSI_BASE + 0x208, tmp);
+
+ /* DSIPHY_PLL_CTRL_3 */
+ tmp = MIPI_INP(MIPI_DSI_BASE + 0x20c);
+ tmp &= ~0x3f;
+ tmp |= (dividers->ref_divider_ratio - 1) & 0x3f;
+ MIPI_OUTP(MIPI_DSI_BASE + 0x20c, tmp);
+
+ /* DSIPHY_PLL_CTRL_8 */
+ tmp = MIPI_INP(MIPI_DSI_BASE + 0x220);
+ tmp &= ~0x0f;
+ tmp |= (dividers->bit_clk_divider - 1) & 0x0f;
+ MIPI_OUTP(MIPI_DSI_BASE + 0x220, tmp);
+
+ /* DSIPHY_PLL_CTRL_9 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x224, (dividers->byte_clk_divider - 1));
+
+ /* DSIPHY_PLL_CTRL_10 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x228, (dividers->dsi_clk_divider - 1));
+
+ return 0;
+}
+
+int mipi_dsi_clk_div_config(uint8 bpp, uint8 lanes,
+ uint32 *expected_dsi_pclk)
+{
+ u32 fb_divider, rate, vco;
+ u32 div_ratio = 0;
+ struct dsi_clk_mnd_table const *mnd_entry = mnd_table;
+ if (pll_divider_config.clk_rate == 0)
+ pll_divider_config.clk_rate = 454000000;
+
+ rate = pll_divider_config.clk_rate / 1000000; /* In Mhz */
+
+ if (rate < 125) {
+ vco = rate * 8;
+ div_ratio = 8;
+ } else if (rate < 250) {
+ vco = rate * 4;
+ div_ratio = 4;
+ } else if (rate < 500) {
+ vco = rate * 2;
+ div_ratio = 2;
+ } else {
+ vco = rate * 1;
+ div_ratio = 1;
+ }
+
+ /* find the mnd settings from mnd_table entry */
+ for (; mnd_entry != mnd_table + ARRAY_SIZE(mnd_table); ++mnd_entry) {
+ if (((mnd_entry->lanes) == lanes) &&
+ ((mnd_entry->bpp) == bpp))
+ break;
+ }
+
+ if (mnd_entry == mnd_table + ARRAY_SIZE(mnd_table)) {
+ pr_err("%s: requested Lanes, %u & BPP, %u, not supported\n",
+ __func__, lanes, bpp);
+ return -EINVAL;
+ }
+ fb_divider = ((vco * PREF_DIV_RATIO) / 27);
+ pll_divider_config.fb_divider = fb_divider;
+ pll_divider_config.ref_divider_ratio = PREF_DIV_RATIO;
+ pll_divider_config.bit_clk_divider = div_ratio;
+ pll_divider_config.byte_clk_divider =
+ pll_divider_config.bit_clk_divider * 8;
+ pll_divider_config.dsi_clk_divider =
+ (mnd_entry->dsiclk_div) * div_ratio;
+
+ if (mnd_entry->dsiclk_d == 0) {
+ dsicore_clk.mnd_mode = 0;
+ dsicore_clk.src = 0x3;
+ dsicore_clk.pre_div_func = (mnd_entry->dsiclk_n - 1);
+ } else {
+ dsicore_clk.mnd_mode = 2;
+ dsicore_clk.src = 0x3;
+ dsicore_clk.m = mnd_entry->dsiclk_m;
+ dsicore_clk.n = mnd_entry->dsiclk_n;
+ dsicore_clk.d = mnd_entry->dsiclk_d;
+ }
+
+ if ((mnd_entry->pclk_d == 0)
+ || (mnd_entry->pclk_m == 1)) {
+ dsi_pclk.mnd_mode = 0;
+ dsi_pclk.src = 0x3;
+ dsi_pclk.pre_div_func = (mnd_entry->pclk_n - 1);
+ *expected_dsi_pclk = ((vco * 1000000) /
+ ((pll_divider_config.dsi_clk_divider)
+ * (mnd_entry->pclk_n)));
+ } else {
+ dsi_pclk.mnd_mode = 2;
+ dsi_pclk.src = 0x3;
+ dsi_pclk.m = mnd_entry->pclk_m;
+ dsi_pclk.n = mnd_entry->pclk_n;
+ dsi_pclk.d = mnd_entry->pclk_d;
+ *expected_dsi_pclk = ((vco * 1000000 * dsi_pclk.m) /
+ ((pll_divider_config.dsi_clk_divider)
+ * (mnd_entry->pclk_n)));
+ }
+ return 0;
+}
+
+static void mipi_dsi_configure_serdes(void)
+{
+ void __iomem *cc;
+
+ /* PHY registers programemd thru S2P interface */
+ if (periph_base) {
+ MIPI_OUTP(periph_base + 0x2c, 0x000000b6);
+ MIPI_OUTP(periph_base + 0x2c, 0x000001b5);
+ MIPI_OUTP(periph_base + 0x2c, 0x000001b4);
+ MIPI_OUTP(periph_base + 0x2c, 0x000003b3);
+ MIPI_OUTP(periph_base + 0x2c, 0x000003a2);
+ MIPI_OUTP(periph_base + 0x2c, 0x000002a1);
+ MIPI_OUTP(periph_base + 0x2c, 0x000008a0);
+ MIPI_OUTP(periph_base + 0x2c, 0x00000d9f);
+ MIPI_OUTP(periph_base + 0x2c, 0x0000109e);
+ MIPI_OUTP(periph_base + 0x2c, 0x0000209d);
+ MIPI_OUTP(periph_base + 0x2c, 0x0000109c);
+ MIPI_OUTP(periph_base + 0x2c, 0x0000079a);
+ MIPI_OUTP(periph_base + 0x2c, 0x00000c99);
+ MIPI_OUTP(periph_base + 0x2c, 0x00002298);
+ MIPI_OUTP(periph_base + 0x2c, 0x000000a7);
+ MIPI_OUTP(periph_base + 0x2c, 0x000000a6);
+ MIPI_OUTP(periph_base + 0x2c, 0x000000a5);
+ MIPI_OUTP(periph_base + 0x2c, 0x00007fa4);
+ MIPI_OUTP(periph_base + 0x2c, 0x0000eea8);
+ MIPI_OUTP(periph_base + 0x2c, 0x000006aa);
+ MIPI_OUTP(periph_base + 0x2c, 0x00002095);
+ MIPI_OUTP(periph_base + 0x2c, 0x00000493);
+ MIPI_OUTP(periph_base + 0x2c, 0x00001092);
+ MIPI_OUTP(periph_base + 0x2c, 0x00000691);
+ MIPI_OUTP(periph_base + 0x2c, 0x00005490);
+ MIPI_OUTP(periph_base + 0x2c, 0x0000038d);
+ MIPI_OUTP(periph_base + 0x2c, 0x0000148c);
+ MIPI_OUTP(periph_base + 0x2c, 0x0000058b);
+ MIPI_OUTP(periph_base + 0x2c, 0x0000078a);
+ MIPI_OUTP(periph_base + 0x2c, 0x00001f89);
+ MIPI_OUTP(periph_base + 0x2c, 0x00003388);
+ MIPI_OUTP(periph_base + 0x2c, 0x00006387);
+ MIPI_OUTP(periph_base + 0x2c, 0x00004886);
+ MIPI_OUTP(periph_base + 0x2c, 0x00005085);
+ MIPI_OUTP(periph_base + 0x2c, 0x00000084);
+ MIPI_OUTP(periph_base + 0x2c, 0x0000da83);
+ MIPI_OUTP(periph_base + 0x2c, 0x0000b182);
+ MIPI_OUTP(periph_base + 0x2c, 0x00002f81);
+ MIPI_OUTP(periph_base + 0x2c, 0x00004080);
+ MIPI_OUTP(periph_base + 0x2c, 0x00004180);
+ MIPI_OUTP(periph_base + 0x2c, 0x000006aa);
+ }
+
+ cc = MIPI_DSI_BASE + 0x0130;
+ MIPI_OUTP(cc, 0x806c11c8);
+ MIPI_OUTP(cc, 0x804c11c8);
+ MIPI_OUTP(cc, 0x806d0080);
+ MIPI_OUTP(cc, 0x804d0080);
+ MIPI_OUTP(cc, 0x00000000);
+ MIPI_OUTP(cc, 0x807b1597);
+ MIPI_OUTP(cc, 0x805b1597);
+ MIPI_OUTP(cc, 0x807c0080);
+ MIPI_OUTP(cc, 0x805c0080);
+ MIPI_OUTP(cc, 0x00000000);
+ MIPI_OUTP(cc, 0x807911c8);
+ MIPI_OUTP(cc, 0x805911c8);
+ MIPI_OUTP(cc, 0x807a0080);
+ MIPI_OUTP(cc, 0x805a0080);
+ MIPI_OUTP(cc, 0x00000000);
+ MIPI_OUTP(cc, 0x80721555);
+ MIPI_OUTP(cc, 0x80521555);
+ MIPI_OUTP(cc, 0x80730000);
+ MIPI_OUTP(cc, 0x80530000);
+ MIPI_OUTP(cc, 0x00000000);
+}
+
+void mipi_dsi_phy_init(int panel_ndx, struct msm_panel_info const *panel_info,
+ int target_type)
+{
+ struct mipi_dsi_phy_ctrl *pd;
+ int i, off;
+
+ MIPI_OUTP(MIPI_DSI_BASE + 0x128, 0x0001);/* start phy sw reset */
+ msleep(100);
+ MIPI_OUTP(MIPI_DSI_BASE + 0x128, 0x0000);/* end phy w reset */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x500, 0x0003);/* regulator_ctrl_0 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x504, 0x0001);/* regulator_ctrl_1 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x508, 0x0001);/* regulator_ctrl_2 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x50c, 0x0000);/* regulator_ctrl_3 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x510, 0x0100);/* regulator_ctrl_4 */
+
+ pd = (panel_info->mipi).dsi_phy_db;
+
+ off = 0x0480; /* strength 0 - 2 */
+ for (i = 0; i < 3; i++) {
+ MIPI_OUTP(MIPI_DSI_BASE + off, pd->strength[i]);
+ wmb();
+ off += 4;
+ }
+
+ off = 0x0470; /* ctrl 0 - 3 */
+ for (i = 0; i < 4; i++) {
+ MIPI_OUTP(MIPI_DSI_BASE + off, pd->ctrl[i]);
+ wmb();
+ off += 4;
+ }
+
+ off = 0x0500; /* regulator ctrl 0 - 4 */
+ for (i = 0; i < 5; i++) {
+ MIPI_OUTP(MIPI_DSI_BASE + off, pd->regulator[i]);
+ wmb();
+ off += 4;
+ }
+ mipi_dsi_calibration();
+
+ off = 0x0204; /* pll ctrl 1 - 19, skip 0 */
+ for (i = 1; i < 20; i++) {
+ MIPI_OUTP(MIPI_DSI_BASE + off, pd->pll[i]);
+ wmb();
+ off += 4;
+ }
+
+ if (panel_info)
+ mipi_dsi_phy_pll_config(panel_info->clk_rate);
+
+ /* pll ctrl 0 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x200, pd->pll[0]);
+ wmb();
+ MIPI_OUTP(MIPI_DSI_BASE + 0x200, (pd->pll[0] | 0x01));
+
+ mipi_dsi_phy_rdy_poll();
+
+ off = 0x0440; /* phy timig ctrl 0 - 11 */
+ for (i = 0; i < 12; i++) {
+ MIPI_OUTP(MIPI_DSI_BASE + off, pd->timing[i]);
+ wmb();
+ off += 4;
+ }
+
+ if (target_type == 1)
+ mipi_dsi_configure_serdes();
+}
+
+void mipi_dsi_clk_enable(void)
+{
+ if (mipi_dsi_clk_on) {
+ pr_err("%s: mipi_dsi_clk already ON\n", __func__);
+ return;
+ }
+
+ mipi_dsi_clk_on = 1;
+
+ clk_enable(amp_pclk); /* clock for AHB-master to AXI */
+ clk_enable(dsi_m_pclk);
+ clk_enable(dsi_s_pclk);
+ if (clk_set_rate(dsi_byte_div_clk, 1) < 0) /* divided by 1 */
+ pr_err("%s: dsi_byte_div_clk - "
+ "clk_set_rate failed\n", __func__);
+ if (clk_set_rate(dsi_esc_clk, 2) < 0) /* divided by 2 */
+ pr_err("%s: dsi_esc_clk - "
+ "clk_set_rate failed\n", __func__);
+ clk_enable(dsi_byte_div_clk);
+ clk_enable(dsi_esc_clk);
+ mipi_dsi_pclk_ctrl(&dsi_pclk, 1);
+ mipi_dsi_clk_ctrl(&dsicore_clk, 1);
+ mipi_dsi_ahb_en();
+ mipi_dsi_sfpb_cfg();
+}
+
+void mipi_dsi_clk_disable(void)
+{
+ if (mipi_dsi_clk_on == 0) {
+ pr_err("%s: mipi_dsi_clk already OFF\n", __func__);
+ return;
+ }
+
+ mipi_dsi_clk_on = 0;
+
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0118, 0);
+
+ mipi_dsi_pclk_ctrl(&dsi_pclk, 0);
+ mipi_dsi_clk_ctrl(&dsicore_clk, 0);
+ clk_disable(dsi_esc_clk);
+ clk_disable(dsi_byte_div_clk);
+ clk_disable(dsi_m_pclk);
+ clk_disable(dsi_s_pclk);
+ clk_disable(amp_pclk); /* clock for AHB-master to AXI */
+}
+
+void mipi_dsi_phy_ctrl(int on)
+{
+ if (on) {
+ /* DSIPHY_PLL_CTRL_5 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0214, 0x050);
+ } else {
+ /* DSIPHY_PLL_CTRL_5 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0214, 0x05f);
+
+ /* DSIPHY_REGULATOR_CTRL_0 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0500, 0x02);
+
+ /* DSIPHY_CTRL_0 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0470, 0x00);
+
+ /* DSIPHY_CTRL_1 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0474, 0x7f);
+
+ /* DSIPHY_PLL_CTRL_0, disbale dsi pll */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0200, 0x40);
+
+ /* disbale dsi clk */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0118, 0);
+ }
+}
+
+#ifdef CONFIG_FB_MSM_HDMI_COMMON
+void hdmi_phy_reset(void)
+{
+ unsigned int phy_reset_polarity = 0x0;
+ unsigned int pll_reset_polarity = 0x0;
+
+ unsigned int val = HDMI_INP_ND(HDMI_PHY_CTRL);
+
+ phy_reset_polarity = val >> 3 & 0x1;
+ pll_reset_polarity = val >> 1 & 0x1;
+
+ if (phy_reset_polarity == 0)
+ HDMI_OUTP(HDMI_PHY_CTRL, val | SW_RESET);
+ else
+ HDMI_OUTP(HDMI_PHY_CTRL, val & (~SW_RESET));
+
+ if (pll_reset_polarity == 0)
+ HDMI_OUTP(HDMI_PHY_CTRL, val | SW_RESET_PLL);
+ else
+ HDMI_OUTP(HDMI_PHY_CTRL, val & (~SW_RESET_PLL));
+
+ msleep(100);
+
+ if (phy_reset_polarity == 0)
+ HDMI_OUTP(HDMI_PHY_CTRL, val & (~SW_RESET));
+ else
+ HDMI_OUTP(HDMI_PHY_CTRL, val | SW_RESET);
+
+ if (pll_reset_polarity == 0)
+ HDMI_OUTP(HDMI_PHY_CTRL, val & (~SW_RESET_PLL));
+ else
+ HDMI_OUTP(HDMI_PHY_CTRL, val | SW_RESET_PLL);
+}
+
+void hdmi_msm_init_phy(int video_format)
+{
+ uint32 offset;
+ pr_err("Video format is : %u\n", video_format);
+
+ HDMI_OUTP(HDMI_PHY_REG_0, 0x1B);
+ HDMI_OUTP(HDMI_PHY_REG_1, 0xf2);
+ HDMI_OUTP(HDMI_PHY_REG_2, 0x7F);
+ HDMI_OUTP(HDMI_PHY_REG_2, 0x3F);
+ HDMI_OUTP(HDMI_PHY_REG_2, 0x1F);
+
+ offset = HDMI_PHY_REG_4;
+ while (offset <= HDMI_PHY_REG_11) {
+ HDMI_OUTP(offset, 0x0);
+ offset += 0x4;
+ }
+
+ HDMI_OUTP(HDMI_PHY_REG_12, HDMI_INP(HDMI_PHY_REG_12) | PWRDN_B);
+ msleep(100);
+
+ HDMI_OUTP(HDMI_PHY_REG_3, 0x20);
+ HDMI_OUTP(HDMI_PHY_REG_12, 0x81);
+ HDMI_OUTP(HDMI_PHY_REG_2, 0x81);
+}
+
+void hdmi_msm_powerdown_phy(void)
+{
+ /* Power down PHY */
+ HDMI_OUTP_ND(HDMI_PHY_REG_2, 0x7F); /*0b01111111*/
+}
+
+void hdmi_frame_ctrl_cfg(const struct hdmi_disp_mode_timing_type *timing)
+{
+ /* 0x02C8 HDMI_FRAME_CTRL
+ * 31 INTERLACED_EN Interlaced or progressive enable bit
+ * 0: Frame in progressive
+ * 1: Frame is interlaced
+ * 29 HSYNC_HDMI_POL HSYNC polarity fed to HDMI core
+ * 0: Active Hi Hsync, detect the rising edge of hsync
+ * 1: Active lo Hsync, Detect the falling edge of Hsync
+ * 28 VSYNC_HDMI_POL VSYNC polarity fed to HDMI core
+ * 0: Active Hi Vsync, detect the rising edge of vsync
+ * 1: Active Lo Vsync, Detect the falling edge of Vsync
+ * 12 RGB_MUX_SEL ALPHA mdp4 input is RGB, mdp4 input is BGR
+ */
+ HDMI_OUTP(0x02C8,
+ ((timing->interlaced << 31) & 0x80000000)
+ | ((timing->active_low_h << 29) & 0x20000000)
+ | ((timing->active_low_v << 28) & 0x10000000));
+}
+
+void hdmi_msm_phy_status_poll(void)
+{
+ unsigned int lock_det, phy_ready;
+ lock_det = 0x1 & HDMI_INP_ND(HDMI_PHY_PLL_STATUS0);
+ if (lock_det) {
+ pr_debug("HDMI Phy PLL Lock Detect Bit is set\n");
+ } else {
+ pr_debug("HDMI Phy Lock Detect Bit is not set,"
+ "waiting for lock detection\n");
+ do {
+ lock_det = 0x1 & \
+ HDMI_INP_ND(HDMI_PHY_PLL_STATUS0);
+ } while (!lock_det);
+ }
+
+ phy_ready = 0x1 & HDMI_INP_ND(HDMI_PHY_REG_15);
+ if (phy_ready) {
+ pr_debug("HDMI Phy Status bit is set and ready\n");
+ } else {
+ pr_debug("HDMI Phy Status bit is not set,"
+ "waiting for ready status\n");
+ do {
+ phy_ready = 0x1 & HDMI_INP_ND(HDMI_PHY_REG_15);
+ } while (!phy_ready);
+ }
+}
+
+#endif
diff --git a/drivers/video/msm/msm_dss_io_8x60.c b/drivers/video/msm/msm_dss_io_8x60.c
new file mode 100644
index 0000000..e38170f
--- /dev/null
+++ b/drivers/video/msm/msm_dss_io_8x60.c
@@ -0,0 +1,613 @@
+/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/clk.h>
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "hdmi_msm.h"
+#include <mach/msm_iomap.h>
+
+/* multimedia sub system clock control */
+char *mmss_cc_base = MSM_MMSS_CLK_CTL_BASE;
+/* multimedia sub system sfpb */
+char *mmss_sfpb_base;
+void __iomem *periph_base;
+
+int mipi_dsi_clk_on;
+static struct dsi_clk_desc dsicore_clk;
+static struct dsi_clk_desc dsi_pclk;
+
+static struct clk *dsi_byte_div_clk;
+static struct clk *dsi_esc_clk;
+static struct clk *dsi_m_pclk;
+static struct clk *dsi_s_pclk;
+
+static struct clk *amp_pclk;
+
+void mipi_dsi_clk_init(struct device *dev)
+{
+ amp_pclk = clk_get(NULL, "amp_pclk");
+ if (IS_ERR(amp_pclk)) {
+ pr_err("can't find amp_pclk\n");
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_m_pclk = clk_get(NULL, "dsi_m_pclk");
+ if (IS_ERR(dsi_m_pclk)) {
+ pr_err("can't find dsi_m_pclk\n");
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_s_pclk = clk_get(NULL, "dsi_s_pclk");
+ if (IS_ERR(dsi_s_pclk)) {
+ pr_err("can't find dsi_s_pclk\n");
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_byte_div_clk = clk_get(NULL, "dsi_byte_div_clk");
+ if (IS_ERR(dsi_byte_div_clk)) {
+ pr_err("can't find dsi_byte_div_clk\n");
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_esc_clk = clk_get(NULL, "dsi_esc_clk");
+ if (IS_ERR(dsi_esc_clk)) {
+ printk(KERN_ERR "can't find dsi_esc_clk\n");
+ goto mipi_dsi_clk_err;
+ }
+
+ return;
+
+mipi_dsi_clk_err:
+ mipi_dsi_clk_deinit(NULL);
+}
+
+void mipi_dsi_clk_deinit(struct device *dev)
+{
+ clk_put(amp_pclk);
+ clk_put(dsi_m_pclk);
+ clk_put(dsi_s_pclk);
+ clk_put(dsi_byte_div_clk);
+ clk_put(dsi_esc_clk);
+}
+
+static void mipi_dsi_clk_ctrl(struct dsi_clk_desc *clk, int clk_en)
+{
+ char *cc, *ns, *md;
+ int pmxo_sel = 0;
+ char mnd_en = 1, root_en = 1;
+ uint32 data, val;
+
+ cc = mmss_cc_base + 0x004c;
+ md = mmss_cc_base + 0x0050;
+ ns = mmss_cc_base + 0x0054;
+
+ if (clk_en) {
+ if (clk->mnd_mode == 0) {
+ data = clk->pre_div_func << 14;
+ data |= clk->src;
+ MIPI_OUTP_SECURE(ns, data);
+ MIPI_OUTP_SECURE(cc, ((pmxo_sel << 8)
+ | (clk->mnd_mode << 6)
+ | (root_en << 2) | clk_en));
+ } else {
+ val = clk->d * 2;
+ data = (~val) & 0x0ff;
+ data |= clk->m << 8;
+ MIPI_OUTP_SECURE(md, data);
+
+ val = clk->n - clk->m;
+ data = (~val) & 0x0ff;
+ data <<= 24;
+ data |= clk->src;
+ MIPI_OUTP_SECURE(ns, data);
+
+ MIPI_OUTP_SECURE(cc, ((pmxo_sel << 8)
+ | (clk->mnd_mode << 6)
+ | (mnd_en << 5)
+ | (root_en << 2) | clk_en));
+ }
+
+ } else
+ MIPI_OUTP_SECURE(cc, 0);
+
+ wmb();
+}
+
+static void mipi_dsi_sfpb_cfg(void)
+{
+ char *sfpb;
+ int data;
+
+ sfpb = mmss_sfpb_base + 0x058;
+
+ data = MIPI_INP(sfpb);
+ data |= 0x01800;
+ MIPI_OUTP(sfpb, data);
+ wmb();
+}
+
+static void mipi_dsi_pclk_ctrl(struct dsi_clk_desc *clk, int clk_en)
+{
+ char *cc, *ns, *md;
+ char mnd_en = 1, root_en = 1;
+ uint32 data, val;
+
+ cc = mmss_cc_base + 0x0130;
+ md = mmss_cc_base + 0x0134;
+ ns = mmss_cc_base + 0x0138;
+
+ if (clk_en) {
+ if (clk->mnd_mode == 0) {
+ data = clk->pre_div_func << 12;
+ data |= clk->src;
+ MIPI_OUTP_SECURE(ns, data);
+ MIPI_OUTP_SECURE(cc, ((clk->mnd_mode << 6)
+ | (root_en << 2) | clk_en));
+ } else {
+ val = clk->d * 2;
+ data = (~val) & 0x0ff;
+ data |= clk->m << 8;
+ MIPI_OUTP_SECURE(md, data);
+
+ val = clk->n - clk->m;
+ data = (~val) & 0x0ff;
+ data <<= 24;
+ data |= clk->src;
+ MIPI_OUTP_SECURE(ns, data);
+
+ MIPI_OUTP_SECURE(cc, ((clk->mnd_mode << 6)
+ | (mnd_en << 5)
+ | (root_en << 2) | clk_en));
+ }
+
+ } else
+ MIPI_OUTP_SECURE(cc, 0);
+
+ wmb();
+}
+
+static void mipi_dsi_ahb_en(void)
+{
+ char *ahb;
+
+ ahb = mmss_cc_base + 0x08;
+
+ pr_debug("%s: ahb=%x %x\n",
+ __func__, (int) ahb, MIPI_INP_SECURE(ahb));
+}
+
+static void mipi_dsi_calibration(void)
+{
+ uint32 data;
+
+ MIPI_OUTP(MIPI_DSI_BASE + 0xf4, 0x0000ff11); /* cal_ctrl */
+ MIPI_OUTP(MIPI_DSI_BASE + 0xf0, 0x01); /* cal_hw_trigger */
+
+ while (1) {
+ data = MIPI_INP(MIPI_DSI_BASE + 0xfc); /* cal_status */
+ if ((data & 0x10000000) == 0)
+ break;
+
+ udelay(10);
+ }
+}
+
+#define PREF_DIV_RATIO 27
+struct dsiphy_pll_divider_config pll_divider_config;
+
+
+int mipi_dsi_phy_pll_config(u32 clk_rate)
+{
+ struct dsiphy_pll_divider_config *dividers;
+ u32 fb_divider, tmp;
+ dividers = &pll_divider_config;
+
+ /* DSIPHY_PLL_CTRL_x: 1 2 3 8 9 10 */
+ /* masks 0xff 0x07 0x3f 0x0f 0xff 0xff */
+
+ /* DSIPHY_PLL_CTRL_1 */
+ fb_divider = ((dividers->fb_divider) / 2) - 1;
+ MIPI_OUTP(MIPI_DSI_BASE + 0x204, fb_divider & 0xff);
+
+ /* DSIPHY_PLL_CTRL_2 */
+ tmp = MIPI_INP(MIPI_DSI_BASE + 0x208);
+ tmp &= ~0x07;
+ tmp |= (fb_divider >> 8) & 0x07;
+ MIPI_OUTP(MIPI_DSI_BASE + 0x208, tmp);
+
+ /* DSIPHY_PLL_CTRL_3 */
+ tmp = MIPI_INP(MIPI_DSI_BASE + 0x20c);
+ tmp &= ~0x3f;
+ tmp |= (dividers->ref_divider_ratio - 1) & 0x3f;
+ MIPI_OUTP(MIPI_DSI_BASE + 0x20c, tmp);
+
+ /* DSIPHY_PLL_CTRL_8 */
+ tmp = MIPI_INP(MIPI_DSI_BASE + 0x220);
+ tmp &= ~0x0f;
+ tmp |= (dividers->bit_clk_divider - 1) & 0x0f;
+ MIPI_OUTP(MIPI_DSI_BASE + 0x220, tmp);
+
+ /* DSIPHY_PLL_CTRL_9 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x224, (dividers->byte_clk_divider - 1));
+
+ /* DSIPHY_PLL_CTRL_10 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x228, (dividers->dsi_clk_divider - 1));
+
+ return 0;
+}
+
+int mipi_dsi_clk_div_config(uint8 bpp, uint8 lanes,
+ uint32 *expected_dsi_pclk)
+{
+ u32 fb_divider, rate, vco;
+ u32 div_ratio = 0;
+ struct dsi_clk_mnd_table const *mnd_entry = mnd_table;
+ if (pll_divider_config.clk_rate == 0)
+ pll_divider_config.clk_rate = 454000000;
+
+ rate = pll_divider_config.clk_rate / 1000000; /* In Mhz */
+
+ if (rate < 125) {
+ vco = rate * 8;
+ div_ratio = 8;
+ } else if (rate < 250) {
+ vco = rate * 4;
+ div_ratio = 4;
+ } else if (rate < 500) {
+ vco = rate * 2;
+ div_ratio = 2;
+ } else {
+ vco = rate * 1;
+ div_ratio = 1;
+ }
+
+ /* find the mnd settings from mnd_table entry */
+ for (; mnd_entry != mnd_table + ARRAY_SIZE(mnd_table); ++mnd_entry) {
+ if (((mnd_entry->lanes) == lanes) &&
+ ((mnd_entry->bpp) == bpp))
+ break;
+ }
+
+ if (mnd_entry == mnd_table + ARRAY_SIZE(mnd_table)) {
+ pr_err("%s: requested Lanes, %u & BPP, %u, not supported\n",
+ __func__, lanes, bpp);
+ return -EINVAL;
+ }
+ fb_divider = ((vco * PREF_DIV_RATIO) / 27);
+ pll_divider_config.fb_divider = fb_divider;
+ pll_divider_config.ref_divider_ratio = PREF_DIV_RATIO;
+ pll_divider_config.bit_clk_divider = div_ratio;
+ pll_divider_config.byte_clk_divider =
+ pll_divider_config.bit_clk_divider * 8;
+ pll_divider_config.dsi_clk_divider =
+ (mnd_entry->dsiclk_div) * div_ratio;
+
+ if ((mnd_entry->dsiclk_d == 0)
+ || (mnd_entry->dsiclk_m == 1)) {
+ dsicore_clk.mnd_mode = 0;
+ dsicore_clk.src = 0x3;
+ dsicore_clk.pre_div_func = (mnd_entry->dsiclk_n - 1);
+ } else {
+ dsicore_clk.mnd_mode = 2;
+ dsicore_clk.src = 0x3;
+ dsicore_clk.m = mnd_entry->dsiclk_m;
+ dsicore_clk.n = mnd_entry->dsiclk_n;
+ dsicore_clk.d = mnd_entry->dsiclk_d;
+ }
+
+ if ((mnd_entry->pclk_d == 0)
+ || (mnd_entry->pclk_m == 1)) {
+ dsi_pclk.mnd_mode = 0;
+ dsi_pclk.src = 0x3;
+ dsi_pclk.pre_div_func = (mnd_entry->pclk_n - 1);
+ *expected_dsi_pclk = ((vco * 1000000) /
+ ((pll_divider_config.dsi_clk_divider)
+ * (mnd_entry->pclk_n)));
+ } else {
+ dsi_pclk.mnd_mode = 2;
+ dsi_pclk.src = 0x3;
+ dsi_pclk.m = mnd_entry->pclk_m;
+ dsi_pclk.n = mnd_entry->pclk_n;
+ dsi_pclk.d = mnd_entry->pclk_d;
+ *expected_dsi_pclk = ((vco * 1000000 * dsi_pclk.m) /
+ ((pll_divider_config.dsi_clk_divider)
+ * (mnd_entry->pclk_n)));
+ }
+ return 0;
+}
+
+void mipi_dsi_phy_init(int panel_ndx, struct msm_panel_info const *panel_info,
+ int target_type)
+{
+ struct mipi_dsi_phy_ctrl *pd;
+ int i, off;
+
+ MIPI_OUTP(MIPI_DSI_BASE + 0x128, 0x0001);/* start phy sw reset */
+ msleep(100);
+ MIPI_OUTP(MIPI_DSI_BASE + 0x128, 0x0000);/* end phy w reset */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x2cc, 0x0003);/* regulator_ctrl_0 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x2d0, 0x0001);/* regulator_ctrl_1 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x2d4, 0x0001);/* regulator_ctrl_2 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x2d8, 0x0000);/* regulator_ctrl_3 */
+#ifdef DSI_POWER
+ MIPI_OUTP(MIPI_DSI_BASE + 0x2dc, 0x0100);/* regulator_ctrl_4 */
+#endif
+
+ pd = (panel_info->mipi).dsi_phy_db;
+
+ off = 0x02cc; /* regulator ctrl 0 */
+ for (i = 0; i < 4; i++) {
+ MIPI_OUTP(MIPI_DSI_BASE + off, pd->regulator[i]);
+ wmb();
+ off += 4;
+ }
+
+ off = 0x0260; /* phy timig ctrl 0 */
+ for (i = 0; i < 11; i++) {
+ MIPI_OUTP(MIPI_DSI_BASE + off, pd->timing[i]);
+ wmb();
+ off += 4;
+ }
+
+ off = 0x0290; /* ctrl 0 */
+ for (i = 0; i < 4; i++) {
+ MIPI_OUTP(MIPI_DSI_BASE + off, pd->ctrl[i]);
+ wmb();
+ off += 4;
+ }
+
+ off = 0x02a0; /* strength 0 */
+ for (i = 0; i < 4; i++) {
+ MIPI_OUTP(MIPI_DSI_BASE + off, pd->strength[i]);
+ wmb();
+ off += 4;
+ }
+
+ mipi_dsi_calibration();
+
+ off = 0x0204; /* pll ctrl 1, skip 0 */
+ for (i = 1; i < 21; i++) {
+ MIPI_OUTP(MIPI_DSI_BASE + off, pd->pll[i]);
+ wmb();
+ off += 4;
+ }
+
+ if (panel_info)
+ mipi_dsi_phy_pll_config(panel_info->clk_rate);
+
+ /* pll ctrl 0 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x200, pd->pll[0]);
+ wmb();
+ MIPI_OUTP(MIPI_DSI_BASE + 0x200, (pd->pll[0] | 0x01));
+}
+
+void mipi_dsi_clk_enable(void)
+{
+ if (mipi_dsi_clk_on) {
+ pr_err("%s: mipi_dsi_clk already ON\n", __func__);
+ return;
+ }
+
+ mipi_dsi_clk_on = 1;
+
+ clk_enable(amp_pclk); /* clock for AHB-master to AXI */
+ clk_enable(dsi_m_pclk);
+ clk_enable(dsi_s_pclk);
+ if (clk_set_rate(dsi_byte_div_clk, 1) < 0) /* divided by 1 */
+ pr_err("%s: clk_set_rate failed\n", __func__);
+ clk_enable(dsi_byte_div_clk);
+ clk_enable(dsi_esc_clk);
+ mipi_dsi_pclk_ctrl(&dsi_pclk, 1);
+ mipi_dsi_clk_ctrl(&dsicore_clk, 1);
+ mipi_dsi_ahb_en();
+ mipi_dsi_sfpb_cfg();
+}
+
+void mipi_dsi_clk_disable(void)
+{
+ if (mipi_dsi_clk_on == 0) {
+ pr_err("%s: mipi_dsi_clk already OFF\n", __func__);
+ return;
+ }
+
+ mipi_dsi_clk_on = 0;
+
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0118, 0);
+
+ mipi_dsi_pclk_ctrl(&dsi_pclk, 0);
+ mipi_dsi_clk_ctrl(&dsicore_clk, 0);
+ clk_disable(dsi_esc_clk);
+ clk_disable(dsi_byte_div_clk);
+ clk_disable(dsi_m_pclk);
+ clk_disable(dsi_s_pclk);
+ clk_disable(amp_pclk); /* clock for AHB-master to AXI */
+}
+
+void mipi_dsi_phy_ctrl(int on)
+{
+ if (on) {
+ /* DSIPHY_PLL_CTRL_5 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0214, 0x050);
+
+ /* DSIPHY_TPA_CTRL_1 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0258, 0x00f);
+
+ /* DSIPHY_TPA_CTRL_2 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x025c, 0x000);
+ } else {
+ /* DSIPHY_PLL_CTRL_5 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0214, 0x05f);
+
+ /* DSIPHY_TPA_CTRL_1 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0258, 0x08f);
+
+ /* DSIPHY_TPA_CTRL_2 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x025c, 0x001);
+
+ /* DSIPHY_REGULATOR_CTRL_0 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x02cc, 0x02);
+
+ /* DSIPHY_CTRL_0 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0290, 0x00);
+
+ /* DSIPHY_CTRL_1 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0294, 0x7f);
+
+ /* DSIPHY_PLL_CTRL_0, disbale dsi pll */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0200, 0x40);
+
+ /* disbale dsi clk */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0118, 0);
+ }
+}
+
+#ifdef CONFIG_FB_MSM_HDMI_COMMON
+#define SW_RESET BIT(2)
+void hdmi_phy_reset(void)
+{
+ unsigned int phy_reset_polarity = 0x0;
+ unsigned int val = HDMI_INP_ND(0x2D4);
+
+ phy_reset_polarity = val >> 3 & 0x1;
+
+ if (phy_reset_polarity == 0)
+ HDMI_OUTP(0x2D4, val | SW_RESET);
+ else
+ HDMI_OUTP(0x2D4, val & (~SW_RESET));
+
+ msleep(100);
+
+ if (phy_reset_polarity == 0)
+ HDMI_OUTP(0x2D4, val & (~SW_RESET));
+ else
+ HDMI_OUTP(0x2D4, val | SW_RESET);
+}
+
+void hdmi_msm_init_phy(int video_format)
+{
+ uint32 offset;
+ /* De-serializer delay D/C for non-lbk mode
+ * PHY REG0 = (DESER_SEL(0) | DESER_DEL_CTRL(3)
+ * | AMUX_OUT_SEL(0))
+ */
+ HDMI_OUTP_ND(0x0300, 0x0C); /*0b00001100*/
+
+ if (video_format == HDMI_VFRMT_720x480p60_16_9) {
+ /* PHY REG1 = DTEST_MUX_SEL(5) | PLL_GAIN_SEL(0)
+ * | OUTVOL_SWING_CTRL(3)
+ */
+ HDMI_OUTP_ND(0x0304, 0x53); /*0b01010011*/
+ } else {
+ /* If the freq. is less than 120MHz, use low gain 0
+ * for board with termination
+ * PHY REG1 = DTEST_MUX_SEL(5) | PLL_GAIN_SEL(0)
+ * | OUTVOL_SWING_CTRL(4)
+ */
+ HDMI_OUTP_ND(0x0304, 0x54); /*0b01010100*/
+ }
+
+ /* No matter what, start from the power down mode
+ * PHY REG2 = PD_PWRGEN | PD_PLL | PD_DRIVE_4 | PD_DRIVE_3
+ * | PD_DRIVE_2 | PD_DRIVE_1 | PD_DESER
+ */
+ HDMI_OUTP_ND(0x0308, 0x7F); /*0b01111111*/
+
+ /* Turn PowerGen on
+ * PHY REG2 = PD_PLL | PD_DRIVE_4 | PD_DRIVE_3
+ * | PD_DRIVE_2 | PD_DRIVE_1 | PD_DESER
+ */
+ HDMI_OUTP_ND(0x0308, 0x3F); /*0b00111111*/
+
+ /* Turn PLL power on
+ * PHY REG2 = PD_DRIVE_4 | PD_DRIVE_3
+ * | PD_DRIVE_2 | PD_DRIVE_1 | PD_DESER
+ */
+ HDMI_OUTP_ND(0x0308, 0x1F); /*0b00011111*/
+
+ /* Write to HIGH after PLL power down de-assert
+ * PHY REG3 = PLL_ENABLE
+ */
+ HDMI_OUTP_ND(0x030C, 0x01);
+ /* ASIC power on; PHY REG9 = 0 */
+ HDMI_OUTP_ND(0x0324, 0x00);
+ /* Enable PLL lock detect, PLL lock det will go high after lock
+ * Enable the re-time logic
+ * PHY REG12 = PLL_LOCK_DETECT_EN | RETIMING_ENABLE
+ */
+ HDMI_OUTP_ND(0x0330, 0x03); /*0b00000011*/
+
+ /* Drivers are on
+ * PHY REG2 = PD_DESER
+ */
+ HDMI_OUTP_ND(0x0308, 0x01); /*0b00000001*/
+ /* If the RX detector is needed
+ * PHY REG2 = RCV_SENSE_EN | PD_DESER
+ */
+ HDMI_OUTP_ND(0x0308, 0x81); /*0b10000001*/
+
+ offset = 0x0310;
+ while (offset <= 0x032C) {
+ HDMI_OUTP(offset, 0x0);
+ offset += 0x4;
+ }
+
+ /* If we want to use lock enable based on counting
+ * PHY REG12 = FORCE_LOCK | PLL_LOCK_DETECT_EN | RETIMING_ENABLE
+ */
+ HDMI_OUTP_ND(0x0330, 0x13); /*0b00010011*/
+}
+
+void hdmi_msm_powerdown_phy(void)
+{
+ /* Disable PLL */
+ HDMI_OUTP_ND(0x030C, 0x00);
+ /* Power down PHY */
+ HDMI_OUTP_ND(0x0308, 0x7F); /*0b01111111*/
+}
+
+void hdmi_frame_ctrl_cfg(const struct hdmi_disp_mode_timing_type *timing)
+{
+ /* 0x02C8 HDMI_FRAME_CTRL
+ * 31 INTERLACED_EN Interlaced or progressive enable bit
+ * 0: Frame in progressive
+ * 1: Frame is interlaced
+ * 29 HSYNC_HDMI_POL HSYNC polarity fed to HDMI core
+ * 0: Active Hi Hsync, detect the rising edge of hsync
+ * 1: Active lo Hsync, Detect the falling edge of Hsync
+ * 28 VSYNC_HDMI_POL VSYNC polarity fed to HDMI core
+ * 0: Active Hi Vsync, detect the rising edge of vsync
+ * 1: Active Lo Vsync, Detect the falling edge of Vsync
+ * 12 RGB_MUX_SEL ALPHA mdp4 input is RGB, mdp4 input is BGR
+ */
+ HDMI_OUTP(0x02C8,
+ ((timing->interlaced << 31) & 0x80000000)
+ | ((timing->active_low_h << 29) & 0x20000000)
+ | ((timing->active_low_v << 28) & 0x10000000)
+ | (1 << 12));
+}
+
+void hdmi_msm_phy_status_poll(void)
+{
+ unsigned int phy_ready;
+ phy_ready = 0x1 & HDMI_INP_ND(0x33c);
+ if (phy_ready) {
+ pr_debug("HDMI Phy Status bit is set and ready\n");
+ } else {
+ pr_debug("HDMI Phy Status bit is not set,"
+ "waiting for ready status\n");
+ do {
+ phy_ready = 0x1 & HDMI_INP_ND(0x33c);
+ } while (!phy_ready);
+ }
+}
+#endif
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index ec35130..1c4cc72 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -3,6 +3,7 @@
* Core MSM framebuffer driver.
*
* Copyright (C) 2007 Google Incorporated
+ * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -14,627 +15,3045 @@
* GNU General Public License for more details.
*/
-#include <linux/platform_device.h>
#include <linux/module.h>
-#include <linux/fb.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/delay.h>
-
-#include <linux/freezer.h>
-#include <linux/wait.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
#include <linux/msm_mdp.h>
-#include <linux/io.h>
-#include <linux/uaccess.h>
-#include <mach/msm_fb.h>
-#include <mach/board.h>
-#include <linux/workqueue.h>
-#include <linux/clk.h>
-#include <linux/debugfs.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
#include <linux/dma-mapping.h>
+#include <mach/board.h>
+#include <linux/uaccess.h>
-#define PRINT_FPS 0
-#define PRINT_BLIT_TIME 0
+#include <linux/workqueue.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
+#include <linux/debugfs.h>
+#include <linux/console.h>
+#include <linux/android_pmem.h>
+#include <linux/leds.h>
+#include <linux/pm_runtime.h>
-#define SLEEPING 0x4
-#define UPDATING 0x3
-#define FULL_UPDATE_DONE 0x2
-#define WAKING 0x1
-#define AWAKE 0x0
+#define MSM_FB_C
+#include "msm_fb.h"
+#include "mddihosti.h"
+#include "tvenc.h"
+#include "mdp.h"
+#include "mdp4.h"
-#define NONE 0
-#define SUSPEND_RESUME 0x1
-#define FPS 0x2
-#define BLIT_TIME 0x4
-#define SHOW_UPDATES 0x8
+#ifdef CONFIG_FB_MSM_LOGO
+#define INIT_IMAGE_FILE "/initlogo.rle"
+extern int load_565rle_image(char *filename);
+#endif
-#define DLOG(mask, fmt, args...) \
-do { \
- if (msmfb_debug_mask & mask) \
- printk(KERN_INFO "msmfb: "fmt, ##args); \
-} while (0)
+#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
+#define MSM_FB_NUM 3
+#endif
-static int msmfb_debug_mask;
-module_param_named(msmfb_debug_mask, msmfb_debug_mask, int,
- S_IRUGO | S_IWUSR | S_IWGRP);
+static unsigned char *fbram;
+static unsigned char *fbram_phys;
+static int fbram_size;
-struct mdp_device *mdp;
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
-struct msmfb_info {
- struct fb_info *fb;
- struct msm_panel_data *panel;
- int xres;
- int yres;
- unsigned output_format;
- unsigned yoffset;
- unsigned frame_requested;
- unsigned frame_done;
- int sleeping;
- unsigned update_frame;
- struct {
- int left;
- int top;
- int eright; /* exclusive */
- int ebottom; /* exclusive */
- } update_info;
- char *black;
+int vsync_mode = 1;
- spinlock_t update_lock;
- struct mutex panel_init_lock;
- wait_queue_head_t frame_wq;
- struct work_struct resume_work;
- struct msmfb_callback dma_callback;
- struct msmfb_callback vsync_callback;
- struct hrtimer fake_vsync;
- ktime_t vsync_request_time;
+#define MAX_BLIT_REQ 256
+
+#define MAX_FBI_LIST 32
+static struct fb_info *fbi_list[MAX_FBI_LIST];
+static int fbi_list_index;
+
+static struct msm_fb_data_type *mfd_list[MAX_FBI_LIST];
+static int mfd_list_index;
+
+static u32 msm_fb_pseudo_palette[16] = {
+ 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
};
-static int msmfb_open(struct fb_info *info, int user)
+u32 msm_fb_debug_enabled;
+/* Setting msm_fb_msg_level to 8 prints out ALL messages */
+u32 msm_fb_msg_level = 7;
+
+/* Setting mddi_msg_level to 8 prints out ALL messages */
+u32 mddi_msg_level = 5;
+
+extern int32 mdp_block_power_cnt[MDP_MAX_BLOCK];
+extern unsigned long mdp_timer_duration;
+
+static int msm_fb_register(struct msm_fb_data_type *mfd);
+static int msm_fb_open(struct fb_info *info, int user);
+static int msm_fb_release(struct fb_info *info, int user);
+static int msm_fb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info);
+static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd);
+int msm_fb_resume_sw_refresher(struct msm_fb_data_type *mfd);
+static int msm_fb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info);
+static int msm_fb_set_par(struct fb_info *info);
+static int msm_fb_blank_sub(int blank_mode, struct fb_info *info,
+ boolean op_enable);
+static int msm_fb_suspend_sub(struct msm_fb_data_type *mfd);
+static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg);
+static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma);
+
+#ifdef MSM_FB_ENABLE_DBGFS
+
+#define MSM_FB_MAX_DBGFS 1024
+#define MAX_BACKLIGHT_BRIGHTNESS 255
+
+int msm_fb_debugfs_file_index;
+struct dentry *msm_fb_debugfs_root;
+struct dentry *msm_fb_debugfs_file[MSM_FB_MAX_DBGFS];
+
+DEFINE_MUTEX(msm_fb_notify_update_sem);
+void msmfb_no_update_notify_timer_cb(unsigned long data)
{
- return 0;
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
+ if (!mfd)
+ pr_err("%s mfd NULL\n", __func__);
+ complete(&mfd->msmfb_no_update_notify);
}
-static int msmfb_release(struct fb_info *info, int user)
+struct dentry *msm_fb_get_debugfs_root(void)
{
- return 0;
+ if (msm_fb_debugfs_root == NULL)
+ msm_fb_debugfs_root = debugfs_create_dir("msm_fb", NULL);
+
+ return msm_fb_debugfs_root;
}
-/* Called from dma interrupt handler, must not sleep */
-static void msmfb_handle_dma_interrupt(struct msmfb_callback *callback)
+void msm_fb_debugfs_file_create(struct dentry *root, const char *name,
+ u32 *var)
{
- unsigned long irq_flags;
- struct msmfb_info *msmfb = container_of(callback, struct msmfb_info,
- dma_callback);
-
- spin_lock_irqsave(&msmfb->update_lock, irq_flags);
- msmfb->frame_done = msmfb->frame_requested;
- if (msmfb->sleeping == UPDATING &&
- msmfb->frame_done == msmfb->update_frame) {
- DLOG(SUSPEND_RESUME, "full update completed\n");
- schedule_work(&msmfb->resume_work);
- }
- spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
- wake_up(&msmfb->frame_wq);
-}
-
-static int msmfb_start_dma(struct msmfb_info *msmfb)
-{
- uint32_t x, y, w, h;
- unsigned addr;
- unsigned long irq_flags;
- uint32_t yoffset;
- s64 time_since_request;
- struct msm_panel_data *panel = msmfb->panel;
-
- spin_lock_irqsave(&msmfb->update_lock, irq_flags);
- time_since_request = ktime_to_ns(ktime_sub(ktime_get(),
- msmfb->vsync_request_time));
- if (time_since_request > 20 * NSEC_PER_MSEC) {
- uint32_t us;
- us = do_div(time_since_request, NSEC_PER_MSEC) / NSEC_PER_USEC;
- printk(KERN_WARNING "msmfb_start_dma %lld.%03u ms after vsync "
- "request\n", time_since_request, us);
- }
- if (msmfb->frame_done == msmfb->frame_requested) {
- spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
- return -1;
- }
- if (msmfb->sleeping == SLEEPING) {
- DLOG(SUSPEND_RESUME, "tried to start dma while asleep\n");
- spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
- return -1;
- }
- x = msmfb->update_info.left;
- y = msmfb->update_info.top;
- w = msmfb->update_info.eright - x;
- h = msmfb->update_info.ebottom - y;
- yoffset = msmfb->yoffset;
- msmfb->update_info.left = msmfb->xres + 1;
- msmfb->update_info.top = msmfb->yres + 1;
- msmfb->update_info.eright = 0;
- msmfb->update_info.ebottom = 0;
- if (unlikely(w > msmfb->xres || h > msmfb->yres ||
- w == 0 || h == 0)) {
- printk(KERN_INFO "invalid update: %d %d %d "
- "%d\n", x, y, w, h);
- msmfb->frame_done = msmfb->frame_requested;
- goto error;
- }
- spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
-
- addr = ((msmfb->xres * (yoffset + y) + x) * 2);
- mdp->dma(mdp, addr + msmfb->fb->fix.smem_start,
- msmfb->xres * 2, w, h, x, y, &msmfb->dma_callback,
- panel->interface_type);
- return 0;
-error:
- spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
- /* some clients need to clear their vsync interrupt */
- if (panel->clear_vsync)
- panel->clear_vsync(panel);
- wake_up(&msmfb->frame_wq);
- return 0;
-}
-
-/* Called from esync interrupt handler, must not sleep */
-static void msmfb_handle_vsync_interrupt(struct msmfb_callback *callback)
-{
- struct msmfb_info *msmfb = container_of(callback, struct msmfb_info,
- vsync_callback);
- msmfb_start_dma(msmfb);
-}
-
-static enum hrtimer_restart msmfb_fake_vsync(struct hrtimer *timer)
-{
- struct msmfb_info *msmfb = container_of(timer, struct msmfb_info,
- fake_vsync);
- msmfb_start_dma(msmfb);
- return HRTIMER_NORESTART;
-}
-
-static void msmfb_pan_update(struct fb_info *info, uint32_t left, uint32_t top,
- uint32_t eright, uint32_t ebottom,
- uint32_t yoffset, int pan_display)
-{
- struct msmfb_info *msmfb = info->par;
- struct msm_panel_data *panel = msmfb->panel;
- unsigned long irq_flags;
- int sleeping;
- int retry = 1;
-
- DLOG(SHOW_UPDATES, "update %d %d %d %d %d %d\n",
- left, top, eright, ebottom, yoffset, pan_display);
-restart:
- spin_lock_irqsave(&msmfb->update_lock, irq_flags);
-
- /* if we are sleeping, on a pan_display wait 10ms (to throttle back
- * drawing otherwise return */
- if (msmfb->sleeping == SLEEPING) {
- DLOG(SUSPEND_RESUME, "drawing while asleep\n");
- spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
- if (pan_display)
- wait_event_interruptible_timeout(msmfb->frame_wq,
- msmfb->sleeping != SLEEPING, HZ/10);
+ if (msm_fb_debugfs_file_index >= MSM_FB_MAX_DBGFS)
return;
- }
- sleeping = msmfb->sleeping;
- /* on a full update, if the last frame has not completed, wait for it */
- if ((pan_display && msmfb->frame_requested != msmfb->frame_done) ||
- sleeping == UPDATING) {
- int ret;
- spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
- ret = wait_event_interruptible_timeout(msmfb->frame_wq,
- msmfb->frame_done == msmfb->frame_requested &&
- msmfb->sleeping != UPDATING, 5 * HZ);
- if (ret <= 0 && (msmfb->frame_requested != msmfb->frame_done ||
- msmfb->sleeping == UPDATING)) {
- if (retry && panel->request_vsync &&
- (sleeping == AWAKE)) {
- panel->request_vsync(panel,
- &msmfb->vsync_callback);
- retry = 0;
- printk(KERN_WARNING "msmfb_pan_display timeout "
- "rerequest vsync\n");
- } else {
- printk(KERN_WARNING "msmfb_pan_display timeout "
- "waiting for frame start, %d %d\n",
- msmfb->frame_requested,
- msmfb->frame_done);
- return;
- }
- }
- goto restart;
- }
-
-
- msmfb->frame_requested++;
- /* if necessary, update the y offset, if this is the
- * first full update on resume, set the sleeping state */
- if (pan_display) {
- msmfb->yoffset = yoffset;
- if (left == 0 && top == 0 && eright == info->var.xres &&
- ebottom == info->var.yres) {
- if (sleeping == WAKING) {
- msmfb->update_frame = msmfb->frame_requested;
- DLOG(SUSPEND_RESUME, "full update starting\n");
- msmfb->sleeping = UPDATING;
- }
- }
- }
-
- /* set the update request */
- if (left < msmfb->update_info.left)
- msmfb->update_info.left = left;
- if (top < msmfb->update_info.top)
- msmfb->update_info.top = top;
- if (eright > msmfb->update_info.eright)
- msmfb->update_info.eright = eright;
- if (ebottom > msmfb->update_info.ebottom)
- msmfb->update_info.ebottom = ebottom;
- DLOG(SHOW_UPDATES, "update queued %d %d %d %d %d\n",
- msmfb->update_info.left, msmfb->update_info.top,
- msmfb->update_info.eright, msmfb->update_info.ebottom,
- msmfb->yoffset);
- spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
-
- /* if the panel is all the way on wait for vsync, otherwise sleep
- * for 16 ms (long enough for the dma to panel) and then begin dma */
- msmfb->vsync_request_time = ktime_get();
- if (panel->request_vsync && (sleeping == AWAKE)) {
- panel->request_vsync(panel, &msmfb->vsync_callback);
- } else {
- if (!hrtimer_active(&msmfb->fake_vsync)) {
- hrtimer_start(&msmfb->fake_vsync,
- ktime_set(0, NSEC_PER_SEC/60),
- HRTIMER_MODE_REL);
- }
- }
+ msm_fb_debugfs_file[msm_fb_debugfs_file_index++] =
+ debugfs_create_u32(name, S_IRUGO | S_IWUSR, root, var);
}
+#endif
-static void msmfb_update(struct fb_info *info, uint32_t left, uint32_t top,
- uint32_t eright, uint32_t ebottom)
+int msm_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
- msmfb_pan_update(info, left, top, eright, ebottom, 0, 0);
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ if (!mfd->cursor_update)
+ return -ENODEV;
+
+ return mfd->cursor_update(info, cursor);
}
-static void power_on_panel(struct work_struct *work)
+static int msm_fb_resource_initialized;
+
+#ifndef CONFIG_FB_BACKLIGHT
+static int lcd_backlight_registered;
+
+static void msm_fb_set_bl_brightness(struct led_classdev *led_cdev,
+ enum led_brightness value)
{
- struct msmfb_info *msmfb =
- container_of(work, struct msmfb_info, resume_work);
- struct msm_panel_data *panel = msmfb->panel;
- unsigned long irq_flags;
+ struct msm_fb_data_type *mfd = dev_get_drvdata(led_cdev->dev->parent);
+ int bl_lvl;
- mutex_lock(&msmfb->panel_init_lock);
- DLOG(SUSPEND_RESUME, "turning on panel\n");
- if (msmfb->sleeping == UPDATING) {
- if (panel->unblank(panel)) {
- printk(KERN_INFO "msmfb: panel unblank failed,"
- "not starting drawing\n");
- goto error;
- }
- spin_lock_irqsave(&msmfb->update_lock, irq_flags);
- msmfb->sleeping = AWAKE;
- wake_up(&msmfb->frame_wq);
- spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
- }
-error:
- mutex_unlock(&msmfb->panel_init_lock);
+ if (value > MAX_BACKLIGHT_BRIGHTNESS)
+ value = MAX_BACKLIGHT_BRIGHTNESS;
+
+ /* This maps android backlight level 0 to 255 into
+ driver backlight level 0 to bl_max with rounding */
+ bl_lvl = (2 * value * mfd->panel_info.bl_max + MAX_BACKLIGHT_BRIGHTNESS)
+ /(2 * MAX_BACKLIGHT_BRIGHTNESS);
+
+ if (!bl_lvl && value)
+ bl_lvl = 1;
+
+ msm_fb_set_backlight(mfd, bl_lvl);
}
-
-static int msmfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
- if ((var->xres != info->var.xres) ||
- (var->yres != info->var.yres) ||
- (var->xres_virtual != info->var.xres_virtual) ||
- (var->yres_virtual != info->var.yres_virtual) ||
- (var->xoffset != info->var.xoffset) ||
- (var->bits_per_pixel != info->var.bits_per_pixel) ||
- (var->grayscale != info->var.grayscale))
- return -EINVAL;
- return 0;
-}
-
-int msmfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
- struct msmfb_info *msmfb = info->par;
- struct msm_panel_data *panel = msmfb->panel;
-
- /* "UPDT" */
- if ((panel->caps & MSMFB_CAP_PARTIAL_UPDATES) &&
- (var->reserved[0] == 0x54445055)) {
- msmfb_pan_update(info, var->reserved[1] & 0xffff,
- var->reserved[1] >> 16,
- var->reserved[2] & 0xffff,
- var->reserved[2] >> 16, var->yoffset, 1);
- } else {
- msmfb_pan_update(info, 0, 0, info->var.xres, info->var.yres,
- var->yoffset, 1);
- }
- return 0;
-}
-
-static void msmfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
-{
- cfb_fillrect(p, rect);
- msmfb_update(p, rect->dx, rect->dy, rect->dx + rect->width,
- rect->dy + rect->height);
-}
-
-static void msmfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
-{
- cfb_copyarea(p, area);
- msmfb_update(p, area->dx, area->dy, area->dx + area->width,
- area->dy + area->height);
-}
-
-static void msmfb_imageblit(struct fb_info *p, const struct fb_image *image)
-{
- cfb_imageblit(p, image);
- msmfb_update(p, image->dx, image->dy, image->dx + image->width,
- image->dy + image->height);
-}
-
-
-static int msmfb_blit(struct fb_info *info,
- void __user *p)
-{
- struct mdp_blit_req req;
- struct mdp_blit_req_list req_list;
- int i;
- int ret;
-
- if (copy_from_user(&req_list, p, sizeof(req_list)))
- return -EFAULT;
-
- for (i = 0; i < req_list.count; i++) {
- struct mdp_blit_req_list *list =
- (struct mdp_blit_req_list *)p;
- if (copy_from_user(&req, &list->req[i], sizeof(req)))
- return -EFAULT;
- ret = mdp->blit(mdp, info, &req);
- if (ret)
- return ret;
- }
- return 0;
-}
-
-
-DEFINE_MUTEX(mdp_ppp_lock);
-
-static int msmfb_ioctl(struct fb_info *p, unsigned int cmd, unsigned long arg)
-{
- void __user *argp = (void __user *)arg;
- int ret;
-
- switch (cmd) {
- case MSMFB_GRP_DISP:
- mdp->set_grp_disp(mdp, arg);
- break;
- case MSMFB_BLIT:
- ret = msmfb_blit(p, argp);
- if (ret)
- return ret;
- break;
- default:
- printk(KERN_INFO "msmfb unknown ioctl: %d\n", cmd);
- return -EINVAL;
- }
- return 0;
-}
-
-static struct fb_ops msmfb_ops = {
- .owner = THIS_MODULE,
- .fb_open = msmfb_open,
- .fb_release = msmfb_release,
- .fb_check_var = msmfb_check_var,
- .fb_pan_display = msmfb_pan_display,
- .fb_fillrect = msmfb_fillrect,
- .fb_copyarea = msmfb_copyarea,
- .fb_imageblit = msmfb_imageblit,
- .fb_ioctl = msmfb_ioctl,
+static struct led_classdev backlight_led = {
+ .name = "lcd-backlight",
+ .brightness = MAX_BACKLIGHT_BRIGHTNESS,
+ .brightness_set = msm_fb_set_bl_brightness,
};
+#endif
-static unsigned PP[16];
+static struct msm_fb_platform_data *msm_fb_pdata;
+static char panel_name[128];
+module_param_string(panel_name, panel_name, sizeof(panel_name) , 0);
-
-
-#define BITS_PER_PIXEL 16
-
-static void setup_fb_info(struct msmfb_info *msmfb)
+int msm_fb_detect_client(const char *name)
{
- struct fb_info *fb_info = msmfb->fb;
- int r;
+ int ret = -EPERM;
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ u32 id;
+#endif
- /* finish setting up the fb_info struct */
- strncpy(fb_info->fix.id, "msmfb", 16);
- fb_info->fix.ypanstep = 1;
-
- fb_info->fbops = &msmfb_ops;
- fb_info->flags = FBINFO_DEFAULT;
-
- fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
- fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
- fb_info->fix.line_length = msmfb->xres * 2;
-
- fb_info->var.xres = msmfb->xres;
- fb_info->var.yres = msmfb->yres;
- fb_info->var.width = msmfb->panel->fb_data->width;
- fb_info->var.height = msmfb->panel->fb_data->height;
- fb_info->var.xres_virtual = msmfb->xres;
- fb_info->var.yres_virtual = msmfb->yres * 2;
- fb_info->var.bits_per_pixel = BITS_PER_PIXEL;
- fb_info->var.accel_flags = 0;
-
- fb_info->var.yoffset = 0;
-
- if (msmfb->panel->caps & MSMFB_CAP_PARTIAL_UPDATES) {
- /*
- * Set the param in the fixed screen, so userspace can't
- * change it. This will be used to check for the
- * capability.
- */
- fb_info->fix.reserved[0] = 0x5444;
- fb_info->fix.reserved[1] = 0x5055;
-
- /*
- * This preloads the value so that if userspace doesn't
- * change it, it will be a full update
- */
- fb_info->var.reserved[0] = 0x54445055;
- fb_info->var.reserved[1] = 0;
- fb_info->var.reserved[2] = (uint16_t)msmfb->xres |
- ((uint32_t)msmfb->yres << 16);
+ MSM_FB_DEBUG("\n name = %s, panel_name = %s", name, panel_name);
+ if (strlen(panel_name)) {
+ if (!strcmp((char *)panel_name, name))
+ return 0;
+ else
+ return -EPERM;
}
- fb_info->var.red.offset = 11;
- fb_info->var.red.length = 5;
- fb_info->var.red.msb_right = 0;
- fb_info->var.green.offset = 5;
- fb_info->var.green.length = 6;
- fb_info->var.green.msb_right = 0;
- fb_info->var.blue.offset = 0;
- fb_info->var.blue.length = 5;
- fb_info->var.blue.msb_right = 0;
+ if (msm_fb_pdata && msm_fb_pdata->detect_client) {
+ ret = msm_fb_pdata->detect_client(name);
- r = fb_alloc_cmap(&fb_info->cmap, 16, 0);
- fb_info->pseudo_palette = PP;
+ /* if it's non mddi panel, we need to pre-scan
+ mddi client to see if we can disable mddi host */
- PP[0] = 0;
- for (r = 1; r < 16; r++)
- PP[r] = 0xffffffff;
-}
-
-static int setup_fbmem(struct msmfb_info *msmfb, struct platform_device *pdev)
-{
- struct fb_info *fb = msmfb->fb;
- struct resource *resource;
- unsigned long size = msmfb->xres * msmfb->yres *
- (BITS_PER_PIXEL >> 3) * 2;
- unsigned char *fbram;
-
- /* board file might have attached a resource describing an fb */
- resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!resource)
- return -EINVAL;
-
- /* check the resource is large enough to fit the fb */
- if (resource->end - resource->start < size) {
- printk(KERN_ERR "allocated resource is too small for "
- "fb\n");
- return -ENOMEM;
- }
- fb->fix.smem_start = resource->start;
- fb->fix.smem_len = resource->end - resource->start;
- fbram = ioremap(resource->start,
- resource->end - resource->start);
- if (fbram == 0) {
- printk(KERN_ERR "msmfb: cannot allocate fbram!\n");
- return -ENOMEM;
- }
- fb->screen_base = fbram;
- return 0;
-}
-
-static int msmfb_probe(struct platform_device *pdev)
-{
- struct fb_info *fb;
- struct msmfb_info *msmfb;
- struct msm_panel_data *panel = pdev->dev.platform_data;
- int ret;
-
- if (!panel) {
- pr_err("msmfb_probe: no platform data\n");
- return -EINVAL;
- }
- if (!panel->fb_data) {
- pr_err("msmfb_probe: no fb_data\n");
- return -EINVAL;
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ if (!ret && msm_fb_pdata->mddi_prescan)
+ id = mddi_get_client_id();
+#endif
}
- fb = framebuffer_alloc(sizeof(struct msmfb_info), &pdev->dev);
- if (!fb)
- return -ENOMEM;
- msmfb = fb->par;
- msmfb->fb = fb;
- msmfb->panel = panel;
- msmfb->xres = panel->fb_data->xres;
- msmfb->yres = panel->fb_data->yres;
-
- ret = setup_fbmem(msmfb, pdev);
- if (ret)
- goto error_setup_fbmem;
-
- setup_fb_info(msmfb);
-
- spin_lock_init(&msmfb->update_lock);
- mutex_init(&msmfb->panel_init_lock);
- init_waitqueue_head(&msmfb->frame_wq);
- INIT_WORK(&msmfb->resume_work, power_on_panel);
- msmfb->black = kzalloc(msmfb->fb->var.bits_per_pixel*msmfb->xres,
- GFP_KERNEL);
-
- printk(KERN_INFO "msmfb_probe() installing %d x %d panel\n",
- msmfb->xres, msmfb->yres);
-
- msmfb->dma_callback.func = msmfb_handle_dma_interrupt;
- msmfb->vsync_callback.func = msmfb_handle_vsync_interrupt;
- hrtimer_init(&msmfb->fake_vsync, CLOCK_MONOTONIC,
- HRTIMER_MODE_REL);
-
-
- msmfb->fake_vsync.function = msmfb_fake_vsync;
-
- ret = register_framebuffer(fb);
- if (ret)
- goto error_register_framebuffer;
-
- msmfb->sleeping = WAKING;
-
- return 0;
-
-error_register_framebuffer:
- iounmap(fb->screen_base);
-error_setup_fbmem:
- framebuffer_release(msmfb->fb);
return ret;
}
-static struct platform_driver msm_panel_driver = {
- /* need to write remove */
- .probe = msmfb_probe,
- .driver = {.name = "msm_panel"},
+static ssize_t msm_fb_msm_fb_type(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
+ struct msm_fb_panel_data *pdata =
+ (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+
+ switch (pdata->panel_info.type) {
+ case NO_PANEL:
+ ret = snprintf(buf, PAGE_SIZE, "no panel\n");
+ break;
+ case MDDI_PANEL:
+ ret = snprintf(buf, PAGE_SIZE, "mddi panel\n");
+ break;
+ case EBI2_PANEL:
+ ret = snprintf(buf, PAGE_SIZE, "ebi2 panel\n");
+ break;
+ case LCDC_PANEL:
+ ret = snprintf(buf, PAGE_SIZE, "lcdc panel\n");
+ break;
+ case EXT_MDDI_PANEL:
+ ret = snprintf(buf, PAGE_SIZE, "ext mddi panel\n");
+ break;
+ case TV_PANEL:
+ ret = snprintf(buf, PAGE_SIZE, "tv panel\n");
+ break;
+ case HDMI_PANEL:
+ ret = snprintf(buf, PAGE_SIZE, "hdmi panel\n");
+ break;
+ case DTV_PANEL:
+ ret = snprintf(buf, PAGE_SIZE, "dtv panel\n");
+ break;
+ default:
+ ret = snprintf(buf, PAGE_SIZE, "unknown panel\n");
+ break;
+ }
+
+ return ret;
+}
+
+static DEVICE_ATTR(msm_fb_type, S_IRUGO, msm_fb_msm_fb_type, NULL);
+static struct attribute *msm_fb_attrs[] = {
+ &dev_attr_msm_fb_type.attr,
+ NULL,
+};
+static struct attribute_group msm_fb_attr_group = {
+ .attrs = msm_fb_attrs,
};
-
-static int msmfb_add_mdp_device(struct device *dev,
- struct class_interface *class_intf)
+static int msm_fb_create_sysfs(struct platform_device *pdev)
{
- /* might need locking if mulitple mdp devices */
- if (mdp)
+ int rc;
+ struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
+
+ rc = sysfs_create_group(&mfd->fbi->dev->kobj, &msm_fb_attr_group);
+ if (rc)
+ MSM_FB_ERR("%s: sysfs group creation failed, rc=%d\n", __func__,
+ rc);
+ return rc;
+}
+static void msm_fb_remove_sysfs(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
+ sysfs_remove_group(&mfd->fbi->dev->kobj, &msm_fb_attr_group);
+}
+
+static int msm_fb_probe(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ int rc;
+ int err = 0;
+
+ MSM_FB_DEBUG("msm_fb_probe\n");
+
+ if ((pdev->id == 0) && (pdev->num_resources > 0)) {
+ msm_fb_pdata = pdev->dev.platform_data;
+ fbram_size =
+ pdev->resource[0].end - pdev->resource[0].start + 1;
+ fbram_phys = (char *)pdev->resource[0].start;
+ fbram = ioremap((unsigned long)fbram_phys, fbram_size);
+
+ if (!fbram) {
+ printk(KERN_ERR "fbram ioremap failed!\n");
+ return -ENOMEM;
+ }
+ MSM_FB_DEBUG("msm_fb_probe: phy_Addr = 0x%x virt = 0x%x\n",
+ (int)fbram_phys, (int)fbram);
+
+ msm_fb_resource_initialized = 1;
return 0;
- mdp = container_of(dev, struct mdp_device, dev);
- return platform_driver_register(&msm_panel_driver);
+ }
+
+ if (!msm_fb_resource_initialized)
+ return -EPERM;
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+ return -ENOMEM;
+
+ mfd->panel_info.frame_count = 0;
+ mfd->bl_level = 0;
+#ifdef CONFIG_FB_MSM_OVERLAY
+ mfd->overlay_play_enable = 1;
+#endif
+ rc = msm_fb_register(mfd);
+ if (rc)
+ return rc;
+ err = pm_runtime_set_active(mfd->fbi->dev);
+ if (err < 0)
+ printk(KERN_ERR "pm_runtime: fail to set active.\n");
+ pm_runtime_enable(mfd->fbi->dev);
+#ifdef CONFIG_FB_BACKLIGHT
+ msm_fb_config_backlight(mfd);
+#else
+ /* android supports only one lcd-backlight/lcd for now */
+ if (!lcd_backlight_registered) {
+ if (led_classdev_register(&pdev->dev, &backlight_led))
+ printk(KERN_ERR "led_classdev_register failed\n");
+ else
+ lcd_backlight_registered = 1;
+ }
+#endif
+
+ pdev_list[pdev_list_cnt++] = pdev;
+ msm_fb_create_sysfs(pdev);
+ return 0;
}
-static void msmfb_remove_mdp_device(struct device *dev,
- struct class_interface *class_intf)
+static int msm_fb_remove(struct platform_device *pdev)
{
- /* might need locking if mulitple mdp devices */
- if (dev != &mdp->dev)
- return;
- platform_driver_unregister(&msm_panel_driver);
- mdp = NULL;
+ struct msm_fb_data_type *mfd;
+
+ MSM_FB_DEBUG("msm_fb_remove\n");
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ msm_fb_remove_sysfs(pdev);
+
+ pm_runtime_disable(mfd->fbi->dev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (msm_fb_suspend_sub(mfd))
+ printk(KERN_ERR "msm_fb_remove: can't stop the device %d\n", mfd->index);
+
+ if (mfd->channel_irq != 0)
+ free_irq(mfd->channel_irq, (void *)mfd);
+
+ if (mfd->vsync_width_boundary)
+ vfree(mfd->vsync_width_boundary);
+
+ if (mfd->vsync_resync_timer.function)
+ del_timer(&mfd->vsync_resync_timer);
+
+ if (mfd->refresh_timer.function)
+ del_timer(&mfd->refresh_timer);
+
+ if (mfd->dma_hrtimer.function)
+ hrtimer_cancel(&mfd->dma_hrtimer);
+
+ if (mfd->msmfb_no_update_notify_timer.function)
+ del_timer(&mfd->msmfb_no_update_notify_timer);
+ complete(&mfd->msmfb_no_update_notify);
+ complete(&mfd->msmfb_update_notify);
+
+ /* remove /dev/fb* */
+ unregister_framebuffer(mfd->fbi);
+
+#ifdef CONFIG_FB_BACKLIGHT
+ /* remove /sys/class/backlight */
+ backlight_device_unregister(mfd->fbi->bl_dev);
+#else
+ if (lcd_backlight_registered) {
+ lcd_backlight_registered = 0;
+ led_classdev_unregister(&backlight_led);
+ }
+#endif
+
+#ifdef MSM_FB_ENABLE_DBGFS
+ if (mfd->sub_dir)
+ debugfs_remove(mfd->sub_dir);
+#endif
+
+ return 0;
}
-static struct class_interface msm_fb_interface = {
- .add_dev = &msmfb_add_mdp_device,
- .remove_dev = &msmfb_remove_mdp_device,
+#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
+static int msm_fb_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct msm_fb_data_type *mfd;
+ int ret = 0;
+
+ MSM_FB_DEBUG("msm_fb_suspend\n");
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if ((!mfd) || (mfd->key != MFD_KEY))
+ return 0;
+
+ console_lock();
+ fb_set_suspend(mfd->fbi, FBINFO_STATE_SUSPENDED);
+
+ ret = msm_fb_suspend_sub(mfd);
+ if (ret != 0) {
+ printk(KERN_ERR "msm_fb: failed to suspend! %d\n", ret);
+ fb_set_suspend(mfd->fbi, FBINFO_STATE_RUNNING);
+ } else {
+ pdev->dev.power.power_state = state;
+ }
+
+ console_unlock();
+ return ret;
+}
+#else
+#define msm_fb_suspend NULL
+#endif
+
+static int msm_fb_suspend_sub(struct msm_fb_data_type *mfd)
+{
+ int ret = 0;
+
+ if ((!mfd) || (mfd->key != MFD_KEY))
+ return 0;
+
+ if (mfd->msmfb_no_update_notify_timer.function)
+ del_timer(&mfd->msmfb_no_update_notify_timer);
+ complete(&mfd->msmfb_no_update_notify);
+
+ /*
+ * suspend this channel
+ */
+ mfd->suspend.sw_refreshing_enable = mfd->sw_refreshing_enable;
+ mfd->suspend.op_enable = mfd->op_enable;
+ mfd->suspend.panel_power_on = mfd->panel_power_on;
+
+ if (mfd->op_enable) {
+ ret =
+ msm_fb_blank_sub(FB_BLANK_POWERDOWN, mfd->fbi,
+ mfd->suspend.op_enable);
+ if (ret) {
+ MSM_FB_INFO
+ ("msm_fb_suspend: can't turn off display!\n");
+ return ret;
+ }
+ mfd->op_enable = FALSE;
+ }
+ /*
+ * try to power down
+ */
+ mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ /*
+ * detach display channel irq if there's any
+ * or wait until vsync-resync completes
+ */
+ if ((mfd->dest == DISPLAY_LCD)) {
+ if (mfd->panel_info.lcd.vsync_enable) {
+ if (mfd->panel_info.lcd.hw_vsync_mode) {
+ if (mfd->channel_irq != 0)
+ disable_irq(mfd->channel_irq);
+ } else {
+ volatile boolean vh_pending;
+ do {
+ vh_pending = mfd->vsync_handler_pending;
+ } while (vh_pending);
+ }
+ }
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int msm_fb_resume_sub(struct msm_fb_data_type *mfd)
+{
+ int ret = 0;
+
+ if ((!mfd) || (mfd->key != MFD_KEY))
+ return 0;
+
+ /* attach display channel irq if there's any */
+ if (mfd->channel_irq != 0)
+ enable_irq(mfd->channel_irq);
+
+ /* resume state var recover */
+ mfd->sw_refreshing_enable = mfd->suspend.sw_refreshing_enable;
+ mfd->op_enable = mfd->suspend.op_enable;
+
+ if (mfd->suspend.panel_power_on) {
+ ret =
+ msm_fb_blank_sub(FB_BLANK_UNBLANK, mfd->fbi,
+ mfd->op_enable);
+ if (ret)
+ MSM_FB_INFO("msm_fb_resume: can't turn on display!\n");
+ }
+
+ return ret;
+}
+#endif
+
+#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
+static int msm_fb_resume(struct platform_device *pdev)
+{
+ /* This resume function is called when interrupt is enabled.
+ */
+ int ret = 0;
+ struct msm_fb_data_type *mfd;
+
+ MSM_FB_DEBUG("msm_fb_resume\n");
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if ((!mfd) || (mfd->key != MFD_KEY))
+ return 0;
+
+ console_lock();
+ ret = msm_fb_resume_sub(mfd);
+ pdev->dev.power.power_state = PMSG_ON;
+ fb_set_suspend(mfd->fbi, FBINFO_STATE_RUNNING);
+ console_unlock();
+
+ return ret;
+}
+#else
+#define msm_fb_resume NULL
+#endif
+
+static int msm_fb_runtime_suspend(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: suspending...\n");
+ return 0;
+}
+
+static int msm_fb_runtime_resume(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: resuming...\n");
+ return 0;
+}
+
+static int msm_fb_runtime_idle(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: idling...\n");
+ return 0;
+}
+
+static struct dev_pm_ops msm_fb_dev_pm_ops = {
+ .runtime_suspend = msm_fb_runtime_suspend,
+ .runtime_resume = msm_fb_runtime_resume,
+ .runtime_idle = msm_fb_runtime_idle,
};
-static int __init msmfb_init(void)
+static struct platform_driver msm_fb_driver = {
+ .probe = msm_fb_probe,
+ .remove = msm_fb_remove,
+#ifndef CONFIG_HAS_EARLYSUSPEND
+ .suspend = msm_fb_suspend,
+ .resume = msm_fb_resume,
+#endif
+ .shutdown = NULL,
+ .driver = {
+ /* Driver name must match the device name added in platform.c. */
+ .name = "msm_fb",
+ .pm = &msm_fb_dev_pm_ops,
+ },
+};
+
+#if defined(CONFIG_HAS_EARLYSUSPEND) && (defined(CONFIG_FB_MSM_OVERLAY) || \
+ defined(CONFIG_FB_MSM_MDP303))
+static void memset32_io(u32 __iomem *_ptr, u32 val, size_t count)
{
- return register_mdp_client(&msm_fb_interface);
+ count >>= 2;
+ while (count--)
+ writel(val, _ptr++);
+}
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void msmfb_early_suspend(struct early_suspend *h)
+{
+ struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+ early_suspend);
+#if defined(CONFIG_FB_MSM_OVERLAY) || defined(CONFIG_FB_MSM_MDP303)
+ /*
+ * For MDP with overlay, set framebuffer with black pixels
+ * to show black screen on HDMI.
+ */
+ struct fb_info *fbi = mfd->fbi;
+ switch (mfd->fbi->var.bits_per_pixel) {
+ case 32:
+ memset32_io((void *)fbi->screen_base, 0xFF000000,
+ fbi->fix.smem_len);
+ break;
+ default:
+ memset32_io((void *)fbi->screen_base, 0x00, fbi->fix.smem_len);
+ break;
+ }
+#endif
+ msm_fb_suspend_sub(mfd);
}
-module_init(msmfb_init);
+static void msmfb_early_resume(struct early_suspend *h)
+{
+ struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+ early_suspend);
+ msm_fb_resume_sub(mfd);
+}
+#endif
+
+void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl)
+{
+ struct msm_fb_panel_data *pdata;
+
+ pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+
+ if ((pdata) && (pdata->set_backlight)) {
+ down(&mfd->sem);
+ mfd->bl_level = bkl_lvl;
+ pdata->set_backlight(mfd);
+ up(&mfd->sem);
+ }
+}
+
+static int msm_fb_blank_sub(int blank_mode, struct fb_info *info,
+ boolean op_enable)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct msm_fb_panel_data *pdata = NULL;
+ int ret = 0;
+
+ if (!op_enable)
+ return -EPERM;
+
+ pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+ if ((!pdata) || (!pdata->on) || (!pdata->off)) {
+ printk(KERN_ERR "msm_fb_blank_sub: no panel operation detected!\n");
+ return -ENODEV;
+ }
+
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ if (!mfd->panel_power_on) {
+ msleep(16);
+ ret = pdata->on(mfd->pdev);
+ if (ret == 0) {
+ mfd->panel_power_on = TRUE;
+
+/* ToDo: possible conflict with android which doesn't expect sw refresher */
+/*
+ if (!mfd->hw_refresh)
+ {
+ if ((ret = msm_fb_resume_sw_refresher(mfd)) != 0)
+ {
+ MSM_FB_INFO("msm_fb_blank_sub: msm_fb_resume_sw_refresher failed = %d!\n",ret);
+ }
+ }
+*/
+ }
+ }
+ break;
+
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_NORMAL:
+ case FB_BLANK_POWERDOWN:
+ default:
+ if (mfd->panel_power_on) {
+ int curr_pwr_state;
+
+ mfd->op_enable = FALSE;
+ curr_pwr_state = mfd->panel_power_on;
+ mfd->panel_power_on = FALSE;
+
+ msleep(16);
+ ret = pdata->off(mfd->pdev);
+ if (ret)
+ mfd->panel_power_on = curr_pwr_state;
+
+ mfd->op_enable = TRUE;
+ }
+ break;
+ }
+
+ return ret;
+}
+
+static void msm_fb_fillrect(struct fb_info *info,
+ const struct fb_fillrect *rect)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ cfb_fillrect(info, rect);
+ if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
+ !mfd->sw_currently_refreshing) {
+ struct fb_var_screeninfo var;
+
+ var = info->var;
+ var.reserved[0] = 0x54445055;
+ var.reserved[1] = (rect->dy << 16) | (rect->dx);
+ var.reserved[2] = ((rect->dy + rect->height) << 16) |
+ (rect->dx + rect->width);
+
+ msm_fb_pan_display(&var, info);
+ }
+}
+
+static void msm_fb_copyarea(struct fb_info *info,
+ const struct fb_copyarea *area)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ cfb_copyarea(info, area);
+ if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
+ !mfd->sw_currently_refreshing) {
+ struct fb_var_screeninfo var;
+
+ var = info->var;
+ var.reserved[0] = 0x54445055;
+ var.reserved[1] = (area->dy << 16) | (area->dx);
+ var.reserved[2] = ((area->dy + area->height) << 16) |
+ (area->dx + area->width);
+
+ msm_fb_pan_display(&var, info);
+ }
+}
+
+static void msm_fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ cfb_imageblit(info, image);
+ if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
+ !mfd->sw_currently_refreshing) {
+ struct fb_var_screeninfo var;
+
+ var = info->var;
+ var.reserved[0] = 0x54445055;
+ var.reserved[1] = (image->dy << 16) | (image->dx);
+ var.reserved[2] = ((image->dy + image->height) << 16) |
+ (image->dx + image->width);
+
+ msm_fb_pan_display(&var, info);
+ }
+}
+
+static int msm_fb_blank(int blank_mode, struct fb_info *info)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ return msm_fb_blank_sub(blank_mode, info, mfd->op_enable);
+}
+
+static int msm_fb_set_lut(struct fb_cmap *cmap, struct fb_info *info)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ if (!mfd->lut_update)
+ return -ENODEV;
+
+ mfd->lut_update(info, cmap);
+ return 0;
+}
+
+/*
+ * Custom Framebuffer mmap() function for MSM driver.
+ * Differs from standard mmap() function by allowing for customized
+ * page-protection.
+ */
+static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma)
+{
+ /* Get frame buffer memory range. */
+ unsigned long start = info->fix.smem_start;
+ u32 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
+ unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ if (off >= len) {
+ /* memory mapped io */
+ off -= len;
+ if (info->var.accel_flags) {
+ mutex_unlock(&info->lock);
+ return -EINVAL;
+ }
+ start = info->fix.mmio_start;
+ len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
+ }
+
+ /* Set VM flags. */
+ start &= PAGE_MASK;
+ if ((vma->vm_end - vma->vm_start + off) > len)
+ return -EINVAL;
+ off += start;
+ vma->vm_pgoff = off >> PAGE_SHIFT;
+ /* This is an IO map - tell maydump to skip this VMA */
+ vma->vm_flags |= VM_IO | VM_RESERVED;
+
+ /* Set VM page protection */
+ if (mfd->mdp_fb_page_protection == MDP_FB_PAGE_PROTECTION_WRITECOMBINE)
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+ else if (mfd->mdp_fb_page_protection ==
+ MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE)
+ vma->vm_page_prot = pgprot_writethroughcache(vma->vm_page_prot);
+ else if (mfd->mdp_fb_page_protection ==
+ MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE)
+ vma->vm_page_prot = pgprot_writebackcache(vma->vm_page_prot);
+ else if (mfd->mdp_fb_page_protection ==
+ MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE)
+ vma->vm_page_prot = pgprot_writebackwacache(vma->vm_page_prot);
+ else
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ /* Remap the frame buffer I/O range */
+ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot))
+ return -EAGAIN;
+
+ return 0;
+}
+
+static struct fb_ops msm_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_open = msm_fb_open,
+ .fb_release = msm_fb_release,
+ .fb_read = NULL,
+ .fb_write = NULL,
+ .fb_cursor = NULL,
+ .fb_check_var = msm_fb_check_var, /* vinfo check */
+ .fb_set_par = msm_fb_set_par, /* set the video mode according to info->var */
+ .fb_setcolreg = NULL, /* set color register */
+ .fb_blank = msm_fb_blank, /* blank display */
+ .fb_pan_display = msm_fb_pan_display, /* pan display */
+ .fb_fillrect = msm_fb_fillrect, /* Draws a rectangle */
+ .fb_copyarea = msm_fb_copyarea, /* Copy data from area to another */
+ .fb_imageblit = msm_fb_imageblit, /* Draws a image to the display */
+ .fb_rotate = NULL,
+ .fb_sync = NULL, /* wait for blit idle, optional */
+ .fb_ioctl = msm_fb_ioctl, /* perform fb specific ioctl (optional) */
+ .fb_mmap = msm_fb_mmap,
+};
+
+static __u32 msm_fb_line_length(__u32 fb_index, __u32 xres, int bpp)
+{
+ /* The adreno GPU hardware requires that the pitch be aligned to
+ 32 pixels for color buffers, so for the cases where the GPU
+ is writing directly to fb0, the framebuffer pitch
+ also needs to be 32 pixel aligned */
+
+ if (fb_index == 0)
+ return ALIGN(xres, 32) * bpp;
+ else
+ return xres * bpp;
+}
+
+static int msm_fb_register(struct msm_fb_data_type *mfd)
+{
+ int ret = -ENODEV;
+ int bpp;
+ struct msm_panel_info *panel_info = &mfd->panel_info;
+ struct fb_info *fbi = mfd->fbi;
+ struct fb_fix_screeninfo *fix;
+ struct fb_var_screeninfo *var;
+ int *id;
+ int fbram_offset;
+
+ /*
+ * fb info initialization
+ */
+ fix = &fbi->fix;
+ var = &fbi->var;
+
+ fix->type_aux = 0; /* if type == FB_TYPE_INTERLEAVED_PLANES */
+ fix->visual = FB_VISUAL_TRUECOLOR; /* True Color */
+ fix->ywrapstep = 0; /* No support */
+ fix->mmio_start = 0; /* No MMIO Address */
+ fix->mmio_len = 0; /* No MMIO Address */
+ fix->accel = FB_ACCEL_NONE;/* FB_ACCEL_MSM needes to be added in fb.h */
+
+ var->xoffset = 0, /* Offset from virtual to visible */
+ var->yoffset = 0, /* resolution */
+ var->grayscale = 0, /* No graylevels */
+ var->nonstd = 0, /* standard pixel format */
+ var->activate = FB_ACTIVATE_VBL, /* activate it at vsync */
+ var->height = -1, /* height of picture in mm */
+ var->width = -1, /* width of picture in mm */
+ var->accel_flags = 0, /* acceleration flags */
+ var->sync = 0, /* see FB_SYNC_* */
+ var->rotate = 0, /* angle we rotate counter clockwise */
+ mfd->op_enable = FALSE;
+
+ switch (mfd->fb_imgType) {
+ case MDP_RGB_565:
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->xpanstep = 1;
+ fix->ypanstep = 1;
+ var->vmode = FB_VMODE_NONINTERLACED;
+ var->blue.offset = 0;
+ var->green.offset = 5;
+ var->red.offset = 11;
+ var->blue.length = 5;
+ var->green.length = 6;
+ var->red.length = 5;
+ var->blue.msb_right = 0;
+ var->green.msb_right = 0;
+ var->red.msb_right = 0;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ bpp = 2;
+ break;
+
+ case MDP_RGB_888:
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->xpanstep = 1;
+ fix->ypanstep = 1;
+ var->vmode = FB_VMODE_NONINTERLACED;
+ var->blue.offset = 0;
+ var->green.offset = 8;
+ var->red.offset = 16;
+ var->blue.length = 8;
+ var->green.length = 8;
+ var->red.length = 8;
+ var->blue.msb_right = 0;
+ var->green.msb_right = 0;
+ var->red.msb_right = 0;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ bpp = 3;
+ break;
+
+ case MDP_ARGB_8888:
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->xpanstep = 1;
+ fix->ypanstep = 1;
+ var->vmode = FB_VMODE_NONINTERLACED;
+ var->blue.offset = 0;
+ var->green.offset = 8;
+ var->red.offset = 16;
+ var->blue.length = 8;
+ var->green.length = 8;
+ var->red.length = 8;
+ var->blue.msb_right = 0;
+ var->green.msb_right = 0;
+ var->red.msb_right = 0;
+ var->transp.offset = 24;
+ var->transp.length = 8;
+ bpp = 4;
+ break;
+
+ case MDP_RGBA_8888:
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->xpanstep = 1;
+ fix->ypanstep = 1;
+ var->vmode = FB_VMODE_NONINTERLACED;
+ var->blue.offset = 8;
+ var->green.offset = 16;
+ var->red.offset = 24;
+ var->blue.length = 8;
+ var->green.length = 8;
+ var->red.length = 8;
+ var->blue.msb_right = 0;
+ var->green.msb_right = 0;
+ var->red.msb_right = 0;
+ var->transp.offset = 0;
+ var->transp.length = 8;
+ bpp = 4;
+ break;
+
+ case MDP_YCRYCB_H2V1:
+ /* ToDo: need to check TV-Out YUV422i framebuffer format */
+ /* we might need to create new type define */
+ fix->type = FB_TYPE_INTERLEAVED_PLANES;
+ fix->xpanstep = 2;
+ fix->ypanstep = 1;
+ var->vmode = FB_VMODE_NONINTERLACED;
+
+ /* how about R/G/B offset? */
+ var->blue.offset = 0;
+ var->green.offset = 5;
+ var->red.offset = 11;
+ var->blue.length = 5;
+ var->green.length = 6;
+ var->red.length = 5;
+ var->blue.msb_right = 0;
+ var->green.msb_right = 0;
+ var->red.msb_right = 0;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ bpp = 2;
+ break;
+
+ default:
+ MSM_FB_ERR("msm_fb_init: fb %d unkown image type!\n",
+ mfd->index);
+ return ret;
+ }
+
+ fix->type = panel_info->is_3d_panel;
+
+ fix->line_length = msm_fb_line_length(mfd->index, panel_info->xres,
+ bpp);
+ /* calculate smem_len based on max size of two supplied modes */
+ fix->smem_len = roundup(MAX(msm_fb_line_length(mfd->index,
+ panel_info->xres,
+ bpp) *
+ panel_info->yres * mfd->fb_page,
+ msm_fb_line_length(mfd->index,
+ panel_info->mode2_xres,
+ bpp) *
+ panel_info->mode2_yres * mfd->fb_page), PAGE_SIZE);
+
+
+
+ mfd->var_xres = panel_info->xres;
+ mfd->var_yres = panel_info->yres;
+
+ var->pixclock = mfd->panel_info.clk_rate;
+ mfd->var_pixclock = var->pixclock;
+
+ var->xres = panel_info->xres;
+ var->yres = panel_info->yres;
+ var->xres_virtual = panel_info->xres;
+ var->yres_virtual = panel_info->yres * mfd->fb_page;
+ var->bits_per_pixel = bpp * 8; /* FrameBuffer color depth */
+ if (mfd->dest == DISPLAY_LCD) {
+ var->reserved[4] = panel_info->lcd.refx100 / 100;
+ } else {
+ var->reserved[4] = panel_info->clk_rate /
+ ((panel_info->lcdc.h_back_porch +
+ panel_info->lcdc.h_front_porch +
+ panel_info->lcdc.h_pulse_width +
+ panel_info->xres) *
+ (panel_info->lcdc.v_back_porch +
+ panel_info->lcdc.v_front_porch +
+ panel_info->lcdc.v_pulse_width +
+ panel_info->yres));
+ }
+ /*
+ * id field for fb app
+ */
+ id = (int *)&mfd->panel;
+
+#if defined(CONFIG_FB_MSM_MDP22)
+ snprintf(fix->id, sizeof(fix->id), "msmfb22_%x", (__u32) *id);
+#elif defined(CONFIG_FB_MSM_MDP30)
+ snprintf(fix->id, sizeof(fix->id), "msmfb30_%x", (__u32) *id);
+#elif defined(CONFIG_FB_MSM_MDP31)
+ snprintf(fix->id, sizeof(fix->id), "msmfb31_%x", (__u32) *id);
+#elif defined(CONFIG_FB_MSM_MDP40)
+ snprintf(fix->id, sizeof(fix->id), "msmfb40_%x", (__u32) *id);
+#else
+ error CONFIG_FB_MSM_MDP undefined !
+#endif
+ fbi->fbops = &msm_fb_ops;
+ fbi->flags = FBINFO_FLAG_DEFAULT;
+ fbi->pseudo_palette = msm_fb_pseudo_palette;
+
+ mfd->ref_cnt = 0;
+ mfd->sw_currently_refreshing = FALSE;
+ mfd->sw_refreshing_enable = TRUE;
+ mfd->panel_power_on = FALSE;
+
+ mfd->pan_waiting = FALSE;
+ init_completion(&mfd->pan_comp);
+ init_completion(&mfd->refresher_comp);
+ sema_init(&mfd->sem, 1);
+
+ init_timer(&mfd->msmfb_no_update_notify_timer);
+ mfd->msmfb_no_update_notify_timer.function =
+ msmfb_no_update_notify_timer_cb;
+ mfd->msmfb_no_update_notify_timer.data = (unsigned long)mfd;
+ init_completion(&mfd->msmfb_update_notify);
+ init_completion(&mfd->msmfb_no_update_notify);
+
+ fbram_offset = PAGE_ALIGN((int)fbram)-(int)fbram;
+ fbram += fbram_offset;
+ fbram_phys += fbram_offset;
+ fbram_size -= fbram_offset;
+
+ if (fbram_size < fix->smem_len) {
+ printk(KERN_ERR "error: no more framebuffer memory!\n");
+ return -ENOMEM;
+ }
+
+ fbi->screen_base = fbram;
+ fbi->fix.smem_start = (unsigned long)fbram_phys;
+
+ memset(fbi->screen_base, 0x0, fix->smem_len);
+
+ mfd->op_enable = TRUE;
+ mfd->panel_power_on = FALSE;
+
+ /* cursor memory allocation */
+ if (mfd->cursor_update) {
+ mfd->cursor_buf = dma_alloc_coherent(NULL,
+ MDP_CURSOR_SIZE,
+ (dma_addr_t *) &mfd->cursor_buf_phys,
+ GFP_KERNEL);
+ if (!mfd->cursor_buf)
+ mfd->cursor_update = 0;
+ }
+
+ if (mfd->lut_update) {
+ ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
+ if (ret)
+ printk(KERN_ERR "%s: fb_alloc_cmap() failed!\n",
+ __func__);
+ }
+
+ if (register_framebuffer(fbi) < 0) {
+ if (mfd->lut_update)
+ fb_dealloc_cmap(&fbi->cmap);
+
+ if (mfd->cursor_buf)
+ dma_free_coherent(NULL,
+ MDP_CURSOR_SIZE,
+ mfd->cursor_buf,
+ (dma_addr_t) mfd->cursor_buf_phys);
+
+ mfd->op_enable = FALSE;
+ return -EPERM;
+ }
+
+ fbram += fix->smem_len;
+ fbram_phys += fix->smem_len;
+ fbram_size -= fix->smem_len;
+
+ MSM_FB_INFO
+ ("FrameBuffer[%d] %dx%d size=%d bytes is registered successfully!\n",
+ mfd->index, fbi->var.xres, fbi->var.yres, fbi->fix.smem_len);
+
+#ifdef CONFIG_FB_MSM_LOGO
+ if (!load_565rle_image(INIT_IMAGE_FILE)) ; /* Flip buffer */
+#endif
+ ret = 0;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ if (mfd->panel_info.type != DTV_PANEL) {
+ mfd->early_suspend.suspend = msmfb_early_suspend;
+ mfd->early_suspend.resume = msmfb_early_resume;
+ mfd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 2;
+ register_early_suspend(&mfd->early_suspend);
+ }
+#endif
+
+#ifdef MSM_FB_ENABLE_DBGFS
+ {
+ struct dentry *root;
+ struct dentry *sub_dir;
+ char sub_name[2];
+
+ root = msm_fb_get_debugfs_root();
+ if (root != NULL) {
+ sub_name[0] = (char)(mfd->index + 0x30);
+ sub_name[1] = '\0';
+ sub_dir = debugfs_create_dir(sub_name, root);
+ } else {
+ sub_dir = NULL;
+ }
+
+ mfd->sub_dir = sub_dir;
+
+ if (sub_dir) {
+ msm_fb_debugfs_file_create(sub_dir, "op_enable",
+ (u32 *) &mfd->op_enable);
+ msm_fb_debugfs_file_create(sub_dir, "panel_power_on",
+ (u32 *) &mfd->
+ panel_power_on);
+ msm_fb_debugfs_file_create(sub_dir, "ref_cnt",
+ (u32 *) &mfd->ref_cnt);
+ msm_fb_debugfs_file_create(sub_dir, "fb_imgType",
+ (u32 *) &mfd->fb_imgType);
+ msm_fb_debugfs_file_create(sub_dir,
+ "sw_currently_refreshing",
+ (u32 *) &mfd->
+ sw_currently_refreshing);
+ msm_fb_debugfs_file_create(sub_dir,
+ "sw_refreshing_enable",
+ (u32 *) &mfd->
+ sw_refreshing_enable);
+
+ msm_fb_debugfs_file_create(sub_dir, "xres",
+ (u32 *) &mfd->panel_info.
+ xres);
+ msm_fb_debugfs_file_create(sub_dir, "yres",
+ (u32 *) &mfd->panel_info.
+ yres);
+ msm_fb_debugfs_file_create(sub_dir, "bpp",
+ (u32 *) &mfd->panel_info.
+ bpp);
+ msm_fb_debugfs_file_create(sub_dir, "type",
+ (u32 *) &mfd->panel_info.
+ type);
+ msm_fb_debugfs_file_create(sub_dir, "wait_cycle",
+ (u32 *) &mfd->panel_info.
+ wait_cycle);
+ msm_fb_debugfs_file_create(sub_dir, "pdest",
+ (u32 *) &mfd->panel_info.
+ pdest);
+ msm_fb_debugfs_file_create(sub_dir, "backbuff",
+ (u32 *) &mfd->panel_info.
+ fb_num);
+ msm_fb_debugfs_file_create(sub_dir, "clk_rate",
+ (u32 *) &mfd->panel_info.
+ clk_rate);
+ msm_fb_debugfs_file_create(sub_dir, "frame_count",
+ (u32 *) &mfd->panel_info.
+ frame_count);
+
+
+ switch (mfd->dest) {
+ case DISPLAY_LCD:
+ msm_fb_debugfs_file_create(sub_dir,
+ "vsync_enable",
+ (u32 *)&mfd->panel_info.lcd.vsync_enable);
+ msm_fb_debugfs_file_create(sub_dir,
+ "refx100",
+ (u32 *) &mfd->panel_info.lcd. refx100);
+ msm_fb_debugfs_file_create(sub_dir,
+ "v_back_porch",
+ (u32 *) &mfd->panel_info.lcd.v_back_porch);
+ msm_fb_debugfs_file_create(sub_dir,
+ "v_front_porch",
+ (u32 *) &mfd->panel_info.lcd.v_front_porch);
+ msm_fb_debugfs_file_create(sub_dir,
+ "v_pulse_width",
+ (u32 *) &mfd->panel_info.lcd.v_pulse_width);
+ msm_fb_debugfs_file_create(sub_dir,
+ "hw_vsync_mode",
+ (u32 *) &mfd->panel_info.lcd.hw_vsync_mode);
+ msm_fb_debugfs_file_create(sub_dir,
+ "vsync_notifier_period", (u32 *)
+ &mfd->panel_info.lcd.vsync_notifier_period);
+ break;
+
+ case DISPLAY_LCDC:
+ msm_fb_debugfs_file_create(sub_dir,
+ "h_back_porch",
+ (u32 *) &mfd->panel_info.lcdc.h_back_porch);
+ msm_fb_debugfs_file_create(sub_dir,
+ "h_front_porch",
+ (u32 *) &mfd->panel_info.lcdc.h_front_porch);
+ msm_fb_debugfs_file_create(sub_dir,
+ "h_pulse_width",
+ (u32 *) &mfd->panel_info.lcdc.h_pulse_width);
+ msm_fb_debugfs_file_create(sub_dir,
+ "v_back_porch",
+ (u32 *) &mfd->panel_info.lcdc.v_back_porch);
+ msm_fb_debugfs_file_create(sub_dir,
+ "v_front_porch",
+ (u32 *) &mfd->panel_info.lcdc.v_front_porch);
+ msm_fb_debugfs_file_create(sub_dir,
+ "v_pulse_width",
+ (u32 *) &mfd->panel_info.lcdc.v_pulse_width);
+ msm_fb_debugfs_file_create(sub_dir,
+ "border_clr",
+ (u32 *) &mfd->panel_info.lcdc.border_clr);
+ msm_fb_debugfs_file_create(sub_dir,
+ "underflow_clr",
+ (u32 *) &mfd->panel_info.lcdc.underflow_clr);
+ msm_fb_debugfs_file_create(sub_dir,
+ "hsync_skew",
+ (u32 *) &mfd->panel_info.lcdc.hsync_skew);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+#endif /* MSM_FB_ENABLE_DBGFS */
+
+ return ret;
+}
+
+static int msm_fb_open(struct fb_info *info, int user)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ int result;
+
+ result = pm_runtime_get_sync(info->dev);
+
+ if (result < 0) {
+ printk(KERN_ERR "pm_runtime: fail to wake up\n");
+ }
+
+
+ if (!mfd->ref_cnt) {
+ mdp_set_dma_pan_info(info, NULL, TRUE);
+
+ if (msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable)) {
+ printk(KERN_ERR "msm_fb_open: can't turn on display!\n");
+ return -1;
+ }
+ }
+
+ mfd->ref_cnt++;
+ return 0;
+}
+
+static int msm_fb_release(struct fb_info *info, int user)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ int ret = 0;
+
+ if (!mfd->ref_cnt) {
+ MSM_FB_INFO("msm_fb_release: try to close unopened fb %d!\n",
+ mfd->index);
+ return -EINVAL;
+ }
+
+ mfd->ref_cnt--;
+
+ if (!mfd->ref_cnt) {
+ if ((ret =
+ msm_fb_blank_sub(FB_BLANK_POWERDOWN, info,
+ mfd->op_enable)) != 0) {
+ printk(KERN_ERR "msm_fb_release: can't turn off display!\n");
+ return ret;
+ }
+ }
+
+ pm_runtime_put(info->dev);
+ return ret;
+}
+
+DEFINE_SEMAPHORE(msm_fb_pan_sem);
+
+static int msm_fb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct mdp_dirty_region dirty;
+ struct mdp_dirty_region *dirtyPtr = NULL;
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ if ((!mfd->op_enable) || (!mfd->panel_power_on))
+ return -EPERM;
+
+ if (var->xoffset > (info->var.xres_virtual - info->var.xres))
+ return -EINVAL;
+
+ if (var->yoffset > (info->var.yres_virtual - info->var.yres))
+ return -EINVAL;
+
+ if (info->fix.xpanstep)
+ info->var.xoffset =
+ (var->xoffset / info->fix.xpanstep) * info->fix.xpanstep;
+
+ if (info->fix.ypanstep)
+ info->var.yoffset =
+ (var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
+
+ /* "UPDT" */
+ if (var->reserved[0] == 0x54445055) {
+ dirty.xoffset = var->reserved[1] & 0xffff;
+ dirty.yoffset = (var->reserved[1] >> 16) & 0xffff;
+
+ if ((var->reserved[2] & 0xffff) <= dirty.xoffset)
+ return -EINVAL;
+ if (((var->reserved[2] >> 16) & 0xffff) <= dirty.yoffset)
+ return -EINVAL;
+
+ dirty.width = (var->reserved[2] & 0xffff) - dirty.xoffset;
+ dirty.height =
+ ((var->reserved[2] >> 16) & 0xffff) - dirty.yoffset;
+ info->var.yoffset = var->yoffset;
+
+ if (dirty.xoffset < 0)
+ return -EINVAL;
+
+ if (dirty.yoffset < 0)
+ return -EINVAL;
+
+ if ((dirty.xoffset + dirty.width) > info->var.xres)
+ return -EINVAL;
+
+ if ((dirty.yoffset + dirty.height) > info->var.yres)
+ return -EINVAL;
+
+ if ((dirty.width <= 0) || (dirty.height <= 0))
+ return -EINVAL;
+
+ dirtyPtr = &dirty;
+ }
+ complete(&mfd->msmfb_update_notify);
+ mutex_lock(&msm_fb_notify_update_sem);
+ if (mfd->msmfb_no_update_notify_timer.function)
+ del_timer(&mfd->msmfb_no_update_notify_timer);
+
+ mfd->msmfb_no_update_notify_timer.expires =
+ jiffies + ((1000 * HZ) / 1000);
+ add_timer(&mfd->msmfb_no_update_notify_timer);
+ mutex_unlock(&msm_fb_notify_update_sem);
+
+ down(&msm_fb_pan_sem);
+ mdp_set_dma_pan_info(info, dirtyPtr,
+ (var->activate == FB_ACTIVATE_VBL));
+ mdp_dma_pan_update(info);
+ up(&msm_fb_pan_sem);
+
+ ++mfd->panel_info.frame_count;
+ return 0;
+}
+
+static int msm_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ if (var->rotate != FB_ROTATE_UR)
+ return -EINVAL;
+ if (var->grayscale != info->var.grayscale)
+ return -EINVAL;
+
+ switch (var->bits_per_pixel) {
+ case 16:
+ if ((var->green.offset != 5) ||
+ !((var->blue.offset == 11)
+ || (var->blue.offset == 0)) ||
+ !((var->red.offset == 11)
+ || (var->red.offset == 0)) ||
+ (var->blue.length != 5) ||
+ (var->green.length != 6) ||
+ (var->red.length != 5) ||
+ (var->blue.msb_right != 0) ||
+ (var->green.msb_right != 0) ||
+ (var->red.msb_right != 0) ||
+ (var->transp.offset != 0) ||
+ (var->transp.length != 0))
+ return -EINVAL;
+ break;
+
+ case 24:
+ if ((var->blue.offset != 0) ||
+ (var->green.offset != 8) ||
+ (var->red.offset != 16) ||
+ (var->blue.length != 8) ||
+ (var->green.length != 8) ||
+ (var->red.length != 8) ||
+ (var->blue.msb_right != 0) ||
+ (var->green.msb_right != 0) ||
+ (var->red.msb_right != 0) ||
+ !(((var->transp.offset == 0) &&
+ (var->transp.length == 0)) ||
+ ((var->transp.offset == 24) &&
+ (var->transp.length == 8))))
+ return -EINVAL;
+ break;
+
+ case 32:
+ /* Figure out if the user meant RGBA or ARGB
+ and verify the position of the RGB components */
+
+ if (var->transp.offset == 24) {
+ if ((var->blue.offset != 0) ||
+ (var->green.offset != 8) ||
+ (var->red.offset != 16))
+ return -EINVAL;
+ } else if (var->transp.offset == 0) {
+ if ((var->blue.offset != 8) ||
+ (var->green.offset != 16) ||
+ (var->red.offset != 24))
+ return -EINVAL;
+ } else
+ return -EINVAL;
+
+ /* Check the common values for both RGBA and ARGB */
+
+ if ((var->blue.length != 8) ||
+ (var->green.length != 8) ||
+ (var->red.length != 8) ||
+ (var->transp.length != 8) ||
+ (var->blue.msb_right != 0) ||
+ (var->green.msb_right != 0) ||
+ (var->red.msb_right != 0))
+ return -EINVAL;
+
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if ((var->xres_virtual <= 0) || (var->yres_virtual <= 0))
+ return -EINVAL;
+
+ if (info->fix.smem_len <
+ (var->xres_virtual*var->yres_virtual*(var->bits_per_pixel/8)))
+ return -EINVAL;
+
+ if ((var->xres == 0) || (var->yres == 0))
+ return -EINVAL;
+
+ if ((var->xres > MAX(mfd->panel_info.xres,
+ mfd->panel_info.mode2_xres)) ||
+ (var->yres > MAX(mfd->panel_info.yres,
+ mfd->panel_info.mode2_yres)))
+ return -EINVAL;
+
+ if (var->xoffset > (var->xres_virtual - var->xres))
+ return -EINVAL;
+
+ if (var->yoffset > (var->yres_virtual - var->yres))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int msm_fb_set_par(struct fb_info *info)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct fb_var_screeninfo *var = &info->var;
+ int old_imgType;
+ int blank = 0;
+
+ old_imgType = mfd->fb_imgType;
+ switch (var->bits_per_pixel) {
+ case 16:
+ if (var->red.offset == 0)
+ mfd->fb_imgType = MDP_BGR_565;
+ else
+ mfd->fb_imgType = MDP_RGB_565;
+ break;
+
+ case 24:
+ if ((var->transp.offset == 0) && (var->transp.length == 0))
+ mfd->fb_imgType = MDP_RGB_888;
+ else if ((var->transp.offset == 24) &&
+ (var->transp.length == 8)) {
+ mfd->fb_imgType = MDP_ARGB_8888;
+ info->var.bits_per_pixel = 32;
+ }
+ break;
+
+ case 32:
+ if (var->transp.offset == 24)
+ mfd->fb_imgType = MDP_ARGB_8888;
+ else
+ mfd->fb_imgType = MDP_RGBA_8888;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if ((mfd->var_pixclock != var->pixclock) ||
+ (mfd->hw_refresh && ((mfd->fb_imgType != old_imgType) ||
+ (mfd->var_pixclock != var->pixclock) ||
+ (mfd->var_xres != var->xres) ||
+ (mfd->var_yres != var->yres)))) {
+ mfd->var_xres = var->xres;
+ mfd->var_yres = var->yres;
+ mfd->var_pixclock = var->pixclock;
+ blank = 1;
+ }
+ mfd->fbi->fix.line_length = msm_fb_line_length(mfd->index, var->xres,
+ var->bits_per_pixel/8);
+
+ if (blank) {
+ msm_fb_blank_sub(FB_BLANK_POWERDOWN, info, mfd->op_enable);
+ msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable);
+ }
+
+ return 0;
+}
+
+static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd)
+{
+ if (mfd->hw_refresh)
+ return -EPERM;
+
+ if (mfd->sw_currently_refreshing) {
+ down(&mfd->sem);
+ mfd->sw_currently_refreshing = FALSE;
+ up(&mfd->sem);
+
+ /* wait until the refresher finishes the last job */
+ wait_for_completion_killable(&mfd->refresher_comp);
+ }
+
+ return 0;
+}
+
+int msm_fb_resume_sw_refresher(struct msm_fb_data_type *mfd)
+{
+ boolean do_refresh;
+
+ if (mfd->hw_refresh)
+ return -EPERM;
+
+ down(&mfd->sem);
+ if ((!mfd->sw_currently_refreshing) && (mfd->sw_refreshing_enable)) {
+ do_refresh = TRUE;
+ mfd->sw_currently_refreshing = TRUE;
+ } else {
+ do_refresh = FALSE;
+ }
+ up(&mfd->sem);
+
+ if (do_refresh)
+ mdp_refresh_screen((unsigned long)mfd);
+
+ return 0;
+}
+
+#if defined CONFIG_FB_MSM_MDP31
+static int mdp_blit_split_height(struct fb_info *info,
+ struct mdp_blit_req *req)
+{
+ int ret;
+ struct mdp_blit_req splitreq;
+ int s_x_0, s_x_1, s_w_0, s_w_1, s_y_0, s_y_1, s_h_0, s_h_1;
+ int d_x_0, d_x_1, d_w_0, d_w_1, d_y_0, d_y_1, d_h_0, d_h_1;
+
+ splitreq = *req;
+ /* break dest roi at height*/
+ d_x_0 = d_x_1 = req->dst_rect.x;
+ d_w_0 = d_w_1 = req->dst_rect.w;
+ d_y_0 = req->dst_rect.y;
+ if (req->dst_rect.h % 32 == 3)
+ d_h_1 = (req->dst_rect.h - 3) / 2 - 1;
+ else if (req->dst_rect.h % 32 == 2)
+ d_h_1 = (req->dst_rect.h - 2) / 2 - 6;
+ else
+ d_h_1 = (req->dst_rect.h - 1) / 2 - 1;
+ d_h_0 = req->dst_rect.h - d_h_1;
+ d_y_1 = d_y_0 + d_h_0;
+ if (req->dst_rect.h == 3) {
+ d_h_1 = 2;
+ d_h_0 = 2;
+ d_y_1 = d_y_0 + 1;
+ }
+
+ /* blit first region */
+ if (((splitreq.flags & 0x07) == 0x04) ||
+ ((splitreq.flags & 0x07) == 0x0)) {
+
+ if (splitreq.flags & MDP_ROT_90) {
+ s_y_0 = s_y_1 = req->src_rect.y;
+ s_h_0 = s_h_1 = req->src_rect.h;
+ s_x_0 = req->src_rect.x;
+ s_w_1 = (req->src_rect.w * d_h_1) / req->dst_rect.h;
+ s_w_0 = req->src_rect.w - s_w_1;
+ s_x_1 = s_x_0 + s_w_0;
+ if (d_h_1 >= 8 * s_w_1) {
+ s_w_1++;
+ s_x_1--;
+ }
+ } else {
+ s_x_0 = s_x_1 = req->src_rect.x;
+ s_w_0 = s_w_1 = req->src_rect.w;
+ s_y_0 = req->src_rect.y;
+ s_h_1 = (req->src_rect.h * d_h_1) / req->dst_rect.h;
+ s_h_0 = req->src_rect.h - s_h_1;
+ s_y_1 = s_y_0 + s_h_0;
+ if (d_h_1 >= 8 * s_h_1) {
+ s_h_1++;
+ s_y_1--;
+ }
+ }
+
+ splitreq.src_rect.h = s_h_0;
+ splitreq.src_rect.y = s_y_0;
+ splitreq.dst_rect.h = d_h_0;
+ splitreq.dst_rect.y = d_y_0;
+ splitreq.src_rect.x = s_x_0;
+ splitreq.src_rect.w = s_w_0;
+ splitreq.dst_rect.x = d_x_0;
+ splitreq.dst_rect.w = d_w_0;
+ } else {
+
+ if (splitreq.flags & MDP_ROT_90) {
+ s_y_0 = s_y_1 = req->src_rect.y;
+ s_h_0 = s_h_1 = req->src_rect.h;
+ s_x_0 = req->src_rect.x;
+ s_w_1 = (req->src_rect.w * d_h_0) / req->dst_rect.h;
+ s_w_0 = req->src_rect.w - s_w_1;
+ s_x_1 = s_x_0 + s_w_0;
+ if (d_h_0 >= 8 * s_w_1) {
+ s_w_1++;
+ s_x_1--;
+ }
+ } else {
+ s_x_0 = s_x_1 = req->src_rect.x;
+ s_w_0 = s_w_1 = req->src_rect.w;
+ s_y_0 = req->src_rect.y;
+ s_h_1 = (req->src_rect.h * d_h_0) / req->dst_rect.h;
+ s_h_0 = req->src_rect.h - s_h_1;
+ s_y_1 = s_y_0 + s_h_0;
+ if (d_h_0 >= 8 * s_h_1) {
+ s_h_1++;
+ s_y_1--;
+ }
+ }
+ splitreq.src_rect.h = s_h_0;
+ splitreq.src_rect.y = s_y_0;
+ splitreq.dst_rect.h = d_h_1;
+ splitreq.dst_rect.y = d_y_1;
+ splitreq.src_rect.x = s_x_0;
+ splitreq.src_rect.w = s_w_0;
+ splitreq.dst_rect.x = d_x_1;
+ splitreq.dst_rect.w = d_w_1;
+ }
+ ret = mdp_ppp_blit(info, &splitreq);
+ if (ret)
+ return ret;
+
+ /* blit second region */
+ if (((splitreq.flags & 0x07) == 0x04) ||
+ ((splitreq.flags & 0x07) == 0x0)) {
+ splitreq.src_rect.h = s_h_1;
+ splitreq.src_rect.y = s_y_1;
+ splitreq.dst_rect.h = d_h_1;
+ splitreq.dst_rect.y = d_y_1;
+ splitreq.src_rect.x = s_x_1;
+ splitreq.src_rect.w = s_w_1;
+ splitreq.dst_rect.x = d_x_1;
+ splitreq.dst_rect.w = d_w_1;
+ } else {
+ splitreq.src_rect.h = s_h_1;
+ splitreq.src_rect.y = s_y_1;
+ splitreq.dst_rect.h = d_h_0;
+ splitreq.dst_rect.y = d_y_0;
+ splitreq.src_rect.x = s_x_1;
+ splitreq.src_rect.w = s_w_1;
+ splitreq.dst_rect.x = d_x_0;
+ splitreq.dst_rect.w = d_w_0;
+ }
+ ret = mdp_ppp_blit(info, &splitreq);
+ return ret;
+}
+#endif
+
+int mdp_blit(struct fb_info *info, struct mdp_blit_req *req)
+{
+ int ret;
+#if defined CONFIG_FB_MSM_MDP31 || defined CONFIG_FB_MSM_MDP30
+ unsigned int remainder = 0, is_bpp_4 = 0;
+ struct mdp_blit_req splitreq;
+ int s_x_0, s_x_1, s_w_0, s_w_1, s_y_0, s_y_1, s_h_0, s_h_1;
+ int d_x_0, d_x_1, d_w_0, d_w_1, d_y_0, d_y_1, d_h_0, d_h_1;
+
+ if (req->flags & MDP_ROT_90) {
+ if (((req->dst_rect.h == 1) && ((req->src_rect.w != 1) ||
+ (req->dst_rect.w != req->src_rect.h))) ||
+ ((req->dst_rect.w == 1) && ((req->src_rect.h != 1) ||
+ (req->dst_rect.h != req->src_rect.w)))) {
+ printk(KERN_ERR "mpd_ppp: error scaling when size is 1!\n");
+ return -EINVAL;
+ }
+ } else {
+ if (((req->dst_rect.w == 1) && ((req->src_rect.w != 1) ||
+ (req->dst_rect.h != req->src_rect.h))) ||
+ ((req->dst_rect.h == 1) && ((req->src_rect.h != 1) ||
+ (req->dst_rect.w != req->src_rect.w)))) {
+ printk(KERN_ERR "mpd_ppp: error scaling when size is 1!\n");
+ return -EINVAL;
+ }
+ }
+#endif
+ if (unlikely(req->src_rect.h == 0 || req->src_rect.w == 0)) {
+ printk(KERN_ERR "mpd_ppp: src img of zero size!\n");
+ return -EINVAL;
+ }
+ if (unlikely(req->dst_rect.h == 0 || req->dst_rect.w == 0))
+ return 0;
+
+#if defined CONFIG_FB_MSM_MDP31
+ /* MDP width split workaround */
+ remainder = (req->dst_rect.w)%32;
+ ret = mdp_get_bytes_per_pixel(req->dst.format,
+ (struct msm_fb_data_type *)info->par);
+ if (ret <= 0) {
+ printk(KERN_ERR "mdp_ppp: incorrect bpp!\n");
+ return -EINVAL;
+ }
+ is_bpp_4 = (ret == 4) ? 1 : 0;
+
+ if ((is_bpp_4 && (remainder == 6 || remainder == 14 ||
+ remainder == 22 || remainder == 30)) || remainder == 3 ||
+ (remainder == 1 && req->dst_rect.w != 1) ||
+ (remainder == 2 && req->dst_rect.w != 2)) {
+ /* make new request as provide by user */
+ splitreq = *req;
+
+ /* break dest roi at width*/
+ d_y_0 = d_y_1 = req->dst_rect.y;
+ d_h_0 = d_h_1 = req->dst_rect.h;
+ d_x_0 = req->dst_rect.x;
+
+ if (remainder == 14)
+ d_w_1 = (req->dst_rect.w - 14) / 2 + 4;
+ else if (remainder == 22)
+ d_w_1 = (req->dst_rect.w - 22) / 2 + 10;
+ else if (remainder == 30)
+ d_w_1 = (req->dst_rect.w - 30) / 2 + 10;
+ else if (remainder == 6)
+ d_w_1 = req->dst_rect.w / 2 - 1;
+ else if (remainder == 3)
+ d_w_1 = (req->dst_rect.w - 3) / 2 - 1;
+ else if (remainder == 2)
+ d_w_1 = (req->dst_rect.w - 2) / 2 - 6;
+ else
+ d_w_1 = (req->dst_rect.w - 1) / 2 - 1;
+ d_w_0 = req->dst_rect.w - d_w_1;
+ d_x_1 = d_x_0 + d_w_0;
+ if (req->dst_rect.w == 3) {
+ d_w_1 = 2;
+ d_w_0 = 2;
+ d_x_1 = d_x_0 + 1;
+ }
+
+ /* blit first region */
+ if (((splitreq.flags & 0x07) == 0x07) ||
+ ((splitreq.flags & 0x07) == 0x0)) {
+
+ if (splitreq.flags & MDP_ROT_90) {
+ s_x_0 = s_x_1 = req->src_rect.x;
+ s_w_0 = s_w_1 = req->src_rect.w;
+ s_y_0 = req->src_rect.y;
+ s_h_1 = (req->src_rect.h * d_w_1) /
+ req->dst_rect.w;
+ s_h_0 = req->src_rect.h - s_h_1;
+ s_y_1 = s_y_0 + s_h_0;
+ if (d_w_1 >= 8 * s_h_1) {
+ s_h_1++;
+ s_y_1--;
+ }
+ } else {
+ s_y_0 = s_y_1 = req->src_rect.y;
+ s_h_0 = s_h_1 = req->src_rect.h;
+ s_x_0 = req->src_rect.x;
+ s_w_1 = (req->src_rect.w * d_w_1) /
+ req->dst_rect.w;
+ s_w_0 = req->src_rect.w - s_w_1;
+ s_x_1 = s_x_0 + s_w_0;
+ if (d_w_1 >= 8 * s_w_1) {
+ s_w_1++;
+ s_x_1--;
+ }
+ }
+
+ splitreq.src_rect.h = s_h_0;
+ splitreq.src_rect.y = s_y_0;
+ splitreq.dst_rect.h = d_h_0;
+ splitreq.dst_rect.y = d_y_0;
+ splitreq.src_rect.x = s_x_0;
+ splitreq.src_rect.w = s_w_0;
+ splitreq.dst_rect.x = d_x_0;
+ splitreq.dst_rect.w = d_w_0;
+ } else {
+ if (splitreq.flags & MDP_ROT_90) {
+ s_x_0 = s_x_1 = req->src_rect.x;
+ s_w_0 = s_w_1 = req->src_rect.w;
+ s_y_0 = req->src_rect.y;
+ s_h_1 = (req->src_rect.h * d_w_0) /
+ req->dst_rect.w;
+ s_h_0 = req->src_rect.h - s_h_1;
+ s_y_1 = s_y_0 + s_h_0;
+ if (d_w_0 >= 8 * s_h_1) {
+ s_h_1++;
+ s_y_1--;
+ }
+ } else {
+ s_y_0 = s_y_1 = req->src_rect.y;
+ s_h_0 = s_h_1 = req->src_rect.h;
+ s_x_0 = req->src_rect.x;
+ s_w_1 = (req->src_rect.w * d_w_0) /
+ req->dst_rect.w;
+ s_w_0 = req->src_rect.w - s_w_1;
+ s_x_1 = s_x_0 + s_w_0;
+ if (d_w_0 >= 8 * s_w_1) {
+ s_w_1++;
+ s_x_1--;
+ }
+ }
+ splitreq.src_rect.h = s_h_0;
+ splitreq.src_rect.y = s_y_0;
+ splitreq.dst_rect.h = d_h_1;
+ splitreq.dst_rect.y = d_y_1;
+ splitreq.src_rect.x = s_x_0;
+ splitreq.src_rect.w = s_w_0;
+ splitreq.dst_rect.x = d_x_1;
+ splitreq.dst_rect.w = d_w_1;
+ }
+
+ if ((splitreq.dst_rect.h % 32 == 3) ||
+ ((req->dst_rect.h % 32) == 1 && req->dst_rect.h != 1) ||
+ ((req->dst_rect.h % 32) == 2 && req->dst_rect.h != 2))
+ ret = mdp_blit_split_height(info, &splitreq);
+ else
+ ret = mdp_ppp_blit(info, &splitreq);
+ if (ret)
+ return ret;
+ /* blit second region */
+ if (((splitreq.flags & 0x07) == 0x07) ||
+ ((splitreq.flags & 0x07) == 0x0)) {
+ splitreq.src_rect.h = s_h_1;
+ splitreq.src_rect.y = s_y_1;
+ splitreq.dst_rect.h = d_h_1;
+ splitreq.dst_rect.y = d_y_1;
+ splitreq.src_rect.x = s_x_1;
+ splitreq.src_rect.w = s_w_1;
+ splitreq.dst_rect.x = d_x_1;
+ splitreq.dst_rect.w = d_w_1;
+ } else {
+ splitreq.src_rect.h = s_h_1;
+ splitreq.src_rect.y = s_y_1;
+ splitreq.dst_rect.h = d_h_0;
+ splitreq.dst_rect.y = d_y_0;
+ splitreq.src_rect.x = s_x_1;
+ splitreq.src_rect.w = s_w_1;
+ splitreq.dst_rect.x = d_x_0;
+ splitreq.dst_rect.w = d_w_0;
+ }
+ if (((splitreq.dst_rect.h % 32) == 3) ||
+ ((req->dst_rect.h % 32) == 1 && req->dst_rect.h != 1) ||
+ ((req->dst_rect.h % 32) == 2 && req->dst_rect.h != 2))
+ ret = mdp_blit_split_height(info, &splitreq);
+ else
+ ret = mdp_ppp_blit(info, &splitreq);
+ if (ret)
+ return ret;
+ } else if ((req->dst_rect.h % 32) == 3 ||
+ ((req->dst_rect.h % 32) == 1 && req->dst_rect.h != 1) ||
+ ((req->dst_rect.h % 32) == 2 && req->dst_rect.h != 2))
+ ret = mdp_blit_split_height(info, req);
+ else
+ ret = mdp_ppp_blit(info, req);
+ return ret;
+#elif defined CONFIG_FB_MSM_MDP30
+ /* MDP width split workaround */
+ remainder = (req->dst_rect.w)%16;
+ ret = mdp_get_bytes_per_pixel(req->dst.format,
+ (struct msm_fb_data_type *)info->par);
+ if (ret <= 0) {
+ printk(KERN_ERR "mdp_ppp: incorrect bpp!\n");
+ return -EINVAL;
+ }
+ is_bpp_4 = (ret == 4) ? 1 : 0;
+
+ if ((is_bpp_4 && (remainder == 6 || remainder == 14))) {
+
+ /* make new request as provide by user */
+ splitreq = *req;
+
+ /* break dest roi at width*/
+ d_y_0 = d_y_1 = req->dst_rect.y;
+ d_h_0 = d_h_1 = req->dst_rect.h;
+ d_x_0 = req->dst_rect.x;
+
+ if (remainder == 14 || remainder == 6)
+ d_w_1 = req->dst_rect.w / 2;
+ else
+ d_w_1 = (req->dst_rect.w - 1) / 2 - 1;
+
+ d_w_0 = req->dst_rect.w - d_w_1;
+ d_x_1 = d_x_0 + d_w_0;
+
+ /* blit first region */
+ if (((splitreq.flags & 0x07) == 0x07) ||
+ ((splitreq.flags & 0x07) == 0x0)) {
+
+ if (splitreq.flags & MDP_ROT_90) {
+ s_x_0 = s_x_1 = req->src_rect.x;
+ s_w_0 = s_w_1 = req->src_rect.w;
+ s_y_0 = req->src_rect.y;
+ s_h_1 = (req->src_rect.h * d_w_1) /
+ req->dst_rect.w;
+ s_h_0 = req->src_rect.h - s_h_1;
+ s_y_1 = s_y_0 + s_h_0;
+ if (d_w_1 >= 8 * s_h_1) {
+ s_h_1++;
+ s_y_1--;
+ }
+ } else {
+ s_y_0 = s_y_1 = req->src_rect.y;
+ s_h_0 = s_h_1 = req->src_rect.h;
+ s_x_0 = req->src_rect.x;
+ s_w_1 = (req->src_rect.w * d_w_1) /
+ req->dst_rect.w;
+ s_w_0 = req->src_rect.w - s_w_1;
+ s_x_1 = s_x_0 + s_w_0;
+ if (d_w_1 >= 8 * s_w_1) {
+ s_w_1++;
+ s_x_1--;
+ }
+ }
+
+ splitreq.src_rect.h = s_h_0;
+ splitreq.src_rect.y = s_y_0;
+ splitreq.dst_rect.h = d_h_0;
+ splitreq.dst_rect.y = d_y_0;
+ splitreq.src_rect.x = s_x_0;
+ splitreq.src_rect.w = s_w_0;
+ splitreq.dst_rect.x = d_x_0;
+ splitreq.dst_rect.w = d_w_0;
+ } else {
+ if (splitreq.flags & MDP_ROT_90) {
+ s_x_0 = s_x_1 = req->src_rect.x;
+ s_w_0 = s_w_1 = req->src_rect.w;
+ s_y_0 = req->src_rect.y;
+ s_h_1 = (req->src_rect.h * d_w_0) /
+ req->dst_rect.w;
+ s_h_0 = req->src_rect.h - s_h_1;
+ s_y_1 = s_y_0 + s_h_0;
+ if (d_w_0 >= 8 * s_h_1) {
+ s_h_1++;
+ s_y_1--;
+ }
+ } else {
+ s_y_0 = s_y_1 = req->src_rect.y;
+ s_h_0 = s_h_1 = req->src_rect.h;
+ s_x_0 = req->src_rect.x;
+ s_w_1 = (req->src_rect.w * d_w_0) /
+ req->dst_rect.w;
+ s_w_0 = req->src_rect.w - s_w_1;
+ s_x_1 = s_x_0 + s_w_0;
+ if (d_w_0 >= 8 * s_w_1) {
+ s_w_1++;
+ s_x_1--;
+ }
+ }
+ splitreq.src_rect.h = s_h_0;
+ splitreq.src_rect.y = s_y_0;
+ splitreq.dst_rect.h = d_h_1;
+ splitreq.dst_rect.y = d_y_1;
+ splitreq.src_rect.x = s_x_0;
+ splitreq.src_rect.w = s_w_0;
+ splitreq.dst_rect.x = d_x_1;
+ splitreq.dst_rect.w = d_w_1;
+ }
+
+ /* No need to split in height */
+ ret = mdp_ppp_blit(info, &splitreq);
+
+ if (ret)
+ return ret;
+
+ /* blit second region */
+ if (((splitreq.flags & 0x07) == 0x07) ||
+ ((splitreq.flags & 0x07) == 0x0)) {
+ splitreq.src_rect.h = s_h_1;
+ splitreq.src_rect.y = s_y_1;
+ splitreq.dst_rect.h = d_h_1;
+ splitreq.dst_rect.y = d_y_1;
+ splitreq.src_rect.x = s_x_1;
+ splitreq.src_rect.w = s_w_1;
+ splitreq.dst_rect.x = d_x_1;
+ splitreq.dst_rect.w = d_w_1;
+ } else {
+ splitreq.src_rect.h = s_h_1;
+ splitreq.src_rect.y = s_y_1;
+ splitreq.dst_rect.h = d_h_0;
+ splitreq.dst_rect.y = d_y_0;
+ splitreq.src_rect.x = s_x_1;
+ splitreq.src_rect.w = s_w_1;
+ splitreq.dst_rect.x = d_x_0;
+ splitreq.dst_rect.w = d_w_0;
+ }
+
+ /* No need to split in height ... just width */
+ ret = mdp_ppp_blit(info, &splitreq);
+
+ if (ret)
+ return ret;
+
+ } else
+ ret = mdp_ppp_blit(info, req);
+ return ret;
+#else
+ ret = mdp_ppp_blit(info, req);
+ return ret;
+#endif
+}
+
+typedef void (*msm_dma_barrier_function_pointer) (void *, size_t);
+
+static inline void msm_fb_dma_barrier_for_rect(struct fb_info *info,
+ struct mdp_img *img, struct mdp_rect *rect,
+ msm_dma_barrier_function_pointer dma_barrier_fp
+ )
+{
+ /*
+ * Compute the start and end addresses of the rectangles.
+ * NOTE: As currently implemented, the data between
+ * the end of one row and the start of the next is
+ * included in the address range rather than
+ * doing multiple calls for each row.
+ */
+ unsigned long start;
+ size_t size;
+ char * const pmem_start = info->screen_base;
+ int bytes_per_pixel = mdp_get_bytes_per_pixel(img->format,
+ (struct msm_fb_data_type *)info->par);
+ if (bytes_per_pixel <= 0) {
+ printk(KERN_ERR "%s incorrect bpp!\n", __func__);
+ return;
+ }
+ start = (unsigned long)pmem_start + img->offset +
+ (img->width * rect->y + rect->x) * bytes_per_pixel;
+ size = (rect->h * img->width + rect->w) * bytes_per_pixel;
+ (*dma_barrier_fp) ((void *) start, size);
+
+}
+
+static inline void msm_dma_nc_pre(void)
+{
+ dmb();
+}
+static inline void msm_dma_wt_pre(void)
+{
+ dmb();
+}
+static inline void msm_dma_todevice_wb_pre(void *start, size_t size)
+{
+ dma_cache_pre_ops(start, size, DMA_TO_DEVICE);
+}
+
+static inline void msm_dma_fromdevice_wb_pre(void *start, size_t size)
+{
+ dma_cache_pre_ops(start, size, DMA_FROM_DEVICE);
+}
+
+static inline void msm_dma_nc_post(void)
+{
+ dmb();
+}
+
+static inline void msm_dma_fromdevice_wt_post(void *start, size_t size)
+{
+ dma_cache_post_ops(start, size, DMA_FROM_DEVICE);
+}
+
+static inline void msm_dma_todevice_wb_post(void *start, size_t size)
+{
+ dma_cache_post_ops(start, size, DMA_TO_DEVICE);
+}
+
+static inline void msm_dma_fromdevice_wb_post(void *start, size_t size)
+{
+ dma_cache_post_ops(start, size, DMA_FROM_DEVICE);
+}
+
+/*
+ * Do the write barriers required to guarantee data is committed to RAM
+ * (from CPU cache or internal buffers) before a DMA operation starts.
+ * NOTE: As currently implemented, the data between
+ * the end of one row and the start of the next is
+ * included in the address range rather than
+ * doing multiple calls for each row.
+*/
+static void msm_fb_ensure_memory_coherency_before_dma(struct fb_info *info,
+ struct mdp_blit_req *req_list,
+ int req_list_count)
+{
+#ifdef CONFIG_ARCH_QSD8X50
+ int i;
+
+ /*
+ * Normally, do the requested barriers for each address
+ * range that corresponds to a rectangle.
+ *
+ * But if at least one write barrier is requested for data
+ * going to or from the device but no address range is
+ * needed for that barrier, then do the barrier, but do it
+ * only once, no matter how many requests there are.
+ */
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ switch (mfd->mdp_fb_page_protection) {
+ default:
+ case MDP_FB_PAGE_PROTECTION_NONCACHED:
+ case MDP_FB_PAGE_PROTECTION_WRITECOMBINE:
+ /*
+ * The following barrier is only done at most once,
+ * since further calls would be redundant.
+ */
+ for (i = 0; i < req_list_count; i++) {
+ if (!(req_list[i].flags
+ & MDP_NO_DMA_BARRIER_START)) {
+ msm_dma_nc_pre();
+ break;
+ }
+ }
+ break;
+
+ case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE:
+ /*
+ * The following barrier is only done at most once,
+ * since further calls would be redundant.
+ */
+ for (i = 0; i < req_list_count; i++) {
+ if (!(req_list[i].flags
+ & MDP_NO_DMA_BARRIER_START)) {
+ msm_dma_wt_pre();
+ break;
+ }
+ }
+ break;
+
+ case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE:
+ case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE:
+ for (i = 0; i < req_list_count; i++) {
+ if (!(req_list[i].flags &
+ MDP_NO_DMA_BARRIER_START)) {
+
+ msm_fb_dma_barrier_for_rect(info,
+ &(req_list[i].src),
+ &(req_list[i].src_rect),
+ msm_dma_todevice_wb_pre
+ );
+
+ msm_fb_dma_barrier_for_rect(info,
+ &(req_list[i].dst),
+ &(req_list[i].dst_rect),
+ msm_dma_todevice_wb_pre
+ );
+ }
+ }
+ break;
+ }
+#else
+ dmb();
+#endif
+}
+
+
+/*
+ * Do the write barriers required to guarantee data will be re-read from RAM by
+ * the CPU after a DMA operation ends.
+ * NOTE: As currently implemented, the data between
+ * the end of one row and the start of the next is
+ * included in the address range rather than
+ * doing multiple calls for each row.
+*/
+static void msm_fb_ensure_memory_coherency_after_dma(struct fb_info *info,
+ struct mdp_blit_req *req_list,
+ int req_list_count)
+{
+#ifdef CONFIG_ARCH_QSD8X50
+ int i;
+
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ switch (mfd->mdp_fb_page_protection) {
+ default:
+ case MDP_FB_PAGE_PROTECTION_NONCACHED:
+ case MDP_FB_PAGE_PROTECTION_WRITECOMBINE:
+ /*
+ * The following barrier is only done at most once,
+ * since further calls would be redundant.
+ */
+ for (i = 0; i < req_list_count; i++) {
+ if (!(req_list[i].flags
+ & MDP_NO_DMA_BARRIER_END)) {
+ msm_dma_nc_post();
+ break;
+ }
+ }
+ break;
+
+ case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE:
+ for (i = 0; i < req_list_count; i++) {
+ if (!(req_list[i].flags &
+ MDP_NO_DMA_BARRIER_END)) {
+
+ msm_fb_dma_barrier_for_rect(info,
+ &(req_list[i].dst),
+ &(req_list[i].dst_rect),
+ msm_dma_fromdevice_wt_post
+ );
+ }
+ }
+ break;
+ case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE:
+ case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE:
+ for (i = 0; i < req_list_count; i++) {
+ if (!(req_list[i].flags &
+ MDP_NO_DMA_BARRIER_END)) {
+
+ msm_fb_dma_barrier_for_rect(info,
+ &(req_list[i].dst),
+ &(req_list[i].dst_rect),
+ msm_dma_fromdevice_wb_post
+ );
+ }
+ }
+ break;
+ }
+#else
+ dmb();
+#endif
+}
+
+/*
+ * NOTE: The userspace issues blit operations in a sequence, the sequence
+ * start with a operation marked START and ends in an operation marked
+ * END. It is guranteed by the userspace that all the blit operations
+ * between START and END are only within the regions of areas designated
+ * by the START and END operations and that the userspace doesnt modify
+ * those areas. Hence it would be enough to perform barrier/cache operations
+ * only on the START and END operations.
+ */
+static int msmfb_blit(struct fb_info *info, void __user *p)
+{
+ /*
+ * CAUTION: The names of the struct types intentionally *DON'T* match
+ * the names of the variables declared -- they appear to be swapped.
+ * Read the code carefully and you should see that the variable names
+ * make sense.
+ */
+ const int MAX_LIST_WINDOW = 16;
+ struct mdp_blit_req req_list[MAX_LIST_WINDOW];
+ struct mdp_blit_req_list req_list_header;
+
+ int count, i, req_list_count;
+
+ /* Get the count size for the total BLIT request. */
+ if (copy_from_user(&req_list_header, p, sizeof(req_list_header)))
+ return -EFAULT;
+ p += sizeof(req_list_header);
+ count = req_list_header.count;
+ if (count < 0 || count >= MAX_BLIT_REQ)
+ return -EINVAL;
+ while (count > 0) {
+ /*
+ * Access the requests through a narrow window to decrease copy
+ * overhead and make larger requests accessible to the
+ * coherency management code.
+ * NOTE: The window size is intended to be larger than the
+ * typical request size, but not require more than 2
+ * kbytes of stack storage.
+ */
+ req_list_count = count;
+ if (req_list_count > MAX_LIST_WINDOW)
+ req_list_count = MAX_LIST_WINDOW;
+ if (copy_from_user(&req_list, p,
+ sizeof(struct mdp_blit_req)*req_list_count))
+ return -EFAULT;
+
+ /*
+ * Ensure that any data CPU may have previously written to
+ * internal state (but not yet committed to memory) is
+ * guaranteed to be committed to memory now.
+ */
+ msm_fb_ensure_memory_coherency_before_dma(info,
+ req_list, req_list_count);
+
+ /*
+ * Do the blit DMA, if required -- returning early only if
+ * there is a failure.
+ */
+ for (i = 0; i < req_list_count; i++) {
+ if (!(req_list[i].flags & MDP_NO_BLIT)) {
+ /* Do the actual blit. */
+ int ret = mdp_blit(info, &(req_list[i]));
+
+ /*
+ * Note that early returns don't guarantee
+ * memory coherency.
+ */
+ if (ret)
+ return ret;
+ }
+ }
+
+ /*
+ * Ensure that CPU cache and other internal CPU state is
+ * updated to reflect any change in memory modified by MDP blit
+ * DMA.
+ */
+ msm_fb_ensure_memory_coherency_after_dma(info,
+ req_list,
+ req_list_count);
+
+ /* Go to next window of requests. */
+ count -= req_list_count;
+ p += sizeof(struct mdp_blit_req)*req_list_count;
+ }
+ return 0;
+}
+
+#ifdef CONFIG_FB_MSM_OVERLAY
+static int msmfb_overlay_get(struct fb_info *info, void __user *p)
+{
+ struct mdp_overlay req;
+ int ret;
+
+ if (copy_from_user(&req, p, sizeof(req)))
+ return -EFAULT;
+
+ ret = mdp4_overlay_get(info, &req);
+ if (ret) {
+ printk(KERN_ERR "%s: ioctl failed \n",
+ __func__);
+ return ret;
+ }
+ if (copy_to_user(p, &req, sizeof(req))) {
+ printk(KERN_ERR "%s: copy2user failed \n",
+ __func__);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int msmfb_overlay_set(struct fb_info *info, void __user *p)
+{
+ struct mdp_overlay req;
+ int ret;
+
+ if (copy_from_user(&req, p, sizeof(req)))
+ return -EFAULT;
+
+ ret = mdp4_overlay_set(info, &req);
+ if (ret) {
+ printk(KERN_ERR "%s: ioctl failed, rc=%d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ if (copy_to_user(p, &req, sizeof(req))) {
+ printk(KERN_ERR "%s: copy2user failed \n",
+ __func__);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int msmfb_overlay_unset(struct fb_info *info, unsigned long *argp)
+{
+ int ret, ndx;
+
+ ret = copy_from_user(&ndx, argp, sizeof(ndx));
+ if (ret) {
+ printk(KERN_ERR "%s:msmfb_overlay_unset ioctl failed \n",
+ __func__);
+ return ret;
+ }
+
+ return mdp4_overlay_unset(info, ndx);
+}
+
+static int msmfb_overlay_play(struct fb_info *info, unsigned long *argp)
+{
+ int ret;
+ struct msmfb_overlay_data req;
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct file *p_src_file = 0;
+ struct file *p_src_plane1_file = 0, *p_src_plane2_file = 0;
+
+ if (mfd->overlay_play_enable == 0) /* nothing to do */
+ return 0;
+
+ ret = copy_from_user(&req, argp, sizeof(req));
+ if (ret) {
+ printk(KERN_ERR "%s:msmfb_overlay_play ioctl failed \n",
+ __func__);
+ return ret;
+ }
+
+ complete(&mfd->msmfb_update_notify);
+ mutex_lock(&msm_fb_notify_update_sem);
+ if (mfd->msmfb_no_update_notify_timer.function)
+ del_timer(&mfd->msmfb_no_update_notify_timer);
+
+ mfd->msmfb_no_update_notify_timer.expires =
+ jiffies + ((1000 * HZ) / 1000);
+ add_timer(&mfd->msmfb_no_update_notify_timer);
+ mutex_unlock(&msm_fb_notify_update_sem);
+
+ ret = mdp4_overlay_play(info, &req, &p_src_file, &p_src_plane1_file,
+ &p_src_plane2_file);
+
+#ifdef CONFIG_ANDROID_PMEM
+ if (p_src_file)
+ put_pmem_file(p_src_file);
+ if (p_src_plane1_file)
+ put_pmem_file(p_src_plane1_file);
+ if (p_src_plane2_file)
+ put_pmem_file(p_src_plane2_file);
+#endif
+
+ return ret;
+}
+
+static int msmfb_overlay_play_enable(struct fb_info *info, unsigned long *argp)
+{
+ int ret, enable;
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ ret = copy_from_user(&enable, argp, sizeof(enable));
+ if (ret) {
+ printk(KERN_ERR "%s:msmfb_overlay_play_enable ioctl failed \n",
+ __func__);
+ return ret;
+ }
+
+ mfd->overlay_play_enable = enable;
+
+ return 0;
+}
+
+
+#ifdef CONFIG_FB_MSM_OVERLAY_WRITEBACK
+static int msmfb_overlay_blt(struct fb_info *info, unsigned long *argp)
+{
+ int ret;
+ struct msmfb_overlay_blt req;
+
+ ret = copy_from_user(&req, argp, sizeof(req));
+ if (ret) {
+ printk(KERN_ERR "%s:msmfb_overlay_blt ioctl failed\n",
+ __func__);
+ return ret;
+ }
+
+ ret = mdp4_overlay_blt(info, &req);
+
+ return ret;
+}
+
+static int msmfb_overlay_blt_off(struct fb_info *info, unsigned long *argp)
+{
+ int ret;
+ struct msmfb_overlay_blt req;
+
+ ret = mdp4_overlay_blt_offset(info, &req);
+
+ ret = copy_to_user(argp, &req, sizeof(req));
+ if (ret)
+ printk(KERN_ERR "%s:msmfb_overlay_blt_off ioctl failed\n",
+ __func__);
+
+ return ret;
+}
+#else
+static int msmfb_overlay_blt(struct fb_info *info, unsigned long *argp)
+{
+ return 0;
+}
+static int msmfb_overlay_blt_off(struct fb_info *info, unsigned long *argp)
+{
+ return 0;
+}
+#endif
+
+static int msmfb_overlay_3d(struct fb_info *info, unsigned long *argp)
+{
+ int ret;
+ struct msmfb_overlay_3d req;
+
+ ret = copy_from_user(&req, argp, sizeof(req));
+ if (ret) {
+ pr_err("%s:msmfb_overlay_3d_ctrl ioctl failed\n",
+ __func__);
+ return ret;
+ }
+
+ ret = mdp4_overlay_3d(info, &req);
+
+ return ret;
+}
+
+#endif
+
+DEFINE_SEMAPHORE(msm_fb_ioctl_ppp_sem);
+DEFINE_MUTEX(msm_fb_ioctl_lut_sem);
+DEFINE_MUTEX(msm_fb_ioctl_hist_sem);
+
+/* Set color conversion matrix from user space */
+
+#ifndef CONFIG_FB_MSM_MDP40
+static void msmfb_set_color_conv(struct mdp_ccs *p)
+{
+ int i;
+
+ if (p->direction == MDP_CCS_RGB2YUV) {
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ /* RGB->YUV primary forward matrix */
+ for (i = 0; i < MDP_CCS_SIZE; i++)
+ writel(p->ccs[i], MDP_CSC_PFMVn(i));
+
+ #ifdef CONFIG_FB_MSM_MDP31
+ for (i = 0; i < MDP_BV_SIZE; i++)
+ writel(p->bv[i], MDP_CSC_POST_BV2n(i));
+ #endif
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ } else {
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ /* YUV->RGB primary reverse matrix */
+ for (i = 0; i < MDP_CCS_SIZE; i++)
+ writel(p->ccs[i], MDP_CSC_PRMVn(i));
+ for (i = 0; i < MDP_BV_SIZE; i++)
+ writel(p->bv[i], MDP_CSC_PRE_BV1n(i));
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ }
+}
+#endif
+
+static int msmfb_notify_update(struct fb_info *info, unsigned long *argp)
+{
+ int ret, notify;
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ ret = copy_from_user(¬ify, argp, sizeof(int));
+ if (ret) {
+ pr_err("%s:ioctl failed\n", __func__);
+ return ret;
+ }
+
+ if (notify > NOTIFY_UPDATE_STOP)
+ return -EINVAL;
+
+ if (notify == NOTIFY_UPDATE_START) {
+ INIT_COMPLETION(mfd->msmfb_update_notify);
+ wait_for_completion_interruptible(&mfd->msmfb_update_notify);
+ } else {
+ INIT_COMPLETION(mfd->msmfb_no_update_notify);
+ wait_for_completion_interruptible(&mfd->msmfb_no_update_notify);
+ }
+ return 0;
+}
+
+static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ void __user *argp = (void __user *)arg;
+ struct fb_cursor cursor;
+ struct fb_cmap cmap;
+ struct mdp_histogram hist;
+#ifndef CONFIG_FB_MSM_MDP40
+ struct mdp_ccs ccs_matrix;
+#endif
+ struct mdp_page_protection fb_page_protection;
+ int ret = 0;
+
+ switch (cmd) {
+#ifdef CONFIG_FB_MSM_OVERLAY
+ case MSMFB_OVERLAY_GET:
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_overlay_get(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
+ break;
+ case MSMFB_OVERLAY_SET:
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_overlay_set(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
+ break;
+ case MSMFB_OVERLAY_UNSET:
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_overlay_unset(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
+ break;
+ case MSMFB_OVERLAY_PLAY:
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_overlay_play(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
+ break;
+ case MSMFB_OVERLAY_PLAY_ENABLE:
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_overlay_play_enable(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
+ break;
+ case MSMFB_OVERLAY_BLT:
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_overlay_blt(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
+ break;
+ case MSMFB_OVERLAY_BLT_OFFSET:
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_overlay_blt_off(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
+ break;
+ case MSMFB_OVERLAY_3D:
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_overlay_3d(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
+ break;
+#endif
+ case MSMFB_BLIT:
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_blit(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
+
+ break;
+
+ /* Ioctl for setting ccs matrix from user space */
+ case MSMFB_SET_CCS_MATRIX:
+#ifndef CONFIG_FB_MSM_MDP40
+ ret = copy_from_user(&ccs_matrix, argp, sizeof(ccs_matrix));
+ if (ret) {
+ printk(KERN_ERR
+ "%s:MSMFB_SET_CCS_MATRIX ioctl failed \n",
+ __func__);
+ return ret;
+ }
+
+ down(&msm_fb_ioctl_ppp_sem);
+ if (ccs_matrix.direction == MDP_CCS_RGB2YUV)
+ mdp_ccs_rgb2yuv = ccs_matrix;
+ else
+ mdp_ccs_yuv2rgb = ccs_matrix;
+
+ msmfb_set_color_conv(&ccs_matrix) ;
+ up(&msm_fb_ioctl_ppp_sem);
+#else
+ ret = -EINVAL;
+#endif
+
+ break;
+
+ /* Ioctl for getting ccs matrix to user space */
+ case MSMFB_GET_CCS_MATRIX:
+#ifndef CONFIG_FB_MSM_MDP40
+ ret = copy_from_user(&ccs_matrix, argp, sizeof(ccs_matrix)) ;
+ if (ret) {
+ printk(KERN_ERR
+ "%s:MSMFB_GET_CCS_MATRIX ioctl failed \n",
+ __func__);
+ return ret;
+ }
+
+ down(&msm_fb_ioctl_ppp_sem);
+ if (ccs_matrix.direction == MDP_CCS_RGB2YUV)
+ ccs_matrix = mdp_ccs_rgb2yuv;
+ else
+ ccs_matrix = mdp_ccs_yuv2rgb;
+
+ ret = copy_to_user(argp, &ccs_matrix, sizeof(ccs_matrix));
+
+ if (ret) {
+ printk(KERN_ERR
+ "%s:MSMFB_GET_CCS_MATRIX ioctl failed \n",
+ __func__);
+ return ret ;
+ }
+ up(&msm_fb_ioctl_ppp_sem);
+#else
+ ret = -EINVAL;
+#endif
+
+ break;
+
+ case MSMFB_GRP_DISP:
+#ifdef CONFIG_FB_MSM_MDP22
+ {
+ unsigned long grp_id;
+
+ ret = copy_from_user(&grp_id, argp, sizeof(grp_id));
+ if (ret)
+ return ret;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ writel(grp_id, MDP_FULL_BYPASS_WORD43);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF,
+ FALSE);
+ break;
+ }
+#else
+ return -EFAULT;
+#endif
+ case MSMFB_SUSPEND_SW_REFRESHER:
+ if (!mfd->panel_power_on)
+ return -EPERM;
+
+ mfd->sw_refreshing_enable = FALSE;
+ ret = msm_fb_stop_sw_refresher(mfd);
+ break;
+
+ case MSMFB_RESUME_SW_REFRESHER:
+ if (!mfd->panel_power_on)
+ return -EPERM;
+
+ mfd->sw_refreshing_enable = TRUE;
+ ret = msm_fb_resume_sw_refresher(mfd);
+ break;
+
+ case MSMFB_CURSOR:
+ ret = copy_from_user(&cursor, argp, sizeof(cursor));
+ if (ret)
+ return ret;
+
+ ret = msm_fb_cursor(info, &cursor);
+ break;
+
+ case MSMFB_SET_LUT:
+ ret = copy_from_user(&cmap, argp, sizeof(cmap));
+ if (ret)
+ return ret;
+
+ mutex_lock(&msm_fb_ioctl_lut_sem);
+ ret = msm_fb_set_lut(&cmap, info);
+ mutex_unlock(&msm_fb_ioctl_lut_sem);
+ break;
+
+ case MSMFB_HISTOGRAM:
+ if (!mfd->do_histogram)
+ return -ENODEV;
+
+ ret = copy_from_user(&hist, argp, sizeof(hist));
+ if (ret)
+ return ret;
+
+ mutex_lock(&msm_fb_ioctl_hist_sem);
+ ret = mfd->do_histogram(info, &hist);
+ mutex_unlock(&msm_fb_ioctl_hist_sem);
+ break;
+
+ case MSMFB_HISTOGRAM_START:
+ if (!mfd->do_histogram)
+ return -ENODEV;
+ ret = mdp_start_histogram(info);
+ break;
+
+ case MSMFB_HISTOGRAM_STOP:
+ if (!mfd->do_histogram)
+ return -ENODEV;
+ ret = mdp_stop_histogram(info);
+ break;
+
+
+ case MSMFB_GET_PAGE_PROTECTION:
+ fb_page_protection.page_protection
+ = mfd->mdp_fb_page_protection;
+ ret = copy_to_user(argp, &fb_page_protection,
+ sizeof(fb_page_protection));
+ if (ret)
+ return ret;
+ break;
+
+ case MSMFB_NOTIFY_UPDATE:
+ ret = msmfb_notify_update(info, argp);
+ break;
+
+ case MSMFB_SET_PAGE_PROTECTION:
+#if defined CONFIG_ARCH_QSD8X50 || defined CONFIG_ARCH_MSM8X60
+ ret = copy_from_user(&fb_page_protection, argp,
+ sizeof(fb_page_protection));
+ if (ret)
+ return ret;
+
+ /* Validate the proposed page protection settings. */
+ switch (fb_page_protection.page_protection) {
+ case MDP_FB_PAGE_PROTECTION_NONCACHED:
+ case MDP_FB_PAGE_PROTECTION_WRITECOMBINE:
+ case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE:
+ /* Write-back cache (read allocate) */
+ case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE:
+ /* Write-back cache (write allocate) */
+ case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE:
+ mfd->mdp_fb_page_protection =
+ fb_page_protection.page_protection;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+#else
+ /*
+ * Don't allow caching until 7k DMA cache operations are
+ * available.
+ */
+ ret = -EINVAL;
+#endif
+ break;
+
+ default:
+ MSM_FB_INFO("MDP: unknown ioctl (cmd=%x) received!\n", cmd);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int msm_fb_register_driver(void)
+{
+ return platform_driver_register(&msm_fb_driver);
+}
+
+struct platform_device *msm_fb_add_device(struct platform_device *pdev)
+{
+ struct msm_fb_panel_data *pdata;
+ struct platform_device *this_dev = NULL;
+ struct fb_info *fbi;
+ struct msm_fb_data_type *mfd = NULL;
+ u32 type, id, fb_num;
+
+ if (!pdev)
+ return NULL;
+ id = pdev->id;
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata)
+ return NULL;
+ type = pdata->panel_info.type;
+
+#if defined MSM_FB_NUM
+ /*
+ * over written fb_num which defined
+ * at panel_info
+ *
+ */
+ if (type == HDMI_PANEL || type == DTV_PANEL || type == TV_PANEL)
+ pdata->panel_info.fb_num = 1;
+ else
+ pdata->panel_info.fb_num = MSM_FB_NUM;
+
+ MSM_FB_INFO("setting pdata->panel_info.fb_num to %d. type: %d\n",
+ pdata->panel_info.fb_num, type);
+#endif
+ fb_num = pdata->panel_info.fb_num;
+
+ if (fb_num <= 0)
+ return NULL;
+
+ if (fbi_list_index >= MAX_FBI_LIST) {
+ printk(KERN_ERR "msm_fb: no more framebuffer info list!\n");
+ return NULL;
+ }
+ /*
+ * alloc panel device data
+ */
+ this_dev = msm_fb_device_alloc(pdata, type, id);
+
+ if (!this_dev) {
+ printk(KERN_ERR
+ "%s: msm_fb_device_alloc failed!\n", __func__);
+ return NULL;
+ }
+
+ /*
+ * alloc framebuffer info + par data
+ */
+ fbi = framebuffer_alloc(sizeof(struct msm_fb_data_type), NULL);
+ if (fbi == NULL) {
+ platform_device_put(this_dev);
+ printk(KERN_ERR "msm_fb: can't alloca framebuffer info data!\n");
+ return NULL;
+ }
+
+ mfd = (struct msm_fb_data_type *)fbi->par;
+ mfd->key = MFD_KEY;
+ mfd->fbi = fbi;
+ mfd->panel.type = type;
+ mfd->panel.id = id;
+ mfd->fb_page = fb_num;
+ mfd->index = fbi_list_index;
+ mfd->mdp_fb_page_protection = MDP_FB_PAGE_PROTECTION_WRITECOMBINE;
+
+ /* link to the latest pdev */
+ mfd->pdev = this_dev;
+
+ mfd_list[mfd_list_index++] = mfd;
+ fbi_list[fbi_list_index++] = fbi;
+
+ /*
+ * set driver data
+ */
+ platform_set_drvdata(this_dev, mfd);
+
+ if (platform_device_add(this_dev)) {
+ printk(KERN_ERR "msm_fb: platform_device_add failed!\n");
+ platform_device_put(this_dev);
+ framebuffer_release(fbi);
+ fbi_list_index--;
+ return NULL;
+ }
+ return this_dev;
+}
+EXPORT_SYMBOL(msm_fb_add_device);
+
+int get_fb_phys_info(unsigned long *start, unsigned long *len, int fb_num)
+{
+ struct fb_info *info;
+
+ if (fb_num > MAX_FBI_LIST)
+ return -1;
+
+ info = fbi_list[fb_num];
+ if (!info)
+ return -1;
+
+ *start = info->fix.smem_start;
+ *len = info->fix.smem_len;
+ return 0;
+}
+EXPORT_SYMBOL(get_fb_phys_info);
+
+int __init msm_fb_init(void)
+{
+ int rc = -ENODEV;
+
+ if (msm_fb_register_driver())
+ return rc;
+
+#ifdef MSM_FB_ENABLE_DBGFS
+ {
+ struct dentry *root;
+
+ if ((root = msm_fb_get_debugfs_root()) != NULL) {
+ msm_fb_debugfs_file_create(root,
+ "msm_fb_msg_printing_level",
+ (u32 *) &msm_fb_msg_level);
+ msm_fb_debugfs_file_create(root,
+ "mddi_msg_printing_level",
+ (u32 *) &mddi_msg_level);
+ msm_fb_debugfs_file_create(root, "msm_fb_debug_enabled",
+ (u32 *) &msm_fb_debug_enabled);
+ }
+ }
+#endif
+
+ return 0;
+}
+
+module_init(msm_fb_init);
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
new file mode 100644
index 0000000..bdf32eb
--- /dev/null
+++ b/drivers/video/msm/msm_fb.h
@@ -0,0 +1,171 @@
+/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MSM_FB_H
+#define MSM_FB_H
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <mach/board.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <mach/memory.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/hrtimer.h>
+
+#include <linux/fb.h>
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+#include "msm_fb_panel.h"
+#include "mdp.h"
+
+#define MSM_FB_DEFAULT_PAGE_SIZE 2
+#define MFD_KEY 0x11161126
+#define MSM_FB_MAX_DEV_LIST 32
+
+struct disp_info_type_suspend {
+ boolean op_enable;
+ boolean sw_refreshing_enable;
+ boolean panel_power_on;
+};
+
+struct msm_fb_data_type {
+ __u32 key;
+ __u32 index;
+ __u32 ref_cnt;
+ __u32 fb_page;
+
+ panel_id_type panel;
+ struct msm_panel_info panel_info;
+
+ DISP_TARGET dest;
+ struct fb_info *fbi;
+
+ boolean op_enable;
+ uint32 fb_imgType;
+ boolean sw_currently_refreshing;
+ boolean sw_refreshing_enable;
+ boolean hw_refresh;
+#ifdef CONFIG_FB_MSM_OVERLAY
+ int overlay_play_enable;
+#endif
+
+ MDPIBUF ibuf;
+ boolean ibuf_flushed;
+ struct timer_list refresh_timer;
+ struct completion refresher_comp;
+
+ boolean pan_waiting;
+ struct completion pan_comp;
+
+ /* vsync */
+ boolean use_mdp_vsync;
+ __u32 vsync_gpio;
+ __u32 total_lcd_lines;
+ __u32 total_porch_lines;
+ __u32 lcd_ref_usec_time;
+ __u32 refresh_timer_duration;
+
+ struct hrtimer dma_hrtimer;
+
+ boolean panel_power_on;
+ struct work_struct dma_update_worker;
+ struct semaphore sem;
+
+ struct timer_list vsync_resync_timer;
+ boolean vsync_handler_pending;
+ struct work_struct vsync_resync_worker;
+
+ ktime_t last_vsync_timetick;
+
+ __u32 *vsync_width_boundary;
+
+ unsigned int pmem_id;
+ struct disp_info_type_suspend suspend;
+
+ __u32 channel_irq;
+
+ struct mdp_dma_data *dma;
+ void (*dma_fnc) (struct msm_fb_data_type *mfd);
+ int (*cursor_update) (struct fb_info *info,
+ struct fb_cursor *cursor);
+ int (*lut_update) (struct fb_info *info,
+ struct fb_cmap *cmap);
+ int (*do_histogram) (struct fb_info *info,
+ struct mdp_histogram *hist);
+ void *cursor_buf;
+ void *cursor_buf_phys;
+
+ void *cmd_port;
+ void *data_port;
+ void *data_port_phys;
+
+ __u32 bl_level;
+
+ struct platform_device *pdev;
+
+ __u32 var_xres;
+ __u32 var_yres;
+ __u32 var_pixclock;
+
+#ifdef MSM_FB_ENABLE_DBGFS
+ struct dentry *sub_dir;
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#ifdef CONFIG_FB_MSM_MDDI
+ struct early_suspend mddi_early_suspend;
+ struct early_suspend mddi_ext_early_suspend;
+#endif
+#endif
+ u32 mdp_fb_page_protection;
+
+ struct clk *ebi1_clk;
+ boolean dma_update_flag;
+ struct timer_list msmfb_no_update_notify_timer;
+ struct completion msmfb_update_notify;
+ struct completion msmfb_no_update_notify;
+};
+
+struct dentry *msm_fb_get_debugfs_root(void);
+void msm_fb_debugfs_file_create(struct dentry *root, const char *name,
+ u32 *var);
+void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl);
+
+struct platform_device *msm_fb_add_device(struct platform_device *pdev);
+
+int msm_fb_detect_client(const char *name);
+
+#ifdef CONFIG_FB_BACKLIGHT
+void msm_fb_config_backlight(struct msm_fb_data_type *mfd);
+#endif
+
+void fill_black_screen(void);
+void unfill_black_screen(void);
+
+#endif /* MSM_FB_H */
diff --git a/drivers/video/msm/msm_fb_bl.c b/drivers/video/msm/msm_fb_bl.c
new file mode 100644
index 0000000..9afbbf1
--- /dev/null
+++ b/drivers/video/msm/msm_fb_bl.c
@@ -0,0 +1,75 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/backlight.h>
+
+#include "msm_fb.h"
+
+static int msm_fb_bl_get_brightness(struct backlight_device *pbd)
+{
+ return pbd->props.brightness;
+}
+
+static int msm_fb_bl_update_status(struct backlight_device *pbd)
+{
+ struct msm_fb_data_type *mfd = bl_get_data(pbd);
+ __u32 bl_lvl;
+
+ bl_lvl = pbd->props.brightness;
+ bl_lvl = mfd->fbi->bl_curve[bl_lvl];
+ msm_fb_set_backlight(mfd, bl_lvl);
+ return 0;
+}
+
+static struct backlight_ops msm_fb_bl_ops = {
+ .get_brightness = msm_fb_bl_get_brightness,
+ .update_status = msm_fb_bl_update_status,
+};
+
+void msm_fb_config_backlight(struct msm_fb_data_type *mfd)
+{
+ struct msm_fb_panel_data *pdata;
+ struct backlight_device *pbd;
+ struct fb_info *fbi;
+ char name[16];
+ struct backlight_properties props;
+
+ fbi = mfd->fbi;
+ pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+
+ if ((pdata) && (pdata->set_backlight)) {
+ snprintf(name, sizeof(name), "msmfb_bl%d", mfd->index);
+ props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+ props.brightness = FB_BACKLIGHT_LEVELS - 1;
+ pbd =
+ backlight_device_register(name, fbi->dev, mfd,
+ &msm_fb_bl_ops, &props);
+ if (!IS_ERR(pbd)) {
+ fbi->bl_dev = pbd;
+ fb_bl_default_curve(fbi,
+ 0,
+ mfd->panel_info.bl_min,
+ mfd->panel_info.bl_max);
+ } else {
+ fbi->bl_dev = NULL;
+ printk(KERN_ERR "msm_fb: backlight_device_register failed!\n");
+ }
+ }
+}
diff --git a/drivers/video/msm/msm_fb_def.h b/drivers/video/msm/msm_fb_def.h
new file mode 100644
index 0000000..1c1f392
--- /dev/null
+++ b/drivers/video/msm/msm_fb_def.h
@@ -0,0 +1,204 @@
+/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MSM_FB_DEF_H
+#define MSM_FB_DEF_H
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/msm_mdp.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
+#include <linux/debugfs.h>
+#include <linux/console.h>
+#include <linux/android_pmem.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+#include <linux/io.h>
+#include <linux/fb.h>
+#include <linux/platform_device.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+#include <mach/hardware.h>
+
+
+typedef s64 int64;
+typedef s32 int32;
+typedef s16 int16;
+typedef s8 int8;
+
+typedef u64 uint64;
+typedef u32 uint32;
+typedef u16 uint16;
+typedef u8 uint8;
+
+typedef s32 int4;
+typedef s16 int2;
+typedef s8 int1;
+
+typedef u32 uint4;
+typedef u16 uint2;
+typedef u8 uint1;
+
+typedef u32 dword;
+typedef u16 word;
+typedef u8 byte;
+
+typedef unsigned int boolean;
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define MSM_FB_ENABLE_DBGFS
+#define FEATURE_MDDI
+
+#if defined(CONFIG_FB_MSM_DEFAULT_DEPTH_RGB565)
+#define MSMFB_DEFAULT_TYPE MDP_RGB_565
+#elif defined(CONFIG_FB_MSM_DEFAULT_DEPTH_ARGB8888)
+#define MSMFB_DEFAULT_TYPE MDP_ARGB_8888
+#elif defined(CONFIG_FB_MSM_DEFAULT_DEPTH_RGBA8888)
+#define MSMFB_DEFAULT_TYPE MDP_RGBA_8888
+#else
+#define MSMFB_DEFAULT_TYPE MDP_RGB_565
+#endif
+
+#define outp32(addr, val) writel(val, addr)
+#define outp16(addr, val) writew(val, addr)
+#define outp8(addr, val) writeb(val, addr)
+#define outp(addr, val) outp32(addr, val)
+
+#ifndef MAX
+#define MAX( x, y ) (((x) > (y)) ? (x) : (y))
+#endif
+
+#ifndef MIN
+#define MIN( x, y ) (((x) < (y)) ? (x) : (y))
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+#define inp32(addr) readl(addr)
+#define inp16(addr) readw(addr)
+#define inp8(addr) readb(addr)
+#define inp(addr) inp32(addr)
+
+#define inpw(port) readw(port)
+#define outpw(port, val) writew(val, port)
+#define inpdw(port) readl(port)
+#define outpdw(port, val) writel(val, port)
+
+
+#define clk_busy_wait(x) msleep_interruptible((x)/1000)
+
+#define memory_barrier()
+
+#define assert(expr) \
+ if(!(expr)) { \
+ printk(KERN_ERR "msm_fb: assertion failed! %s,%s,%s,line=%d\n",\
+ #expr, __FILE__, __func__, __LINE__); \
+ }
+
+#define ASSERT(x) assert(x)
+
+#define DISP_EBI2_LOCAL_DEFINE
+#ifdef DISP_EBI2_LOCAL_DEFINE
+#define LCD_PRIM_BASE_PHYS 0x98000000
+#define LCD_SECD_BASE_PHYS 0x9c000000
+#define EBI2_PRIM_LCD_RS_PIN 0x20000
+#define EBI2_SECD_LCD_RS_PIN 0x20000
+
+#define EBI2_PRIM_LCD_CLR 0xC0
+#define EBI2_PRIM_LCD_SEL 0x40
+
+#define EBI2_SECD_LCD_CLR 0x300
+#define EBI2_SECD_LCD_SEL 0x100
+#endif
+
+extern u32 msm_fb_msg_level;
+
+/*
+ * Message printing priorities:
+ * LEVEL 0 KERN_EMERG (highest priority)
+ * LEVEL 1 KERN_ALERT
+ * LEVEL 2 KERN_CRIT
+ * LEVEL 3 KERN_ERR
+ * LEVEL 4 KERN_WARNING
+ * LEVEL 5 KERN_NOTICE
+ * LEVEL 6 KERN_INFO
+ * LEVEL 7 KERN_DEBUG (Lowest priority)
+ */
+#define MSM_FB_EMERG(msg, ...) \
+ if (msm_fb_msg_level > 0) \
+ printk(KERN_EMERG msg, ## __VA_ARGS__);
+#define MSM_FB_ALERT(msg, ...) \
+ if (msm_fb_msg_level > 1) \
+ printk(KERN_ALERT msg, ## __VA_ARGS__);
+#define MSM_FB_CRIT(msg, ...) \
+ if (msm_fb_msg_level > 2) \
+ printk(KERN_CRIT msg, ## __VA_ARGS__);
+#define MSM_FB_ERR(msg, ...) \
+ if (msm_fb_msg_level > 3) \
+ printk(KERN_ERR msg, ## __VA_ARGS__);
+#define MSM_FB_WARNING(msg, ...) \
+ if (msm_fb_msg_level > 4) \
+ printk(KERN_WARNING msg, ## __VA_ARGS__);
+#define MSM_FB_NOTICE(msg, ...) \
+ if (msm_fb_msg_level > 5) \
+ printk(KERN_NOTICE msg, ## __VA_ARGS__);
+#define MSM_FB_INFO(msg, ...) \
+ if (msm_fb_msg_level > 6) \
+ printk(KERN_INFO msg, ## __VA_ARGS__);
+#define MSM_FB_DEBUG(msg, ...) \
+ if (msm_fb_msg_level > 7) \
+ printk(KERN_DEBUG msg, ## __VA_ARGS__);
+
+#ifdef MSM_FB_C
+unsigned char *msm_mdp_base;
+unsigned char *msm_pmdh_base;
+unsigned char *msm_emdh_base;
+unsigned char *mipi_dsi_base;
+#else
+extern unsigned char *msm_mdp_base;
+extern unsigned char *msm_pmdh_base;
+extern unsigned char *msm_emdh_base;
+extern unsigned char *mipi_dsi_base;
+#endif
+
+#undef ENABLE_MDDI_MULTI_READ_WRITE
+#undef ENABLE_FWD_LINK_SKEW_CALIBRATION
+
+#endif /* MSM_FB_DEF_H */
diff --git a/drivers/video/msm/msm_fb_panel.c b/drivers/video/msm/msm_fb_panel.c
new file mode 100644
index 0000000..84de095
--- /dev/null
+++ b/drivers/video/msm/msm_fb_panel.c
@@ -0,0 +1,141 @@
+/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
+#include <linux/debugfs.h>
+
+#include "msm_fb_panel.h"
+
+int panel_next_on(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct msm_fb_panel_data *pdata;
+ struct msm_fb_panel_data *next_pdata;
+ struct platform_device *next_pdev;
+
+ pdata = (struct msm_fb_panel_data *)pdev->dev.platform_data;
+
+ if (pdata) {
+ next_pdev = pdata->next;
+ if (next_pdev) {
+ next_pdata =
+ (struct msm_fb_panel_data *)next_pdev->dev.
+ platform_data;
+ if ((next_pdata) && (next_pdata->on))
+ ret = next_pdata->on(next_pdev);
+ }
+ }
+
+ return ret;
+}
+
+int panel_next_off(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct msm_fb_panel_data *pdata;
+ struct msm_fb_panel_data *next_pdata;
+ struct platform_device *next_pdev;
+
+ pdata = (struct msm_fb_panel_data *)pdev->dev.platform_data;
+
+ if (pdata) {
+ next_pdev = pdata->next;
+ if (next_pdev) {
+ next_pdata =
+ (struct msm_fb_panel_data *)next_pdev->dev.
+ platform_data;
+ if ((next_pdata) && (next_pdata->on))
+ ret = next_pdata->off(next_pdev);
+ }
+ }
+
+ return ret;
+}
+
+struct platform_device *msm_fb_device_alloc(struct msm_fb_panel_data *pdata,
+ u32 type, u32 id)
+{
+ struct platform_device *this_dev = NULL;
+ char dev_name[16];
+
+ switch (type) {
+ case EBI2_PANEL:
+ snprintf(dev_name, sizeof(dev_name), "ebi2_lcd");
+ break;
+
+ case MDDI_PANEL:
+ snprintf(dev_name, sizeof(dev_name), "mddi");
+ break;
+
+ case EXT_MDDI_PANEL:
+ snprintf(dev_name, sizeof(dev_name), "mddi_ext");
+ break;
+
+ case TV_PANEL:
+ snprintf(dev_name, sizeof(dev_name), "tvenc");
+ break;
+
+ case HDMI_PANEL:
+ case LCDC_PANEL:
+ snprintf(dev_name, sizeof(dev_name), "lcdc");
+ break;
+
+ case DTV_PANEL:
+ snprintf(dev_name, sizeof(dev_name), "dtv");
+ break;
+
+ case MIPI_VIDEO_PANEL:
+ case MIPI_CMD_PANEL:
+ snprintf(dev_name, sizeof(dev_name), "mipi_dsi");
+ break;
+
+ default:
+ return NULL;
+ }
+
+ if (pdata != NULL)
+ pdata->next = NULL;
+ else
+ return NULL;
+
+ this_dev =
+ platform_device_alloc(dev_name, ((u32) type << 16) | (u32) id);
+
+ if (this_dev) {
+ if (platform_device_add_data
+ (this_dev, pdata, sizeof(struct msm_fb_panel_data))) {
+ printk
+ ("msm_fb_device_alloc: platform_device_add_data failed!\n");
+ platform_device_put(this_dev);
+ return NULL;
+ }
+ }
+
+ return this_dev;
+}
diff --git a/drivers/video/msm/msm_fb_panel.h b/drivers/video/msm/msm_fb_panel.h
new file mode 100644
index 0000000..bbf5a38
--- /dev/null
+++ b/drivers/video/msm/msm_fb_panel.h
@@ -0,0 +1,199 @@
+/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MSM_FB_PANEL_H
+#define MSM_FB_PANEL_H
+
+#include "msm_fb_def.h"
+
+struct msm_fb_data_type;
+
+typedef void (*msm_fb_vsync_handler_type) (void *arg);
+
+/* panel id type */
+typedef struct panel_id_s {
+ uint16 id;
+ uint16 type;
+} panel_id_type;
+
+/* panel type list */
+#define NO_PANEL 0xffff /* No Panel */
+#define MDDI_PANEL 1 /* MDDI */
+#define EBI2_PANEL 2 /* EBI2 */
+#define LCDC_PANEL 3 /* internal LCDC type */
+#define EXT_MDDI_PANEL 4 /* Ext.MDDI */
+#define TV_PANEL 5 /* TV */
+#define HDMI_PANEL 6 /* HDMI TV */
+#define DTV_PANEL 7 /* DTV */
+#define MIPI_VIDEO_PANEL 8 /* MIPI */
+#define MIPI_CMD_PANEL 9 /* MIPI */
+
+/* panel class */
+typedef enum {
+ DISPLAY_LCD = 0, /* lcd = ebi2/mddi */
+ DISPLAY_LCDC, /* lcdc */
+ DISPLAY_TV, /* TV Out */
+ DISPLAY_EXT_MDDI, /* External MDDI */
+} DISP_TARGET;
+
+/* panel device locaiton */
+typedef enum {
+ DISPLAY_1 = 0, /* attached as first device */
+ DISPLAY_2, /* attached on second device */
+ MAX_PHYS_TARGET_NUM,
+} DISP_TARGET_PHYS;
+
+/* panel info type */
+struct lcd_panel_info {
+ __u32 vsync_enable;
+ __u32 refx100;
+ __u32 v_back_porch;
+ __u32 v_front_porch;
+ __u32 v_pulse_width;
+ __u32 hw_vsync_mode;
+ __u32 vsync_notifier_period;
+ __u32 rev;
+};
+
+struct lcdc_panel_info {
+ __u32 h_back_porch;
+ __u32 h_front_porch;
+ __u32 h_pulse_width;
+ __u32 v_back_porch;
+ __u32 v_front_porch;
+ __u32 v_pulse_width;
+ __u32 border_clr;
+ __u32 underflow_clr;
+ __u32 hsync_skew;
+};
+
+struct mddi_panel_info {
+ __u32 vdopkt;
+};
+
+/* DSI PHY configuration */
+struct mipi_dsi_phy_ctrl {
+ uint32 regulator[5];
+ uint32 timing[12];
+ uint32 ctrl[4];
+ uint32 strength[4];
+ uint32 pll[21];
+};
+
+struct mipi_panel_info {
+ char mode; /* video/cmd */
+ char interleave_mode;
+ char crc_check;
+ char ecc_check;
+ char dst_format; /* shared by video and command */
+ char data_lane0;
+ char data_lane1;
+ char data_lane2;
+ char data_lane3;
+ char dlane_swap; /* data lane swap */
+ char rgb_swap;
+ char b_sel;
+ char g_sel;
+ char r_sel;
+ char rx_eot_ignore;
+ char tx_eot_append;
+ char t_clk_post; /* 0xc0, DSI_CLKOUT_TIMING_CTRL */
+ char t_clk_pre; /* 0xc0, DSI_CLKOUT_TIMING_CTRL */
+ char vc; /* virtual channel */
+ struct mipi_dsi_phy_ctrl *dsi_phy_db;
+ /* video mode */
+ char pulse_mode_hsa_he;
+ char hfp_power_stop;
+ char hbp_power_stop;
+ char hsa_power_stop;
+ char eof_bllp_power_stop;
+ char bllp_power_stop;
+ char traffic_mode;
+ char frame_rate;
+ /* command mode */
+ char interleave_max;
+ char insert_dcs_cmd;
+ char wr_mem_continue;
+ char wr_mem_start;
+ char te_sel;
+ char stream; /* 0 or 1 */
+ char mdp_trigger;
+ char dma_trigger;
+ uint32 dsi_pclk_rate;
+ /* Pad width */
+ uint32 xres_pad;
+ /* Pad height */
+ uint32 yres_pad;
+};
+
+struct msm_panel_info {
+ __u32 xres;
+ __u32 yres;
+ __u32 bpp;
+ __u32 mode2_xres;
+ __u32 mode2_yres;
+ __u32 mode2_bpp;
+ __u32 type;
+ __u32 wait_cycle;
+ DISP_TARGET_PHYS pdest;
+ __u32 bl_max;
+ __u32 bl_min;
+ __u32 fb_num;
+ __u32 clk_rate;
+ __u32 clk_min;
+ __u32 clk_max;
+ __u32 frame_count;
+ __u32 is_3d_panel;
+
+
+ struct mddi_panel_info mddi;
+ struct lcd_panel_info lcd;
+ struct lcdc_panel_info lcdc;
+
+ struct mipi_panel_info mipi;
+};
+
+#define MSM_FB_SINGLE_MODE_PANEL(pinfo) \
+ do { \
+ (pinfo)->mode2_xres = 0; \
+ (pinfo)->mode2_yres = 0; \
+ (pinfo)->mode2_bpp = 0; \
+ } while (0)
+
+struct msm_fb_panel_data {
+ struct msm_panel_info panel_info;
+ void (*set_rect) (int x, int y, int xres, int yres);
+ void (*set_vsync_notifier) (msm_fb_vsync_handler_type, void *arg);
+ void (*set_backlight) (struct msm_fb_data_type *);
+
+ /* function entry chain */
+ int (*on) (struct platform_device *pdev);
+ int (*off) (struct platform_device *pdev);
+ struct platform_device *next;
+ int (*clk_func) (int enable);
+};
+
+/*===========================================================================
+ FUNCTIONS PROTOTYPES
+============================================================================*/
+struct platform_device *msm_fb_device_alloc(struct msm_fb_panel_data *pdata,
+ u32 type, u32 id);
+int panel_next_on(struct platform_device *pdev);
+int panel_next_off(struct platform_device *pdev);
+
+int lcdc_device_register(struct msm_panel_info *pinfo);
+
+int mddi_toshiba_device_register(struct msm_panel_info *pinfo,
+ u32 channel, u32 panel);
+
+#endif /* MSM_FB_PANEL_H */
diff --git a/drivers/video/msm/tvenc.c b/drivers/video/msm/tvenc.c
new file mode 100644
index 0000000..73e2428
--- /dev/null
+++ b/drivers/video/msm/tvenc.c
@@ -0,0 +1,521 @@
+/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <mach/msm_reqs.h>
+
+#define TVENC_C
+#include "tvenc.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+#ifdef CONFIG_MSM_NPA_SYSTEM_BUS
+/* NPA Flow ID */
+#define MSM_SYSTEM_BUS_RATE MSM_AXI_FLOW_MDP_DTV_720P_2BPP
+#else
+/* AXI rate in KHz */
+#define MSM_SYSTEM_BUS_RATE 128000000
+#endif
+
+static int tvenc_probe(struct platform_device *pdev);
+static int tvenc_remove(struct platform_device *pdev);
+
+static int tvenc_off(struct platform_device *pdev);
+static int tvenc_on(struct platform_device *pdev);
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+
+static struct clk *tvenc_clk;
+static struct clk *tvdac_clk;
+static struct clk *tvenc_pclk;
+static struct clk *mdp_tv_clk;
+#ifdef CONFIG_FB_MSM_MDP40
+static struct clk *tv_src_clk;
+#endif
+
+#ifdef CONFIG_MSM_BUS_SCALING
+static uint32_t tvenc_bus_scale_handle;
+#endif
+
+static int tvenc_runtime_suspend(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: suspending...\n");
+ return 0;
+}
+
+static int tvenc_runtime_resume(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: resuming...\n");
+ return 0;
+}
+
+static struct dev_pm_ops tvenc_dev_pm_ops = {
+ .runtime_suspend = tvenc_runtime_suspend,
+ .runtime_resume = tvenc_runtime_resume,
+};
+
+static struct platform_driver tvenc_driver = {
+ .probe = tvenc_probe,
+ .remove = tvenc_remove,
+ .suspend = NULL,
+ .resume = NULL,
+ .shutdown = NULL,
+ .driver = {
+ .name = "tvenc",
+ .pm = &tvenc_dev_pm_ops
+ },
+};
+
+int tvenc_set_encoder_clock(boolean clock_on)
+{
+ int ret = 0;
+ if (clock_on) {
+#ifdef CONFIG_FB_MSM_MDP40
+ /* Consolidated clock used by both HDMI & TV encoder.
+ Clock exists only in MDP4 and not in older versions */
+ ret = clk_set_rate(tv_src_clk, 27000000);
+ if (ret) {
+ pr_err("%s: tvsrc_clk set rate failed! %d\n",
+ __func__, ret);
+ goto tvsrc_err;
+ }
+#endif
+ ret = clk_enable(tvenc_clk);
+ if (ret) {
+ pr_err("%s: tvenc_clk enable failed! %d\n",
+ __func__, ret);
+ goto tvsrc_err;
+ }
+
+ if (!IS_ERR(tvenc_pclk)) {
+ ret = clk_enable(tvenc_pclk);
+ if (ret) {
+ pr_err("%s: tvenc_pclk enable failed! %d\n",
+ __func__, ret);
+ goto tvencp_err;
+ }
+ }
+ return ret;
+ } else {
+ if (!IS_ERR(tvenc_pclk))
+ clk_disable(tvenc_pclk);
+ clk_disable(tvenc_clk);
+ return ret;
+ }
+tvencp_err:
+ clk_disable(tvenc_clk);
+tvsrc_err:
+ return ret;
+}
+
+int tvenc_set_clock(boolean clock_on)
+{
+ int ret = 0;
+ if (clock_on) {
+ if (tvenc_pdata->poll) {
+ ret = tvenc_set_encoder_clock(CLOCK_ON);
+ if (ret) {
+ pr_err("%s: TVenc clock(s) enable failed! %d\n",
+ __func__, ret);
+ goto tvenc_err;
+ }
+ }
+ ret = clk_enable(tvdac_clk);
+ if (ret) {
+ pr_err("%s: tvdac_clk enable failed! %d\n",
+ __func__, ret);
+ goto tvdac_err;
+ }
+ if (!IS_ERR(mdp_tv_clk)) {
+ ret = clk_enable(mdp_tv_clk);
+ if (ret) {
+ pr_err("%s: mdp_tv_clk enable failed! %d\n",
+ __func__, ret);
+ goto mdptv_err;
+ }
+ }
+ return ret;
+ } else {
+ if (!IS_ERR(mdp_tv_clk))
+ clk_disable(mdp_tv_clk);
+ clk_disable(tvdac_clk);
+ if (tvenc_pdata->poll)
+ tvenc_set_encoder_clock(CLOCK_OFF);
+ return ret;
+ }
+
+mdptv_err:
+ clk_disable(tvdac_clk);
+tvdac_err:
+ tvenc_set_encoder_clock(CLOCK_OFF);
+tvenc_err:
+ return ret;
+}
+
+static int tvenc_off(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ struct msm_fb_data_type *mfd;
+
+ mfd = platform_get_drvdata(pdev);
+
+ ret = panel_next_off(pdev);
+ if (ret)
+ pr_err("%s: tvout_off failed! %d\n",
+ __func__, ret);
+
+ tvenc_set_clock(CLOCK_OFF);
+
+ if (tvenc_pdata && tvenc_pdata->pm_vid_en)
+ ret = tvenc_pdata->pm_vid_en(0);
+#ifdef CONFIG_MSM_BUS_SCALING
+ if (tvenc_bus_scale_handle > 0)
+ msm_bus_scale_client_update_request(tvenc_bus_scale_handle,
+ 0);
+#else
+ if (mfd->ebi1_clk)
+ clk_disable(mfd->ebi1_clk);
+#endif
+
+ if (ret)
+ pr_err("%s: pm_vid_en(off) failed! %d\n",
+ __func__, ret);
+ mdp4_extn_disp = 0;
+ return ret;
+}
+
+static int tvenc_on(struct platform_device *pdev)
+{
+ int ret = 0;
+
+#ifndef CONFIG_MSM_BUS_SCALING
+ struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
+#endif
+
+#ifdef CONFIG_MSM_BUS_SCALING
+ if (tvenc_bus_scale_handle > 0)
+ msm_bus_scale_client_update_request(tvenc_bus_scale_handle,
+ 1);
+#else
+ if (mfd->ebi1_clk)
+ clk_enable(mfd->ebi1_clk);
+#endif
+ mdp_set_core_clk(1);
+ mdp4_extn_disp = 1;
+ if (tvenc_pdata && tvenc_pdata->pm_vid_en)
+ ret = tvenc_pdata->pm_vid_en(1);
+ if (ret) {
+ pr_err("%s: pm_vid_en(on) failed! %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ ret = tvenc_set_clock(CLOCK_ON);
+ if (ret) {
+ pr_err("%s: tvenc_set_clock(CLOCK_ON) failed! %d\n",
+ __func__, ret);
+ tvenc_pdata->pm_vid_en(0);
+ goto error;
+ }
+
+ ret = panel_next_on(pdev);
+ if (ret) {
+ pr_err("%s: tvout_on failed! %d\n",
+ __func__, ret);
+ tvenc_set_clock(CLOCK_OFF);
+ tvenc_pdata->pm_vid_en(0);
+ }
+
+error:
+ return ret;
+
+}
+
+void tvenc_gen_test_pattern(struct msm_fb_data_type *mfd)
+{
+ uint32 reg = 0, i;
+
+ reg = readl(MSM_TV_ENC_CTL);
+ reg |= TVENC_CTL_TEST_PATT_EN;
+
+ for (i = 0; i < 3; i++) {
+ TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */
+
+ switch (i) {
+ /*
+ * TV Encoder - Color Bar Test Pattern
+ */
+ case 0:
+ reg |= TVENC_CTL_TPG_CLRBAR;
+ break;
+ /*
+ * TV Encoder - Red Frame Test Pattern
+ */
+ case 1:
+ reg |= TVENC_CTL_TPG_REDCLR;
+ break;
+ /*
+ * TV Encoder - Modulated Ramp Test Pattern
+ */
+ default:
+ reg |= TVENC_CTL_TPG_MODRAMP;
+ break;
+ }
+
+ TV_OUT(TV_ENC_CTL, reg);
+ mdelay(5000);
+
+ switch (i) {
+ /*
+ * TV Encoder - Color Bar Test Pattern
+ */
+ case 0:
+ reg &= ~TVENC_CTL_TPG_CLRBAR;
+ break;
+ /*
+ * TV Encoder - Red Frame Test Pattern
+ */
+ case 1:
+ reg &= ~TVENC_CTL_TPG_REDCLR;
+ break;
+ /*
+ * TV Encoder - Modulated Ramp Test Pattern
+ */
+ default:
+ reg &= ~TVENC_CTL_TPG_MODRAMP;
+ break;
+ }
+ }
+}
+
+static int tvenc_resource_initialized;
+
+static int tvenc_probe(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct platform_device *mdp_dev = NULL;
+ struct msm_fb_panel_data *pdata = NULL;
+ int rc;
+
+ if (pdev->id == 0) {
+ tvenc_base = ioremap(pdev->resource[0].start,
+ pdev->resource[0].end -
+ pdev->resource[0].start + 1);
+ if (!tvenc_base) {
+ pr_err("tvenc_base ioremap failed!\n");
+ return -ENOMEM;
+ }
+ tvenc_pdata = pdev->dev.platform_data;
+ tvenc_resource_initialized = 1;
+ return 0;
+ }
+
+ if (!tvenc_resource_initialized)
+ return -EPERM;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+ return -ENOMEM;
+
+ if (tvenc_base == NULL)
+ return -ENOMEM;
+
+ mdp_dev = platform_device_alloc("mdp", pdev->id);
+ if (!mdp_dev)
+ return -ENOMEM;
+
+ /*
+ * link to the latest pdev
+ */
+ mfd->pdev = mdp_dev;
+ mfd->dest = DISPLAY_TV;
+
+ /*
+ * alloc panel device data
+ */
+ if (platform_device_add_data
+ (mdp_dev, pdev->dev.platform_data,
+ sizeof(struct msm_fb_panel_data))) {
+ pr_err("tvenc_probe: platform_device_add_data failed!\n");
+ platform_device_put(mdp_dev);
+ return -ENOMEM;
+ }
+ /*
+ * data chain
+ */
+ pdata = mdp_dev->dev.platform_data;
+ pdata->on = tvenc_on;
+ pdata->off = tvenc_off;
+ pdata->next = pdev;
+
+ /*
+ * get/set panel specific fb info
+ */
+ mfd->panel_info = pdata->panel_info;
+#ifdef CONFIG_FB_MSM_MDP40
+ mfd->fb_imgType = MDP_RGB_565; /* base layer */
+#else
+ mfd->fb_imgType = MDP_YCRYCB_H2V1;
+#endif
+
+#ifdef CONFIG_MSM_BUS_SCALING
+ if (!tvenc_bus_scale_handle && tvenc_pdata &&
+ tvenc_pdata->bus_scale_table) {
+ tvenc_bus_scale_handle =
+ msm_bus_scale_register_client(
+ tvenc_pdata->bus_scale_table);
+ if (!tvenc_bus_scale_handle) {
+ printk(KERN_ERR "%s not able to get bus scale\n",
+ __func__);
+ }
+ }
+#else
+ mfd->ebi1_clk = clk_get(NULL, "ebi1_tv_clk");
+ if (IS_ERR(mfd->ebi1_clk)) {
+ rc = PTR_ERR(mfd->ebi1_clk);
+ goto tvenc_probe_err;
+ }
+ clk_set_rate(mfd->ebi1_clk, MSM_SYSTEM_BUS_RATE);
+#endif
+
+ /*
+ * set driver data
+ */
+ platform_set_drvdata(mdp_dev, mfd);
+
+ /*
+ * register in mdp driver
+ */
+ rc = platform_device_add(mdp_dev);
+ if (rc)
+ goto tvenc_probe_err;
+
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+
+
+ pdev_list[pdev_list_cnt++] = pdev;
+
+ return 0;
+
+tvenc_probe_err:
+#ifdef CONFIG_MSM_BUS_SCALING
+ if (tvenc_pdata && tvenc_pdata->bus_scale_table &&
+ tvenc_bus_scale_handle > 0) {
+ msm_bus_scale_unregister_client(tvenc_bus_scale_handle);
+ tvenc_bus_scale_handle = 0;
+ }
+#endif
+ platform_device_put(mdp_dev);
+ return rc;
+}
+
+static int tvenc_remove(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+
+ mfd = platform_get_drvdata(pdev);
+
+#ifdef CONFIG_MSM_BUS_SCALING
+ if (tvenc_pdata && tvenc_pdata->bus_scale_table &&
+ tvenc_bus_scale_handle > 0) {
+ msm_bus_scale_unregister_client(tvenc_bus_scale_handle);
+ tvenc_bus_scale_handle = 0;
+ }
+#else
+ clk_put(mfd->ebi1_clk);
+#endif
+
+ pm_runtime_disable(&pdev->dev);
+ return 0;
+}
+
+static int tvenc_register_driver(void)
+{
+ return platform_driver_register(&tvenc_driver);
+}
+
+static int __init tvenc_driver_init(void)
+{
+ int ret;
+ tvenc_clk = clk_get(NULL, "tv_enc_clk");
+ tvdac_clk = clk_get(NULL, "tv_dac_clk");
+ tvenc_pclk = clk_get(NULL, "tv_enc_pclk");
+ mdp_tv_clk = clk_get(NULL, "mdp_tv_clk");
+
+#ifdef CONFIG_FB_MSM_MDP40
+ tv_src_clk = clk_get(NULL, "tv_src_clk");
+ if (IS_ERR(tv_src_clk))
+ tv_src_clk = tvenc_clk; /* Fallback to slave */
+#endif
+
+ if (IS_ERR(tvenc_clk)) {
+ pr_err("%s: error: can't get tvenc_clk!\n", __func__);
+ return PTR_ERR(tvenc_clk);
+ }
+
+ if (IS_ERR(tvdac_clk)) {
+ pr_err("%s: error: can't get tvdac_clk!\n", __func__);
+ return PTR_ERR(tvdac_clk);
+ }
+
+ if (IS_ERR(tvenc_pclk)) {
+ ret = PTR_ERR(tvenc_pclk);
+ if (-ENOENT == ret)
+ pr_info("%s: tvenc_pclk does not exist!\n", __func__);
+ else {
+ pr_err("%s: error: can't get tvenc_pclk!\n", __func__);
+ return ret;
+ }
+ }
+
+ if (IS_ERR(mdp_tv_clk)) {
+ ret = PTR_ERR(mdp_tv_clk);
+ if (-ENOENT == ret)
+ pr_info("%s: mdp_tv_clk does not exist!\n", __func__);
+ else {
+ pr_err("%s: error: can't get mdp_tv_clk!\n", __func__);
+ return ret;
+ }
+ }
+
+ return tvenc_register_driver();
+}
+
+module_init(tvenc_driver_init);
diff --git a/drivers/video/msm/tvenc.h b/drivers/video/msm/tvenc.h
new file mode 100644
index 0000000..c64c160
--- /dev/null
+++ b/drivers/video/msm/tvenc.h
@@ -0,0 +1,129 @@
+/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef TVENC_H
+#define TVENC_H
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+#include "msm_fb_panel.h"
+
+#define NTSC_M 0 /* North America, Korea */
+#define NTSC_J 1 /* Japan */
+#define PAL_BDGHIN 2 /* Non-argentina PAL-N */
+#define PAL_M 3 /* PAL-M */
+#define PAL_N 4 /* Argentina PAL-N */
+
+#define CLOCK_OFF 0
+#define CLOCK_ON 1
+
+/* 3.57954545 Mhz */
+#define TVENC_CTL_TV_MODE_NTSC_M_PAL60 0
+/* 3.57961149 Mhz */
+#define TVENC_CTL_TV_MODE_PAL_M BIT(0)
+/*non-Argintina = 4.3361875 Mhz */
+#define TVENC_CTL_TV_MODE_PAL_BDGHIN BIT(1)
+/*Argentina = 3.582055625 Mhz */
+#define TVENC_CTL_TV_MODE_PAL_N (BIT(1)|BIT(0))
+
+#define TVENC_CTL_ENC_EN BIT(2)
+#define TVENC_CTL_CC_EN BIT(3)
+#define TVENC_CTL_CGMS_EN BIT(4)
+#define TVENC_CTL_MACRO_EN BIT(5)
+#define TVENC_CTL_Y_FILTER_W_NOTCH BIT(6)
+#define TVENC_CTL_Y_FILTER_WO_NOTCH 0
+#define TVENC_CTL_Y_FILTER_EN BIT(7)
+#define TVENC_CTL_CR_FILTER_EN BIT(8)
+#define TVENC_CTL_CB_FILTER_EN BIT(9)
+#define TVENC_CTL_SINX_FILTER_EN BIT(10)
+#define TVENC_CTL_TEST_PATT_EN BIT(11)
+#define TVENC_CTL_OUTPUT_INV BIT(12)
+#define TVENC_CTL_PAL60_MODE BIT(13)
+#define TVENC_CTL_NTSCJ_MODE BIT(14)
+#define TVENC_CTL_S_VIDEO_EN BIT(19)
+
+
+#define TVENC_CTL_TPG_CLRBAR 0
+#define TVENC_CTL_TPG_MODRAMP BIT(15)
+#define TVENC_CTL_TPG_REDCLR BIT(16)
+#define TVENC_CTL_TPG_NTSC_CBAR (BIT(16)|BIT(15))
+#define TVENC_CTL_TPG_BLACK BIT(17)
+#define TVENC_CTL_TPG_WHITE100 (BIT(17)|BIT(15))
+#define TVENC_CTL_TPG_YELLOW75 (BIT(17)|BIT(16))
+#define TVENC_CTL_TPG_CYAN75 (BIT(17)|BIT(16)|BIT(15))
+#define TVENC_CTL_TPG_GREEN75 BIT(18)
+#define TVENC_CTL_TPG_MAGENTA75 (BIT(18)|BIT(15))
+#define TVENC_CTL_TPG_RED75 (BIT(18)|BIT(16))
+#define TVENC_CTL_TPG_BLUE75 (BIT(18)|BIT(16)|BIT(15))
+#define TVENC_CTL_TPG_WHITE75 (BIT(18)|BIT(17))
+#define TVENC_CTL_TPG_WHITE_TRSTN (BIT(18)|BIT(17)|BIT(15))
+
+#define TVENC_LOAD_DETECT_EN BIT(8)
+
+#ifdef TVENC_C
+void *tvenc_base;
+struct tvenc_platform_data *tvenc_pdata;
+#else
+extern void *tvenc_base;
+extern struct tvenc_platform_data *tvenc_pdata;
+#endif
+
+#define TV_OUT(reg, v) writel(v, tvenc_base + MSM_##reg)
+#define TV_IN(reg) readl(tvenc_base + MSM_##reg)
+
+#define MSM_TV_ENC_CTL 0x00
+#define MSM_TV_LEVEL 0x04
+#define MSM_TV_GAIN 0x08
+#define MSM_TV_OFFSET 0x0c
+#define MSM_TV_CGMS 0x10
+#define MSM_TV_SYNC_1 0x14
+#define MSM_TV_SYNC_2 0x18
+#define MSM_TV_SYNC_3 0x1c
+#define MSM_TV_SYNC_4 0x20
+#define MSM_TV_SYNC_5 0x24
+#define MSM_TV_SYNC_6 0x28
+#define MSM_TV_SYNC_7 0x2c
+#define MSM_TV_BURST_V1 0x30
+#define MSM_TV_BURST_V2 0x34
+#define MSM_TV_BURST_V3 0x38
+#define MSM_TV_BURST_V4 0x3c
+#define MSM_TV_BURST_H 0x40
+#define MSM_TV_SOL_REQ_ODD 0x44
+#define MSM_TV_SOL_REQ_EVEN 0x48
+#define MSM_TV_DAC_CTL 0x4c
+#define MSM_TV_TEST_MUX 0x50
+#define MSM_TV_TEST_MODE 0x54
+#define MSM_TV_TEST_MISR_RESET 0x58
+#define MSM_TV_TEST_EXPORT_MISR 0x5c
+#define MSM_TV_TEST_MISR_CURR_VAL 0x60
+#define MSM_TV_TEST_SOF_CFG 0x64
+#define MSM_TV_DAC_INTF 0x100
+
+#define MSM_TV_INTR_ENABLE 0x200
+#define MSM_TV_INTR_STATUS 0x204
+#define MSM_TV_INTR_CLEAR 0x208
+
+int tvenc_set_encoder_clock(boolean clock_on);
+int tvenc_set_clock(boolean clock_on);
+#endif /* TVENC_H */
diff --git a/drivers/video/msm/tvout_msm.c b/drivers/video/msm/tvout_msm.c
new file mode 100644
index 0000000..6912961
--- /dev/null
+++ b/drivers/video/msm/tvout_msm.c
@@ -0,0 +1,648 @@
+/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+#include "msm_fb.h"
+#include "tvenc.h"
+#include "external_common.h"
+
+#define TVOUT_HPD_DUTY_CYCLE 3000
+
+#define TV_DIMENSION_MAX_WIDTH 720
+#define TV_DIMENSION_MAX_HEIGHT 576
+
+struct tvout_msm_state_type {
+ struct external_common_state_type common;
+ struct platform_device *pdev;
+ struct timer_list hpd_state_timer;
+ struct timer_list hpd_work_timer;
+ struct work_struct hpd_work;
+ uint32 hpd_int_status;
+ uint32 prev_hpd_int_status;
+ uint32 five_retry;
+ int irq;
+ uint16 y_res;
+ boolean hpd_initialized;
+ boolean disp_powered_up;
+#ifdef CONFIG_SUSPEND
+ boolean pm_suspended;
+#endif
+
+};
+
+static struct tvout_msm_state_type *tvout_msm_state;
+static DEFINE_MUTEX(tvout_msm_state_mutex);
+
+static int tvout_off(struct platform_device *pdev);
+static int tvout_on(struct platform_device *pdev);
+static void tvout_check_status(void);
+
+static void tvout_msm_turn_on(boolean power_on)
+{
+ uint32 reg_val = 0;
+ reg_val = TV_IN(TV_ENC_CTL);
+ if (power_on) {
+ DEV_DBG("%s: TV Encoder turned on\n", __func__);
+ reg_val |= TVENC_CTL_ENC_EN;
+ } else {
+ DEV_DBG("%s: TV Encoder turned off\n", __func__);
+ reg_val = 0;
+ }
+ /* Enable TV Encoder*/
+ TV_OUT(TV_ENC_CTL, reg_val);
+}
+
+static void tvout_check_status()
+{
+ tvout_msm_state->hpd_int_status &= 0x05;
+ /* hpd_int_status could either be 0x05 or 0x04 for a cable
+ plug-out event when cable detect is driven by polling. */
+ if ((((tvout_msm_state->hpd_int_status == 0x05) ||
+ (tvout_msm_state->hpd_int_status == 0x04)) &&
+ (tvout_msm_state->prev_hpd_int_status == BIT(2))) ||
+ ((tvout_msm_state->hpd_int_status == 0x01) &&
+ (tvout_msm_state->prev_hpd_int_status == BIT(0)))) {
+ DEV_DBG("%s: cable event sent already!", __func__);
+ return;
+ }
+
+ if (tvout_msm_state->hpd_int_status & BIT(2)) {
+ DEV_DBG("%s: cable plug-out\n", __func__);
+ mutex_lock(&external_common_state_hpd_mutex);
+ external_common_state->hpd_state = FALSE;
+ mutex_unlock(&external_common_state_hpd_mutex);
+ kobject_uevent(external_common_state->uevent_kobj,
+ KOBJ_OFFLINE);
+ tvout_msm_state->prev_hpd_int_status = BIT(2);
+ } else if (tvout_msm_state->hpd_int_status & BIT(0)) {
+ DEV_DBG("%s: cable plug-in\n", __func__);
+ mutex_lock(&external_common_state_hpd_mutex);
+ external_common_state->hpd_state = TRUE;
+ mutex_unlock(&external_common_state_hpd_mutex);
+ kobject_uevent(external_common_state->uevent_kobj,
+ KOBJ_ONLINE);
+ tvout_msm_state->prev_hpd_int_status = BIT(0);
+ }
+}
+
+/* ISR for TV out cable detect */
+static irqreturn_t tvout_msm_isr(int irq, void *dev_id)
+{
+ tvout_msm_state->hpd_int_status = TV_IN(TV_INTR_STATUS);
+ TV_OUT(TV_INTR_CLEAR, tvout_msm_state->hpd_int_status);
+ DEV_DBG("%s: ISR: 0x%02x\n", __func__,
+ tvout_msm_state->hpd_int_status & 0x05);
+
+ if (tvenc_pdata->poll)
+ if (!tvout_msm_state || !tvout_msm_state->disp_powered_up) {
+ DEV_DBG("%s: ISR ignored, display not yet powered on\n",
+ __func__);
+ return IRQ_HANDLED;
+ }
+ if (tvout_msm_state->hpd_int_status & BIT(0) ||
+ tvout_msm_state->hpd_int_status & BIT(2)) {
+ /* Use .75sec to debounce the interrupt */
+ mod_timer(&tvout_msm_state->hpd_state_timer, jiffies
+ + msecs_to_jiffies(750));
+ }
+
+ return IRQ_HANDLED;
+}
+
+/* Interrupt debounce timer */
+static void tvout_msm_hpd_state_timer(unsigned long data)
+{
+#ifdef CONFIG_SUSPEND
+ mutex_lock(&tvout_msm_state_mutex);
+ if (tvout_msm_state->pm_suspended) {
+ mutex_unlock(&tvout_msm_state_mutex);
+ DEV_WARN("%s: ignored, pm_suspended\n", __func__);
+ return;
+ }
+ mutex_unlock(&tvout_msm_state_mutex);
+#endif
+
+ if (tvenc_pdata->poll)
+ if (!tvout_msm_state || !tvout_msm_state->disp_powered_up) {
+ DEV_DBG("%s: ignored, display powered off\n", __func__);
+ return;
+ }
+
+ /* TV_INTR_STATUS[0x204]
+ When a TV_ENC interrupt occurs, then reading this register will
+ indicate what caused the interrupt since that each bit indicates
+ the source of the interrupt that had happened. If multiple
+ interrupt sources had happened, then multiple bits of this
+ register will be set
+ Bit 0 : Load present on Video1
+ Bit 1 : Load present on Video2
+ Bit 2 : Load removed on Video1
+ Bit 3 : Load removed on Video2
+ */
+
+ /* Locking interrupt status is not required because
+ last status read after debouncing is used */
+ if ((tvout_msm_state->hpd_int_status & 0x05) == 0x05) {
+ /* SW-workaround :If the status read after debouncing is
+ 0x05(indicating both load present & load removed- which can't
+ happen in reality), force an update. If status remains 0x05
+ after retry, it's a cable unplug event */
+ if (++tvout_msm_state->five_retry < 2) {
+ uint32 reg;
+ DEV_DBG("tvout: Timer: 0x05\n");
+ TV_OUT(TV_INTR_CLEAR, 0xf);
+ reg = TV_IN(TV_DAC_INTF);
+ TV_OUT(TV_DAC_INTF, reg & ~TVENC_LOAD_DETECT_EN);
+ TV_OUT(TV_INTR_CLEAR, 0xf);
+ reg = TV_IN(TV_DAC_INTF);
+ TV_OUT(TV_DAC_INTF, reg | TVENC_LOAD_DETECT_EN);
+ return;
+ }
+ }
+ tvout_msm_state->five_retry = 0;
+ tvout_check_status();
+}
+
+static void tvout_msm_hpd_work(struct work_struct *work)
+{
+ uint32 reg;
+
+#ifdef CONFIG_SUSPEND
+ mutex_lock(&tvout_msm_state_mutex);
+ if (tvout_msm_state->pm_suspended) {
+ mutex_unlock(&tvout_msm_state_mutex);
+ DEV_WARN("%s: ignored, pm_suspended\n", __func__);
+ return;
+ }
+ mutex_unlock(&tvout_msm_state_mutex);
+#endif
+
+ /* Enable power lines & clocks */
+ tvenc_pdata->pm_vid_en(1);
+ tvenc_set_clock(CLOCK_ON);
+
+ /* Enable encoder to get a stable interrupt */
+ reg = TV_IN(TV_ENC_CTL);
+ TV_OUT(TV_ENC_CTL, reg | TVENC_CTL_ENC_EN);
+
+ /* SW- workaround to update status register */
+ reg = TV_IN(TV_DAC_INTF);
+ TV_OUT(TV_DAC_INTF, reg & ~TVENC_LOAD_DETECT_EN);
+ TV_OUT(TV_INTR_CLEAR, 0xf);
+ reg = TV_IN(TV_DAC_INTF);
+ TV_OUT(TV_DAC_INTF, reg | TVENC_LOAD_DETECT_EN);
+
+ tvout_msm_state->hpd_int_status = TV_IN(TV_INTR_STATUS);
+
+ /* Disable TV encoder */
+ reg = TV_IN(TV_ENC_CTL);
+ TV_OUT(TV_ENC_CTL, reg & ~TVENC_CTL_ENC_EN);
+
+ /*Disable power lines & clocks */
+ tvenc_set_clock(CLOCK_OFF);
+ tvenc_pdata->pm_vid_en(0);
+
+ DEV_DBG("%s: ISR: 0x%02x\n", __func__,
+ tvout_msm_state->hpd_int_status & 0x05);
+
+ mod_timer(&tvout_msm_state->hpd_work_timer, jiffies
+ + msecs_to_jiffies(TVOUT_HPD_DUTY_CYCLE));
+
+ tvout_check_status();
+}
+
+static void tvout_msm_hpd_work_timer(unsigned long data)
+{
+ schedule_work(&tvout_msm_state->hpd_work);
+}
+
+static int tvout_on(struct platform_device *pdev)
+{
+ uint32 reg = 0;
+ struct fb_var_screeninfo *var;
+ struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+#ifdef CONFIG_SUSPEND
+ mutex_lock(&tvout_msm_state_mutex);
+ if (tvout_msm_state->pm_suspended) {
+ mutex_unlock(&tvout_msm_state_mutex);
+ DEV_WARN("%s: ignored, pm_suspended\n", __func__);
+ return -ENODEV;
+ }
+ mutex_unlock(&tvout_msm_state_mutex);
+#endif
+
+ var = &mfd->fbi->var;
+ if (var->reserved[3] >= NTSC_M && var->reserved[3] <= PAL_N)
+ external_common_state->video_resolution = var->reserved[3];
+
+ tvout_msm_state->pdev = pdev;
+ if (del_timer(&tvout_msm_state->hpd_work_timer))
+ DEV_DBG("%s: work timer stopped\n", __func__);
+
+ TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */
+
+ switch (external_common_state->video_resolution) {
+ case NTSC_M:
+ case NTSC_J:
+ TV_OUT(TV_CGMS, 0x0);
+ /* NTSC Timing */
+ TV_OUT(TV_SYNC_1, 0x0020009e);
+ TV_OUT(TV_SYNC_2, 0x011306B4);
+ TV_OUT(TV_SYNC_3, 0x0006000C);
+ TV_OUT(TV_SYNC_4, 0x0028020D);
+ TV_OUT(TV_SYNC_5, 0x005E02FB);
+ TV_OUT(TV_SYNC_6, 0x0006000C);
+ TV_OUT(TV_SYNC_7, 0x00000012);
+ TV_OUT(TV_BURST_V1, 0x0013020D);
+ TV_OUT(TV_BURST_V2, 0x0014020C);
+ TV_OUT(TV_BURST_V3, 0x0013020D);
+ TV_OUT(TV_BURST_V4, 0x0014020C);
+ TV_OUT(TV_BURST_H, 0x00AE00F2);
+ TV_OUT(TV_SOL_REQ_ODD, 0x00280208);
+ TV_OUT(TV_SOL_REQ_EVEN, 0x00290209);
+
+ reg |= TVENC_CTL_TV_MODE_NTSC_M_PAL60;
+
+ if (external_common_state->video_resolution == NTSC_M) {
+ /* Cr gain 11, Cb gain C6, y_gain 97 */
+ TV_OUT(TV_GAIN, 0x0081B697);
+ } else {
+ /* Cr gain 11, Cb gain C6, y_gain 97 */
+ TV_OUT(TV_GAIN, 0x008bc4a3);
+ reg |= TVENC_CTL_NTSCJ_MODE;
+ }
+
+ var->yres = 480;
+ break;
+ case PAL_BDGHIN:
+ case PAL_N:
+ /* PAL Timing */
+ TV_OUT(TV_SYNC_1, 0x00180097);
+ TV_OUT(TV_SYNC_3, 0x0005000a);
+ TV_OUT(TV_SYNC_4, 0x00320271);
+ TV_OUT(TV_SYNC_5, 0x005602f9);
+ TV_OUT(TV_SYNC_6, 0x0005000a);
+ TV_OUT(TV_SYNC_7, 0x0000000f);
+ TV_OUT(TV_BURST_V1, 0x0012026e);
+ TV_OUT(TV_BURST_V2, 0x0011026d);
+ TV_OUT(TV_BURST_V3, 0x00100270);
+ TV_OUT(TV_BURST_V4, 0x0013026f);
+ TV_OUT(TV_SOL_REQ_ODD, 0x0030026e);
+ TV_OUT(TV_SOL_REQ_EVEN, 0x0031026f);
+
+ if (external_common_state->video_resolution == PAL_BDGHIN) {
+ /* Cr gain 11, Cb gain C6, y_gain 97 */
+ TV_OUT(TV_GAIN, 0x0088c1a0);
+ TV_OUT(TV_CGMS, 0x00012345);
+ TV_OUT(TV_SYNC_2, 0x011f06c0);
+ TV_OUT(TV_BURST_H, 0x00af00ea);
+ reg |= TVENC_CTL_TV_MODE_PAL_BDGHIN;
+ } else {
+ /* Cr gain 11, Cb gain C6, y_gain 97 */
+ TV_OUT(TV_GAIN, 0x0081b697);
+ TV_OUT(TV_CGMS, 0x000af317);
+ TV_OUT(TV_SYNC_2, 0x12006c0);
+ TV_OUT(TV_BURST_H, 0x00af00fa);
+ reg |= TVENC_CTL_TV_MODE_PAL_N;
+ }
+ var->yres = 576;
+ break;
+ case PAL_M:
+ /* Cr gain 11, Cb gain C6, y_gain 97 */
+ TV_OUT(TV_GAIN, 0x0081b697);
+ TV_OUT(TV_CGMS, 0x000af317);
+ TV_OUT(TV_TEST_MUX, 0x000001c3);
+ TV_OUT(TV_TEST_MODE, 0x00000002);
+ /* PAL Timing */
+ TV_OUT(TV_SYNC_1, 0x0020009e);
+ TV_OUT(TV_SYNC_2, 0x011306b4);
+ TV_OUT(TV_SYNC_3, 0x0006000c);
+ TV_OUT(TV_SYNC_4, 0x0028020D);
+ TV_OUT(TV_SYNC_5, 0x005e02fb);
+ TV_OUT(TV_SYNC_6, 0x0006000c);
+ TV_OUT(TV_SYNC_7, 0x00000012);
+ TV_OUT(TV_BURST_V1, 0x0012020b);
+ TV_OUT(TV_BURST_V2, 0x0016020c);
+ TV_OUT(TV_BURST_V3, 0x00150209);
+ TV_OUT(TV_BURST_V4, 0x0013020c);
+ TV_OUT(TV_BURST_H, 0x00bf010b);
+ TV_OUT(TV_SOL_REQ_ODD, 0x00280208);
+ TV_OUT(TV_SOL_REQ_EVEN, 0x00290209);
+
+ reg |= TVENC_CTL_TV_MODE_PAL_M;
+ var->yres = 480;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ reg |= TVENC_CTL_Y_FILTER_EN | TVENC_CTL_CR_FILTER_EN |
+ TVENC_CTL_CB_FILTER_EN | TVENC_CTL_SINX_FILTER_EN;
+
+ /* DC offset to 0. */
+ TV_OUT(TV_LEVEL, 0x00000000);
+ TV_OUT(TV_OFFSET, 0x008080f0);
+
+#ifdef CONFIG_FB_MSM_TVOUT_SVIDEO
+ reg |= TVENC_CTL_S_VIDEO_EN;
+#endif
+#if defined(CONFIG_FB_MSM_MDP31)
+ TV_OUT(TV_DAC_INTF, 0x29);
+#endif
+ TV_OUT(TV_ENC_CTL, reg);
+
+ if (!tvout_msm_state->hpd_initialized) {
+ tvout_msm_state->hpd_initialized = TRUE;
+ /* Load detect enable */
+ reg = TV_IN(TV_DAC_INTF);
+ reg |= TVENC_LOAD_DETECT_EN;
+ TV_OUT(TV_DAC_INTF, reg);
+ }
+
+ tvout_msm_state->disp_powered_up = TRUE;
+ tvout_msm_turn_on(TRUE);
+
+ if (tvenc_pdata->poll) {
+ /* Enable Load present & removal interrupts for Video1 */
+ TV_OUT(TV_INTR_ENABLE, 0x5);
+
+ /* Enable interrupts when display is on */
+ enable_irq(tvout_msm_state->irq);
+ }
+ return 0;
+}
+
+static int tvout_off(struct platform_device *pdev)
+{
+ /* Disable TV encoder irqs when display is off */
+ if (tvenc_pdata->poll)
+ disable_irq(tvout_msm_state->irq);
+ tvout_msm_turn_on(FALSE);
+ tvout_msm_state->hpd_initialized = FALSE;
+ tvout_msm_state->disp_powered_up = FALSE;
+ if (tvenc_pdata->poll) {
+ mod_timer(&tvout_msm_state->hpd_work_timer, jiffies
+ + msecs_to_jiffies(TVOUT_HPD_DUTY_CYCLE));
+ }
+ return 0;
+}
+
+static int __devinit tvout_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+ uint32 reg;
+ struct platform_device *fb_dev;
+
+#ifdef CONFIG_FB_MSM_TVOUT_NTSC_M
+ external_common_state->video_resolution = NTSC_M;
+#elif defined CONFIG_FB_MSM_TVOUT_NTSC_J
+ external_common_state->video_resolution = NTSC_J;
+#elif defined CONFIG_FB_MSM_TVOUT_PAL_M
+ external_common_state->video_resolution = PAL_M;
+#elif defined CONFIG_FB_MSM_TVOUT_PAL_N
+ external_common_state->video_resolution = PAL_N;
+#elif defined CONFIG_FB_MSM_TVOUT_PAL_BDGHIN
+ external_common_state->video_resolution = PAL_BDGHIN;
+#endif
+ external_common_state->dev = &pdev->dev;
+ if (pdev->id == 0) {
+ struct resource *res;
+
+ #define GET_RES(name, mode) do { \
+ res = platform_get_resource_byname(pdev, mode, name); \
+ if (!res) { \
+ DEV_DBG("'" name "' resource not found\n"); \
+ rc = -ENODEV; \
+ goto error; \
+ } \
+ } while (0)
+
+ #define GET_IRQ(var, name) do { \
+ GET_RES(name, IORESOURCE_IRQ); \
+ var = res->start; \
+ } while (0)
+
+ GET_IRQ(tvout_msm_state->irq, "tvout_device_irq");
+ #undef GET_IRQ
+ #undef GET_RES
+ return 0;
+ }
+
+ DEV_DBG("%s: tvout_msm_state->irq : %d",
+ __func__, tvout_msm_state->irq);
+
+ rc = request_irq(tvout_msm_state->irq, &tvout_msm_isr,
+ IRQF_TRIGGER_HIGH, "tvout_msm_isr", NULL);
+
+ if (rc) {
+ DEV_DBG("Init FAILED: IRQ request, rc=%d\n", rc);
+ goto error;
+ }
+ disable_irq(tvout_msm_state->irq);
+
+ init_timer(&tvout_msm_state->hpd_state_timer);
+ tvout_msm_state->hpd_state_timer.function =
+ tvout_msm_hpd_state_timer;
+ tvout_msm_state->hpd_state_timer.data = (uint32)NULL;
+ tvout_msm_state->hpd_state_timer.expires = jiffies
+ + msecs_to_jiffies(1000);
+
+ if (tvenc_pdata->poll) {
+ init_timer(&tvout_msm_state->hpd_work_timer);
+ tvout_msm_state->hpd_work_timer.function =
+ tvout_msm_hpd_work_timer;
+ tvout_msm_state->hpd_work_timer.data = (uint32)NULL;
+ tvout_msm_state->hpd_work_timer.expires = jiffies
+ + msecs_to_jiffies(1000);
+ }
+ fb_dev = msm_fb_add_device(pdev);
+ if (fb_dev) {
+ rc = external_common_state_create(fb_dev);
+ if (rc) {
+ DEV_ERR("Init FAILED: tvout_msm_state_create, rc=%d\n",
+ rc);
+ goto error;
+ }
+ if (tvenc_pdata->poll) {
+ /* Start polling timer to detect load */
+ mod_timer(&tvout_msm_state->hpd_work_timer, jiffies
+ + msecs_to_jiffies(TVOUT_HPD_DUTY_CYCLE));
+ } else {
+ /* Enable interrupt to detect load */
+ tvenc_set_encoder_clock(CLOCK_ON);
+ reg = TV_IN(TV_DAC_INTF);
+ reg |= TVENC_LOAD_DETECT_EN;
+ TV_OUT(TV_DAC_INTF, reg);
+ TV_OUT(TV_INTR_ENABLE, 0x5);
+ enable_irq(tvout_msm_state->irq);
+ }
+ } else
+ DEV_ERR("Init FAILED: failed to add fb device\n");
+error:
+ return 0;
+}
+
+static int __devexit tvout_remove(struct platform_device *pdev)
+{
+ external_common_state_remove();
+ kfree(tvout_msm_state);
+ tvout_msm_state = NULL;
+ return 0;
+}
+
+#ifdef CONFIG_SUSPEND
+static int tvout_device_pm_suspend(struct device *dev)
+{
+ mutex_lock(&tvout_msm_state_mutex);
+ if (tvout_msm_state->pm_suspended) {
+ mutex_unlock(&tvout_msm_state_mutex);
+ return 0;
+ }
+ if (tvenc_pdata->poll) {
+ if (del_timer(&tvout_msm_state->hpd_work_timer))
+ DEV_DBG("%s: suspending cable detect timer\n",
+ __func__);
+ } else {
+ disable_irq(tvout_msm_state->irq);
+ tvenc_set_encoder_clock(CLOCK_OFF);
+ }
+ tvout_msm_state->pm_suspended = TRUE;
+ mutex_unlock(&tvout_msm_state_mutex);
+ return 0;
+}
+
+static int tvout_device_pm_resume(struct device *dev)
+{
+ mutex_lock(&tvout_msm_state_mutex);
+ if (!tvout_msm_state->pm_suspended) {
+ mutex_unlock(&tvout_msm_state_mutex);
+ return 0;
+ }
+
+ if (tvenc_pdata->poll) {
+ tvout_msm_state->pm_suspended = FALSE;
+ mod_timer(&tvout_msm_state->hpd_work_timer, jiffies
+ + msecs_to_jiffies(TVOUT_HPD_DUTY_CYCLE));
+ mutex_unlock(&tvout_msm_state_mutex);
+ DEV_DBG("%s: resuming cable detect timer\n", __func__);
+ } else {
+ tvenc_set_encoder_clock(CLOCK_ON);
+ tvout_msm_state->pm_suspended = FALSE;
+ mutex_unlock(&tvout_msm_state_mutex);
+ enable_irq(tvout_msm_state->irq);
+ DEV_DBG("%s: enable cable detect interrupt\n", __func__);
+ }
+ return 0;
+}
+#else
+#define tvout_device_pm_suspend NULL
+#define tvout_device_pm_resume NULL
+#endif
+
+
+static const struct dev_pm_ops tvout_device_pm_ops = {
+ .suspend = tvout_device_pm_suspend,
+ .resume = tvout_device_pm_resume,
+};
+
+static struct platform_driver this_driver = {
+ .probe = tvout_probe,
+ .remove = tvout_remove,
+ .driver = {
+ .name = "tvout_device",
+ .pm = &tvout_device_pm_ops,
+ },
+};
+
+static struct msm_fb_panel_data tvout_panel_data = {
+ .panel_info.xres = TV_DIMENSION_MAX_WIDTH,
+ .panel_info.yres = TV_DIMENSION_MAX_HEIGHT,
+ .panel_info.type = TV_PANEL,
+ .panel_info.pdest = DISPLAY_2,
+ .panel_info.wait_cycle = 0,
+#ifdef CONFIG_FB_MSM_MDP40
+ .panel_info.bpp = 24,
+#else
+ .panel_info.bpp = 16,
+#endif
+ .panel_info.fb_num = 2,
+ .on = tvout_on,
+ .off = tvout_off,
+};
+
+static struct platform_device this_device = {
+ .name = "tvout_device",
+ .id = 1,
+ .dev = {
+ .platform_data = &tvout_panel_data,
+ }
+};
+
+static int __init tvout_init(void)
+{
+ int ret;
+ tvout_msm_state = kzalloc(sizeof(*tvout_msm_state), GFP_KERNEL);
+ if (!tvout_msm_state) {
+ DEV_ERR("tvout_msm_init FAILED: out of memory\n");
+ ret = -ENOMEM;
+ goto init_exit;
+ }
+
+ external_common_state = &tvout_msm_state->common;
+ ret = platform_driver_register(&this_driver);
+ if (ret) {
+ DEV_ERR("tvout_device_init FAILED: platform_driver_register\
+ rc=%d\n", ret);
+ goto init_exit;
+ }
+
+ ret = platform_device_register(&this_device);
+ if (ret) {
+ DEV_ERR("tvout_device_init FAILED: platform_driver_register\
+ rc=%d\n", ret);
+ platform_driver_unregister(&this_driver);
+ goto init_exit;
+ }
+
+ INIT_WORK(&tvout_msm_state->hpd_work, tvout_msm_hpd_work);
+ return 0;
+
+init_exit:
+ kfree(tvout_msm_state);
+ tvout_msm_state = NULL;
+ return ret;
+}
+
+static void __exit tvout_exit(void)
+{
+ platform_device_unregister(&this_device);
+ platform_driver_unregister(&this_driver);
+}
+
+module_init(tvout_init);
+module_exit(tvout_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("1.0");
+MODULE_AUTHOR("Qualcomm Innovation Center, Inc.");
+MODULE_DESCRIPTION("TV out driver");
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
new file mode 100644
index 0000000..b55c884
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
@@ -0,0 +1,634 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <mach/msm_memtypes.h>
+#include "vcd_ddl.h"
+#include "vcd_ddl_metadata.h"
+#include "vcd_res_tracker_api.h"
+
+static unsigned int first_time;
+
+u32 ddl_device_init(struct ddl_init_config *ddl_init_config,
+ void *client_data)
+{
+ struct ddl_context *ddl_context;
+ struct res_trk_firmware_addr firmware_addr;
+ u32 status = VCD_S_SUCCESS;
+ void *ptr = NULL;
+ DDL_MSG_HIGH("ddl_device_init");
+
+ if ((!ddl_init_config) || (!ddl_init_config->ddl_callback) ||
+ (!ddl_init_config->core_virtual_base_addr)) {
+ DDL_MSG_ERROR("ddl_dev_init:Bad_argument");
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+ ddl_context = ddl_get_context();
+ if (DDL_IS_INITIALIZED(ddl_context)) {
+ DDL_MSG_ERROR("ddl_dev_init:Multiple_init");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (!DDL_IS_IDLE(ddl_context)) {
+ DDL_MSG_ERROR("ddl_dev_init:Ddl_busy");
+ return VCD_ERR_BUSY;
+ }
+ memset(ddl_context, 0, sizeof(struct ddl_context));
+ DDL_BUSY(ddl_context);
+ ddl_context->memtype = res_trk_get_mem_type();
+ if (ddl_context->memtype == -1) {
+ DDL_MSG_ERROR("ddl_dev_init:Illegal memtype");
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+ ddl_context->ddl_callback = ddl_init_config->ddl_callback;
+ if (ddl_init_config->interrupt_clr)
+ ddl_context->interrupt_clr =
+ ddl_init_config->interrupt_clr;
+ ddl_context->core_virtual_base_addr =
+ ddl_init_config->core_virtual_base_addr;
+ ddl_context->client_data = client_data;
+ ddl_context->ddl_hw_response.arg1 = DDL_INVALID_INTR_STATUS;
+
+ ddl_context->frame_channel_depth = VCD_FRAME_COMMAND_DEPTH;
+
+ DDL_MSG_LOW("%s() : virtual address of core(%x)\n", __func__,
+ (u32) ddl_init_config->core_virtual_base_addr);
+ vidc_1080p_set_device_base_addr(
+ ddl_context->core_virtual_base_addr);
+ ddl_context->cmd_state = DDL_CMD_INVALID;
+ ddl_client_transact(DDL_INIT_CLIENTS, NULL);
+ ddl_context->fw_memory_size =
+ DDL_FW_INST_GLOBAL_CONTEXT_SPACE_SIZE;
+ if (ddl_context->memtype == MEMTYPE_SMI_KERNEL) {
+ ptr = ddl_pmem_alloc(&ddl_context->dram_base_a,
+ ddl_context->fw_memory_size, DDL_KILO_BYTE(128));
+ } else {
+ if (!res_trk_get_firmware_addr(&firmware_addr) &&
+ firmware_addr.buf_size >= ddl_context->fw_memory_size) {
+ if (DDL_ADDR_IS_ALIGNED(firmware_addr.device_addr,
+ DDL_KILO_BYTE(128))) {
+ ptr = (void *) firmware_addr.base_addr;
+ ddl_context->dram_base_a.physical_base_addr =
+ ddl_context->dram_base_a.align_physical_addr =
+ (u8 *)firmware_addr.device_addr;
+ ddl_context->dram_base_a.align_virtual_addr =
+ ddl_context->dram_base_a.virtual_base_addr =
+ firmware_addr.base_addr;
+ ddl_context->dram_base_a.buffer_size =
+ ddl_context->fw_memory_size;
+ } else {
+ DDL_MSG_ERROR("firmware base not aligned %p",
+ (void *)firmware_addr.device_addr);
+ }
+ }
+ }
+ if (!ptr) {
+ DDL_MSG_ERROR("Memory Aocation Failed for FW Base");
+ status = VCD_ERR_ALLOC_FAIL;
+ } else {
+ DDL_MSG_LOW("%s() : physical address of base(%x)\n",
+ __func__, (u32) ddl_context->dram_base_a.\
+ align_physical_addr);
+ ddl_context->dram_base_b.align_physical_addr =
+ ddl_context->dram_base_a.align_physical_addr;
+ ddl_context->dram_base_b.align_virtual_addr =
+ ddl_context->dram_base_a.align_virtual_addr;
+ }
+ if (!status) {
+ ptr = ddl_pmem_alloc(&ddl_context->metadata_shared_input,
+ DDL_METADATA_TOTAL_INPUTBUFSIZE,
+ DDL_LINEAR_BUFFER_ALIGN_BYTES);
+ if (!ptr) {
+ DDL_MSG_ERROR("ddl_device_init: metadata alloc fail");
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ }
+ if (!status && !ddl_fw_init(&ddl_context->dram_base_a)) {
+ DDL_MSG_ERROR("ddl_dev_init:fw_init_failed");
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (!status && ddl_context->memtype == MEMTYPE_EBI1)
+ clean_caches((unsigned long)firmware_addr.base_addr,
+ firmware_addr.buf_size, firmware_addr.device_addr);
+
+ if (!status) {
+ ddl_context->cmd_state = DDL_CMD_DMA_INIT;
+ ddl_vidc_core_init(ddl_context);
+ } else {
+ ddl_release_context_buffers(ddl_context);
+ DDL_IDLE(ddl_context);
+ }
+ return status;
+}
+
+u32 ddl_device_release(void *client_data)
+{
+ struct ddl_context *ddl_context;
+
+ DDL_MSG_HIGH("ddl_device_release");
+ ddl_context = ddl_get_context();
+ if (!DDL_IS_IDLE(ddl_context)) {
+ DDL_MSG_ERROR("ddl_dev_rel:Ddl_busy");
+ return VCD_ERR_BUSY;
+ }
+ if (!DDL_IS_INITIALIZED(ddl_context)) {
+ DDL_MSG_ERROR("ddl_dev_rel:Not_inited");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (!ddl_client_transact(DDL_ACTIVE_CLIENT, NULL)) {
+ DDL_MSG_ERROR("ddl_dev_rel:Client_present_err");
+ return VCD_ERR_CLIENT_PRESENT;
+ }
+ DDL_BUSY(ddl_context);
+ ddl_context->device_state = DDL_DEVICE_NOTINIT;
+ ddl_context->client_data = client_data;
+ ddl_context->cmd_state = DDL_CMD_INVALID;
+ ddl_vidc_core_term(ddl_context);
+ DDL_MSG_LOW("FW_ENDDONE");
+ ddl_context->core_virtual_base_addr = NULL;
+ ddl_release_context_buffers(ddl_context);
+ DDL_IDLE(ddl_context);
+ return VCD_S_SUCCESS;
+}
+
+u32 ddl_open(u32 **ddl_handle, u32 decoding)
+{
+ struct ddl_context *ddl_context;
+ struct ddl_client_context *ddl;
+ void *ptr;
+ u32 status;
+
+ DDL_MSG_HIGH("ddl_open");
+ if (!ddl_handle) {
+ DDL_MSG_ERROR("ddl_open:Bad_handle");
+ return VCD_ERR_BAD_HANDLE;
+ }
+ ddl_context = ddl_get_context();
+ if (!DDL_IS_INITIALIZED(ddl_context)) {
+ DDL_MSG_ERROR("ddl_open:Not_inited");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ status = ddl_client_transact(DDL_GET_CLIENT, &ddl);
+ if (status) {
+ DDL_MSG_ERROR("ddl_open:Client_trasac_failed");
+ return status;
+ }
+ ptr = ddl_pmem_alloc(&ddl->shared_mem[0],
+ DDL_FW_AUX_HOST_CMD_SPACE_SIZE, sizeof(u32));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ if (!status && ddl_context->frame_channel_depth
+ == VCD_DUAL_FRAME_COMMAND_CHANNEL) {
+ ptr = ddl_pmem_alloc(&ddl->shared_mem[1],
+ DDL_FW_AUX_HOST_CMD_SPACE_SIZE, sizeof(u32));
+ if (!ptr) {
+ ddl_pmem_free(&ddl->shared_mem[0]);
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ }
+ if (!status) {
+ memset(ddl->shared_mem[0].align_virtual_addr, 0,
+ DDL_FW_AUX_HOST_CMD_SPACE_SIZE);
+ if (ddl_context->frame_channel_depth ==
+ VCD_DUAL_FRAME_COMMAND_CHANNEL) {
+ memset(ddl->shared_mem[1].align_virtual_addr, 0,
+ DDL_FW_AUX_HOST_CMD_SPACE_SIZE);
+ }
+ DDL_MSG_LOW("ddl_state_transition: %s ~~> DDL_CLIENT_OPEN",
+ ddl_get_state_string(ddl->client_state));
+ ddl->client_state = DDL_CLIENT_OPEN;
+ ddl->codec_data.hdr.decoding = decoding;
+ ddl->decoding = decoding;
+ ddl_set_default_meta_data_hdr(ddl);
+ ddl_set_initial_default_values(ddl);
+ *ddl_handle = (u32 *) ddl;
+ } else {
+ ddl_pmem_free(&ddl->shared_mem[0]);
+ if (ddl_context->frame_channel_depth
+ == VCD_DUAL_FRAME_COMMAND_CHANNEL)
+ ddl_pmem_free(&ddl->shared_mem[1]);
+ ddl_client_transact(DDL_FREE_CLIENT, &ddl);
+ }
+ return status;
+}
+
+u32 ddl_close(u32 **ddl_handle)
+{
+ struct ddl_context *ddl_context;
+ struct ddl_client_context **pp_ddl =
+ (struct ddl_client_context **)ddl_handle;
+
+ DDL_MSG_HIGH("ddl_close");
+ if (!pp_ddl || !*pp_ddl) {
+ DDL_MSG_ERROR("ddl_close:Bad_handle");
+ return VCD_ERR_BAD_HANDLE;
+ }
+ ddl_context = ddl_get_context();
+ if (!DDL_IS_INITIALIZED(ddl_context)) {
+ DDL_MSG_ERROR("ddl_close:Not_inited");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (!DDLCLIENT_STATE_IS(*pp_ddl, DDL_CLIENT_OPEN)) {
+ DDL_MSG_ERROR("ddl_close:Not_in_open_state");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ ddl_pmem_free(&(*pp_ddl)->shared_mem[0]);
+ if (ddl_context->frame_channel_depth ==
+ VCD_DUAL_FRAME_COMMAND_CHANNEL)
+ ddl_pmem_free(&(*pp_ddl)->shared_mem[1]);
+ DDL_MSG_LOW("ddl_state_transition: %s ~~> DDL_CLIENT_INVALID",
+ ddl_get_state_string((*pp_ddl)->client_state));
+ (*pp_ddl)->client_state = DDL_CLIENT_INVALID;
+ ddl_codec_type_transact(*pp_ddl, true, (enum vcd_codec)0);
+ ddl_client_transact(DDL_FREE_CLIENT, pp_ddl);
+ return VCD_S_SUCCESS;
+}
+
+u32 ddl_encode_start(u32 *ddl_handle, void *client_data)
+{
+ struct ddl_client_context *ddl =
+ (struct ddl_client_context *) ddl_handle;
+ struct ddl_context *ddl_context;
+ struct ddl_encoder_data *encoder;
+ void *ptr;
+ u32 status = VCD_S_SUCCESS;
+ DDL_MSG_HIGH("ddl_encode_start");
+ if (vidc_msg_timing) {
+ if (first_time < 2) {
+ ddl_reset_core_time_variables(ENC_OP_TIME);
+ first_time++;
+ }
+ ddl_set_core_start_time(__func__, ENC_OP_TIME);
+ }
+ ddl_context = ddl_get_context();
+ if (!DDL_IS_INITIALIZED(ddl_context)) {
+ DDL_MSG_ERROR("ddl_enc_start:Not_inited");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (DDL_IS_BUSY(ddl_context)) {
+ DDL_MSG_ERROR("ddl_enc_start:Ddl_busy");
+ return VCD_ERR_BUSY;
+ }
+ if (!ddl || ddl->decoding) {
+ DDL_MSG_ERROR("ddl_enc_start:Bad_handle");
+ return VCD_ERR_BAD_HANDLE;
+ }
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)) {
+ DDL_MSG_ERROR("ddl_enc_start:Not_opened");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (!ddl_encoder_ready_to_start(ddl)) {
+ DDL_MSG_ERROR("ddl_enc_start:Err_param_settings");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ encoder = &ddl->codec_data.encoder;
+ status = ddl_allocate_enc_hw_buffers(ddl);
+ if (status)
+ return status;
+#ifdef DDL_BUF_LOG
+ ddl_list_buffers(ddl);
+#endif
+ if ((encoder->codec.codec == VCD_CODEC_MPEG4 &&
+ !encoder->short_header.short_header) ||
+ encoder->codec.codec == VCD_CODEC_H264) {
+ ptr = ddl_pmem_alloc(&encoder->seq_header,
+ DDL_ENC_SEQHEADER_SIZE, DDL_LINEAR_BUFFER_ALIGN_BYTES);
+ if (!ptr) {
+ ddl_free_enc_hw_buffers(ddl);
+ DDL_MSG_ERROR("ddl_enc_start:Seq_hdr_alloc_failed");
+ return VCD_ERR_ALLOC_FAIL;
+ }
+ } else {
+ encoder->seq_header.buffer_size = 0;
+ encoder->seq_header.virtual_base_addr = 0;
+ encoder->seq_header.align_physical_addr = 0;
+ encoder->seq_header.align_virtual_addr = 0;
+ }
+ if (!ddl_take_command_channel(ddl_context, ddl, client_data))
+ return VCD_ERR_BUSY;
+ ddl_vidc_channel_set(ddl);
+ return status;
+}
+
+u32 ddl_decode_start(u32 *ddl_handle, struct vcd_sequence_hdr *header,
+ void *client_data)
+{
+ struct ddl_client_context *ddl =
+ (struct ddl_client_context *) ddl_handle;
+ struct ddl_context *ddl_context;
+ struct ddl_decoder_data *decoder;
+ u32 status = VCD_S_SUCCESS;
+
+ DDL_MSG_HIGH("ddl_decode_start");
+ if (vidc_msg_timing) {
+ ddl_reset_core_time_variables(DEC_OP_TIME);
+ ddl_reset_core_time_variables(DEC_IP_TIME);
+ }
+ ddl_context = ddl_get_context();
+ if (!DDL_IS_INITIALIZED(ddl_context)) {
+ DDL_MSG_ERROR("ddl_dec_start:Not_inited");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (DDL_IS_BUSY(ddl_context)) {
+ DDL_MSG_ERROR("ddl_dec_start:Ddl_busy");
+ return VCD_ERR_BUSY;
+ }
+ if (!ddl || !ddl->decoding) {
+ DDL_MSG_ERROR("ddl_dec_start:Bad_handle");
+ return VCD_ERR_BAD_HANDLE;
+ }
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)) {
+ DDL_MSG_ERROR("ddl_dec_start:Not_in_opened_state");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+
+ if ((header) && ((!header->sequence_header_len) ||
+ (!header->sequence_header))) {
+ DDL_MSG_ERROR("ddl_dec_start:Bad_param_seq_header");
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+ if (!ddl_decoder_ready_to_start(ddl, header)) {
+ DDL_MSG_ERROR("ddl_dec_start:Err_param_settings");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ decoder = &ddl->codec_data.decoder;
+ status = ddl_allocate_dec_hw_buffers(ddl);
+ if (status)
+ return status;
+#ifdef DDL_BUF_LOG
+ ddl_list_buffers(ddl);
+#endif
+ if (!ddl_take_command_channel(ddl_context, ddl, client_data))
+ return VCD_ERR_BUSY;
+ if (header) {
+ decoder->header_in_start = true;
+ decoder->decode_config = *header;
+ } else {
+ decoder->header_in_start = false;
+ decoder->decode_config.sequence_header_len = 0;
+ }
+ ddl_vidc_channel_set(ddl);
+ return status;
+}
+
+u32 ddl_decode_frame(u32 *ddl_handle,
+ struct ddl_frame_data_tag *input_bits, void *client_data)
+{
+ u32 vcd_status = VCD_S_SUCCESS;
+ struct ddl_client_context *ddl =
+ (struct ddl_client_context *) ddl_handle;
+ struct ddl_context *ddl_context;
+ struct ddl_decoder_data *decoder;
+ DDL_MSG_HIGH("ddl_decode_frame");
+ ddl_context = ddl_get_context();
+ if (!DDL_IS_INITIALIZED(ddl_context)) {
+ DDL_MSG_ERROR("ddl_dec_frame:Not_inited");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (DDL_IS_BUSY(ddl_context)) {
+ DDL_MSG_ERROR("ddl_dec_frame:Ddl_busy");
+ return VCD_ERR_BUSY;
+ }
+ if (!ddl || !ddl->decoding) {
+ DDL_MSG_ERROR("ddl_dec_frame:Bad_handle");
+ return VCD_ERR_BAD_HANDLE;
+ }
+ if (!input_bits || ((!input_bits->vcd_frm.physical ||
+ !input_bits->vcd_frm.data_len) &&
+ (!(VCD_FRAME_FLAG_EOS & input_bits->vcd_frm.flags)))) {
+ DDL_MSG_ERROR("ddl_dec_frame:Bad_input_param");
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME) &&
+ !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_INITCODEC) &&
+ !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_DPB)) {
+ DDL_MSG_ERROR("Dec_frame:Wrong_state");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ decoder = &(ddl->codec_data.decoder);
+ if (DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_INITCODEC) &&
+ !ddl->codec_data.decoder.dp_buf.no_of_dec_pic_buf) {
+ DDL_MSG_ERROR("ddl_dec_frame:Dpbs_requied");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (!ddl_take_command_channel(ddl_context, ddl, client_data))
+ return VCD_ERR_BUSY;
+
+ ddl->input_frame = *input_bits;
+ if (DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME))
+ ddl_vidc_decode_frame_run(ddl);
+ else {
+ if (!ddl->codec_data.decoder.dp_buf.no_of_dec_pic_buf) {
+ DDL_MSG_ERROR("ddl_dec_frame:Dpbs_requied");
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ } else if (DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_DPB)) {
+ vcd_status = ddl_vidc_decode_set_buffers(ddl);
+ if (vcd_status)
+ ddl_release_command_channel(ddl_context,
+ ddl->command_channel);
+ } else if (DDLCLIENT_STATE_IS(ddl,
+ DDL_CLIENT_WAIT_FOR_INITCODEC)) {
+ if (decoder->codec.codec == VCD_CODEC_DIVX_3) {
+ if ((!decoder->client_frame_size.width) ||
+ (!decoder->client_frame_size.height))
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ ddl->codec_data.decoder.decode_config.sequence_header =
+ ddl->input_frame.vcd_frm.physical;
+ ddl->codec_data.decoder.decode_config.sequence_header_len =
+ ddl->input_frame.vcd_frm.data_len;
+ ddl_vidc_decode_init_codec(ddl);
+ } else {
+ DDL_MSG_ERROR("Dec_frame:Wrong_state");
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ }
+ if (vcd_status)
+ DDL_IDLE(ddl_context);
+ }
+ return vcd_status;
+}
+
+u32 ddl_encode_frame(u32 *ddl_handle,
+ struct ddl_frame_data_tag *input_frame,
+ struct ddl_frame_data_tag *output_bit, void *client_data)
+{
+ struct ddl_client_context *ddl =
+ (struct ddl_client_context *) ddl_handle;
+ struct ddl_context *ddl_context;
+ u32 vcd_status = VCD_S_SUCCESS;
+
+ DDL_MSG_HIGH("ddl_encode_frame");
+ if (vidc_msg_timing)
+ ddl_set_core_start_time(__func__, ENC_OP_TIME);
+ ddl_context = ddl_get_context();
+ if (!DDL_IS_INITIALIZED(ddl_context)) {
+ DDL_MSG_ERROR("ddl_enc_frame:Not_inited");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (DDL_IS_BUSY(ddl_context)) {
+ DDL_MSG_ERROR("ddl_enc_frame:Ddl_busy");
+ return VCD_ERR_BUSY;
+ }
+ if (!ddl || ddl->decoding) {
+ DDL_MSG_ERROR("ddl_enc_frame:Bad_handle");
+ return VCD_ERR_BAD_HANDLE;
+ }
+ if (!input_frame || !input_frame->vcd_frm.physical ||
+ !input_frame->vcd_frm.data_len) {
+ DDL_MSG_ERROR("ddl_enc_frame:Bad_input_params");
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+ if ((((u32) input_frame->vcd_frm.physical +
+ input_frame->vcd_frm.offset) &
+ (DDL_STREAMBUF_ALIGN_GUARD_BYTES))) {
+ DDL_MSG_ERROR("ddl_enc_frame:Un_aligned_yuv_start_address");
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+ if (!output_bit || !output_bit->vcd_frm.physical ||
+ !output_bit->vcd_frm.alloc_len) {
+ DDL_MSG_ERROR("ddl_enc_frame:Bad_output_params");
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+ if ((ddl->codec_data.encoder.output_buf_req.sz +
+ output_bit->vcd_frm.offset) >
+ output_bit->vcd_frm.alloc_len)
+ DDL_MSG_ERROR("ddl_enc_frame:offset_large,"
+ "Exceeds_min_buf_size");
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME)) {
+ DDL_MSG_ERROR("ddl_enc_frame:Wrong_state");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (!ddl_take_command_channel(ddl_context, ddl, client_data))
+ return VCD_ERR_BUSY;
+
+ ddl->input_frame = *input_frame;
+ ddl->output_frame = *output_bit;
+ if (ddl->codec_data.encoder.i_period.b_frames > 0) {
+ if (!ddl->b_count) {
+ ddl->first_output_frame = *output_bit;
+ ddl->b_count++;
+ } else if (ddl->codec_data.encoder.i_period.b_frames >=
+ ddl->b_count) {
+ ddl->extra_output_frame[ddl->b_count-1] =
+ *output_bit;
+ ddl->output_frame = ddl->first_output_frame;
+ ddl->b_count++;
+ }
+ }
+ ddl_insert_input_frame_to_pool(ddl, input_frame);
+ if (!vcd_status)
+ ddl_vidc_encode_frame_run(ddl);
+ else
+ DDL_MSG_ERROR("insert to frame pool failed %u", vcd_status);
+ return vcd_status;
+}
+
+u32 ddl_decode_end(u32 *ddl_handle, void *client_data)
+{
+ struct ddl_client_context *ddl =
+ (struct ddl_client_context *) ddl_handle;
+ struct ddl_context *ddl_context;
+
+ DDL_MSG_HIGH("ddl_decode_end");
+ if (vidc_msg_timing) {
+ ddl_reset_core_time_variables(DEC_OP_TIME);
+ ddl_reset_core_time_variables(DEC_IP_TIME);
+ }
+ ddl_context = ddl_get_context();
+ if (!DDL_IS_INITIALIZED(ddl_context)) {
+ DDL_MSG_ERROR("ddl_dec_end:Not_inited");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (DDL_IS_BUSY(ddl_context)) {
+ DDL_MSG_ERROR("ddl_dec_end:Ddl_busy");
+ return VCD_ERR_BUSY;
+ }
+ if (!ddl || !ddl->decoding) {
+ DDL_MSG_ERROR("ddl_dec_end:Bad_handle");
+ return VCD_ERR_BAD_HANDLE;
+ }
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME) &&
+ !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_INITCODEC) &&
+ !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_DPB) &&
+ !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_FAVIDC_ERROR)) {
+ DDL_MSG_ERROR("ddl_dec_end:Wrong_state");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (!ddl_take_command_channel(ddl_context, ddl, client_data))
+ return VCD_ERR_BUSY;
+ ddl_vidc_channel_end(ddl);
+ return VCD_S_SUCCESS;
+}
+
+u32 ddl_encode_end(u32 *ddl_handle, void *client_data)
+{
+ struct ddl_client_context *ddl =
+ (struct ddl_client_context *) ddl_handle;
+ struct ddl_context *ddl_context;
+
+ DDL_MSG_HIGH("ddl_encode_end");
+ if (vidc_msg_timing)
+ ddl_reset_core_time_variables(ENC_OP_TIME);
+ ddl_context = ddl_get_context();
+ if (!DDL_IS_INITIALIZED(ddl_context)) {
+ DDL_MSG_ERROR("ddl_enc_end:Not_inited");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (DDL_IS_BUSY(ddl_context)) {
+ DDL_MSG_ERROR("ddl_enc_end:Ddl_busy");
+ return VCD_ERR_BUSY;
+ }
+ if (!ddl || ddl->decoding) {
+ DDL_MSG_ERROR("ddl_enc_end:Bad_handle");
+ return VCD_ERR_BAD_HANDLE;
+ }
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME) &&
+ !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_INITCODEC) &&
+ !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_FAVIDC_ERROR)) {
+ DDL_MSG_ERROR("ddl_enc_end:Wrong_state");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (!ddl_take_command_channel(ddl_context, ddl, client_data))
+ return VCD_ERR_BUSY;
+ ddl_vidc_channel_end(ddl);
+ return VCD_S_SUCCESS;
+}
+
+u32 ddl_reset_hw(u32 mode)
+{
+ struct ddl_context *ddl_context;
+ struct ddl_client_context *ddl;
+ u32 i;
+
+ DDL_MSG_HIGH("ddl_reset_hw");
+ DDL_MSG_LOW("ddl_reset_hw:called");
+ ddl_context = ddl_get_context();
+ ddl_context->cmd_state = DDL_CMD_INVALID;
+ DDL_BUSY(ddl_context);
+ if (ddl_context->core_virtual_base_addr) {
+ vidc_1080p_do_sw_reset(VIDC_1080P_RESET_IN_SEQ_FIRST_STAGE);
+ msleep(DDL_SW_RESET_SLEEP);
+ vidc_1080p_do_sw_reset(VIDC_1080P_RESET_IN_SEQ_SECOND_STAGE);
+ msleep(DDL_SW_RESET_SLEEP);
+ ddl_context->core_virtual_base_addr = NULL;
+ }
+ ddl_context->device_state = DDL_DEVICE_NOTINIT;
+ for (i = 0; i < VCD_MAX_NO_CLIENT; i++) {
+ ddl = ddl_context->ddl_clients[i];
+ ddl_context->ddl_clients[i] = NULL;
+ if (ddl) {
+ ddl_release_client_internal_buffers(ddl);
+ ddl_client_transact(DDL_FREE_CLIENT, &ddl);
+ }
+ }
+ ddl_release_context_buffers(ddl_context);
+ memset(ddl_context, 0, sizeof(struct ddl_context));
+ return true;
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
new file mode 100644
index 0000000..9084ea8
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
@@ -0,0 +1,446 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _VCD_DDL_H_
+#define _VCD_DDL_H_
+
+#include "vcd_ddl_api.h"
+#include "vcd_ddl_core.h"
+#include "vcd_ddl_utils.h"
+#include "vidc.h"
+#include "vidc_hwio.h"
+#include "vidc_pix_cache.h"
+#include "vidc.h"
+
+#define DDL_IDLE_STATE 0
+#define DDL_BUSY_STATE 1
+#define DDL_ERROR_STATE 2
+#define DDL_RUN_STATE 3
+
+#define DDL_IS_BUSY(ddl_context) \
+ ((ddl_context)->ddl_busy == DDL_BUSY_STATE)
+#define DDL_IS_IDLE(ddl_context) \
+ ((ddl_context)->ddl_busy == DDL_IDLE_STATE)
+#define DDL_BUSY(ddl_context) \
+ ((ddl_context)->ddl_busy = DDL_BUSY_STATE)
+#define DDL_IDLE(ddl_context) \
+ ((ddl_context)->ddl_busy = DDL_IDLE_STATE)
+#define DDL_ERROR(ddl_context) \
+ ((ddl_context)->ddl_busy = DDL_ERROR_STATE)
+#define DDL_RUN(ddl_context) \
+ ((ddl_context)->ddl_busy = DDL_RUN_STATE)
+
+#define DDL_DEVICE_NOTINIT 0
+#define DDL_DEVICE_INITED 1
+#define DDL_DEVICE_HWFATAL 2
+
+#define DDL_IS_INITIALIZED(ddl_context) \
+ (ddl_context->device_state == DDL_DEVICE_INITED)
+#define DDLCOMMAND_STATE_IS(ddl_context, command_state) \
+ (command_state == (ddl_context)->cmd_state)
+#define DDLCLIENT_STATE_IS(ddl, state) \
+ (state == (ddl)->client_state)
+
+#define DDL_DPB_OP_INIT 1
+#define DDL_DPB_OP_MARK_FREE 2
+#define DDL_DPB_OP_MARK_BUSY 3
+#define DDL_DPB_OP_SET_MASK 4
+#define DDL_DPB_OP_RETRIEVE 5
+
+#define DDL_INIT_CLIENTS 0
+#define DDL_GET_CLIENT 1
+#define DDL_FREE_CLIENT 2
+#define DDL_ACTIVE_CLIENT 3
+
+#define DDL_INVALID_CHANNEL_ID ((u32)~0)
+#define DDL_INVALID_CODEC_TYPE ((u32)~0)
+#define DDL_INVALID_INTR_STATUS ((u32)~0)
+
+#define DDL_ENC_REQ_IFRAME 0x01
+#define DDL_ENC_CHANGE_IPERIOD 0x02
+#define DDL_ENC_CHANGE_BITRATE 0x04
+#define DDL_ENC_CHANGE_FRAMERATE 0x08
+#define DDL_ENC_CHANGE_CIR 0x10
+
+#define DDL_DEC_REQ_OUTPUT_FLUSH 0x1
+
+#define DDL_MIN_NUM_OF_B_FRAME 0
+#define DDL_MAX_NUM_OF_B_FRAME 1
+#define DDL_DEFAULT_NUM_OF_B_FRAME DDL_MIN_NUM_OF_B_FRAME
+
+#define DDL_MIN_NUM_REF_FOR_P_FRAME 1
+#define DDL_MAX_NUM_REF_FOR_P_FRAME 2
+
+#define DDL_MAX_NUM_IN_INPUTFRAME_POOL (DDL_MAX_NUM_OF_B_FRAME + 1)
+
+struct ddl_buf_addr{
+ u8 *virtual_base_addr;
+ u8 *physical_base_addr;
+ u8 *align_physical_addr;
+ u8 *align_virtual_addr;
+ u32 buffer_size;
+};
+enum ddl_cmd_state{
+ DDL_CMD_INVALID = 0x0,
+ DDL_CMD_DMA_INIT = 0x1,
+ DDL_CMD_CPU_RESET = 0x2,
+ DDL_CMD_CHANNEL_SET = 0x3,
+ DDL_CMD_INIT_CODEC = 0x4,
+ DDL_CMD_HEADER_PARSE = 0x5,
+ DDL_CMD_DECODE_SET_DPB = 0x6,
+ DDL_CMD_DECODE_FRAME = 0x7,
+ DDL_CMD_ENCODE_FRAME = 0x8,
+ DDL_CMD_EOS = 0x9,
+ DDL_CMD_CHANNEL_END = 0xA,
+ DDL_CMD_32BIT = 0x7FFFFFFF
+};
+enum ddl_client_state{
+ DDL_CLIENT_INVALID = 0x0,
+ DDL_CLIENT_OPEN = 0x1,
+ DDL_CLIENT_WAIT_FOR_CHDONE = 0x2,
+ DDL_CLIENT_WAIT_FOR_INITCODEC = 0x3,
+ DDL_CLIENT_WAIT_FOR_INITCODECDONE = 0x4,
+ DDL_CLIENT_WAIT_FOR_DPB = 0x5,
+ DDL_CLIENT_WAIT_FOR_DPBDONE = 0x6,
+ DDL_CLIENT_WAIT_FOR_FRAME = 0x7,
+ DDL_CLIENT_WAIT_FOR_FRAME_DONE = 0x8,
+ DDL_CLIENT_WAIT_FOR_EOS_DONE = 0x9,
+ DDL_CLIENT_WAIT_FOR_CHEND = 0xA,
+ DDL_CLIENT_FATAL_ERROR = 0xB,
+ DDL_CLIENT_FAVIDC_ERROR = 0xC,
+ DDL_CLIENT_32BIT = 0x7FFFFFFF
+};
+struct ddl_hw_interface{
+ u32 cmd;
+ u32 arg1;
+ u32 arg2;
+ u32 arg3;
+ u32 arg4;
+};
+struct ddl_mask{
+ u32 client_mask;
+ u32 hw_mask;
+};
+struct ddl_yuv_buffer_size{
+ u32 size_yuv;
+ u32 size_y;
+ u32 size_c;
+};
+struct ddl_dec_buffer_size{
+ u32 sz_dpb0;
+ u32 sz_dpb1;
+ u32 sz_mv;
+ u32 sz_vert_nb_mv;
+ u32 sz_nb_ip;
+ u32 sz_luma;
+ u32 sz_chroma;
+ u32 sz_nb_dcac;
+ u32 sz_upnb_mv;
+ u32 sz_sub_anchor_mv;
+ u32 sz_overlap_xform;
+ u32 sz_bit_plane3;
+ u32 sz_bit_plane2;
+ u32 sz_bit_plane1;
+ u32 sz_stx_parser;
+ u32 sz_desc;
+ u32 sz_cpb;
+ u32 sz_context;
+};
+struct ddl_dec_buffers{
+ struct ddl_buf_addr desc;
+ struct ddl_buf_addr nb_dcac;
+ struct ddl_buf_addr upnb_mv;
+ struct ddl_buf_addr sub_anchor_mv;
+ struct ddl_buf_addr overlay_xform;
+ struct ddl_buf_addr bit_plane3;
+ struct ddl_buf_addr bit_plane2;
+ struct ddl_buf_addr bit_plane1;
+ struct ddl_buf_addr stx_parser;
+ struct ddl_buf_addr h264_mv[DDL_MAX_BUFFER_COUNT];
+ struct ddl_buf_addr h264_vert_nb_mv;
+ struct ddl_buf_addr h264_nb_ip;
+ struct ddl_buf_addr context;
+};
+struct ddl_enc_buffer_size{
+ u32 sz_cur_y;
+ u32 sz_cur_c;
+ u32 sz_dpb_y;
+ u32 sz_dpb_c;
+ u32 sz_strm;
+ u32 sz_mv;
+ u32 sz_col_zero;
+ u32 sz_md;
+ u32 sz_pred;
+ u32 sz_nbor_info;
+ u32 sz_acdc_coef;
+ u32 sz_mb_info;
+ u32 sz_context;
+};
+struct ddl_enc_buffers{
+ struct ddl_buf_addr dpb_y[4];
+ struct ddl_buf_addr dpb_c[4];
+ struct ddl_buf_addr mv;
+ struct ddl_buf_addr col_zero;
+ struct ddl_buf_addr md;
+ struct ddl_buf_addr pred;
+ struct ddl_buf_addr nbor_info;
+ struct ddl_buf_addr acdc_coef;
+ struct ddl_buf_addr mb_info;
+ struct ddl_buf_addr context;
+ u32 dpb_count;
+ u32 sz_dpb_y;
+ u32 sz_dpb_c;
+};
+struct ddl_codec_data_hdr{
+ u32 decoding;
+};
+struct ddl_encoder_data{
+ struct ddl_codec_data_hdr hdr;
+ struct vcd_property_codec codec;
+ struct vcd_property_frame_size frame_size;
+ struct vcd_property_frame_rate frame_rate;
+ struct vcd_property_target_bitrate target_bit_rate;
+ struct vcd_property_profile profile;
+ struct vcd_property_level level;
+ struct vcd_property_rate_control rc;
+ struct vcd_property_multi_slice multi_slice;
+ struct ddl_buf_addr meta_data_input;
+ struct vcd_property_short_header short_header;
+ struct vcd_property_vop_timing vop_timing;
+ struct vcd_property_db_config db_control;
+ struct vcd_property_entropy_control entropy_control;
+ struct vcd_property_i_period i_period;
+ struct vcd_property_session_qp session_qp;
+ struct vcd_property_qp_range qp_range;
+ struct vcd_property_rc_level rc_level;
+ struct vcd_property_frame_level_rc_params frame_level_rc;
+ struct vcd_property_adaptive_rc_params adaptive_rc;
+ struct vcd_property_intra_refresh_mb_number intra_refresh;
+ struct vcd_property_buffer_format buf_format;
+ struct vcd_property_buffer_format recon_buf_format;
+ struct ddl_buf_addr seq_header;
+ struct vcd_buffer_requirement input_buf_req;
+ struct vcd_buffer_requirement output_buf_req;
+ struct vcd_buffer_requirement client_input_buf_req;
+ struct vcd_buffer_requirement client_output_buf_req;
+ struct ddl_enc_buffers hw_bufs;
+ struct ddl_yuv_buffer_size input_buf_size;
+ struct vidc_1080p_enc_frame_info enc_frame_info;
+ u32 meta_data_enable_flag;
+ u32 suffix;
+ u32 meta_data_offset;
+ u32 hdr_ext_control;
+ u32 r_cframe_skip;
+ u32 vb_vbuffer_size;
+ u32 dynamic_prop_change;
+ u32 dynmic_prop_change_req;
+ u32 seq_header_length;
+ u32 intra_frame_insertion;
+ u32 mb_info_enable;
+ u32 ext_enc_control_val;
+ u32 num_references_for_p_frame;
+};
+struct ddl_decoder_data {
+ struct ddl_codec_data_hdr hdr;
+ struct vcd_property_codec codec;
+ struct vcd_property_buffer_format buf_format;
+ struct vcd_property_frame_size frame_size;
+ struct vcd_property_frame_size client_frame_size;
+ struct vcd_property_profile profile;
+ struct vcd_property_level level;
+ struct ddl_buf_addr meta_data_input;
+ struct vcd_property_post_filter post_filter;
+ struct vcd_sequence_hdr decode_config;
+ struct ddl_property_dec_pic_buffers dp_buf;
+ struct ddl_mask dpb_mask;
+ struct vcd_buffer_requirement actual_input_buf_req;
+ struct vcd_buffer_requirement min_input_buf_req;
+ struct vcd_buffer_requirement client_input_buf_req;
+ struct vcd_buffer_requirement actual_output_buf_req;
+ struct vcd_buffer_requirement min_output_buf_req;
+ struct vcd_buffer_requirement client_output_buf_req;
+ struct ddl_dec_buffers hw_bufs;
+ struct ddl_yuv_buffer_size dpb_buf_size;
+ struct vidc_1080p_dec_disp_info dec_disp_info;
+ u32 progressive_only;
+ u32 output_order;
+ u32 meta_data_enable_flag;
+ u32 suffix;
+ u32 meta_data_offset;
+ u32 header_in_start;
+ u32 min_dpb_num;
+ u32 y_cb_cr_size;
+ u32 dynamic_prop_change;
+ u32 dynmic_prop_change_req;
+ u32 flush_pending;
+ u32 meta_data_exists;
+ u32 idr_only_decoding;
+ u32 field_needed_for_prev_ip;
+ u32 prev_ip_frm_tag;
+ u32 cont_mode;
+};
+union ddl_codec_data{
+ struct ddl_codec_data_hdr hdr;
+ struct ddl_decoder_data decoder;
+ struct ddl_encoder_data encoder;
+};
+struct ddl_context{
+ int memtype;
+ u8 *core_virtual_base_addr;
+ void *client_data;
+ u32 device_state;
+ u32 ddl_busy;
+ u32 cmd_err_status;
+ u32 disp_pic_err_status;
+ u32 pix_cache_enable;
+ u32 fw_version;
+ u32 fw_memory_size;
+ u32 cmd_seq_num;
+ u32 response_cmd_ch_id;
+ enum ddl_cmd_state cmd_state;
+ struct ddl_client_context *current_ddl[2];
+ struct ddl_buf_addr metadata_shared_input;
+ struct ddl_client_context *ddl_clients[VCD_MAX_NO_CLIENT];
+ struct ddl_buf_addr dram_base_a;
+ struct ddl_buf_addr dram_base_b;
+ struct ddl_hw_interface ddl_hw_response;
+ void (*ddl_callback) (u32 event, u32 status, void *payload,
+ size_t sz, u32 *ddl_handle, void *const client_data);
+ void (*interrupt_clr) (void);
+ void (*vidc_decode_seq_start[2])
+ (struct vidc_1080p_dec_seq_start_param *param);
+ void (*vidc_set_dec_resolution[2])
+ (u32 width, u32 height);
+ void(*vidc_decode_init_buffers[2])
+ (struct vidc_1080p_dec_init_buffers_param *param);
+ void(*vidc_decode_frame_start[2])
+ (struct vidc_1080p_dec_frame_start_param *param);
+ void(*vidc_encode_seq_start[2])
+ (struct vidc_1080p_enc_seq_start_param *param);
+ void(*vidc_encode_frame_start[2])
+ (struct vidc_1080p_enc_frame_start_param *param);
+ u32 frame_channel_depth;
+};
+struct ddl_client_context{
+ struct ddl_context *ddl_context;
+ enum ddl_client_state client_state;
+ struct ddl_frame_data_tag first_output_frame;
+ struct ddl_frame_data_tag
+ extra_output_frame[DDL_MAX_NUM_OF_B_FRAME];
+ struct ddl_frame_data_tag input_frame;
+ struct ddl_frame_data_tag output_frame;
+ struct ddl_frame_data_tag
+ input_frame_pool[DDL_MAX_NUM_IN_INPUTFRAME_POOL];
+ union ddl_codec_data codec_data;
+ enum ddl_cmd_state cmd_state;
+ struct ddl_buf_addr shared_mem[2];
+ void *client_data;
+ u32 decoding;
+ u32 channel_id;
+ u32 command_channel;
+ u32 b_count;
+ s32 extra_output_buf_count;
+ u32 instance_id;
+};
+
+struct ddl_context *ddl_get_context(void);
+void ddl_vidc_core_init(struct ddl_context *);
+void ddl_vidc_core_term(struct ddl_context *);
+void ddl_vidc_channel_set(struct ddl_client_context *);
+void ddl_vidc_channel_end(struct ddl_client_context *);
+void ddl_vidc_encode_init_codec(struct ddl_client_context *);
+void ddl_vidc_decode_init_codec(struct ddl_client_context *);
+void ddl_vidc_encode_frame_run(struct ddl_client_context *);
+void ddl_vidc_decode_frame_run(struct ddl_client_context *);
+void ddl_vidc_decode_eos_run(struct ddl_client_context *ddl);
+void ddl_release_context_buffers(struct ddl_context *);
+void ddl_release_client_internal_buffers(struct ddl_client_context *ddl);
+u32 ddl_vidc_decode_set_buffers(struct ddl_client_context *);
+u32 ddl_decoder_dpb_transact(struct ddl_decoder_data *decoder,
+ struct ddl_frame_data_tag *in_out_frame, u32 operation);
+u32 ddl_decoder_dpb_init(struct ddl_client_context *ddl);
+u32 ddl_client_transact(u32 , struct ddl_client_context **);
+u32 ddl_set_default_decoder_buffer_req(struct ddl_decoder_data *decoder,
+ u32 estimate);
+void ddl_set_default_encoder_buffer_req(struct ddl_encoder_data
+ *encoder);
+void ddl_set_default_dec_property(struct ddl_client_context *);
+u32 ddl_encoder_ready_to_start(struct ddl_client_context *);
+u32 ddl_decoder_ready_to_start(struct ddl_client_context *,
+ struct vcd_sequence_hdr *);
+u32 ddl_get_yuv_buffer_size(struct vcd_property_frame_size *frame_size,
+ struct vcd_property_buffer_format *buf_format, u32 interlace,
+ u32 decoding, u32 *pn_c_offset);
+void ddl_calculate_stride(struct vcd_property_frame_size *frame_size,
+ u32 interlace);
+u32 ddl_codec_type_transact(struct ddl_client_context *ddl,
+ u32 remove, enum vcd_codec requested_codec);
+void ddl_vidc_encode_dynamic_property(struct ddl_client_context *ddl,
+ u32 enable);
+void ddl_vidc_decode_dynamic_property(struct ddl_client_context *ddl,
+ u32 enable);
+void ddl_set_initial_default_values(struct ddl_client_context *ddl);
+
+u32 ddl_take_command_channel(struct ddl_context *ddl_context,
+ struct ddl_client_context *ddl, void *client_data);
+void ddl_release_command_channel(struct ddl_context *ddl_context,
+ u32 command_channel);
+struct ddl_client_context *ddl_get_current_ddl_client_for_channel_id(
+ struct ddl_context *ddl_context, u32 channel_id);
+struct ddl_client_context *ddl_get_current_ddl_client_for_command(
+ struct ddl_context *ddl_context,
+ enum ddl_cmd_state cmd_state);
+
+u32 ddl_get_yuv_buf_size(u32 width, u32 height, u32 format);
+void ddl_free_dec_hw_buffers(struct ddl_client_context *ddl);
+void ddl_free_enc_hw_buffers(struct ddl_client_context *ddl);
+void ddl_calc_dec_hw_buffers_size(enum vcd_codec codec, u32 width,
+ u32 height, u32 h264_dpb,
+ struct ddl_dec_buffer_size *buf_size);
+u32 ddl_allocate_dec_hw_buffers(struct ddl_client_context *ddl);
+u32 ddl_calc_enc_hw_buffers_size(enum vcd_codec codec, u32 width,
+ u32 height, enum vcd_yuv_buffer_format input_format,
+ struct ddl_client_context *ddl,
+ struct ddl_enc_buffer_size *buf_size);
+u32 ddl_allocate_enc_hw_buffers(struct ddl_client_context *ddl);
+
+u32 ddl_handle_core_errors(struct ddl_context *ddl_context);
+void ddl_client_fatal_cb(struct ddl_client_context *ddl);
+void ddl_hw_fatal_cb(struct ddl_client_context *ddl);
+
+void *ddl_pmem_alloc(struct ddl_buf_addr *addr, size_t sz, u32 alignment);
+void ddl_pmem_free(struct ddl_buf_addr *addr);
+
+u32 ddl_get_input_frame_from_pool(struct ddl_client_context *ddl,
+ u8 *input_buffer_address);
+u32 ddl_insert_input_frame_to_pool(struct ddl_client_context *ddl,
+ struct ddl_frame_data_tag *ddl_input_frame);
+
+void ddl_decoder_chroma_dpb_change(struct ddl_client_context *ddl);
+u32 ddl_check_reconfig(struct ddl_client_context *ddl);
+void ddl_handle_reconfig(u32 res_change, struct ddl_client_context *ddl);
+
+#ifdef DDL_BUF_LOG
+void ddl_list_buffers(struct ddl_client_context *ddl);
+#endif
+#ifdef DDL_MSG_LOG
+s8 *ddl_get_state_string(enum ddl_client_state client_state);
+#endif
+extern unsigned char *vidc_video_codec_fw;
+extern u32 vidc_video_codec_fw_size;
+
+u32 ddl_fw_init(struct ddl_buf_addr *dram_base);
+void ddl_get_fw_info(const unsigned char **fw_array_addr,
+ unsigned int *fw_size);
+void ddl_fw_release(void);
+#endif
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h
new file mode 100644
index 0000000..51a0d13
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h
@@ -0,0 +1,110 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _VCD_DDL_API_H_
+#define _VCD_DDL_API_H_
+
+#include "vidc.h"
+#include "vcd_api.h"
+
+#define VCD_EVT_RESP_DDL_BASE 0x3000
+#define VCD_EVT_RESP_DEVICE_INIT (VCD_EVT_RESP_DDL_BASE + 0x1)
+#define VCD_EVT_RESP_OUTPUT_REQ (VCD_EVT_RESP_DDL_BASE + 0x2)
+#define VCD_EVT_RESP_EOS_DONE (VCD_EVT_RESP_DDL_BASE + 0x3)
+#define VCD_EVT_RESP_TRANSACTION_PENDING (VCD_EVT_RESP_DDL_BASE + 0x4)
+
+#define VCD_S_DDL_ERR_BASE 0x90000000
+#define VCD_ERR_MAX_NO_CODEC (VCD_S_DDL_ERR_BASE + 0x1)
+#define VCD_ERR_CLIENT_PRESENT (VCD_S_DDL_ERR_BASE + 0x2)
+#define VCD_ERR_CLIENT_FATAL (VCD_S_DDL_ERR_BASE + 0x3)
+#define VCD_ERR_NO_SEQ_HDR (VCD_S_DDL_ERR_BASE + 0x4)
+
+#define VCD_I_CUSTOM_BASE (VCD_I_RESERVED_BASE)
+#define VCD_I_RC_LEVEL_CONFIG (VCD_I_CUSTOM_BASE + 0x1)
+#define VCD_I_FRAME_LEVEL_RC (VCD_I_CUSTOM_BASE + 0x2)
+#define VCD_I_ADAPTIVE_RC (VCD_I_CUSTOM_BASE + 0x3)
+#define VCD_I_CUSTOM_DDL_BASE (VCD_I_RESERVED_BASE + 0x100)
+#define DDL_I_INPUT_BUF_REQ (VCD_I_CUSTOM_DDL_BASE + 0x1)
+#define DDL_I_OUTPUT_BUF_REQ (VCD_I_CUSTOM_DDL_BASE + 0x2)
+#define DDL_I_DPB (VCD_I_CUSTOM_DDL_BASE + 0x3)
+#define DDL_I_DPB_RELEASE (VCD_I_CUSTOM_DDL_BASE + 0x4)
+#define DDL_I_DPB_RETRIEVE (VCD_I_CUSTOM_DDL_BASE + 0x5)
+#define DDL_I_REQ_OUTPUT_FLUSH (VCD_I_CUSTOM_DDL_BASE + 0x6)
+#define DDL_I_SEQHDR_ALIGN_BYTES (VCD_I_CUSTOM_DDL_BASE + 0x7)
+#define DDL_I_CAPABILITY (VCD_I_CUSTOM_DDL_BASE + 0x8)
+#define DDL_I_FRAME_PROC_UNITS (VCD_I_CUSTOM_DDL_BASE + 0x9)
+#define DDL_I_SEQHDR_PRESENT (VCD_I_CUSTOM_DDL_BASE + 0xA)
+
+#define DDL_FRAME_VGA_SIZE (640*480)
+#define DDL_FRAME_720P_WIDTH 1280
+#define DDL_FRAME_720P_HEIGHT 720
+
+struct vcd_property_rc_level{
+ u32 frame_level_rc;
+ u32 mb_level_rc;
+};
+struct vcd_property_frame_level_rc_params{
+ u32 reaction_coeff;
+};
+struct vcd_property_adaptive_rc_params{
+ u32 disable_dark_region_as_flag;
+ u32 disable_smooth_region_as_flag;
+ u32 disable_static_region_as_flag;
+ u32 disable_activity_region_flag;
+};
+struct ddl_property_dec_pic_buffers{
+ struct ddl_frame_data_tag *dec_pic_buffers;
+ u32 no_of_dec_pic_buf;
+};
+struct ddl_property_capability{
+ u32 max_num_client;
+ u32 general_command_depth;
+ u32 exclusive;
+ u32 frame_command_depth;
+ u32 ddl_time_out_in_ms;
+};
+struct ddl_init_config{
+ int memtype;
+ u8 *core_virtual_base_addr;
+ void (*interrupt_clr) (void);
+ void (*ddl_callback) (u32 event, u32 status, void *payload, size_t sz,
+ u32 *ddl_handle, void *const client_data);
+};
+struct ddl_frame_data_tag{
+ struct vcd_frame_data vcd_frm;
+ u32 frm_trans_end;
+ u32 frm_delta;
+};
+u32 ddl_device_init(struct ddl_init_config *ddl_init_config,
+ void *client_data);
+u32 ddl_device_release(void *client_data);
+u32 ddl_open(u32 **ddl_handle, u32 decoding);
+u32 ddl_close(u32 **ddl_handle);
+u32 ddl_encode_start(u32 *ddl_handle, void *client_data);
+u32 ddl_encode_frame(u32 *ddl_handle,
+ struct ddl_frame_data_tag *input_frame,
+ struct ddl_frame_data_tag *output_bit, void *client_data);
+u32 ddl_encode_end(u32 *ddl_handle, void *client_data);
+u32 ddl_decode_start(u32 *ddl_handle, struct vcd_sequence_hdr *header,
+ void *client_data);
+u32 ddl_decode_frame(u32 *ddl_handle,
+ struct ddl_frame_data_tag *input_bits, void *client_data);
+u32 ddl_decode_end(u32 *ddl_handle, void *client_data);
+u32 ddl_set_property(u32 *ddl_handle,
+ struct vcd_property_hdr *property_hdr, void *property_value);
+u32 ddl_get_property(u32 *ddl_handle,
+ struct vcd_property_hdr *property_hdr, void *property_value);
+u32 ddl_process_core_response(void);
+u32 ddl_reset_hw(u32 mode);
+void ddl_read_and_clear_interrupt(void);
+#endif
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
new file mode 100644
index 0000000..86ecec3
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
@@ -0,0 +1,134 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _VCD_DDL_CORE_H_
+#define _VCD_DDL_CORE_H_
+
+#define DDL_LINEAR_BUF_ALIGN_MASK 0xFFFFF800U
+#define DDL_LINEAR_BUF_ALIGN_GUARD_BYTES 0x7FF
+#define DDL_LINEAR_BUFFER_ALIGN_BYTES 2048
+#define DDL_TILE_BUF_ALIGN_MASK 0xFFFFE000U
+#define DDL_TILE_BUF_ALIGN_GUARD_BYTES 0x1FFF
+#define DDL_TILE_BUFFER_ALIGN_BYTES 8192
+
+#define DDL_YUV_BUF_TYPE_LINEAR 0
+#define DDL_YUV_BUF_TYPE_TILE 1
+
+#define DDL_NO_OF_MB(nWidth, nHeight) \
+ ((((nWidth) + 15) >> 4) * (((nHeight) + 15) >> 4))
+
+#define DDL_MAX_FRAME_WIDTH 1920
+#define DDL_MAX_FRAME_HEIGHT 1088
+
+#define MAX_DPB_SIZE_L4PT0_MBS DDL_KILO_BYTE(32)
+#define MAX_FRAME_SIZE_L4PT0_MBS DDL_KILO_BYTE(8)
+
+#define DDL_MAX_MB_PER_FRAME (DDL_NO_OF_MB(DDL_MAX_FRAME_WIDTH,\
+ DDL_MAX_FRAME_HEIGHT))
+
+#define DDL_DB_LINE_BUF_SIZE\
+ (((((DDL_MAX_FRAME_WIDTH * 4) - 1) / 256) + 1) * 8 * 1024)
+
+#define DDL_MAX_FRAME_RATE 120
+#define DDL_INITIAL_FRAME_RATE 30
+
+#define DDL_MAX_BIT_RATE (20*1024*1024)
+#define DDL_MAX_MB_PER_SEC (DDL_MAX_MB_PER_FRAME * DDL_INITIAL_FRAME_RATE)
+
+#define DDL_SW_RESET_SLEEP 1
+#define VCD_MAX_NO_CLIENT 4
+#define VCD_SINGLE_FRAME_COMMAND_CHANNEL 1
+#define VCD_DUAL_FRAME_COMMAND_CHANNEL 2
+#define VCD_FRAME_COMMAND_DEPTH VCD_SINGLE_FRAME_COMMAND_CHANNEL
+#define VCD_GENEVIDC_COMMAND_DEPTH 1
+#define VCD_COMMAND_EXCLUSIVE true
+#define DDL_HW_TIMEOUT_IN_MS 1000
+#define DDL_STREAMBUF_ALIGN_GUARD_BYTES 0x7FF
+
+#define DDL_CONTEXT_MEMORY (1024 * 15 * (VCD_MAX_NO_CLIENT + 1))
+
+#define DDL_ENC_MIN_DPB_BUFFERS 2
+#define DDL_ENC_MAX_DPB_BUFFERS 4
+
+#define DDL_FW_AUX_HOST_CMD_SPACE_SIZE (DDL_KILO_BYTE(10))
+#define DDL_FW_INST_GLOBAL_CONTEXT_SPACE_SIZE (DDL_KILO_BYTE(500))
+#define DDL_FW_H264DEC_CONTEXT_SPACE_SIZE (DDL_KILO_BYTE(800))
+#define DDL_FW_OTHER_CONTEXT_SPACE_SIZE (DDL_KILO_BYTE(10))
+
+#define VCD_DEC_CPB_SIZE (DDL_KILO_BYTE(512))
+#define DDL_DBG_CORE_DUMP_SIZE (DDL_KILO_BYTE(10))
+
+#define DDL_BUFEND_PAD 256
+#define DDL_ENC_SEQHEADER_SIZE (512+DDL_BUFEND_PAD)
+#define DDL_MAX_BUFFER_COUNT 32
+#define DDL_MIN_BUFFER_COUNT 1
+
+#define DDL_MPEG_REFBUF_COUNT 2
+#define DDL_MPEG_COMV_BUF_NO 2
+#define DDL_H263_COMV_BUF_NO 0
+#define DDL_COMV_BUFLINE_NO 128
+#define DDL_VC1_COMV_BUFLINE_NO 32
+
+#define DDL_MAX_H264_QP 51
+#define DDL_MAX_MPEG4_QP 31
+
+#define DDL_CONCEALMENT_Y_COLOR 16
+#define DDL_CONCEALMENT_C_COLOR 128
+
+#define DDL_ALLOW_DEC_FRAMESIZE(width, height) \
+ ((DDL_NO_OF_MB(width, height) <= \
+ MAX_FRAME_SIZE_L4PT0_MBS) && \
+ (width <= DDL_MAX_FRAME_WIDTH) && \
+ (height <= DDL_MAX_FRAME_WIDTH) && \
+ ((width >= 32 && height >= 16) || \
+ (width >= 16 && height >= 32)))
+
+#define DDL_ALLOW_ENC_FRAMESIZE(width, height) \
+ ((DDL_NO_OF_MB(width, height) <= \
+ MAX_FRAME_SIZE_L4PT0_MBS) && \
+ (width <= DDL_MAX_FRAME_WIDTH) && \
+ (height <= DDL_MAX_FRAME_WIDTH) && \
+ ((width >= 32 && height >= 32)))
+
+#define DDL_LINEAR_ALIGN_WIDTH 16
+#define DDL_LINEAR_ALIGN_HEIGHT 16
+#define DDL_LINEAR_MULTIPLY_FACTOR 2048
+#define DDL_TILE_ALIGN_WIDTH 128
+#define DDL_TILE_ALIGN_HEIGHT 32
+#define DDL_TILE_MULTIPLY_FACTOR 8192
+#define DDL_TILE_ALIGN(val, grid) \
+ (((val) + (grid) - 1) / (grid) * (grid))
+
+#define VCD_DDL_720P_YUV_BUF_SIZE ((1280*720*3) >> 1)
+#define VCD_DDL_WVGA_BUF_SIZE (800*480)
+
+#define VCD_DDL_TEST_MAX_WIDTH (DDL_MAX_FRAME_WIDTH)
+#define VCD_DDL_TEST_MAX_HEIGHT (DDL_MAX_FRAME_HEIGHT)
+
+#define VCD_DDL_TEST_MAX_NUM_H264_DPB 8
+
+#define VCD_DDL_TEST_NUM_ENC_INPUT_BUFS 6
+#define VCD_DDL_TEST_NUM_ENC_OUTPUT_BUFS 4
+
+#define VCD_DDL_TEST_DEFAULT_WIDTH 176
+#define VCD_DDL_TEST_DEFAULT_HEIGHT 144
+
+#define DDL_PIXEL_CACHE_NOT_IDLE 0x4000
+#define DDL_PIXEL_CACHE_STATUS_READ_RETRY 10
+#define DDL_PIXEL_CACHE_STATUS_READ_SLEEP 200
+
+#define DDL_RESL_CHANGE_NO_CHANGE 0
+#define DDL_RESL_CHANGE_INCREASED 1
+#define DDL_RESL_CHANGE_DECREASED 2
+
+#endif
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c
new file mode 100644
index 0000000..d658647
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c
@@ -0,0 +1,755 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "vcd_ddl.h"
+#include "vcd_ddl_shared_mem.h"
+#include "vidc.h"
+
+static u32 ddl_handle_hw_fatal_errors(struct ddl_client_context *ddl);
+static u32 ddl_handle_client_fatal_errors(
+ struct ddl_client_context *ddl);
+static void ddl_input_failed_cb(struct ddl_client_context *ddl,
+ u32 vcd_event, u32 vcd_status);
+static u32 ddl_handle_core_recoverable_errors(
+ struct ddl_client_context *ddl);
+static u32 ddl_handle_core_warnings(u32 error_code);
+static void ddl_release_prev_field(
+ struct ddl_client_context *ddl);
+static u32 ddl_handle_dec_seq_hdr_fail_error(struct ddl_client_context *ddl);
+static void print_core_errors(u32 error_code);
+static void print_core_recoverable_errors(u32 error_code);
+
+void ddl_hw_fatal_cb(struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ u32 error_code = ddl_context->cmd_err_status;
+
+ DDL_MSG_FATAL("VIDC_HW_FATAL");
+ ddl->cmd_state = DDL_CMD_INVALID;
+ ddl_context->device_state = DDL_DEVICE_HWFATAL;
+
+ ddl_context->ddl_callback(VCD_EVT_IND_HWERRFATAL, VCD_ERR_HW_FATAL,
+ &error_code, sizeof(error_code),
+ (u32 *)ddl, ddl->client_data);
+
+ ddl_release_command_channel(ddl_context, ddl->command_channel);
+}
+
+static u32 ddl_handle_hw_fatal_errors(struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ u32 status = false, error_code = ddl_context->cmd_err_status;
+
+ switch (error_code) {
+ case VIDC_1080P_ERROR_INVALID_CHANNEL_NUMBER:
+ case VIDC_1080P_ERROR_INVALID_COMMAND_ID:
+ case VIDC_1080P_ERROR_CHANNEL_ALREADY_IN_USE:
+ case VIDC_1080P_ERROR_CHANNEL_NOT_OPEN_BEFORE_CHANNEL_CLOSE:
+ case VIDC_1080P_ERROR_OPEN_CH_ERROR_SEQ_START:
+ case VIDC_1080P_ERROR_SEQ_START_ALREADY_CALLED:
+ case VIDC_1080P_ERROR_OPEN_CH_ERROR_INIT_BUFFERS:
+ case VIDC_1080P_ERROR_SEQ_START_ERROR_INIT_BUFFERS:
+ case VIDC_1080P_ERROR_INIT_BUFFER_ALREADY_CALLED:
+ case VIDC_1080P_ERROR_OPEN_CH_ERROR_FRAME_START:
+ case VIDC_1080P_ERROR_SEQ_START_ERROR_FRAME_START:
+ case VIDC_1080P_ERROR_INIT_BUFFERS_ERROR_FRAME_START:
+ case VIDC_1080P_ERROR_RESOLUTION_CHANGED:
+ case VIDC_1080P_ERROR_INVALID_COMMAND_LAST_FRAME:
+ case VIDC_1080P_ERROR_INVALID_COMMAND:
+ case VIDC_1080P_ERROR_INVALID_CODEC_TYPE:
+ case VIDC_1080P_ERROR_MEM_ALLOCATION_FAILED:
+ case VIDC_1080P_ERROR_INSUFFICIENT_CONTEXT_SIZE:
+ case VIDC_1080P_ERROR_DIVIDE_BY_ZERO:
+ case VIDC_1080P_ERROR_DESCRIPTOR_BUFFER_EMPTY:
+ case VIDC_1080P_ERROR_DMA_TX_NOT_COMPLETE:
+ case VIDC_1080P_ERROR_VSP_NOT_READY:
+ case VIDC_1080P_ERROR_BUFFER_FULL_STATE:
+ ddl_hw_fatal_cb(ddl);
+ status = true;
+ break;
+ default:
+ break;
+ }
+ return status;
+}
+
+void ddl_client_fatal_cb(struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+
+ if (ddl->cmd_state == DDL_CMD_DECODE_FRAME)
+ ddl_vidc_decode_dynamic_property(ddl, false);
+ else if (ddl->cmd_state == DDL_CMD_ENCODE_FRAME)
+ ddl_vidc_encode_dynamic_property(ddl, false);
+ ddl->cmd_state = DDL_CMD_INVALID;
+ DDL_MSG_LOW("ddl_state_transition: %s ~~> DDL_CLIENT_FAVIDC_ERROR",
+ ddl_get_state_string(ddl->client_state));
+ ddl->client_state = DDL_CLIENT_FAVIDC_ERROR;
+ ddl_context->ddl_callback(VCD_EVT_IND_HWERRFATAL,
+ VCD_ERR_CLIENT_FATAL, NULL, 0, (u32 *)ddl,
+ ddl->client_data);
+ ddl_release_command_channel(ddl_context, ddl->command_channel);
+}
+
+static u32 ddl_handle_client_fatal_errors(
+ struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ u32 status = false;
+
+ switch (ddl_context->cmd_err_status) {
+ case VIDC_1080P_ERROR_UNSUPPORTED_FEATURE_IN_PROFILE:
+ case VIDC_1080P_ERROR_RESOLUTION_NOT_SUPPORTED:
+ case VIDC_1080P_ERROR_VOS_END_CODE_RECEIVED:
+ case VIDC_1080P_ERROR_FRAME_RATE_NOT_SUPPORTED:
+ case VIDC_1080P_ERROR_INVALID_QP_VALUE:
+ case VIDC_1080P_ERROR_INVALID_RC_REACTION_COEFFICIENT:
+ case VIDC_1080P_ERROR_INVALID_CPB_SIZE_AT_GIVEN_LEVEL:
+ case VIDC_1080P_ERROR_B_FRAME_NOT_SUPPORTED:
+ case VIDC_1080P_ERROR_ALLOC_DPB_SIZE_NOT_SUFFICIENT:
+ case VIDC_1080P_ERROR_NUM_DPB_OUT_OF_RANGE:
+ case VIDC_1080P_ERROR_NULL_METADATA_INPUT_POINTER:
+ case VIDC_1080P_ERROR_NULL_DPB_POINTER:
+ case VIDC_1080P_ERROR_NULL_OTH_EXT_BUFADDR:
+ case VIDC_1080P_ERROR_NULL_MV_POINTER:
+ status = true;
+ DDL_MSG_ERROR("VIDC_CLIENT_FATAL!!");
+ break;
+ default:
+ break;
+ }
+ if (!status)
+ DDL_MSG_ERROR("VIDC_UNKNOWN_OP_FAILED %d",
+ ddl_context->cmd_err_status);
+ ddl_client_fatal_cb(ddl);
+ return true;
+}
+
+static void ddl_input_failed_cb(struct ddl_client_context *ddl,
+ u32 vcd_event, u32 vcd_status)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ u32 payload_size = sizeof(struct ddl_frame_data_tag);
+
+ ddl->cmd_state = DDL_CMD_INVALID;
+ if (ddl->decoding)
+ ddl_vidc_decode_dynamic_property(ddl, false);
+ else
+ ddl_vidc_encode_dynamic_property(ddl, false);
+ if (ddl->client_state == DDL_CLIENT_WAIT_FOR_INITCODECDONE) {
+ payload_size = 0;
+ DDL_MSG_LOW("ddl_state_transition: %s ~~> "
+ "DDL_CLIENT_WAIT_FOR_INITCODEC",
+ ddl_get_state_string(ddl->client_state));
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_INITCODEC;
+ } else {
+ DDL_MSG_LOW("ddl_state_transition: %s ~~> "
+ "DDL_CLIENT_WAIT_FOR_FRAME",
+ ddl_get_state_string(ddl->client_state));
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME;
+ }
+ if (vcd_status == VCD_ERR_IFRAME_EXPECTED)
+ vcd_status = VCD_S_SUCCESS;
+ ddl_context->ddl_callback(vcd_event, vcd_status, &ddl->input_frame,
+ payload_size, (u32 *)ddl, ddl->client_data);
+}
+
+static u32 ddl_handle_core_recoverable_errors(
+ struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ u32 vcd_status = VCD_S_SUCCESS;
+ u32 vcd_event = VCD_EVT_RESP_INPUT_DONE;
+ u32 eos = false, status = false;
+
+ if (ddl->decoding) {
+ if (ddl_handle_dec_seq_hdr_fail_error(ddl))
+ return true;
+ }
+
+ if ((ddl->cmd_state != DDL_CMD_DECODE_FRAME) &&
+ (ddl->cmd_state != DDL_CMD_ENCODE_FRAME))
+ return false;
+
+ if (ddl->decoding &&
+ (ddl->codec_data.decoder.field_needed_for_prev_ip == 1)) {
+ ddl->codec_data.decoder.field_needed_for_prev_ip = 0;
+ ddl_release_prev_field(ddl);
+ if (ddl_context->cmd_err_status ==
+ VIDC_1080P_ERROR_NON_PAIRED_FIELD_NOT_SUPPORTED) {
+ ddl_vidc_decode_frame_run(ddl);
+ return true;
+ }
+ }
+
+ switch (ddl_context->cmd_err_status) {
+ case VIDC_1080P_ERROR_SYNC_POINT_NOT_RECEIVED:
+ vcd_status = VCD_ERR_IFRAME_EXPECTED;
+ break;
+ case VIDC_1080P_ERROR_NO_BUFFER_RELEASED_FROM_HOST:
+ {
+ u32 pending_display = 0, release_mask;
+
+ release_mask =
+ ddl->codec_data.decoder.\
+ dpb_mask.hw_mask;
+ while (release_mask > 0) {
+ if (release_mask & 0x1)
+ pending_display++;
+ release_mask >>= 1;
+ }
+ if (pending_display >= ddl->codec_data.\
+ decoder.min_dpb_num) {
+ DDL_MSG_ERROR("VIDC_FW_ISSUE_REQ_BUF");
+ ddl_client_fatal_cb(ddl);
+ status = true;
+ } else {
+ vcd_event = VCD_EVT_RESP_OUTPUT_REQ;
+ DDL_MSG_LOW("VIDC_OUTPUT_BUF_REQ!!");
+ }
+ break;
+ }
+ case VIDC_1080P_ERROR_BIT_STREAM_BUF_EXHAUST:
+ case VIDC_1080P_ERROR_DESCRIPTOR_TABLE_ENTRY_INVALID:
+ case VIDC_1080P_ERROR_MB_COEFF_NOT_DONE:
+ case VIDC_1080P_ERROR_CODEC_SLICE_NOT_DONE:
+ case VIDC_1080P_ERROR_VIDC_CORE_TIME_OUT:
+ case VIDC_1080P_ERROR_VC1_BITPLANE_DECODE_ERR:
+ case VIDC_1080P_ERROR_RESOLUTION_MISMATCH:
+ case VIDC_1080P_ERROR_NV_QUANT_ERR:
+ case VIDC_1080P_ERROR_SYNC_MARKER_ERR:
+ case VIDC_1080P_ERROR_FEATURE_NOT_SUPPORTED:
+ case VIDC_1080P_ERROR_MEM_CORRUPTION:
+ case VIDC_1080P_ERROR_INVALID_REFERENCE_FRAME:
+ case VIDC_1080P_ERROR_PICTURE_CODING_TYPE_ERR:
+ case VIDC_1080P_ERROR_MV_RANGE_ERR:
+ case VIDC_1080P_ERROR_PICTURE_STRUCTURE_ERR:
+ case VIDC_1080P_ERROR_SLICE_ADDR_INVALID:
+ case VIDC_1080P_ERROR_NON_FRAME_DATA_RECEIVED:
+ case VIDC_1080P_ERROR_INCOMPLETE_FRAME:
+ case VIDC_1080P_ERROR_NALU_HEADER_ERROR:
+ case VIDC_1080P_ERROR_SPS_PARSE_ERROR:
+ case VIDC_1080P_ERROR_PPS_PARSE_ERROR:
+ case VIDC_1080P_ERROR_HEADER_NOT_FOUND:
+ case VIDC_1080P_ERROR_SLICE_PARSE_ERROR:
+ case VIDC_1080P_ERROR_NON_PAIRED_FIELD_NOT_SUPPORTED:
+ vcd_status = VCD_ERR_BITSTREAM_ERR;
+ DDL_MSG_ERROR("VIDC_BIT_STREAM_ERR");
+ break;
+ case VIDC_1080P_ERROR_B_FRAME_NOT_SUPPORTED:
+ case VIDC_1080P_ERROR_UNSUPPORTED_FEATURE_IN_PROFILE:
+ case VIDC_1080P_ERROR_RESOLUTION_NOT_SUPPORTED:
+ if (ddl->decoding) {
+ vcd_status = VCD_ERR_BITSTREAM_ERR;
+ DDL_MSG_ERROR("VIDC_BIT_STREAM_ERR");
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (((vcd_status) || (vcd_event != VCD_EVT_RESP_INPUT_DONE)) &&
+ !status) {
+ ddl->input_frame.frm_trans_end = true;
+ eos = ((vcd_event == VCD_EVT_RESP_INPUT_DONE) &&
+ (ddl->input_frame.vcd_frm.flags & VCD_FRAME_FLAG_EOS));
+ if (((ddl->decoding) && (eos)) || !ddl->decoding)
+ ddl->input_frame.frm_trans_end = false;
+ ddl_input_failed_cb(ddl, vcd_event, vcd_status);
+ if (!ddl->decoding) {
+ ddl->output_frame.frm_trans_end = !eos;
+ ddl->output_frame.vcd_frm.data_len = 0;
+ ddl_context->ddl_callback(VCD_EVT_RESP_OUTPUT_DONE,
+ VCD_ERR_FAIL, &ddl->output_frame,
+ sizeof(struct ddl_frame_data_tag), (u32 *)ddl,
+ ddl->client_data);
+ if (eos) {
+ DDL_MSG_LOW("VIDC_ENC_EOS_DONE");
+ ddl_context->ddl_callback(VCD_EVT_RESP_EOS_DONE,
+ VCD_S_SUCCESS, NULL, 0, (u32 *)ddl,
+ ddl->client_data);
+ }
+ }
+ if ((ddl->decoding) && (eos))
+ ddl_vidc_decode_eos_run(ddl);
+ else
+ ddl_release_command_channel(ddl_context,
+ ddl->command_channel);
+ status = true;
+ }
+ return status;
+}
+
+static u32 ddl_handle_core_warnings(u32 err_status)
+{
+ u32 status = false;
+
+ switch (err_status) {
+ case VIDC_1080P_WARN_COMMAND_FLUSHED:
+ case VIDC_1080P_WARN_FRAME_RATE_UNKNOWN:
+ case VIDC_1080P_WARN_ASPECT_RATIO_UNKNOWN:
+ case VIDC_1080P_WARN_COLOR_PRIMARIES_UNKNOWN:
+ case VIDC_1080P_WARN_TRANSFER_CHAR_UNKNOWN:
+ case VIDC_1080P_WARN_MATRIX_COEFF_UNKNOWN:
+ case VIDC_1080P_WARN_NON_SEQ_SLICE_ADDR:
+ case VIDC_1080P_WARN_BROKEN_LINK:
+ case VIDC_1080P_WARN_FRAME_CONCEALED:
+ case VIDC_1080P_WARN_PROFILE_UNKNOWN:
+ case VIDC_1080P_WARN_LEVEL_UNKNOWN:
+ case VIDC_1080P_WARN_BIT_RATE_NOT_SUPPORTED:
+ case VIDC_1080P_WARN_COLOR_DIFF_FORMAT_NOT_SUPPORTED:
+ case VIDC_1080P_WARN_NULL_EXTRA_METADATA_POINTER:
+ case VIDC_1080P_ERROR_NULL_FW_DEBUG_INFO_POINTER:
+ case VIDC_1080P_ERROR_ALLOC_DEBUG_INFO_SIZE_INSUFFICIENT:
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_NUM_CONCEAL_MB:
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_QP:
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_CONCEAL_MB:
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_VC1_PARAM:
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_SEI:
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_VUI:
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_EXTRA:
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_DATA_NONE:
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_MB_INFO:
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_SLICE_SIZE:
+ case VIDC_1080P_WARN_RESOLUTION_WARNING:
+ status = true;
+ DDL_MSG_ERROR("VIDC_WARNING_IGNORED");
+ break;
+ default:
+ break;
+ }
+ return status;
+}
+
+u32 ddl_handle_core_errors(struct ddl_context *ddl_context)
+{
+ struct ddl_client_context *ddl;
+ u32 channel_inst_id, status = false;
+ u32 disp_status;
+
+ if (!ddl_context->cmd_err_status &&
+ !ddl_context->disp_pic_err_status) {
+ DDL_MSG_ERROR("VIDC_NO_ERROR");
+ return false;
+ }
+ vidc_1080p_get_returned_channel_inst_id(&channel_inst_id);
+ vidc_1080p_clear_returned_channel_inst_id();
+ ddl = ddl_get_current_ddl_client_for_channel_id(ddl_context,
+ ddl_context->response_cmd_ch_id);
+ if (!ddl) {
+ DDL_MSG_ERROR("VIDC_SPURIOUS_INTERRUPT_ERROR");
+ return true;
+ }
+ if (ddl_context->cmd_err_status) {
+ print_core_errors(ddl_context->cmd_err_status);
+ print_core_recoverable_errors(ddl_context->cmd_err_status);
+ }
+ if (ddl_context->disp_pic_err_status)
+ print_core_errors(ddl_context->disp_pic_err_status);
+ status = ddl_handle_core_warnings(ddl_context->cmd_err_status);
+ disp_status = ddl_handle_core_warnings(
+ ddl_context->disp_pic_err_status);
+ if (!status && !disp_status) {
+ DDL_MSG_ERROR("ddl_warning:Unknown");
+ status = ddl_handle_hw_fatal_errors(ddl);
+ if (!status)
+ status = ddl_handle_core_recoverable_errors(ddl);
+ if (!status)
+ status = ddl_handle_client_fatal_errors(ddl);
+ }
+ return status;
+}
+
+static void ddl_release_prev_field(struct ddl_client_context *ddl)
+{
+ ddl->output_frame.vcd_frm.ip_frm_tag =
+ ddl->codec_data.decoder.prev_ip_frm_tag;
+ ddl->output_frame.vcd_frm.physical = NULL;
+ ddl->output_frame.vcd_frm.virtual = NULL;
+ ddl->output_frame.frm_trans_end = false;
+ ddl->ddl_context->ddl_callback(VCD_EVT_RESP_OUTPUT_DONE,
+ VCD_ERR_INTRLCD_FIELD_DROP, &(ddl->output_frame),
+ sizeof(struct ddl_frame_data_tag),
+ (u32 *) ddl, ddl->client_data);
+}
+
+static u32 ddl_handle_dec_seq_hdr_fail_error(struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ u32 status = false;
+
+ if ((ddl->cmd_state != DDL_CMD_HEADER_PARSE) ||
+ (ddl->client_state != DDL_CLIENT_WAIT_FOR_INITCODECDONE)) {
+ DDL_MSG_ERROR("STATE-CRITICAL-HDDONE");
+ return false;
+ }
+
+ switch (ddl_context->cmd_err_status) {
+ case VIDC_1080P_ERROR_UNSUPPORTED_FEATURE_IN_PROFILE:
+ case VIDC_1080P_ERROR_RESOLUTION_NOT_SUPPORTED:
+ case VIDC_1080P_ERROR_HEADER_NOT_FOUND:
+ case VIDC_1080P_ERROR_SPS_PARSE_ERROR:
+ case VIDC_1080P_ERROR_PPS_PARSE_ERROR:
+ {
+ struct ddl_decoder_data *decoder = &ddl->codec_data.decoder;
+ if (ddl_context->cmd_err_status ==
+ VIDC_1080P_ERROR_UNSUPPORTED_FEATURE_IN_PROFILE
+ && decoder->codec.codec == VCD_CODEC_H264) {
+ DDL_MSG_ERROR("Unsupported Feature for H264");
+ ddl_client_fatal_cb(ddl);
+ return true;
+ }
+ if ((ddl_context->cmd_err_status ==
+ VIDC_1080P_ERROR_RESOLUTION_NOT_SUPPORTED)
+ && (decoder->codec.codec == VCD_CODEC_H263
+ || decoder->codec.codec == VCD_CODEC_H264
+ || decoder->codec.codec == VCD_CODEC_MPEG4
+ || decoder->codec.codec == VCD_CODEC_VC1
+ || decoder->codec.codec == VCD_CODEC_VC1_RCV)) {
+ DDL_MSG_ERROR("Unsupported resolution");
+ ddl_client_fatal_cb(ddl);
+ return true;
+ }
+
+ DDL_MSG_ERROR("SEQHDR-FAILED");
+ if (decoder->header_in_start) {
+ decoder->header_in_start = false;
+ ddl_context->ddl_callback(VCD_EVT_RESP_START,
+ VCD_ERR_SEQHDR_PARSE_FAIL, NULL, 0,
+ (u32 *) ddl, ddl->client_data);
+ } else {
+ ddl->input_frame.frm_trans_end = true;
+ if ((ddl->input_frame.vcd_frm.flags &
+ VCD_FRAME_FLAG_EOS)) {
+ ddl->input_frame.frm_trans_end = false;
+ }
+ ddl_vidc_decode_dynamic_property(ddl, false);
+ ddl_context->ddl_callback(
+ VCD_EVT_RESP_INPUT_DONE,
+ VCD_ERR_SEQHDR_PARSE_FAIL, &ddl->input_frame,
+ sizeof(struct ddl_frame_data_tag), (u32 *)ddl,
+ ddl->client_data);
+ if ((ddl->input_frame.vcd_frm.flags &
+ VCD_FRAME_FLAG_EOS)) {
+ DDL_MSG_HIGH("EOS_DONE-fromDDL");
+ ddl_context->ddl_callback(VCD_EVT_RESP_EOS_DONE,
+ VCD_S_SUCCESS, NULL, 0, (u32 *) ddl,
+ ddl->client_data);
+ }
+ }
+ DDL_MSG_LOW("ddl_state_transition: %s ~~> "
+ "DDL_CLIENT_WAIT_FOR_INITCODEC",
+ ddl_get_state_string(ddl->client_state));
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_INITCODEC;
+ ddl_release_command_channel(ddl_context, ddl->command_channel);
+ status = true;
+ break;
+ }
+ default:
+ break;
+ }
+ return status;
+}
+
+void print_core_errors(u32 error_code)
+{
+ s8 *string = NULL;
+
+ switch (error_code) {
+ case VIDC_1080P_ERROR_INVALID_CHANNEL_NUMBER:
+ string = "VIDC_1080P_ERROR_INVALID_CHANNEL_NUMBER";
+ break;
+ case VIDC_1080P_ERROR_INVALID_COMMAND_ID:
+ string = "VIDC_1080P_ERROR_INVALID_COMMAND_ID";
+ break;
+ case VIDC_1080P_ERROR_CHANNEL_ALREADY_IN_USE:
+ string = "VIDC_1080P_ERROR_CHANNEL_ALREADY_IN_USE";
+ break;
+ case VIDC_1080P_ERROR_CHANNEL_NOT_OPEN_BEFORE_CHANNEL_CLOSE:
+ string =
+ "VIDC_1080P_ERROR_CHANNEL_NOT_OPEN_BEFORE_CHANNEL_CLOSE";
+ break;
+ case VIDC_1080P_ERROR_OPEN_CH_ERROR_SEQ_START:
+ string = "VIDC_1080P_ERROR_OPEN_CH_ERROR_SEQ_START";
+ break;
+ case VIDC_1080P_ERROR_SEQ_START_ALREADY_CALLED:
+ string = "VIDC_1080P_ERROR_SEQ_START_ALREADY_CALLED";
+ break;
+ case VIDC_1080P_ERROR_OPEN_CH_ERROR_INIT_BUFFERS:
+ string = "VIDC_1080P_ERROR_OPEN_CH_ERROR_INIT_BUFFERS";
+ break;
+ case VIDC_1080P_ERROR_SEQ_START_ERROR_INIT_BUFFERS:
+ string = "VIDC_1080P_ERROR_SEQ_START_ERROR_INIT_BUFFERS";
+ break;
+ case VIDC_1080P_ERROR_INIT_BUFFER_ALREADY_CALLED:
+ string = "VIDC_1080P_ERROR_INIT_BUFFER_ALREADY_CALLED";
+ break;
+ case VIDC_1080P_ERROR_OPEN_CH_ERROR_FRAME_START:
+ string = "VIDC_1080P_ERROR_OPEN_CH_ERROR_FRAME_START";
+ break;
+ case VIDC_1080P_ERROR_SEQ_START_ERROR_FRAME_START:
+ string = "VIDC_1080P_ERROR_SEQ_START_ERROR_FRAME_START";
+ break;
+ case VIDC_1080P_ERROR_INIT_BUFFERS_ERROR_FRAME_START:
+ string = "VIDC_1080P_ERROR_INIT_BUFFERS_ERROR_FRAME_START";
+ break;
+ case VIDC_1080P_ERROR_RESOLUTION_CHANGED:
+ string = "VIDC_1080P_ERROR_RESOLUTION_CHANGED";
+ break;
+ case VIDC_1080P_ERROR_INVALID_COMMAND_LAST_FRAME:
+ string = "VIDC_1080P_ERROR_INVALID_COMMAND_LAST_FRAME";
+ break;
+ case VIDC_1080P_ERROR_INVALID_COMMAND:
+ string = "VIDC_1080P_ERROR_INVALID_COMMAND";
+ break;
+ case VIDC_1080P_ERROR_INVALID_CODEC_TYPE:
+ string = "VIDC_1080P_ERROR_INVALID_CODEC_TYPE";
+ break;
+ case VIDC_1080P_ERROR_MEM_ALLOCATION_FAILED:
+ string = "VIDC_1080P_ERROR_MEM_ALLOCATION_FAILED";
+ break;
+ case VIDC_1080P_ERROR_INSUFFICIENT_CONTEXT_SIZE:
+ string = "VIDC_1080P_ERROR_INSUFFICIENT_CONTEXT_SIZE";
+ break;
+ case VIDC_1080P_ERROR_DIVIDE_BY_ZERO:
+ string = "VIDC_1080P_ERROR_DIVIDE_BY_ZERO";
+ break;
+ case VIDC_1080P_ERROR_DESCRIPTOR_BUFFER_EMPTY:
+ string = "VIDC_1080P_ERROR_DESCRIPTOR_BUFFER_EMPTY";
+ break;
+ case VIDC_1080P_ERROR_DMA_TX_NOT_COMPLETE:
+ string = "VIDC_1080P_ERROR_DMA_TX_NOT_COMPLETE";
+ break;
+ case VIDC_1080P_ERROR_VSP_NOT_READY:
+ string = "VIDC_1080P_ERROR_VSP_NOT_READY";
+ break;
+ case VIDC_1080P_ERROR_BUFFER_FULL_STATE:
+ string = "VIDC_1080P_ERROR_BUFFER_FULL_STATE";
+ break;
+ case VIDC_1080P_ERROR_UNSUPPORTED_FEATURE_IN_PROFILE:
+ string = "VIDC_1080P_ERROR_UNSUPPORTED_FEATURE_IN_PROFILE";
+ break;
+ case VIDC_1080P_ERROR_HEADER_NOT_FOUND:
+ string = "VIDC_1080P_ERROR_HEADER_NOT_FOUND";
+ break;
+ case VIDC_1080P_ERROR_VOS_END_CODE_RECEIVED:
+ string = "VIDC_1080P_ERROR_VOS_END_CODE_RECEIVED";
+ break;
+ case VIDC_1080P_ERROR_RESOLUTION_NOT_SUPPORTED:
+ string = "VIDC_1080P_ERROR_RESOLUTION_NOT_SUPPORTED";
+ break;
+ case VIDC_1080P_ERROR_FRAME_RATE_NOT_SUPPORTED:
+ string = "VIDC_1080P_ERROR_FRAME_RATE_NOT_SUPPORTED";
+ break;
+ case VIDC_1080P_ERROR_INVALID_QP_VALUE:
+ string = "VIDC_1080P_ERROR_INVALID_QP_VALUE";
+ break;
+ case VIDC_1080P_ERROR_INVALID_RC_REACTION_COEFFICIENT:
+ string = "VIDC_1080P_ERROR_INVALID_RC_REACTION_COEFFICIENT";
+ break;
+ case VIDC_1080P_ERROR_INVALID_CPB_SIZE_AT_GIVEN_LEVEL:
+ string = "VIDC_1080P_ERROR_INVALID_CPB_SIZE_AT_GIVEN_LEVEL";
+ break;
+ case VIDC_1080P_ERROR_B_FRAME_NOT_SUPPORTED:
+ string = "VIDC_1080P_ERROR_B_FRAME_NOT_SUPPORTED";
+ break;
+ case VIDC_1080P_ERROR_ALLOC_DPB_SIZE_NOT_SUFFICIENT:
+ string = "VIDC_1080P_ERROR_ALLOC_DPB_SIZE_NOT_SUFFICIENT";
+ break;
+ case VIDC_1080P_ERROR_NUM_DPB_OUT_OF_RANGE:
+ string = "VIDC_1080P_ERROR_NUM_DPB_OUT_OF_RANGE";
+ break;
+ case VIDC_1080P_ERROR_NULL_METADATA_INPUT_POINTER:
+ string = "VIDC_1080P_ERROR_NULL_METADATA_INPUT_POINTER";
+ break;
+ case VIDC_1080P_ERROR_NULL_DPB_POINTER:
+ string = "VIDC_1080P_ERROR_NULL_DPB_POINTER";
+ break;
+ case VIDC_1080P_ERROR_NULL_OTH_EXT_BUFADDR:
+ string = "VIDC_1080P_ERROR_NULL_OTH_EXT_BUFADDR";
+ break;
+ case VIDC_1080P_ERROR_NULL_MV_POINTER:
+ string = "VIDC_1080P_ERROR_NULL_MV_POINTER";
+ break;
+ case VIDC_1080P_ERROR_NON_PAIRED_FIELD_NOT_SUPPORTED:
+ string = "VIDC_1080P_ERROR_NON_PAIRED_FIELD_NOT_SUPPORTED";
+ break;
+ case VIDC_1080P_WARN_COMMAND_FLUSHED:
+ string = "VIDC_1080P_WARN_COMMAND_FLUSHED";
+ break;
+ case VIDC_1080P_WARN_FRAME_RATE_UNKNOWN:
+ string = "VIDC_1080P_WARN_FRAME_RATE_UNKNOWN";
+ break;
+ case VIDC_1080P_WARN_ASPECT_RATIO_UNKNOWN:
+ string = "VIDC_1080P_WARN_ASPECT_RATIO_UNKNOWN";
+ break;
+ case VIDC_1080P_WARN_COLOR_PRIMARIES_UNKNOWN:
+ string = "VIDC_1080P_WARN_COLOR_PRIMARIES_UNKNOWN";
+ break;
+ case VIDC_1080P_WARN_TRANSFER_CHAR_UNKNOWN:
+ string = "VIDC_1080P_WARN_TRANSFER_CHAR_UNKNOWN";
+ break;
+ case VIDC_1080P_WARN_MATRIX_COEFF_UNKNOWN:
+ string = "VIDC_1080P_WARN_MATRIX_COEFF_UNKNOWN";
+ break;
+ case VIDC_1080P_WARN_NON_SEQ_SLICE_ADDR:
+ string = "VIDC_1080P_WARN_NON_SEQ_SLICE_ADDR";
+ break;
+ case VIDC_1080P_WARN_BROKEN_LINK:
+ string = "VIDC_1080P_WARN_BROKEN_LINK";
+ break;
+ case VIDC_1080P_WARN_FRAME_CONCEALED:
+ string = "VIDC_1080P_WARN_FRAME_CONCEALED";
+ break;
+ case VIDC_1080P_WARN_PROFILE_UNKNOWN:
+ string = "VIDC_1080P_WARN_PROFILE_UNKNOWN";
+ break;
+ case VIDC_1080P_WARN_LEVEL_UNKNOWN:
+ string = "VIDC_1080P_WARN_LEVEL_UNKNOWN";
+ break;
+ case VIDC_1080P_WARN_BIT_RATE_NOT_SUPPORTED:
+ string = "VIDC_1080P_WARN_BIT_RATE_NOT_SUPPORTED";
+ break;
+ case VIDC_1080P_WARN_COLOR_DIFF_FORMAT_NOT_SUPPORTED:
+ string = "VIDC_1080P_WARN_COLOR_DIFF_FORMAT_NOT_SUPPORTED";
+ break;
+ case VIDC_1080P_WARN_NULL_EXTRA_METADATA_POINTER:
+ string = "VIDC_1080P_WARN_NULL_EXTRA_METADATA_POINTER";
+ break;
+ case VIDC_1080P_ERROR_NULL_FW_DEBUG_INFO_POINTER:
+ string = "VIDC_1080P_ERROR_NULL_FW_DEBUG_INFO_POINTER";
+ break;
+ case VIDC_1080P_ERROR_ALLOC_DEBUG_INFO_SIZE_INSUFFICIENT:
+ string =
+ "VIDC_1080P_ERROR_ALLOC_DEBUG_INFO_SIZE_INSUFFICIENT";
+ break;
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_NUM_CONCEAL_MB:
+ string = "VIDC_1080P_WARN_METADATA_NO_SPACE_NUM_CONCEAL_MB";
+ break;
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_QP:
+ string = "VIDC_1080P_WARN_METADATA_NO_SPACE_QP";
+ break;
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_CONCEAL_MB:
+ string = "VIDC_1080P_WARN_METADATA_NO_SPACE_CONCEAL_MB";
+ break;
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_VC1_PARAM:
+ string = "VIDC_1080P_WARN_METADATA_NO_SPACE_VC1_PARAM";
+ break;
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_SEI:
+ string = "VIDC_1080P_WARN_METADATA_NO_SPACE_SEI";
+ break;
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_VUI:
+ string = "VIDC_1080P_WARN_METADATA_NO_SPACE_VUI";
+ break;
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_EXTRA:
+ string = "VIDC_1080P_WARN_METADATA_NO_SPACE_EXTRA";
+ break;
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_DATA_NONE:
+ string = "VIDC_1080P_WARN_METADATA_NO_SPACE_DATA_NONE";
+ break;
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_MB_INFO:
+ string = "VIDC_1080P_WARN_METADATA_NO_SPACE_MB_INFO";
+ break;
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_SLICE_SIZE:
+ string = "VIDC_1080P_WARN_METADATA_NO_SPACE_SLICE_SIZE";
+ break;
+ case VIDC_1080P_WARN_RESOLUTION_WARNING:
+ string = "VIDC_1080P_WARN_RESOLUTION_WARNING";
+ break;
+ }
+ if (string)
+ DDL_MSG_ERROR("Error code = 0x%x : %s", error_code, string);
+}
+
+void print_core_recoverable_errors(u32 error_code)
+{
+ s8 *string = NULL;
+
+ switch (error_code) {
+ case VIDC_1080P_ERROR_SYNC_POINT_NOT_RECEIVED:
+ string = "VIDC_1080P_ERROR_SYNC_POINT_NOT_RECEIVED";
+ break;
+ case VIDC_1080P_ERROR_NO_BUFFER_RELEASED_FROM_HOST:
+ string = "VIDC_1080P_ERROR_NO_BUFFER_RELEASED_FROM_HOST";
+ break;
+ case VIDC_1080P_ERROR_BIT_STREAM_BUF_EXHAUST:
+ string = "VIDC_1080P_ERROR_BIT_STREAM_BUF_EXHAUST";
+ break;
+ case VIDC_1080P_ERROR_DESCRIPTOR_TABLE_ENTRY_INVALID:
+ string = "VIDC_1080P_ERROR_DESCRIPTOR_TABLE_ENTRY_INVALID";
+ break;
+ case VIDC_1080P_ERROR_MB_COEFF_NOT_DONE:
+ string = "VIDC_1080P_ERROR_MB_COEFF_NOT_DONE";
+ break;
+ case VIDC_1080P_ERROR_CODEC_SLICE_NOT_DONE:
+ string = "VIDC_1080P_ERROR_CODEC_SLICE_NOT_DONE";
+ break;
+ case VIDC_1080P_ERROR_VIDC_CORE_TIME_OUT:
+ string = "VIDC_1080P_ERROR_VIDC_CORE_TIME_OUT";
+ break;
+ case VIDC_1080P_ERROR_VC1_BITPLANE_DECODE_ERR:
+ string = "VIDC_1080P_ERROR_VC1_BITPLANE_DECODE_ERR";
+ break;
+ case VIDC_1080P_ERROR_RESOLUTION_MISMATCH:
+ string = "VIDC_1080P_ERROR_RESOLUTION_MISMATCH";
+ break;
+ case VIDC_1080P_ERROR_NV_QUANT_ERR:
+ string = "VIDC_1080P_ERROR_NV_QUANT_ERR";
+ break;
+ case VIDC_1080P_ERROR_SYNC_MARKER_ERR:
+ string = "VIDC_1080P_ERROR_SYNC_MARKER_ERR";
+ break;
+ case VIDC_1080P_ERROR_FEATURE_NOT_SUPPORTED:
+ string = "VIDC_1080P_ERROR_FEATURE_NOT_SUPPORTED";
+ break;
+ case VIDC_1080P_ERROR_MEM_CORRUPTION:
+ string = "VIDC_1080P_ERROR_MEM_CORRUPTION";
+ break;
+ case VIDC_1080P_ERROR_INVALID_REFERENCE_FRAME:
+ string = "VIDC_1080P_ERROR_INVALID_REFERENCE_FRAME";
+ break;
+ case VIDC_1080P_ERROR_PICTURE_CODING_TYPE_ERR:
+ string = "VIDC_1080P_ERROR_PICTURE_CODING_TYPE_ERR";
+ break;
+ case VIDC_1080P_ERROR_MV_RANGE_ERR:
+ string = "VIDC_1080P_ERROR_MV_RANGE_ERR";
+ break;
+ case VIDC_1080P_ERROR_PICTURE_STRUCTURE_ERR:
+ string = "VIDC_1080P_ERROR_PICTURE_STRUCTURE_ERR";
+ break;
+ case VIDC_1080P_ERROR_SLICE_ADDR_INVALID:
+ string = "VIDC_1080P_ERROR_SLICE_ADDR_INVALID";
+ break;
+ case VIDC_1080P_ERROR_NON_FRAME_DATA_RECEIVED:
+ string = "VIDC_1080P_ERROR_NON_FRAME_DATA_RECEIVED";
+ break;
+ case VIDC_1080P_ERROR_INCOMPLETE_FRAME:
+ string = "VIDC_1080P_ERROR_INCOMPLETE_FRAME";
+ break;
+ case VIDC_1080P_ERROR_NALU_HEADER_ERROR:
+ string = "VIDC_1080P_ERROR_NALU_HEADER_ERROR";
+ break;
+ case VIDC_1080P_ERROR_SPS_PARSE_ERROR:
+ string = "VIDC_1080P_ERROR_SPS_PARSE_ERROR";
+ break;
+ case VIDC_1080P_ERROR_PPS_PARSE_ERROR:
+ string = "VIDC_1080P_ERROR_PPS_PARSE_ERROR";
+ break;
+ case VIDC_1080P_ERROR_SLICE_PARSE_ERROR:
+ string = "VIDC_1080P_ERROR_SLICE_PARSE_ERROR";
+ break;
+ }
+ if (string)
+ DDL_MSG_ERROR("Recoverable Error code = 0x%x : %s",
+ error_code, string);
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
new file mode 100644
index 0000000..1b700bd
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
@@ -0,0 +1,959 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <mach/msm_memtypes.h>
+#include "vcd_ddl.h"
+#include "vcd_ddl_shared_mem.h"
+
+struct ddl_context *ddl_get_context(void)
+{
+ static struct ddl_context ddl_context;
+ return &ddl_context;
+}
+
+#ifdef DDL_MSG_LOG
+s8 *ddl_get_state_string(enum ddl_client_state client_state)
+{
+ s8 *ptr;
+
+ switch (client_state) {
+ case DDL_CLIENT_INVALID:
+ ptr = "INVALID ";
+ break;
+ case DDL_CLIENT_OPEN:
+ ptr = "OPEN ";
+ break;
+ case DDL_CLIENT_WAIT_FOR_CHDONE:
+ ptr = "WAIT_FOR_CHDONE ";
+ break;
+ case DDL_CLIENT_WAIT_FOR_INITCODEC:
+ ptr = "WAIT_FOR_INITCODEC ";
+ break;
+ case DDL_CLIENT_WAIT_FOR_INITCODECDONE:
+ ptr = "WAIT_FOR_INITCODECDONE";
+ break;
+ case DDL_CLIENT_WAIT_FOR_DPB:
+ ptr = "WAIT_FOR_DPB ";
+ break;
+ case DDL_CLIENT_WAIT_FOR_DPBDONE:
+ ptr = "WAIT_FOR_DPBDONE";
+ break;
+ case DDL_CLIENT_WAIT_FOR_FRAME:
+ ptr = "WAIT_FOR_FRAME ";
+ break;
+ case DDL_CLIENT_WAIT_FOR_FRAME_DONE:
+ ptr = "WAIT_FOR_FRAME_DONE ";
+ break;
+ case DDL_CLIENT_WAIT_FOR_EOS_DONE:
+ ptr = "WAIT_FOR_EOS_DONE ";
+ break;
+ case DDL_CLIENT_WAIT_FOR_CHEND:
+ ptr = "WAIT_FOR_CHEND ";
+ break;
+ case DDL_CLIENT_FATAL_ERROR:
+ ptr = "FATAL_ERROR";
+ break;
+ default:
+ ptr = "UNKNOWN ";
+ break;
+ }
+ return ptr;
+}
+#endif
+
+u32 ddl_client_transact(u32 operation,
+ struct ddl_client_context **pddl_client)
+{
+ struct ddl_context *ddl_context;
+ u32 ret_status = VCD_ERR_FAIL;
+ s32 counter;
+
+ ddl_context = ddl_get_context();
+ switch (operation) {
+ case DDL_FREE_CLIENT:
+ ret_status = VCD_ERR_MAX_CLIENT;
+ for (counter = 0; (counter < VCD_MAX_NO_CLIENT) &&
+ (ret_status == VCD_ERR_MAX_CLIENT); ++counter) {
+ if (*pddl_client == ddl_context->ddl_clients
+ [counter]) {
+ kfree(*pddl_client);
+ *pddl_client = NULL;
+ ddl_context->ddl_clients[counter]
+ = NULL;
+ ret_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case DDL_GET_CLIENT:
+ ret_status = VCD_ERR_MAX_CLIENT;
+ for (counter = (VCD_MAX_NO_CLIENT - 1); (counter >= 0) &&
+ (ret_status == VCD_ERR_MAX_CLIENT); --counter) {
+ if (!ddl_context->ddl_clients[counter]) {
+ *pddl_client =
+ (struct ddl_client_context *)
+ kmalloc(sizeof(struct
+ ddl_client_context), GFP_KERNEL);
+ if (!*pddl_client)
+ ret_status = VCD_ERR_ALLOC_FAIL;
+ else {
+ memset(*pddl_client, 0,
+ sizeof(struct
+ ddl_client_context));
+ ddl_context->ddl_clients
+ [counter] = *pddl_client;
+ (*pddl_client)->ddl_context =
+ ddl_context;
+ ret_status = VCD_S_SUCCESS;
+ }
+ }
+ }
+ break;
+ case DDL_INIT_CLIENTS:
+ for (counter = 0; counter < VCD_MAX_NO_CLIENT; ++counter)
+ ddl_context->ddl_clients[counter] = NULL;
+ ret_status = VCD_S_SUCCESS;
+ break;
+ case DDL_ACTIVE_CLIENT:
+ for (counter = 0; counter < VCD_MAX_NO_CLIENT;
+ ++counter) {
+ if (ddl_context->ddl_clients[counter]) {
+ ret_status = VCD_S_SUCCESS;
+ break;
+ }
+ }
+ break;
+ default:
+ ret_status = VCD_ERR_ILLEGAL_PARM;
+ break;
+ }
+ return ret_status;
+}
+
+u32 ddl_decoder_dpb_transact(struct ddl_decoder_data *decoder,
+ struct ddl_frame_data_tag *in_out_frame, u32 operation)
+{
+ struct ddl_frame_data_tag *found_frame = NULL;
+ struct ddl_mask *dpb_mask = &decoder->dpb_mask;
+ u32 vcd_status = VCD_S_SUCCESS, loopc;
+
+ switch (operation) {
+ case DDL_DPB_OP_MARK_BUSY:
+ case DDL_DPB_OP_MARK_FREE:
+ for (loopc = 0; !found_frame && loopc <
+ decoder->dp_buf.no_of_dec_pic_buf; ++loopc) {
+ if (in_out_frame->vcd_frm.physical ==
+ decoder->dp_buf.dec_pic_buffers[loopc].
+ vcd_frm.physical) {
+ found_frame = &(decoder->dp_buf.
+ dec_pic_buffers[loopc]);
+ break;
+ }
+ }
+ if (found_frame) {
+ if (operation == DDL_DPB_OP_MARK_BUSY) {
+ dpb_mask->hw_mask &=
+ (~(u32)(0x1 << loopc));
+ *in_out_frame = *found_frame;
+ } else if (operation == DDL_DPB_OP_MARK_FREE) {
+ dpb_mask->client_mask |= (0x1 << loopc);
+ *found_frame = *in_out_frame;
+ }
+ } else {
+ in_out_frame->vcd_frm.physical = NULL;
+ in_out_frame->vcd_frm.virtual = NULL;
+ vcd_status = VCD_ERR_BAD_POINTER;
+ DDL_MSG_ERROR("BUF_NOT_FOUND");
+ }
+ break;
+ case DDL_DPB_OP_SET_MASK:
+ dpb_mask->hw_mask |= dpb_mask->client_mask;
+ dpb_mask->client_mask = 0;
+ break;
+ case DDL_DPB_OP_INIT:
+ {
+ u32 dpb_size;
+ dpb_size = (!decoder->meta_data_offset) ?
+ decoder->dp_buf.dec_pic_buffers[0].vcd_frm.alloc_len :
+ decoder->meta_data_offset;
+ }
+ break;
+ case DDL_DPB_OP_RETRIEVE:
+ {
+ u32 position;
+ if (dpb_mask->client_mask) {
+ position = 0x1;
+ for (loopc = 0; loopc <
+ decoder->dp_buf.no_of_dec_pic_buf &&
+ !found_frame; ++loopc) {
+ if (dpb_mask->client_mask & position) {
+ found_frame = &decoder->dp_buf.
+ dec_pic_buffers[loopc];
+ dpb_mask->client_mask &=
+ ~(position);
+ }
+ position <<= 1;
+ }
+ } else if (dpb_mask->hw_mask) {
+ position = 0x1;
+ for (loopc = 0; loopc <
+ decoder->dp_buf.no_of_dec_pic_buf &&
+ !found_frame; ++loopc) {
+ if (dpb_mask->hw_mask & position) {
+ found_frame = &decoder->dp_buf.
+ dec_pic_buffers[loopc];
+ dpb_mask->hw_mask &= ~(position);
+ }
+ position <<= 1;
+ }
+ }
+ if (found_frame)
+ *in_out_frame = *found_frame;
+ else {
+ in_out_frame->vcd_frm.physical = NULL;
+ in_out_frame->vcd_frm.virtual = NULL;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return vcd_status;
+}
+
+u32 ddl_decoder_dpb_init(struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_decoder_data *decoder = &ddl->codec_data.decoder;
+ struct ddl_dec_buffers *dec_buffers = &decoder->hw_bufs;
+ struct ddl_frame_data_tag *frame;
+ u32 luma[DDL_MAX_BUFFER_COUNT], chroma[DDL_MAX_BUFFER_COUNT];
+ u32 mv[DDL_MAX_BUFFER_COUNT], luma_size, i, dpb;
+
+ frame = &decoder->dp_buf.dec_pic_buffers[0];
+ luma_size = ddl_get_yuv_buf_size(decoder->frame_size.width,
+ decoder->frame_size.height, DDL_YUV_BUF_TYPE_TILE);
+ dpb = decoder->dp_buf.no_of_dec_pic_buf;
+ DDL_MSG_LOW("%s Decoder num DPB buffers = %u Luma Size = %u"
+ __func__, dpb, luma_size);
+ if (dpb > DDL_MAX_BUFFER_COUNT)
+ dpb = DDL_MAX_BUFFER_COUNT;
+ for (i = 0; i < dpb; i++) {
+ if (frame[i].vcd_frm.virtual) {
+ memset(frame[i].vcd_frm.virtual, 0x10101010, luma_size);
+ memset(frame[i].vcd_frm.virtual + luma_size, 0x80808080,
+ frame[i].vcd_frm.alloc_len - luma_size);
+ }
+
+ luma[i] = DDL_OFFSET(ddl_context->dram_base_a.
+ align_physical_addr, frame[i].vcd_frm.physical);
+ chroma[i] = luma[i] + luma_size;
+ DDL_MSG_LOW("%s Decoder Luma address = %x Chroma address = %x"
+ __func__, luma[i], chroma[i]);
+ }
+ switch (decoder->codec.codec) {
+ case VCD_CODEC_MPEG1:
+ case VCD_CODEC_MPEG2:
+ vidc_1080p_set_decode_recon_buffers(dpb, luma, chroma);
+ break;
+ case VCD_CODEC_DIVX_3:
+ case VCD_CODEC_DIVX_4:
+ case VCD_CODEC_DIVX_5:
+ case VCD_CODEC_DIVX_6:
+ case VCD_CODEC_XVID:
+ case VCD_CODEC_MPEG4:
+ vidc_1080p_set_decode_recon_buffers(dpb, luma, chroma);
+ vidc_1080p_set_mpeg4_divx_decode_work_buffers(
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ dec_buffers->nb_dcac),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ dec_buffers->upnb_mv),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ dec_buffers->sub_anchor_mv),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ dec_buffers->overlay_xform),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ dec_buffers->stx_parser));
+ break;
+ case VCD_CODEC_H263:
+ vidc_1080p_set_decode_recon_buffers(dpb, luma, chroma);
+ vidc_1080p_set_h263_decode_work_buffers(
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ dec_buffers->nb_dcac),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ dec_buffers->upnb_mv),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ dec_buffers->sub_anchor_mv),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ dec_buffers->overlay_xform));
+ break;
+ case VCD_CODEC_VC1:
+ case VCD_CODEC_VC1_RCV:
+ vidc_1080p_set_decode_recon_buffers(dpb, luma, chroma);
+ vidc_1080p_set_vc1_decode_work_buffers(
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ dec_buffers->nb_dcac),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ dec_buffers->upnb_mv),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ dec_buffers->sub_anchor_mv),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ dec_buffers->overlay_xform),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ dec_buffers->bit_plane1),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ dec_buffers->bit_plane2),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ dec_buffers->bit_plane3));
+ break;
+ case VCD_CODEC_H264:
+ for (i = 0; i < dpb; i++)
+ mv[i] = DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ dec_buffers->h264_mv[i]);
+ vidc_1080p_set_h264_decode_buffers(dpb,
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ dec_buffers->h264_vert_nb_mv),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ dec_buffers->h264_nb_ip),
+ luma, chroma, mv);
+ break;
+ default:
+ break;
+ }
+ return VCD_S_SUCCESS;
+}
+
+void ddl_release_context_buffers(struct ddl_context *ddl_context)
+{
+ if (ddl_context->memtype == MEMTYPE_SMI_KERNEL) {
+ ddl_pmem_free(&ddl_context->dram_base_a);
+ ddl_pmem_free(&ddl_context->dram_base_b);
+ }
+ ddl_pmem_free(&ddl_context->metadata_shared_input);
+ ddl_fw_release();
+}
+
+void ddl_release_client_internal_buffers(struct ddl_client_context *ddl)
+{
+ if (ddl->decoding) {
+ struct ddl_decoder_data *decoder =
+ &(ddl->codec_data.decoder);
+ kfree(decoder->dp_buf.dec_pic_buffers);
+ decoder->dp_buf.dec_pic_buffers = NULL;
+ ddl_vidc_decode_dynamic_property(ddl, false);
+ decoder->decode_config.sequence_header_len = 0;
+ decoder->decode_config.sequence_header = NULL;
+ decoder->dpb_mask.client_mask = 0;
+ decoder->dpb_mask.hw_mask = 0;
+ decoder->dp_buf.no_of_dec_pic_buf = 0;
+ decoder->dynamic_prop_change = 0;
+ ddl_free_dec_hw_buffers(ddl);
+ } else {
+ struct ddl_encoder_data *encoder =
+ &(ddl->codec_data.encoder);
+ ddl_pmem_free(&encoder->seq_header);
+ ddl_vidc_encode_dynamic_property(ddl, false);
+ encoder->dynamic_prop_change = 0;
+ ddl_free_enc_hw_buffers(ddl);
+ }
+}
+
+u32 ddl_codec_type_transact(struct ddl_client_context *ddl,
+ u32 remove, enum vcd_codec requested_codec)
+{
+ if (requested_codec > VCD_CODEC_VC1_RCV ||
+ requested_codec < VCD_CODEC_H264)
+ return false;
+ if (!ddl->decoding && requested_codec != VCD_CODEC_MPEG4 &&
+ requested_codec != VCD_CODEC_H264 &&
+ requested_codec != VCD_CODEC_H263)
+ return false;
+
+ return true;
+}
+
+u32 ddl_take_command_channel(struct ddl_context *ddl_context,
+ struct ddl_client_context *ddl, void *client_data)
+{
+ u32 status = true;
+
+ if (!ddl_context->current_ddl[0]) {
+ ddl_context->current_ddl[0] = ddl;
+ ddl->client_data = client_data;
+ ddl->command_channel = 0;
+ } else if (!ddl_context->current_ddl[1]) {
+ ddl_context->current_ddl[1] = ddl;
+ ddl->client_data = client_data;
+ ddl->command_channel = 1;
+ } else
+ status = false;
+ if (status) {
+ if (ddl_context->current_ddl[0] &&
+ ddl_context->current_ddl[1])
+ DDL_BUSY(ddl_context);
+ else
+ DDL_RUN(ddl_context);
+ }
+ return status;
+}
+
+void ddl_release_command_channel(struct ddl_context *ddl_context,
+ u32 command_channel)
+{
+ ddl_context->current_ddl[command_channel]->client_data = NULL;
+ ddl_context->current_ddl[command_channel] = NULL;
+ if (!ddl_context->current_ddl[0] &&
+ !ddl_context->current_ddl[1])
+ DDL_IDLE(ddl_context);
+ else
+ DDL_RUN(ddl_context);
+}
+
+struct ddl_client_context *ddl_get_current_ddl_client_for_channel_id(
+ struct ddl_context *ddl_context, u32 channel_id)
+{
+ struct ddl_client_context *ddl;
+
+ if (ddl_context->current_ddl[0] && channel_id ==
+ ddl_context->current_ddl[0]->command_channel)
+ ddl = ddl_context->current_ddl[0];
+ else if (ddl_context->current_ddl[1] && channel_id ==
+ ddl_context->current_ddl[1]->command_channel)
+ ddl = ddl_context->current_ddl[1];
+ else {
+ DDL_MSG_LOW("STATE-CRITICAL-FRMRUN");
+ DDL_MSG_ERROR("Unexpected channel ID = %d", channel_id);
+ ddl = NULL;
+ }
+ return ddl;
+}
+
+struct ddl_client_context *ddl_get_current_ddl_client_for_command(
+ struct ddl_context *ddl_context,
+ enum ddl_cmd_state cmd_state)
+{
+ struct ddl_client_context *ddl;
+
+ if (ddl_context->current_ddl[0] &&
+ cmd_state == ddl_context->current_ddl[0]->cmd_state)
+ ddl = ddl_context->current_ddl[0];
+ else if (ddl_context->current_ddl[1] &&
+ cmd_state == ddl_context->current_ddl[1]->cmd_state)
+ ddl = ddl_context->current_ddl[1];
+ else {
+ DDL_MSG_LOW("STATE-CRITICAL-FRMRUN");
+ DDL_MSG_ERROR("Error: Unexpected cmd_state = %d",
+ cmd_state);
+ ddl = NULL;
+ }
+ return ddl;
+}
+
+u32 ddl_get_yuv_buf_size(u32 width, u32 height, u32 format)
+{
+ u32 mem_size, width_round_up, height_round_up, align;
+
+ width_round_up = width;
+ height_round_up = height;
+ if (format == DDL_YUV_BUF_TYPE_TILE) {
+ width_round_up = DDL_ALIGN(width, DDL_TILE_ALIGN_WIDTH);
+ height_round_up = DDL_ALIGN(height, DDL_TILE_ALIGN_HEIGHT);
+ align = DDL_TILE_MULTIPLY_FACTOR;
+ }
+ if (format == DDL_YUV_BUF_TYPE_LINEAR) {
+ width_round_up = DDL_ALIGN(width, DDL_LINEAR_ALIGN_WIDTH);
+ align = DDL_LINEAR_MULTIPLY_FACTOR;
+ }
+ mem_size = (width_round_up * height_round_up);
+ mem_size = DDL_ALIGN(mem_size, align);
+ return mem_size;
+}
+void ddl_free_dec_hw_buffers(struct ddl_client_context *ddl)
+{
+ struct ddl_dec_buffers *dec_bufs =
+ &ddl->codec_data.decoder.hw_bufs;
+ ddl_pmem_free(&dec_bufs->h264_nb_ip);
+ ddl_pmem_free(&dec_bufs->h264_vert_nb_mv);
+ ddl_pmem_free(&dec_bufs->nb_dcac);
+ ddl_pmem_free(&dec_bufs->upnb_mv);
+ ddl_pmem_free(&dec_bufs->sub_anchor_mv);
+ ddl_pmem_free(&dec_bufs->overlay_xform);
+ ddl_pmem_free(&dec_bufs->bit_plane3);
+ ddl_pmem_free(&dec_bufs->bit_plane2);
+ ddl_pmem_free(&dec_bufs->bit_plane1);
+ ddl_pmem_free(&dec_bufs->stx_parser);
+ ddl_pmem_free(&dec_bufs->desc);
+ ddl_pmem_free(&dec_bufs->context);
+ memset(dec_bufs, 0, sizeof(struct ddl_dec_buffers));
+}
+
+void ddl_free_enc_hw_buffers(struct ddl_client_context *ddl)
+{
+ struct ddl_enc_buffers *enc_bufs =
+ &ddl->codec_data.encoder.hw_bufs;
+ u32 i;
+
+ for (i = 0; i < enc_bufs->dpb_count; i++) {
+ ddl_pmem_free(&enc_bufs->dpb_y[i]);
+ ddl_pmem_free(&enc_bufs->dpb_c[i]);
+ }
+ ddl_pmem_free(&enc_bufs->mv);
+ ddl_pmem_free(&enc_bufs->col_zero);
+ ddl_pmem_free(&enc_bufs->md);
+ ddl_pmem_free(&enc_bufs->pred);
+ ddl_pmem_free(&enc_bufs->nbor_info);
+ ddl_pmem_free(&enc_bufs->acdc_coef);
+ ddl_pmem_free(&enc_bufs->context);
+ memset(enc_bufs, 0, sizeof(struct ddl_enc_buffers));
+}
+
+u32 ddl_get_input_frame_from_pool(struct ddl_client_context *ddl,
+ u8 *input_buffer_address)
+{
+ u32 vcd_status = VCD_S_SUCCESS, i, found = false;
+
+ for (i = 0; i < DDL_MAX_NUM_IN_INPUTFRAME_POOL && !found; i++) {
+ if (input_buffer_address ==
+ ddl->input_frame_pool[i].vcd_frm.physical) {
+ found = true;
+ ddl->input_frame = ddl->input_frame_pool[i];
+ memset(&ddl->input_frame_pool[i], 0,
+ sizeof(struct ddl_frame_data_tag));
+ }
+ }
+ if (!found)
+ vcd_status = VCD_ERR_FAIL;
+
+ return vcd_status;
+}
+
+u32 ddl_insert_input_frame_to_pool(struct ddl_client_context *ddl,
+ struct ddl_frame_data_tag *ddl_input_frame)
+{
+ u32 vcd_status = VCD_S_SUCCESS, i, found = false;
+
+ for (i = 0; i < DDL_MAX_NUM_IN_INPUTFRAME_POOL && !found; i++) {
+ if (!ddl->input_frame_pool[i].vcd_frm.physical) {
+ found = true;
+ ddl->input_frame_pool[i] = *ddl_input_frame;
+ }
+ }
+ if (!found)
+ vcd_status = VCD_ERR_FAIL;
+
+ return vcd_status;
+}
+
+void ddl_calc_dec_hw_buffers_size(enum vcd_codec codec, u32 width,
+ u32 height, u32 dpb, struct ddl_dec_buffer_size *buf_size)
+{
+ u32 sz_dpb0 = 0, sz_dpb1 = 0, sz_mv = 0;
+ u32 sz_luma = 0, sz_chroma = 0, sz_nb_dcac = 0, sz_upnb_mv = 0;
+ u32 sz_sub_anchor_mv = 0, sz_overlap_xform = 0, sz_bit_plane3 = 0;
+ u32 sz_bit_plane2 = 0, sz_bit_plane1 = 0, sz_stx_parser = 0;
+ u32 sz_desc, sz_cpb, sz_context, sz_vert_nb_mv = 0, sz_nb_ip = 0;
+
+ if (codec == VCD_CODEC_H264) {
+ sz_mv = ddl_get_yuv_buf_size(width,
+ height>>2, DDL_YUV_BUF_TYPE_TILE);
+ sz_nb_ip = DDL_KILO_BYTE(32);
+ sz_vert_nb_mv = DDL_KILO_BYTE(16);
+ } else {
+ if ((codec == VCD_CODEC_MPEG4) ||
+ (codec == VCD_CODEC_DIVX_3) ||
+ (codec == VCD_CODEC_DIVX_4) ||
+ (codec == VCD_CODEC_DIVX_5) ||
+ (codec == VCD_CODEC_DIVX_6) ||
+ (codec == VCD_CODEC_XVID) ||
+ (codec == VCD_CODEC_H263)) {
+ sz_nb_dcac = DDL_KILO_BYTE(16);
+ sz_upnb_mv = DDL_KILO_BYTE(68);
+ sz_sub_anchor_mv = DDL_KILO_BYTE(136);
+ sz_overlap_xform = DDL_KILO_BYTE(32);
+ if (codec != VCD_CODEC_H263)
+ sz_stx_parser = DDL_KILO_BYTE(68);
+ } else if ((codec == VCD_CODEC_VC1) ||
+ (codec == VCD_CODEC_VC1_RCV)) {
+ sz_nb_dcac = DDL_KILO_BYTE(16);
+ sz_upnb_mv = DDL_KILO_BYTE(68);
+ sz_sub_anchor_mv = DDL_KILO_BYTE(136);
+ sz_overlap_xform = DDL_KILO_BYTE(32);
+ sz_bit_plane3 = DDL_KILO_BYTE(2);
+ sz_bit_plane2 = DDL_KILO_BYTE(2);
+ sz_bit_plane1 = DDL_KILO_BYTE(2);
+ }
+ }
+ sz_desc = DDL_KILO_BYTE(128);
+ sz_cpb = VCD_DEC_CPB_SIZE;
+ if (codec == VCD_CODEC_H264)
+ sz_context = DDL_FW_H264DEC_CONTEXT_SPACE_SIZE;
+ else
+ sz_context = DDL_FW_OTHER_CONTEXT_SPACE_SIZE;
+ if (buf_size) {
+ buf_size->sz_dpb0 = sz_dpb0;
+ buf_size->sz_dpb1 = sz_dpb1;
+ buf_size->sz_mv = sz_mv;
+ buf_size->sz_vert_nb_mv = sz_vert_nb_mv;
+ buf_size->sz_nb_ip = sz_nb_ip;
+ buf_size->sz_luma = sz_luma;
+ buf_size->sz_chroma = sz_chroma;
+ buf_size->sz_nb_dcac = sz_nb_dcac;
+ buf_size->sz_upnb_mv = sz_upnb_mv;
+ buf_size->sz_sub_anchor_mv = sz_sub_anchor_mv;
+ buf_size->sz_overlap_xform = sz_overlap_xform;
+ buf_size->sz_bit_plane3 = sz_bit_plane3;
+ buf_size->sz_bit_plane2 = sz_bit_plane2;
+ buf_size->sz_bit_plane1 = sz_bit_plane1;
+ buf_size->sz_stx_parser = sz_stx_parser;
+ buf_size->sz_desc = sz_desc;
+ buf_size->sz_cpb = sz_cpb;
+ buf_size->sz_context = sz_context;
+ }
+}
+
+u32 ddl_allocate_dec_hw_buffers(struct ddl_client_context *ddl)
+{
+ struct ddl_dec_buffers *dec_bufs;
+ struct ddl_dec_buffer_size buf_size;
+ u32 status = VCD_S_SUCCESS, dpb = 0;
+ u32 width = 0, height = 0;
+ u8 *ptr;
+
+ dec_bufs = &ddl->codec_data.decoder.hw_bufs;
+ ddl_calc_dec_hw_buffers_size(ddl->codec_data.decoder.
+ codec.codec, width, height, dpb, &buf_size);
+ if (buf_size.sz_context > 0) {
+ ptr = ddl_pmem_alloc(&dec_bufs->context, buf_size.sz_context,
+ DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (buf_size.sz_nb_ip > 0) {
+ ptr = ddl_pmem_alloc(&dec_bufs->h264_nb_ip, buf_size.sz_nb_ip,
+ DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (buf_size.sz_vert_nb_mv > 0) {
+ ptr = ddl_pmem_alloc(&dec_bufs->h264_vert_nb_mv,
+ buf_size.sz_vert_nb_mv, DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (buf_size.sz_nb_dcac > 0) {
+ ptr = ddl_pmem_alloc(&dec_bufs->nb_dcac, buf_size.sz_nb_dcac,
+ DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (buf_size.sz_upnb_mv > 0) {
+ ptr = ddl_pmem_alloc(&dec_bufs->upnb_mv, buf_size.sz_upnb_mv,
+ DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (buf_size.sz_sub_anchor_mv > 0) {
+ ptr = ddl_pmem_alloc(&dec_bufs->sub_anchor_mv,
+ buf_size.sz_sub_anchor_mv, DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (buf_size.sz_overlap_xform > 0) {
+ ptr = ddl_pmem_alloc(&dec_bufs->overlay_xform,
+ buf_size.sz_overlap_xform, DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (buf_size.sz_bit_plane3 > 0) {
+ ptr = ddl_pmem_alloc(&dec_bufs->bit_plane3,
+ buf_size.sz_bit_plane3, DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (buf_size.sz_bit_plane2 > 0) {
+ ptr = ddl_pmem_alloc(&dec_bufs->bit_plane2,
+ buf_size.sz_bit_plane2, DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (buf_size.sz_bit_plane1 > 0) {
+ ptr = ddl_pmem_alloc(&dec_bufs->bit_plane1,
+ buf_size.sz_bit_plane1, DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (buf_size.sz_stx_parser > 0) {
+ ptr = ddl_pmem_alloc(&dec_bufs->stx_parser,
+ buf_size.sz_stx_parser, DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (buf_size.sz_desc > 0) {
+ ptr = ddl_pmem_alloc(&dec_bufs->desc, buf_size.sz_desc,
+ DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (status)
+ ddl_free_dec_hw_buffers(ddl);
+ return status;
+}
+
+u32 ddl_calc_enc_hw_buffers_size(enum vcd_codec codec, u32 width,
+ u32 height, enum vcd_yuv_buffer_format input_format,
+ struct ddl_client_context *ddl,
+ struct ddl_enc_buffer_size *buf_size)
+{
+ u32 status = VCD_S_SUCCESS, mb_x, mb_y;
+ u32 sz_cur_y, sz_cur_c, sz_dpb_y, sz_dpb_c, sz_strm = 0, sz_mv;
+ u32 sz_md = 0, sz_pred = 0, sz_nbor_info = 0 , sz_acdc_coef = 0;
+ u32 sz_mb_info = 0, sz_context, sz_col_zero = 0;
+
+ mb_x = (width + 15) / 16;
+ mb_y = (height + 15) / 16;
+ sz_dpb_y = ddl_get_yuv_buf_size(width,
+ height, DDL_YUV_BUF_TYPE_TILE);
+ sz_dpb_c = ddl_get_yuv_buf_size(width, height>>1,
+ DDL_YUV_BUF_TYPE_TILE);
+ if (input_format ==
+ VCD_BUFFER_FORMAT_NV12_16M2KA) {
+ sz_cur_y = ddl_get_yuv_buf_size(width, height,
+ DDL_YUV_BUF_TYPE_LINEAR);
+ sz_cur_c = ddl_get_yuv_buf_size(width, height>>1,
+ DDL_YUV_BUF_TYPE_LINEAR);
+ } else if (VCD_BUFFER_FORMAT_TILE_4x2 == input_format) {
+ sz_cur_y = sz_dpb_y;
+ sz_cur_c = sz_dpb_c;
+ } else
+ status = VCD_ERR_NOT_SUPPORTED;
+ if (!status) {
+ sz_strm = DDL_ALIGN(ddl_get_yuv_buf_size(width, height,
+ DDL_YUV_BUF_TYPE_LINEAR) + ddl_get_yuv_buf_size(width,
+ height/2, DDL_YUV_BUF_TYPE_LINEAR), DDL_KILO_BYTE(4));
+ sz_mv = DDL_ALIGN(2 * mb_x * 8, DDL_KILO_BYTE(2));
+ if ((codec == VCD_CODEC_MPEG4) ||
+ (codec == VCD_CODEC_H264)) {
+ sz_col_zero = DDL_ALIGN(((mb_x * mb_y + 7) / 8) *
+ 8, DDL_KILO_BYTE(2));
+ }
+ if ((codec == VCD_CODEC_MPEG4) ||
+ (codec == VCD_CODEC_H263)) {
+ sz_acdc_coef = DDL_ALIGN((width / 2) * 8,
+ DDL_KILO_BYTE(2));
+ } else if (codec == VCD_CODEC_H264) {
+ sz_md = DDL_ALIGN(mb_x * 48, DDL_KILO_BYTE(2));
+ sz_pred = DDL_ALIGN(2 * 8 * 1024, DDL_KILO_BYTE(2));
+ if (ddl) {
+ if (ddl->codec_data.encoder.
+ entropy_control.entropy_sel ==
+ VCD_ENTROPY_SEL_CAVLC)
+ sz_nbor_info = DDL_ALIGN(8 * 8 * mb_x,
+ DDL_KILO_BYTE(2));
+ else if (ddl->codec_data.encoder.
+ entropy_control.entropy_sel ==
+ VCD_ENTROPY_SEL_CABAC)
+ sz_nbor_info = DDL_ALIGN(8 * 24 *
+ mb_x, DDL_KILO_BYTE(2));
+ if ((ddl->codec_data.encoder.
+ mb_info_enable) &&
+ (codec == VCD_CODEC_H264)) {
+ sz_mb_info = DDL_ALIGN(mb_x * mb_y *
+ 6 * 8, DDL_KILO_BYTE(2));
+ }
+ }
+ } else {
+ sz_nbor_info = DDL_ALIGN(8 * 24 * mb_x,
+ DDL_KILO_BYTE(2));
+ sz_mb_info = DDL_ALIGN(mb_x * mb_y * 6 * 8,
+ DDL_KILO_BYTE(2));
+ }
+ sz_context = DDL_FW_OTHER_CONTEXT_SPACE_SIZE;
+ if (buf_size) {
+ buf_size->sz_cur_y = sz_cur_y;
+ buf_size->sz_cur_c = sz_cur_c;
+ buf_size->sz_dpb_y = sz_dpb_y;
+ buf_size->sz_dpb_c = sz_dpb_c;
+ buf_size->sz_strm = sz_strm;
+ buf_size->sz_mv = sz_mv;
+ buf_size->sz_col_zero = sz_col_zero;
+ buf_size->sz_md = sz_md;
+ buf_size->sz_pred = sz_pred;
+ buf_size->sz_nbor_info = sz_nbor_info;
+ buf_size->sz_acdc_coef = sz_acdc_coef;
+ buf_size->sz_mb_info = sz_mb_info;
+ buf_size->sz_context = sz_context;
+ }
+ }
+ return status;
+}
+
+u32 ddl_allocate_enc_hw_buffers(struct ddl_client_context *ddl)
+{
+ struct ddl_enc_buffers *enc_bufs;
+ struct ddl_enc_buffer_size buf_size;
+ void *ptr;
+ u32 status = VCD_S_SUCCESS;
+
+ enc_bufs = &ddl->codec_data.encoder.hw_bufs;
+ enc_bufs->dpb_count = DDL_ENC_MIN_DPB_BUFFERS;
+
+ if ((ddl->codec_data.encoder.i_period.b_frames >
+ DDL_MIN_NUM_OF_B_FRAME) ||
+ (ddl->codec_data.encoder.num_references_for_p_frame
+ > DDL_MIN_NUM_REF_FOR_P_FRAME))
+ enc_bufs->dpb_count = DDL_ENC_MAX_DPB_BUFFERS;
+ DDL_MSG_HIGH("Encoder num DPB buffers allocated = %d",
+ enc_bufs->dpb_count);
+
+ status = ddl_calc_enc_hw_buffers_size(
+ ddl->codec_data.encoder.codec.codec,
+ ddl->codec_data.encoder.frame_size.width,
+ ddl->codec_data.encoder.frame_size.height,
+ ddl->codec_data.encoder.buf_format.buffer_format,
+ ddl, &buf_size);
+ buf_size.sz_strm = ddl->codec_data.encoder.
+ client_output_buf_req.sz;
+ if (!status) {
+ enc_bufs->sz_dpb_y = buf_size.sz_dpb_y;
+ enc_bufs->sz_dpb_c = buf_size.sz_dpb_c;
+ if (buf_size.sz_mv > 0) {
+ ptr = ddl_pmem_alloc(&enc_bufs->mv, buf_size.sz_mv,
+ DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (buf_size.sz_col_zero > 0) {
+ ptr = ddl_pmem_alloc(&enc_bufs->col_zero,
+ buf_size.sz_col_zero, DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (buf_size.sz_md > 0) {
+ ptr = ddl_pmem_alloc(&enc_bufs->md, buf_size.sz_md,
+ DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (buf_size.sz_pred > 0) {
+ ptr = ddl_pmem_alloc(&enc_bufs->pred,
+ buf_size.sz_pred, DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (buf_size.sz_nbor_info > 0) {
+ ptr = ddl_pmem_alloc(&enc_bufs->nbor_info,
+ buf_size.sz_nbor_info, DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (buf_size.sz_acdc_coef > 0) {
+ ptr = ddl_pmem_alloc(&enc_bufs->acdc_coef,
+ buf_size.sz_acdc_coef, DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (buf_size.sz_mb_info > 0) {
+ ptr = ddl_pmem_alloc(&enc_bufs->mb_info,
+ buf_size.sz_mb_info, DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (buf_size.sz_context > 0) {
+ ptr = ddl_pmem_alloc(&enc_bufs->context,
+ buf_size.sz_context, DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (status)
+ ddl_free_enc_hw_buffers(ddl);
+ }
+ return status;
+}
+
+void ddl_decoder_chroma_dpb_change(struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_decoder_data *decoder = &ddl->codec_data.decoder;
+ struct ddl_frame_data_tag *frame =
+ &(decoder->dp_buf.dec_pic_buffers[0]);
+ u32 luma[DDL_MAX_BUFFER_COUNT];
+ u32 chroma[DDL_MAX_BUFFER_COUNT];
+ u32 luma_size, i, dpb;
+ luma_size = decoder->dpb_buf_size.size_y;
+ dpb = decoder->dp_buf.no_of_dec_pic_buf;
+ DDL_MSG_HIGH("%s Decoder num DPB buffers = %u Luma Size = %u"
+ __func__, dpb, luma_size);
+ if (dpb > DDL_MAX_BUFFER_COUNT)
+ dpb = DDL_MAX_BUFFER_COUNT;
+ for (i = 0; i < dpb; i++) {
+ luma[i] = DDL_OFFSET(
+ ddl_context->dram_base_a.align_physical_addr,
+ frame[i].vcd_frm.physical);
+ chroma[i] = luma[i] + luma_size;
+ DDL_MSG_LOW("%s Decoder Luma address = %x"
+ "Chroma address = %x", __func__, luma[i], chroma[i]);
+ }
+ vidc_1080p_set_decode_recon_buffers(dpb, luma, chroma);
+}
+
+u32 ddl_check_reconfig(struct ddl_client_context *ddl)
+{
+ u32 need_reconfig = true;
+ struct ddl_decoder_data *decoder = &ddl->codec_data.decoder;
+ if (decoder->cont_mode) {
+ if ((decoder->actual_output_buf_req.sz <=
+ decoder->client_output_buf_req.sz) &&
+ (decoder->actual_output_buf_req.actual_count <=
+ decoder->client_output_buf_req.actual_count)) {
+ need_reconfig = false;
+ if (decoder->min_dpb_num >
+ decoder->min_output_buf_req.min_count) {
+ decoder->min_output_buf_req =
+ decoder->actual_output_buf_req;
+ }
+ DDL_MSG_LOW("%s Decoder width = %u height = %u "
+ "Client width = %u height = %u\n",
+ __func__, decoder->frame_size.width,
+ decoder->frame_size.height,
+ decoder->client_frame_size.width,
+ decoder->client_frame_size.height);
+ }
+ } else {
+ if ((decoder->frame_size.width ==
+ decoder->client_frame_size.width) &&
+ (decoder->frame_size.height ==
+ decoder->client_frame_size.height) &&
+ (decoder->actual_output_buf_req.sz <=
+ decoder->client_output_buf_req.sz) &&
+ (decoder->actual_output_buf_req.min_count ==
+ decoder->client_output_buf_req.min_count) &&
+ (decoder->actual_output_buf_req.actual_count ==
+ decoder->client_output_buf_req.actual_count) &&
+ (decoder->frame_size.scan_lines ==
+ decoder->client_frame_size.scan_lines) &&
+ (decoder->frame_size.stride ==
+ decoder->client_frame_size.stride))
+ need_reconfig = false;
+ }
+ return need_reconfig;
+}
+
+void ddl_handle_reconfig(u32 res_change, struct ddl_client_context *ddl)
+{
+ if (res_change) {
+ DDL_MSG_LOW("%s Resolution change, start realloc\n",
+ __func__);
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_EOS_DONE;
+ ddl->cmd_state = DDL_CMD_EOS;
+ vidc_1080p_frame_start_realloc(ddl->instance_id);
+ }
+}
+
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
new file mode 100644
index 0000000..be46e97
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
@@ -0,0 +1,1638 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+
+#include "vcd_ddl.h"
+#include "vcd_ddl_shared_mem.h"
+#include "vcd_ddl_metadata.h"
+#include <linux/delay.h>
+
+static void ddl_decoder_input_done_callback(
+ struct ddl_client_context *ddl, u32 frame_transact_end);
+static u32 ddl_decoder_output_done_callback(
+ struct ddl_client_context *ddl, u32 frame_transact_end);
+static u32 ddl_get_decoded_frame(struct vcd_frame_data *frame,
+ enum vidc_1080p_decode_frame frame_type);
+static u32 ddl_get_encoded_frame(struct vcd_frame_data *frame,
+ enum vcd_codec codec,
+ enum vidc_1080p_encode_frame frame_type);
+static void ddl_get_dec_profile_level(struct ddl_decoder_data *decoder,
+ u32 profile, u32 level);
+static void ddl_handle_enc_frame_done(struct ddl_client_context *ddl);
+
+static void ddl_fw_status_done_callback(struct ddl_context *ddl_context)
+{
+ DDL_MSG_MED("ddl_fw_status_done_callback");
+ if (!DDLCOMMAND_STATE_IS(ddl_context, DDL_CMD_DMA_INIT)) {
+ DDL_MSG_ERROR("UNKWN_DMADONE");
+ } else {
+ DDL_MSG_LOW("FW_STATUS_DONE");
+ vidc_1080p_set_host2risc_cmd(VIDC_1080P_HOST2RISC_CMD_SYS_INIT,
+ ddl_context->fw_memory_size, 0, 0, 0);
+ }
+}
+
+static void ddl_sys_init_done_callback(struct ddl_context *ddl_context,
+ u32 fw_size)
+{
+ u32 vcd_status = VCD_S_SUCCESS;
+
+ DDL_MSG_MED("ddl_sys_init_done_callback");
+ if (!DDLCOMMAND_STATE_IS(ddl_context, DDL_CMD_DMA_INIT)) {
+ DDL_MSG_ERROR("UNKNOWN_SYS_INIT_DONE");
+ } else {
+ ddl_context->cmd_state = DDL_CMD_INVALID;
+ DDL_MSG_LOW("SYS_INIT_DONE");
+ vidc_1080p_get_fw_version(&ddl_context->fw_version);
+ if (ddl_context->fw_memory_size >= fw_size) {
+ ddl_context->device_state = DDL_DEVICE_INITED;
+ vcd_status = VCD_S_SUCCESS;
+ } else
+ vcd_status = VCD_ERR_FAIL;
+ ddl_context->ddl_callback(VCD_EVT_RESP_DEVICE_INIT,
+ vcd_status, NULL, 0, NULL,
+ ddl_context->client_data);
+ DDL_IDLE(ddl_context);
+ }
+}
+
+static void ddl_decoder_eos_done_callback(
+ struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+
+ if (!ddl->decoding) {
+ DDL_MSG_ERROR("STATE-CRITICAL-EOSDONE");
+ ddl_client_fatal_cb(ddl);
+ } else {
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME;
+ DDL_MSG_LOW("EOS_DONE");
+ ddl_context->ddl_callback(VCD_EVT_RESP_EOS_DONE,
+ VCD_S_SUCCESS, NULL, 0, (u32 *)ddl,
+ ddl->client_data);
+ ddl_release_command_channel(ddl_context,
+ ddl->command_channel);
+ }
+}
+
+static u32 ddl_channel_set_callback(struct ddl_context *ddl_context,
+ u32 instance_id)
+{
+ struct ddl_client_context *ddl;
+ u32 ret = false;
+
+ DDL_MSG_MED("ddl_channel_open_callback");
+ ddl = ddl_get_current_ddl_client_for_command(ddl_context,
+ DDL_CMD_CHANNEL_SET);
+ if (ddl) {
+ ddl->cmd_state = DDL_CMD_INVALID;
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_CHDONE)) {
+ DDL_MSG_ERROR("STATE-CRITICAL-CHSET");
+ ddl_release_command_channel(ddl_context,
+ ddl->command_channel);
+ } else {
+ DDL_MSG_LOW("CH_SET_DONE");
+ DDL_MSG_LOW("ddl_state_transition: %s ~~>"
+ "DDL_CLIENT_WAIT_FOR_INITCODEC",
+ ddl_get_state_string(ddl->client_state));
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_INITCODEC;
+ ddl->instance_id = instance_id;
+ if (ddl->decoding) {
+ if (vidc_msg_timing)
+ ddl_calc_core_proc_time(__func__,
+ DEC_OP_TIME);
+ if (ddl->codec_data.decoder.header_in_start)
+ ddl_vidc_decode_init_codec(ddl);
+ else {
+ ddl_context->ddl_callback(
+ VCD_EVT_RESP_START,
+ VCD_S_SUCCESS, NULL, 0,
+ (u32 *)ddl,
+ ddl->client_data);
+ ddl_release_command_channel(
+ ddl_context,
+ ddl->command_channel);
+ ret = true;
+ }
+ } else
+ ddl_vidc_encode_init_codec(ddl);
+ }
+ }
+ return ret;
+}
+
+static u32 ddl_encoder_seq_done_callback(struct ddl_context *ddl_context,
+ struct ddl_client_context *ddl)
+{
+ struct ddl_encoder_data *encoder;
+
+ DDL_MSG_MED("ddl_encoder_seq_done_callback");
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_INITCODECDONE)) {
+ DDL_MSG_ERROR("STATE-CRITICAL-INITCODEC");
+ ddl_client_fatal_cb(ddl);
+ return true;
+ }
+ if (vidc_msg_timing)
+ ddl_calc_core_proc_time(__func__, ENC_OP_TIME);
+ ddl->cmd_state = DDL_CMD_INVALID;
+ DDL_MSG_LOW("ddl_state_transition: %s ~~> DDL_CLIENT_WAIT_FOR_FRAME",
+ ddl_get_state_string(ddl->client_state));
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME;
+ DDL_MSG_LOW("INIT_CODEC_DONE");
+ encoder = &ddl->codec_data.encoder;
+ vidc_1080p_get_encoder_sequence_header_size(
+ &encoder->seq_header_length);
+ if ((encoder->codec.codec == VCD_CODEC_H264) &&
+ (encoder->profile.profile == VCD_PROFILE_H264_BASELINE))
+ if ((encoder->seq_header.align_virtual_addr) &&
+ (encoder->seq_header_length > 6))
+ encoder->seq_header.align_virtual_addr[6] = 0xC0;
+ ddl_context->ddl_callback(VCD_EVT_RESP_START, VCD_S_SUCCESS,
+ NULL, 0, (u32 *) ddl, ddl->client_data);
+ ddl_release_command_channel(ddl_context,
+ ddl->command_channel);
+ return true;
+}
+
+static void parse_hdr_size_data(struct ddl_client_context *ddl,
+ struct vidc_1080p_seq_hdr_info *seq_hdr_info)
+{
+ u32 progressive;
+ struct ddl_decoder_data *decoder = &ddl->codec_data.decoder;
+ if (decoder->output_order == VCD_DEC_ORDER_DISPLAY) {
+ decoder->frame_size.width = seq_hdr_info->img_size_x;
+ decoder->frame_size.height = seq_hdr_info->img_size_y;
+ progressive = seq_hdr_info->disp_progressive;
+ } else {
+ vidc_sm_get_dec_order_resl(
+ &ddl->shared_mem[ddl->command_channel],
+ &decoder->frame_size.width,
+ &decoder->frame_size.height);
+ progressive = seq_hdr_info->dec_progressive;
+ }
+ decoder->min_dpb_num = seq_hdr_info->min_num_dpb;
+ vidc_sm_get_min_yc_dpb_sizes(
+ &ddl->shared_mem[ddl->command_channel],
+ &seq_hdr_info->min_luma_dpb_size,
+ &seq_hdr_info->min_chroma_dpb_size);
+ decoder->y_cb_cr_size = seq_hdr_info->min_luma_dpb_size +
+ seq_hdr_info->min_chroma_dpb_size;
+ decoder->dpb_buf_size.size_yuv = decoder->y_cb_cr_size;
+ decoder->dpb_buf_size.size_y =
+ seq_hdr_info->min_luma_dpb_size;
+ decoder->dpb_buf_size.size_c =
+ seq_hdr_info->min_chroma_dpb_size;
+ decoder->progressive_only = progressive ? false : true;
+}
+
+static void parse_hdr_crop_data(struct ddl_client_context *ddl,
+ struct vidc_1080p_seq_hdr_info *seq_hdr_info)
+{
+ struct ddl_decoder_data *decoder = &ddl->codec_data.decoder;
+ u32 crop_exists = (decoder->output_order == VCD_DEC_ORDER_DISPLAY) ?
+ seq_hdr_info->disp_crop_exists : seq_hdr_info->dec_crop_exists;
+ if (crop_exists) {
+ if (decoder->output_order ==
+ VCD_DEC_ORDER_DISPLAY)
+ vidc_sm_get_crop_info(
+ &ddl->shared_mem[ddl->command_channel],
+ &seq_hdr_info->crop_left_offset,
+ &seq_hdr_info->crop_right_offset,
+ &seq_hdr_info->crop_top_offset,
+ &seq_hdr_info->crop_bottom_offset);
+ else
+ vidc_sm_get_dec_order_crop_info(
+ &ddl->shared_mem[ddl->command_channel],
+ &seq_hdr_info->crop_left_offset,
+ &seq_hdr_info->crop_right_offset,
+ &seq_hdr_info->crop_top_offset,
+ &seq_hdr_info->crop_bottom_offset);
+ decoder->frame_size.width -=
+ seq_hdr_info->crop_right_offset +
+ seq_hdr_info->crop_left_offset;
+ decoder->frame_size.height -=
+ seq_hdr_info->crop_top_offset +
+ seq_hdr_info->crop_bottom_offset;
+ }
+}
+
+static u32 ddl_decoder_seq_done_callback(struct ddl_context *ddl_context,
+ struct ddl_client_context *ddl)
+{
+ struct ddl_decoder_data *decoder = &ddl->codec_data.decoder;
+ struct vidc_1080p_seq_hdr_info seq_hdr_info;
+ u32 process_further = true;
+ struct ddl_profile_info_type disp_profile_info;
+
+ DDL_MSG_MED("ddl_decoder_seq_done_callback");
+ if (!ddl->decoding ||
+ !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_INITCODECDONE)) {
+ DDL_MSG_ERROR("STATE-CRITICAL-HDDONE");
+ ddl_client_fatal_cb(ddl);
+ } else {
+ if (vidc_msg_timing)
+ ddl_calc_core_proc_time(__func__, DEC_OP_TIME);
+ ddl->cmd_state = DDL_CMD_INVALID;
+ DDL_MSG_LOW("ddl_state_transition: %s ~~>"
+ "DDL_CLIENT_WAIT_FOR_DPB",
+ ddl_get_state_string(ddl->client_state));
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_DPB;
+ DDL_MSG_LOW("HEADER_DONE");
+ vidc_1080p_get_decode_seq_start_result(&seq_hdr_info);
+ parse_hdr_size_data(ddl, &seq_hdr_info);
+ if (!seq_hdr_info.img_size_x || !seq_hdr_info.img_size_y) {
+ DDL_MSG_ERROR("FATAL:ZeroImageSize");
+ ddl_client_fatal_cb(ddl);
+ return process_further;
+ }
+ vidc_sm_get_profile_info(&ddl->shared_mem
+ [ddl->command_channel], &disp_profile_info);
+ disp_profile_info.pic_profile = seq_hdr_info.profile;
+ disp_profile_info.pic_level = seq_hdr_info.level;
+ ddl_get_dec_profile_level(decoder, seq_hdr_info.profile,
+ seq_hdr_info.level);
+ switch (decoder->codec.codec) {
+ case VCD_CODEC_H264:
+ if (decoder->profile.profile == VCD_PROFILE_H264_HIGH ||
+ decoder->profile.profile ==
+ VCD_PROFILE_UNKNOWN) {
+ if ((disp_profile_info.chroma_format_idc >
+ VIDC_1080P_IDCFORMAT_420) ||
+ (disp_profile_info.bit_depth_luma_minus8
+ || disp_profile_info.
+ bit_depth_chroma_minus8)) {
+ DDL_MSG_ERROR("Unsupported H.264 "
+ "feature: IDC format : %d, Bitdepth: %d",
+ disp_profile_info.
+ chroma_format_idc,
+ (disp_profile_info.
+ bit_depth_luma_minus8
+ || disp_profile_info.
+ bit_depth_chroma_minus8));
+ ddl_client_fatal_cb(ddl);
+ return process_further;
+ }
+ }
+ break;
+ case VCD_CODEC_MPEG4:
+ case VCD_CODEC_DIVX_4:
+ case VCD_CODEC_DIVX_5:
+ case VCD_CODEC_DIVX_6:
+ case VCD_CODEC_XVID:
+ if (seq_hdr_info.data_partition)
+ if ((seq_hdr_info.img_size_x *
+ seq_hdr_info.img_size_y) > (720 * 576)) {
+ DDL_MSG_ERROR("Unsupported DP clip");
+ ddl_client_fatal_cb(ddl);
+ return process_further;
+ }
+ break;
+ default:
+ break;
+ }
+ ddl_calculate_stride(&decoder->frame_size,
+ !decoder->progressive_only);
+ decoder->frame_size.scan_lines =
+ DDL_ALIGN(decoder->frame_size.height, DDL_TILE_ALIGN_HEIGHT);
+ decoder->frame_size.stride =
+ DDL_ALIGN(decoder->frame_size.width, DDL_TILE_ALIGN_WIDTH);
+ parse_hdr_crop_data(ddl, &seq_hdr_info);
+ if (decoder->codec.codec == VCD_CODEC_H264 &&
+ seq_hdr_info.level > VIDC_1080P_H264_LEVEL4) {
+ DDL_MSG_ERROR("WARNING: H264MaxLevelExceeded : %d",
+ seq_hdr_info.level);
+ }
+ ddl_set_default_decoder_buffer_req(decoder, false);
+ if (decoder->header_in_start) {
+ if (!(decoder->cont_mode) ||
+ (decoder->min_dpb_num >
+ decoder->client_output_buf_req.min_count) ||
+ (decoder->actual_output_buf_req.sz >
+ decoder->client_output_buf_req.sz)) {
+ decoder->client_frame_size =
+ decoder->frame_size;
+ decoder->client_output_buf_req =
+ decoder->actual_output_buf_req;
+ decoder->client_input_buf_req =
+ decoder->actual_input_buf_req;
+ }
+ ddl_context->ddl_callback(VCD_EVT_RESP_START,
+ VCD_S_SUCCESS, NULL, 0, (u32 *) ddl,
+ ddl->client_data);
+ ddl_release_command_channel(ddl_context,
+ ddl->command_channel);
+ } else {
+ u32 seq_hdr_only_frame = false;
+ u32 need_reconfig = false;
+ struct vcd_frame_data *input_vcd_frm =
+ &ddl->input_frame.vcd_frm;
+ need_reconfig = ddl_check_reconfig(ddl);
+ DDL_MSG_HIGH("%s : need_reconfig = %u\n", __func__,
+ need_reconfig);
+ if (input_vcd_frm->flags &
+ VCD_FRAME_FLAG_EOS) {
+ need_reconfig = false;
+ }
+ if (((input_vcd_frm->flags &
+ VCD_FRAME_FLAG_CODECCONFIG) &&
+ (!(input_vcd_frm->flags &
+ VCD_FRAME_FLAG_SYNCFRAME))) ||
+ input_vcd_frm->data_len <=
+ seq_hdr_info.dec_frm_size) {
+ seq_hdr_only_frame = true;
+ input_vcd_frm->offset +=
+ seq_hdr_info.dec_frm_size;
+ input_vcd_frm->data_len = 0;
+ input_vcd_frm->flags |=
+ VCD_FRAME_FLAG_CODECCONFIG;
+ ddl->input_frame.frm_trans_end =
+ !need_reconfig;
+ ddl_context->ddl_callback(
+ VCD_EVT_RESP_INPUT_DONE,
+ VCD_S_SUCCESS, &ddl->input_frame,
+ sizeof(struct ddl_frame_data_tag),
+ (u32 *) ddl, ddl->client_data);
+ } else {
+ if (decoder->codec.codec ==
+ VCD_CODEC_VC1_RCV) {
+ vidc_sm_set_start_byte_number(
+ &ddl->shared_mem
+ [ddl->command_channel],
+ seq_hdr_info.dec_frm_size);
+ }
+ }
+ if (need_reconfig) {
+ struct ddl_frame_data_tag *payload =
+ &ddl->input_frame;
+ u32 payload_size =
+ sizeof(struct ddl_frame_data_tag);
+ decoder->client_frame_size =
+ decoder->frame_size;
+ decoder->client_output_buf_req =
+ decoder->actual_output_buf_req;
+ decoder->client_input_buf_req =
+ decoder->actual_input_buf_req;
+ if (seq_hdr_only_frame) {
+ payload = NULL;
+ payload_size = 0;
+ }
+ DDL_MSG_HIGH("%s : sending port reconfig\n",
+ __func__);
+ ddl_context->ddl_callback(
+ VCD_EVT_IND_OUTPUT_RECONFIG,
+ VCD_S_SUCCESS, payload,
+ payload_size, (u32 *) ddl,
+ ddl->client_data);
+ }
+ if (!need_reconfig && !seq_hdr_only_frame) {
+ if (!ddl_vidc_decode_set_buffers(ddl))
+ process_further = false;
+ else {
+ DDL_MSG_ERROR("ddl_vidc_decode_set_"
+ "buffers failed");
+ ddl_client_fatal_cb(ddl);
+ }
+ } else
+ ddl_release_command_channel(ddl_context,
+ ddl->command_channel);
+ }
+ }
+ return process_further;
+}
+
+static u32 ddl_sequence_done_callback(struct ddl_context *ddl_context)
+{
+ struct ddl_client_context *ddl;
+ u32 channel_inst_id, ret;
+
+ vidc_1080p_get_returned_channel_inst_id(&channel_inst_id);
+ vidc_1080p_clear_returned_channel_inst_id();
+ ddl = ddl_get_current_ddl_client_for_channel_id(ddl_context,
+ ddl_context->response_cmd_ch_id);
+ if (!ddl) {
+ DDL_MSG_ERROR("UNKWN_SEQ_DONE");
+ ret = true;
+ } else {
+ if (ddl->decoding)
+ ret = ddl_decoder_seq_done_callback(ddl_context,
+ ddl);
+ else
+ ret = ddl_encoder_seq_done_callback(ddl_context,
+ ddl);
+ }
+ return ret;
+}
+
+static u32 ddl_dpb_buffers_set_done_callback(
+ struct ddl_context *ddl_context)
+{
+ struct ddl_client_context *ddl;
+ u32 channel_inst_id, ret_status = true;
+
+ DDL_MSG_MED("ddl_dpb_buffers_set_done_callback");
+ vidc_1080p_get_returned_channel_inst_id(&channel_inst_id);
+ vidc_1080p_clear_returned_channel_inst_id();
+ ddl = ddl_get_current_ddl_client_for_command(ddl_context,
+ DDL_CMD_DECODE_SET_DPB);
+ if (ddl) {
+ ddl->cmd_state = DDL_CMD_INVALID;
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_DPBDONE)) {
+ DDL_MSG_ERROR("STATE-CRITICAL-DPBDONE");
+ ddl_client_fatal_cb(ddl);
+ } else {
+ DDL_MSG_LOW("INTR_DPBDONE");
+ DDL_MSG_LOW("ddl_state_transition: %s ~~>"
+ "DDL_CLIENT_WAIT_FOR_FRAME",
+ ddl_get_state_string(ddl->client_state));
+ if (vidc_msg_timing) {
+ ddl_calc_core_proc_time(__func__, DEC_OP_TIME);
+ ddl_reset_core_time_variables(DEC_OP_TIME);
+ }
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME;
+ ddl_vidc_decode_frame_run(ddl);
+ ret_status = false;
+ }
+ }
+ return ret_status;
+}
+
+static void ddl_encoder_frame_run_callback(
+ struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_encoder_data *encoder =
+ &(ddl->codec_data.encoder);
+ struct vcd_frame_data *output_frame =
+ &(ddl->output_frame.vcd_frm);
+ u32 bottom_frame_tag;
+
+ DDL_MSG_MED("ddl_encoder_frame_run_callback");
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME_DONE) &&
+ !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_EOS_DONE)) {
+ DDL_MSG_ERROR("STATE-CRITICAL-ENCFRMRUN");
+ ddl_client_fatal_cb(ddl);
+ } else {
+ if (vidc_msg_timing)
+ ddl_calc_core_proc_time(__func__, ENC_OP_TIME);
+ DDL_MSG_LOW("ENC_FRM_RUN_DONE");
+ ddl->cmd_state = DDL_CMD_INVALID;
+ vidc_1080p_get_encode_frame_info(&encoder->enc_frame_info);
+ vidc_sm_get_frame_tags(&ddl->shared_mem
+ [ddl->command_channel],
+ &output_frame->ip_frm_tag, &bottom_frame_tag);
+
+ if (encoder->meta_data_enable_flag)
+ vidc_sm_get_metadata_status(&ddl->shared_mem
+ [ddl->command_channel],
+ &encoder->enc_frame_info.meta_data_exists);
+
+ if (encoder->enc_frame_info.enc_frame_size ||
+ (encoder->enc_frame_info.enc_frame ==
+ VIDC_1080P_ENCODE_FRAMETYPE_SKIPPED) ||
+ DDLCLIENT_STATE_IS(ddl,
+ DDL_CLIENT_WAIT_FOR_EOS_DONE)) {
+ u8 *input_buffer_address = NULL;
+ output_frame->data_len =
+ encoder->enc_frame_info.enc_frame_size;
+ output_frame->flags |= VCD_FRAME_FLAG_ENDOFFRAME;
+ ddl_get_encoded_frame(output_frame,
+ encoder->codec.codec,
+ encoder->enc_frame_info.enc_frame);
+ ddl_process_encoder_metadata(ddl);
+ ddl_vidc_encode_dynamic_property(ddl, false);
+ ddl->input_frame.frm_trans_end = false;
+ input_buffer_address = ddl_context->dram_base_a.\
+ align_physical_addr +
+ encoder->enc_frame_info.enc_luma_address;
+ ddl_get_input_frame_from_pool(ddl,
+ input_buffer_address);
+ ddl_context->ddl_callback(VCD_EVT_RESP_INPUT_DONE,
+ VCD_S_SUCCESS, &(ddl->input_frame),
+ sizeof(struct ddl_frame_data_tag),
+ (u32 *)ddl, ddl->client_data);
+ ddl->output_frame.frm_trans_end =
+ DDLCLIENT_STATE_IS(ddl,
+ DDL_CLIENT_WAIT_FOR_EOS_DONE) ? false : true;
+ ddl_context->ddl_callback(VCD_EVT_RESP_OUTPUT_DONE,
+ VCD_S_SUCCESS, &(ddl->output_frame),
+ sizeof(struct ddl_frame_data_tag),
+ (u32 *)ddl, ddl->client_data);
+
+ if (DDLCLIENT_STATE_IS(ddl,
+ DDL_CLIENT_WAIT_FOR_EOS_DONE) &&
+ encoder->i_period.b_frames) {
+ if ((ddl->extra_output_buf_count < 0) ||
+ (ddl->extra_output_buf_count >
+ encoder->i_period.b_frames)) {
+ DDL_MSG_ERROR("Invalid B frame output"
+ "buffer index");
+ } else {
+ struct vidc_1080p_enc_frame_start_param
+ enc_param;
+ ddl->output_frame = ddl->\
+ extra_output_frame[ddl->\
+ extra_output_buf_count];
+ ddl->\
+ extra_output_buf_count--;
+ output_frame =
+ &ddl->output_frame.\
+ vcd_frm;
+ memset(&enc_param, 0,
+ sizeof(enc_param));
+ enc_param.cmd_seq_num =
+ ++ddl_context->cmd_seq_num;
+ enc_param.inst_id = ddl->instance_id;
+ enc_param.shared_mem_addr_offset =
+ DDL_ADDR_OFFSET(ddl_context->\
+ dram_base_a, ddl->shared_mem
+ [ddl->command_channel]);
+ enc_param.stream_buffer_addr_offset =
+ DDL_OFFSET(ddl_context->\
+ dram_base_a.\
+ align_physical_addr,
+ output_frame->physical);
+ enc_param.stream_buffer_size =
+ encoder->client_output_buf_req.sz;
+ enc_param.encode =
+ VIDC_1080P_ENC_TYPE_LAST_FRAME_DATA;
+ ddl->cmd_state = DDL_CMD_ENCODE_FRAME;
+ ddl_context->vidc_encode_frame_start
+ [ddl->command_channel]
+ (&enc_param);
+ } } else {
+ DDL_MSG_LOW("ddl_state_transition: %s ~~>"
+ "DDL_CLIENT_WAIT_FOR_FRAME",
+ ddl_get_state_string(
+ ddl->client_state));
+ ddl->client_state =
+ DDL_CLIENT_WAIT_FOR_FRAME;
+ ddl_release_command_channel(ddl_context,
+ ddl->command_channel);
+ }
+ } else {
+ ddl_context->ddl_callback(
+ VCD_EVT_RESP_TRANSACTION_PENDING,
+ VCD_S_SUCCESS, NULL, 0, (u32 *)ddl,
+ ddl->client_data);
+ DDL_MSG_LOW("ddl_state_transition: %s ~~>"
+ "DDL_CLIENT_WAIT_FOR_FRAME",
+ ddl_get_state_string(ddl->client_state));
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME;
+ ddl_release_command_channel(ddl_context,
+ ddl->command_channel);
+ }
+ }
+}
+
+static void get_dec_status(struct ddl_client_context *ddl,
+ struct vidc_1080p_dec_disp_info *dec_disp_info,
+ u32 output_order, u32 *status, u32 *rsl_chg)
+{
+ if (output_order == VCD_DEC_ORDER_DISPLAY) {
+ vidc_1080p_get_display_frame_result(dec_disp_info);
+ *status = dec_disp_info->display_status;
+ *rsl_chg = dec_disp_info->disp_resl_change;
+ } else {
+ vidc_1080p_get_decode_frame_result(dec_disp_info);
+ vidc_sm_get_dec_order_resl(
+ &ddl->shared_mem[ddl->command_channel],
+ &dec_disp_info->img_size_x,
+ &dec_disp_info->img_size_y);
+ *status = dec_disp_info->decode_status;
+ *rsl_chg = dec_disp_info->dec_resl_change;
+ }
+}
+
+static u32 ddl_decoder_frame_run_callback(struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_decoder_data *decoder = &ddl->codec_data.decoder;
+ u32 callback_end = false, ret_status = false;
+ u32 eos_present = false, rsl_chg;
+ u32 more_field_needed, extended_rsl_chg;
+ enum vidc_1080p_display_status disp_status;
+ DDL_MSG_MED("ddl_decoder_frame_run_callback");
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME_DONE)) {
+ DDL_MSG_ERROR("STATE-CRITICAL-DECFRMRUN");
+ ddl_client_fatal_cb(ddl);
+ ret_status = true;
+ } else {
+ DDL_MSG_LOW("DEC_FRM_RUN_DONE");
+ ddl->cmd_state = DDL_CMD_INVALID;
+ get_dec_status(ddl, &ddl->codec_data.decoder.dec_disp_info,
+ ddl->codec_data.decoder.output_order,
+ &disp_status, &rsl_chg);
+
+ vidc_sm_get_extended_decode_status(
+ &ddl->shared_mem[ddl->command_channel],
+ &more_field_needed,
+ &extended_rsl_chg);
+ decoder->field_needed_for_prev_ip =
+ more_field_needed;
+ decoder->prev_ip_frm_tag =
+ ddl->input_frame.vcd_frm.ip_frm_tag;
+
+ ddl_vidc_decode_dynamic_property(ddl, false);
+ if (rsl_chg != DDL_RESL_CHANGE_NO_CHANGE) {
+ ddl_handle_reconfig(rsl_chg, ddl);
+ ret_status = false;
+ } else {
+ if ((VCD_FRAME_FLAG_EOS &
+ ddl->input_frame.vcd_frm.flags)) {
+ callback_end = false;
+ eos_present = true;
+ }
+ if (disp_status ==
+ VIDC_1080P_DISPLAY_STATUS_DECODE_ONLY ||
+ disp_status ==
+ VIDC_1080P_DISPLAY_STATUS_DECODE_AND_DISPLAY) {
+ if (!eos_present)
+ callback_end =
+ (disp_status ==
+ VIDC_1080P_DISPLAY_STATUS_DECODE_ONLY);
+ ddl_decoder_input_done_callback(ddl,
+ callback_end);
+ }
+ if (disp_status ==
+ VIDC_1080P_DISPLAY_STATUS_DECODE_AND_DISPLAY ||
+ disp_status ==
+ VIDC_1080P_DISPLAY_STATUS_DISPLAY_ONLY) {
+ if (!eos_present)
+ callback_end = (disp_status ==
+ VIDC_1080P_DISPLAY_STATUS_DECODE_AND_DISPLAY);
+ if (ddl_decoder_output_done_callback(
+ ddl, callback_end))
+ ret_status = true;
+ }
+ if (!ret_status) {
+ if (disp_status ==
+ VIDC_1080P_DISPLAY_STATUS_DISPLAY_ONLY
+ || disp_status ==
+ VIDC_1080P_DISPLAY_STATUS_DPB_EMPTY ||
+ disp_status ==
+ VIDC_1080P_DISPLAY_STATUS_NOOP) {
+ ddl_vidc_decode_frame_run(ddl);
+ } else if (eos_present)
+ ddl_vidc_decode_eos_run(ddl);
+ else {
+ ddl->client_state =
+ DDL_CLIENT_WAIT_FOR_FRAME;
+ ddl_release_command_channel(ddl_context,
+ ddl->command_channel);
+ ret_status = true;
+ }
+ }
+ }
+ }
+ return ret_status;
+}
+
+static u32 ddl_eos_frame_done_callback(
+ struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_decoder_data *decoder = &ddl->codec_data.decoder;
+ struct ddl_mask *dpb_mask = &decoder->dpb_mask;
+ u32 ret_status = true, rsl_chg, more_field_needed;
+ enum vidc_1080p_display_status disp_status;
+
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_EOS_DONE)) {
+ DDL_MSG_ERROR("STATE-CRITICAL-EOSFRMRUN");
+ ddl_client_fatal_cb(ddl);
+ } else {
+ DDL_MSG_LOW("EOS_FRM_RUN_DONE");
+ ddl->cmd_state = DDL_CMD_INVALID;
+ get_dec_status(ddl, &ddl->codec_data.decoder.dec_disp_info,
+ ddl->codec_data.decoder.output_order,
+ &disp_status, &rsl_chg);
+ vidc_sm_get_extended_decode_status(
+ &ddl->shared_mem[ddl->command_channel],
+ &more_field_needed, &rsl_chg);
+
+ decoder->field_needed_for_prev_ip =
+ more_field_needed;
+ decoder->prev_ip_frm_tag =
+ ddl->input_frame.vcd_frm.ip_frm_tag;
+ ddl_vidc_decode_dynamic_property(ddl, false);
+ if (disp_status ==
+ VIDC_1080P_DISPLAY_STATUS_DPB_EMPTY) {
+ if (rsl_chg) {
+ decoder->header_in_start = false;
+ decoder->decode_config.sequence_header =
+ ddl->input_frame.vcd_frm.physical;
+ decoder->decode_config.sequence_header_len =
+ ddl->input_frame.vcd_frm.data_len;
+ ddl_vidc_decode_init_codec(ddl);
+ ret_status = false;
+ } else
+ ddl_decoder_eos_done_callback(ddl);
+ } else {
+ struct vidc_1080p_dec_frame_start_param dec_param;
+ ret_status = false;
+ if (disp_status ==
+ VIDC_1080P_DISPLAY_STATUS_DISPLAY_ONLY) {
+ if (ddl_decoder_output_done_callback(
+ ddl, false))
+ ret_status = true;
+ } else if (disp_status !=
+ VIDC_1080P_DISPLAY_STATUS_NOOP)
+ DDL_MSG_ERROR("EOS-STATE-CRITICAL-"
+ "WRONG-DISP-STATUS");
+ if (!ret_status) {
+ ddl_decoder_dpb_transact(decoder, NULL,
+ DDL_DPB_OP_SET_MASK);
+ ddl->cmd_state = DDL_CMD_EOS;
+
+ memset(&dec_param, 0, sizeof(dec_param));
+
+ dec_param.cmd_seq_num =
+ ++ddl_context->cmd_seq_num;
+ dec_param.inst_id = ddl->instance_id;
+ dec_param.shared_mem_addr_offset =
+ DDL_ADDR_OFFSET(
+ ddl_context->dram_base_a,
+ ddl->shared_mem[ddl->command_channel]);
+ dec_param.release_dpb_bit_mask =
+ dpb_mask->hw_mask;
+ dec_param.decode =
+ VIDC_1080P_DEC_TYPE_LAST_FRAME_DATA;
+
+ ddl_context->vidc_decode_frame_start[ddl->\
+ command_channel](&dec_param);
+ }
+ }
+ }
+ return ret_status;
+}
+
+static u32 ddl_frame_run_callback(struct ddl_context *ddl_context)
+{
+ struct ddl_client_context *ddl;
+ u32 channel_inst_id;
+ u32 return_status = true;
+
+ vidc_1080p_get_returned_channel_inst_id(&channel_inst_id);
+ vidc_1080p_clear_returned_channel_inst_id();
+ ddl = ddl_get_current_ddl_client_for_channel_id(ddl_context,
+ ddl_context->response_cmd_ch_id);
+ if (ddl) {
+ if (ddl_context->pix_cache_enable) {
+ struct vidc_1080P_pix_cache_statistics
+ pixel_cache_stats;
+ vidc_pix_cache_get_statistics(&pixel_cache_stats);
+
+ DDL_MSG_HIGH(" pixel cache hits = %d,"
+ "miss = %d", pixel_cache_stats.access_hit,
+ pixel_cache_stats.access_miss);
+ DDL_MSG_HIGH(" pixel cache core reqs = %d,"
+ "axi reqs = %d", pixel_cache_stats.core_req,
+ pixel_cache_stats.axi_req);
+ DDL_MSG_HIGH(" pixel cache core bus stats = %d,"
+ "axi bus stats = %d", pixel_cache_stats.core_bus,
+ pixel_cache_stats.axi_bus);
+ }
+
+ if (ddl->cmd_state == DDL_CMD_DECODE_FRAME)
+ return_status = ddl_decoder_frame_run_callback(ddl);
+ else if (ddl->cmd_state == DDL_CMD_ENCODE_FRAME)
+ ddl_encoder_frame_run_callback(ddl);
+ else if (ddl->cmd_state == DDL_CMD_EOS)
+ return_status = ddl_eos_frame_done_callback(ddl);
+ else {
+ DDL_MSG_ERROR("UNKWN_FRAME_DONE");
+ return_status = false;
+ }
+ } else
+ return_status = false;
+
+ return return_status;
+}
+
+static void ddl_channel_end_callback(struct ddl_context *ddl_context)
+{
+ struct ddl_client_context *ddl;
+
+ DDL_MSG_MED("ddl_channel_end_callback");
+ ddl = ddl_get_current_ddl_client_for_command(ddl_context,
+ DDL_CMD_CHANNEL_END);
+ if (ddl) {
+ ddl->cmd_state = DDL_CMD_INVALID;
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_CHEND)) {
+ DDL_MSG_LOW("STATE-CRITICAL-CHEND");
+ } else {
+ DDL_MSG_LOW("CH_END_DONE");
+ ddl_release_client_internal_buffers(ddl);
+ ddl_context->ddl_callback(VCD_EVT_RESP_STOP,
+ VCD_S_SUCCESS, NULL, 0, (u32 *)ddl,
+ ddl->client_data);
+ DDL_MSG_LOW("ddl_state_transition: %s ~~>"
+ "DDL_CLIENT_OPEN",
+ ddl_get_state_string(ddl->client_state));
+ ddl->client_state = DDL_CLIENT_OPEN;
+ }
+ ddl_release_command_channel(ddl_context,
+ ddl->command_channel);
+ }
+}
+
+static void ddl_edfu_callback(struct ddl_context *ddl_context)
+{
+ struct ddl_client_context *ddl;
+ u32 channel_inst_id;
+
+ DDL_MSG_MED("ddl_edfu_callback");
+ vidc_1080p_get_returned_channel_inst_id(&channel_inst_id);
+ vidc_1080p_clear_returned_channel_inst_id();
+ ddl = ddl_get_current_ddl_client_for_channel_id(ddl_context,
+ ddl_context->response_cmd_ch_id);
+ if (ddl) {
+ if (ddl->cmd_state != DDL_CMD_ENCODE_FRAME)
+ DDL_MSG_LOW("UNKWN_EDFU");
+ }
+}
+
+static void ddl_encoder_eos_done(struct ddl_context *ddl_context)
+{
+ struct ddl_client_context *ddl;
+ u32 channel_inst_id;
+
+ vidc_1080p_get_returned_channel_inst_id(&channel_inst_id);
+ vidc_1080p_clear_returned_channel_inst_id();
+ ddl = ddl_get_current_ddl_client_for_channel_id(ddl_context,
+ ddl_context->response_cmd_ch_id);
+ if (!ddl || (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_EOS_DONE))) {
+ DDL_MSG_ERROR("STATE-CRITICAL-EOSFRMDONE");
+ ddl_client_fatal_cb(ddl);
+ } else {
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ vidc_1080p_get_encode_frame_info(&encoder->enc_frame_info);
+ ddl_handle_enc_frame_done(ddl);
+ DDL_MSG_LOW("encoder_eos_done");
+ ddl->cmd_state = DDL_CMD_INVALID;
+ DDL_MSG_LOW("ddl_state_transition: %s ~~>"
+ "DDL_CLIENT_WAIT_FOR_FRAME",
+ ddl_get_state_string(ddl->client_state));
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME;
+ DDL_MSG_LOW("eos_done");
+ ddl_context->ddl_callback(VCD_EVT_RESP_EOS_DONE,
+ VCD_S_SUCCESS, NULL, 0,
+ (u32 *)ddl, ddl->client_data);
+ ddl_release_command_channel(ddl_context,
+ ddl->command_channel);
+ }
+}
+
+static u32 ddl_process_intr_status(struct ddl_context *ddl_context,
+ u32 intr_status)
+{
+ u32 return_status = true;
+ switch (intr_status) {
+ case VIDC_1080P_RISC2HOST_CMD_OPEN_CH_RET:
+ return_status = ddl_channel_set_callback(ddl_context,
+ ddl_context->response_cmd_ch_id);
+ break;
+ case VIDC_1080P_RISC2HOST_CMD_CLOSE_CH_RET:
+ ddl_channel_end_callback(ddl_context);
+ break;
+ case VIDC_1080P_RISC2HOST_CMD_SEQ_DONE_RET:
+ return_status = ddl_sequence_done_callback(ddl_context);
+ break;
+ case VIDC_1080P_RISC2HOST_CMD_FRAME_DONE_RET:
+ return_status = ddl_frame_run_callback(ddl_context);
+ break;
+ case VIDC_1080P_RISC2HOST_CMD_SYS_INIT_RET:
+ ddl_sys_init_done_callback(ddl_context,
+ ddl_context->response_cmd_ch_id);
+ break;
+ case VIDC_1080P_RISC2HOST_CMD_FW_STATUS_RET:
+ ddl_fw_status_done_callback(ddl_context);
+ break;
+ case VIDC_1080P_RISC2HOST_CMD_EDFU_INT_RET:
+ ddl_edfu_callback(ddl_context);
+ break;
+ case VIDC_1080P_RISC2HOST_CMD_ENC_COMPLETE_RET:
+ ddl_encoder_eos_done(ddl_context);
+ break;
+ case VIDC_1080P_RISC2HOST_CMD_ERROR_RET:
+ DDL_MSG_ERROR("CMD_ERROR_INTR");
+ return_status = ddl_handle_core_errors(ddl_context);
+ break;
+ case VIDC_1080P_RISC2HOST_CMD_INIT_BUFFERS_RET:
+ return_status =
+ ddl_dpb_buffers_set_done_callback(ddl_context);
+ break;
+ default:
+ DDL_MSG_LOW("UNKWN_INTR");
+ break;
+ }
+ return return_status;
+}
+
+void ddl_read_and_clear_interrupt(void)
+{
+ struct ddl_context *ddl_context;
+ struct ddl_hw_interface *ddl_hw_response;
+
+ ddl_context = ddl_get_context();
+ if (!ddl_context->core_virtual_base_addr) {
+ DDL_MSG_LOW("SPURIOUS_INTERRUPT");
+ } else {
+ ddl_hw_response = &ddl_context->ddl_hw_response;
+ vidc_1080p_get_risc2host_cmd(&ddl_hw_response->cmd,
+ &ddl_hw_response->arg1, &ddl_hw_response->arg2,
+ &ddl_hw_response->arg3, &ddl_hw_response->arg4);
+ vidc_1080p_clear_risc2host_cmd();
+ vidc_1080p_clear_interrupt();
+ vidc_1080p_get_risc2host_cmd_status(ddl_hw_response->arg2,
+ &ddl_context->cmd_err_status,
+ &ddl_context->disp_pic_err_status);
+ ddl_context->response_cmd_ch_id = ddl_hw_response->arg1;
+ }
+}
+
+u32 ddl_process_core_response(void)
+{
+ struct ddl_context *ddl_context;
+ struct ddl_hw_interface *ddl_hw_response;
+ u32 status = false;
+
+ ddl_context = ddl_get_context();
+ if (!ddl_context->core_virtual_base_addr) {
+ DDL_MSG_LOW("SPURIOUS_INTERRUPT");
+ return status;
+ }
+ ddl_hw_response = &ddl_context->ddl_hw_response;
+ status = ddl_process_intr_status(ddl_context, ddl_hw_response->cmd);
+ if (ddl_context->interrupt_clr)
+ (*ddl_context->interrupt_clr)();
+ return status;
+}
+
+static void ddl_decoder_input_done_callback(
+ struct ddl_client_context *ddl, u32 frame_transact_end)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
+ struct vidc_1080p_dec_disp_info *dec_disp_info =
+ &decoder->dec_disp_info;
+ struct vcd_frame_data *input_vcd_frm = &(ddl->input_frame.vcd_frm);
+ u32 is_interlaced;
+ vidc_1080p_get_decoded_frame_size(
+ &dec_disp_info->input_bytes_consumed);
+ vidc_sm_set_start_byte_number(&ddl->shared_mem
+ [ddl->command_channel], 0);
+ vidc_1080p_get_decode_frame(&dec_disp_info->input_frame);
+ ddl_get_decoded_frame(input_vcd_frm,
+ dec_disp_info->input_frame);
+ vidc_1080p_get_decode_frame_result(dec_disp_info);
+ is_interlaced = (dec_disp_info->decode_coding ==
+ VIDC_1080P_DISPLAY_CODING_INTERLACED);
+ if (decoder->output_order == VCD_DEC_ORDER_DECODE) {
+ dec_disp_info->tag_bottom = is_interlaced ?
+ dec_disp_info->tag_top :
+ VCD_FRAMETAG_INVALID;
+ dec_disp_info->tag_top = input_vcd_frm->ip_frm_tag;
+ }
+ input_vcd_frm->interlaced = is_interlaced;
+ input_vcd_frm->offset += dec_disp_info->input_bytes_consumed;
+ input_vcd_frm->data_len -= dec_disp_info->input_bytes_consumed;
+ ddl->input_frame.frm_trans_end = frame_transact_end;
+ if (vidc_msg_timing)
+ ddl_calc_core_proc_time(__func__, DEC_IP_TIME);
+ ddl_context->ddl_callback(VCD_EVT_RESP_INPUT_DONE, VCD_S_SUCCESS,
+ &ddl->input_frame, sizeof(struct ddl_frame_data_tag),
+ (u32 *)ddl, ddl->client_data);
+}
+
+static void get_dec_op_done_data(struct vidc_1080p_dec_disp_info *dec_disp_info,
+ u32 output_order, u8 **physical, u32 *is_interlaced)
+{
+ enum vidc_1080p_display_coding disp_coding;
+ if (output_order == VCD_DEC_ORDER_DECODE) {
+ *physical = (u8 *)(dec_disp_info->decode_y_addr << 11);
+ disp_coding = dec_disp_info->decode_coding;
+ } else {
+ *physical = (u8 *)(dec_disp_info->display_y_addr << 11);
+ disp_coding = dec_disp_info->display_coding;
+ }
+ *is_interlaced = (disp_coding ==
+ VIDC_1080P_DISPLAY_CODING_INTERLACED);
+}
+
+static void get_dec_op_done_crop(u32 output_order,
+ struct vidc_1080p_dec_disp_info *dec_disp_info,
+ struct vcd_frame_rect *crop_data,
+ struct vcd_property_frame_size *op_frame_sz,
+ struct vcd_property_frame_size *frame_sz,
+ struct ddl_buf_addr *shared_mem)
+{
+ u32 crop_exists =
+ (output_order == VCD_DEC_ORDER_DECODE) ?
+ dec_disp_info->dec_crop_exists :
+ dec_disp_info->disp_crop_exists;
+ crop_data->left = 0;
+ crop_data->top = 0;
+ crop_data->right = dec_disp_info->img_size_x;
+ crop_data->bottom = dec_disp_info->img_size_y;
+ op_frame_sz->width = dec_disp_info->img_size_x;
+ op_frame_sz->height = dec_disp_info->img_size_y;
+ ddl_calculate_stride(op_frame_sz, false);
+ op_frame_sz->stride = DDL_ALIGN(op_frame_sz->width,
+ DDL_TILE_ALIGN_WIDTH);
+ op_frame_sz->scan_lines = DDL_ALIGN(op_frame_sz->height,
+ DDL_TILE_ALIGN_HEIGHT);
+ DDL_MSG_LOW("%s img_size_x = %u img_size_y = %u\n",
+ __func__, dec_disp_info->img_size_x,
+ dec_disp_info->img_size_y);
+ if (crop_exists) {
+ if (output_order == VCD_DEC_ORDER_DECODE)
+ vidc_sm_get_dec_order_crop_info(shared_mem,
+ &dec_disp_info->crop_left_offset,
+ &dec_disp_info->crop_right_offset,
+ &dec_disp_info->crop_top_offset,
+ &dec_disp_info->crop_bottom_offset);
+ else
+ vidc_sm_get_crop_info(shared_mem,
+ &dec_disp_info->crop_left_offset,
+ &dec_disp_info->crop_right_offset,
+ &dec_disp_info->crop_top_offset,
+ &dec_disp_info->crop_bottom_offset);
+ crop_data->left = dec_disp_info->crop_left_offset;
+ crop_data->top = dec_disp_info->crop_top_offset;
+ crop_data->right -= dec_disp_info->crop_right_offset;
+ crop_data->bottom -= dec_disp_info->crop_bottom_offset;
+ op_frame_sz->width = crop_data->right - crop_data->left;
+ op_frame_sz->height = crop_data->bottom - crop_data->top;
+ }
+}
+
+static u32 ddl_decoder_output_done_callback(
+ struct ddl_client_context *ddl, u32 frame_transact_end)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
+ struct vidc_1080p_dec_disp_info *dec_disp_info =
+ &(decoder->dec_disp_info);
+ struct ddl_frame_data_tag *output_frame = &(ddl->output_frame);
+ struct vcd_frame_data *output_vcd_frm = &(output_frame->vcd_frm);
+ u32 vcd_status, free_luma_dpb = 0, disp_pict = 0, is_interlaced;
+ get_dec_op_done_data(dec_disp_info, decoder->output_order,
+ &output_vcd_frm->physical, &is_interlaced);
+ decoder->progressive_only = !(is_interlaced);
+ output_vcd_frm->frame = VCD_FRAME_YUV;
+ if (decoder->codec.codec == VCD_CODEC_MPEG4 ||
+ decoder->codec.codec == VCD_CODEC_VC1 ||
+ decoder->codec.codec == VCD_CODEC_VC1_RCV ||
+ (decoder->codec.codec >= VCD_CODEC_DIVX_3 &&
+ decoder->codec.codec <= VCD_CODEC_XVID)) {
+ vidc_sm_get_displayed_picture_frame(&ddl->shared_mem
+ [ddl->command_channel], &disp_pict);
+ if (decoder->output_order == VCD_DEC_ORDER_DISPLAY) {
+ if (!disp_pict) {
+ output_vcd_frm->frame = VCD_FRAME_NOTCODED;
+ vidc_sm_get_available_luma_dpb_address(
+ &ddl->shared_mem[ddl->command_channel],
+ &free_luma_dpb);
+ }
+ } else {
+ if (dec_disp_info->input_frame ==
+ VIDC_1080P_DECODE_FRAMETYPE_NOT_CODED) {
+ output_vcd_frm->frame = VCD_FRAME_NOTCODED;
+ vidc_sm_get_available_luma_dpb_dec_order_address(
+ &ddl->shared_mem[ddl->command_channel],
+ &free_luma_dpb);
+ }
+ }
+ if (free_luma_dpb)
+ output_vcd_frm->physical =
+ (u8 *)(free_luma_dpb << 11);
+ }
+ vcd_status = ddl_decoder_dpb_transact(decoder, output_frame,
+ DDL_DPB_OP_MARK_BUSY);
+ if (vcd_status) {
+ DDL_MSG_ERROR("CORRUPTED_OUTPUT_BUFFER_ADDRESS");
+ ddl_hw_fatal_cb(ddl);
+ } else {
+ vidc_sm_get_metadata_status(&ddl->shared_mem
+ [ddl->command_channel],
+ &decoder->meta_data_exists);
+ if (decoder->output_order == VCD_DEC_ORDER_DISPLAY)
+ vidc_sm_get_frame_tags(&ddl->shared_mem
+ [ddl->command_channel],
+ &dec_disp_info->tag_top,
+ &dec_disp_info->tag_bottom);
+ output_vcd_frm->ip_frm_tag = dec_disp_info->tag_top;
+ vidc_sm_get_picture_times(&ddl->shared_mem
+ [ddl->command_channel],
+ &dec_disp_info->pic_time_top,
+ &dec_disp_info->pic_time_bottom);
+ get_dec_op_done_crop(decoder->output_order, dec_disp_info,
+ &output_vcd_frm->dec_op_prop.disp_frm,
+ &output_vcd_frm->dec_op_prop.frm_size,
+ &decoder->frame_size,
+ &ddl->shared_mem[ddl_context->response_cmd_ch_id]);
+ if ((decoder->cont_mode) &&
+ ((output_vcd_frm->dec_op_prop.frm_size.width !=
+ decoder->frame_size.width) ||
+ (output_vcd_frm->dec_op_prop.frm_size.height !=
+ decoder->frame_size.height) ||
+ (decoder->frame_size.width !=
+ decoder->client_frame_size.width) ||
+ (decoder->frame_size.height !=
+ decoder->client_frame_size.height))) {
+ DDL_MSG_LOW("%s o/p width = %u o/p height = %u"
+ "decoder width = %u decoder height = %u ",
+ __func__,
+ output_vcd_frm->dec_op_prop.frm_size.width,
+ output_vcd_frm->dec_op_prop.frm_size.height,
+ decoder->frame_size.width,
+ decoder->frame_size.height);
+ DDL_MSG_HIGH("%s Sending INFO_OP_RECONFIG event\n",
+ __func__);
+ ddl_context->ddl_callback(
+ VCD_EVT_IND_INFO_OUTPUT_RECONFIG,
+ VCD_S_SUCCESS, NULL, 0,
+ (u32 *)ddl,
+ ddl->client_data);
+ decoder->frame_size =
+ output_vcd_frm->dec_op_prop.frm_size;
+ decoder->client_frame_size = decoder->frame_size;
+ decoder->y_cb_cr_size =
+ ddl_get_yuv_buffer_size(&decoder->frame_size,
+ &decoder->buf_format,
+ (!decoder->progressive_only),
+ decoder->codec.codec, NULL);
+ decoder->actual_output_buf_req.sz =
+ decoder->y_cb_cr_size + decoder->suffix;
+ decoder->min_output_buf_req =
+ decoder->actual_output_buf_req;
+ DDL_MSG_LOW("%s y_cb_cr_size = %u "
+ "actual_output_buf_req.sz = %u"
+ "min_output_buf_req.sz = %u\n",
+ decoder->y_cb_cr_size,
+ decoder->actual_output_buf_req.sz,
+ decoder->min_output_buf_req.sz);
+ vidc_sm_set_chroma_addr_change(
+ &ddl->shared_mem[ddl->command_channel],
+ false);
+ }
+ output_vcd_frm->interlaced = is_interlaced;
+ output_vcd_frm->intrlcd_ip_frm_tag =
+ (!is_interlaced || !dec_disp_info->tag_bottom) ?
+ VCD_FRAMETAG_INVALID : dec_disp_info->tag_bottom;
+ output_vcd_frm->offset = 0;
+ output_vcd_frm->data_len = decoder->y_cb_cr_size;
+ if (free_luma_dpb) {
+ output_vcd_frm->data_len = 0;
+ output_vcd_frm->flags |= VCD_FRAME_FLAG_DECODEONLY;
+ }
+ output_vcd_frm->flags |= VCD_FRAME_FLAG_ENDOFFRAME;
+ output_frame->frm_trans_end = frame_transact_end;
+ if (vidc_msg_timing)
+ ddl_calc_core_proc_time(__func__, DEC_OP_TIME);
+ ddl_process_decoder_metadata(ddl);
+ ddl_context->ddl_callback(VCD_EVT_RESP_OUTPUT_DONE,
+ vcd_status, output_frame,
+ sizeof(struct ddl_frame_data_tag),
+ (u32 *)ddl, ddl->client_data);
+ }
+ return vcd_status;
+}
+
+static u32 ddl_get_decoded_frame(struct vcd_frame_data *frame,
+ enum vidc_1080p_decode_frame frame_type)
+{
+ u32 status = true;
+
+ switch (frame_type) {
+ case VIDC_1080P_DECODE_FRAMETYPE_I:
+ frame->flags |= VCD_FRAME_FLAG_SYNCFRAME;
+ frame->frame = VCD_FRAME_I;
+ break;
+ case VIDC_1080P_DECODE_FRAMETYPE_P:
+ frame->frame = VCD_FRAME_P;
+ break;
+ case VIDC_1080P_DECODE_FRAMETYPE_B:
+ frame->frame = VCD_FRAME_B;
+ break;
+ case VIDC_1080P_DECODE_FRAMETYPE_NOT_CODED:
+ frame->frame = VCD_FRAME_NOTCODED;
+ frame->data_len = 0;
+ DDL_MSG_HIGH("DDL_INFO:Decoder:NotCodedFrame>");
+ break;
+ case VIDC_1080P_DECODE_FRAMETYPE_OTHERS:
+ frame->frame = VCD_FRAME_YUV;
+ break;
+ case VIDC_1080P_DECODE_FRAMETYPE_32BIT:
+ default:
+ DDL_MSG_ERROR("UNKNOWN-FRAMETYPE");
+ status = false;
+ break;
+ }
+ return status;
+}
+
+static u32 ddl_get_encoded_frame(struct vcd_frame_data *frame,
+ enum vcd_codec codec,
+ enum vidc_1080p_encode_frame frame_type)
+{
+ u32 status = true;
+
+ if (codec == VCD_CODEC_H264) {
+ switch (frame_type) {
+ case VIDC_1080P_ENCODE_FRAMETYPE_NOT_CODED:
+ frame->frame = VCD_FRAME_P;
+ break;
+ case VIDC_1080P_ENCODE_FRAMETYPE_I:
+ frame->flags |= VCD_FRAME_FLAG_SYNCFRAME;
+ frame->frame = VCD_FRAME_I;
+ break;
+ case VIDC_1080P_ENCODE_FRAMETYPE_P:
+ frame->frame = VCD_FRAME_P;
+ break;
+ case VIDC_1080P_ENCODE_FRAMETYPE_B:
+ frame->frame = VCD_FRAME_B;
+ frame->flags |= VCD_FRAME_FLAG_BFRAME;
+ break;
+ case VIDC_1080P_ENCODE_FRAMETYPE_SKIPPED:
+ frame->frame = VCD_FRAME_NOTCODED;
+ frame->data_len = 0;
+ break;
+ case VIDC_1080P_ENCODE_FRAMETYPE_OTHERS:
+ DDL_MSG_LOW("FRAMETYPE-OTHERS");
+ break;
+ case VIDC_1080P_ENCODE_FRAMETYPE_32BIT:
+ default:
+ DDL_MSG_LOW("UNKNOWN-FRAMETYPE");
+ status = false;
+ break;
+ }
+ } else if (codec == VCD_CODEC_MPEG4) {
+ switch (frame_type) {
+ case VIDC_1080P_ENCODE_FRAMETYPE_NOT_CODED:
+ frame->frame = VCD_FRAME_P;
+ break;
+ case VIDC_1080P_ENCODE_FRAMETYPE_I:
+ frame->flags |= VCD_FRAME_FLAG_SYNCFRAME;
+ frame->frame = VCD_FRAME_I;
+ break;
+ case VIDC_1080P_ENCODE_FRAMETYPE_P:
+ frame->frame = VCD_FRAME_P;
+ break;
+ case VIDC_1080P_ENCODE_FRAMETYPE_B:
+ frame->frame = VCD_FRAME_B;
+ frame->flags |= VCD_FRAME_FLAG_BFRAME;
+ break;
+ case VIDC_1080P_ENCODE_FRAMETYPE_SKIPPED:
+ frame->frame = VCD_FRAME_NOTCODED;
+ frame->data_len = 0;
+ break;
+ case VIDC_1080P_ENCODE_FRAMETYPE_OTHERS:
+ DDL_MSG_LOW("FRAMETYPE-OTHERS");
+ break;
+ case VIDC_1080P_ENCODE_FRAMETYPE_32BIT:
+ default:
+ DDL_MSG_LOW("UNKNOWN-FRAMETYPE");
+ status = false;
+ break;
+ }
+ } else if (codec == VCD_CODEC_H263) {
+ switch (frame_type) {
+ case VIDC_1080P_ENCODE_FRAMETYPE_NOT_CODED:
+ frame->frame = VCD_FRAME_P;
+ break;
+ case VIDC_1080P_ENCODE_FRAMETYPE_I:
+ frame->flags |= VCD_FRAME_FLAG_SYNCFRAME;
+ frame->frame = VCD_FRAME_I;
+ break;
+ case VIDC_1080P_ENCODE_FRAMETYPE_P:
+ frame->frame = VCD_FRAME_P;
+ break;
+ case VIDC_1080P_ENCODE_FRAMETYPE_SKIPPED:
+ frame->frame = VCD_FRAME_NOTCODED;
+ frame->data_len = 0;
+ break;
+ case VIDC_1080P_ENCODE_FRAMETYPE_OTHERS:
+ DDL_MSG_LOW("FRAMETYPE-OTHERS");
+ break;
+ case VIDC_1080P_ENCODE_FRAMETYPE_32BIT:
+ default:
+ DDL_MSG_LOW("UNKNOWN-FRAMETYPE");
+ status = false;
+ break;
+ }
+ } else
+ status = false;
+ DDL_MSG_HIGH("Enc Frame Type %u", (u32)frame->frame);
+ return status;
+}
+
+static void ddl_get_mpeg4_dec_level(enum vcd_codec_level *level,
+ u32 level_codec, enum vcd_codec_profile mpeg4_profile)
+{
+ switch (level_codec) {
+ case VIDC_1080P_MPEG4_LEVEL0:
+ *level = VCD_LEVEL_MPEG4_0;
+ break;
+ case VIDC_1080P_MPEG4_LEVEL0b:
+ *level = VCD_LEVEL_MPEG4_0b;
+ break;
+ case VIDC_1080P_MPEG4_LEVEL1:
+ *level = VCD_LEVEL_MPEG4_1;
+ break;
+ case VIDC_1080P_MPEG4_LEVEL2:
+ *level = VCD_LEVEL_MPEG4_2;
+ break;
+ case VIDC_1080P_MPEG4_LEVEL3:
+ *level = VCD_LEVEL_MPEG4_3;
+ break;
+ case VIDC_1080P_MPEG4_LEVEL3b:
+ if (mpeg4_profile == VCD_PROFILE_MPEG4_SP)
+ *level = VCD_LEVEL_MPEG4_7;
+ else
+ *level = VCD_LEVEL_MPEG4_3b;
+ break;
+ case VIDC_1080P_MPEG4_LEVEL4a:
+ *level = VCD_LEVEL_MPEG4_4a;
+ break;
+ case VIDC_1080P_MPEG4_LEVEL5:
+ *level = VCD_LEVEL_MPEG4_5;
+ break;
+ case VIDC_1080P_MPEG4_LEVEL6:
+ *level = VCD_LEVEL_MPEG4_6;
+ break;
+ default:
+ *level = VCD_LEVEL_UNKNOWN;
+ break;
+ }
+}
+
+static void ddl_get_h264_dec_level(enum vcd_codec_level *level,
+ u32 level_codec)
+{
+ switch (level_codec) {
+ case VIDC_1080P_H264_LEVEL1:
+ *level = VCD_LEVEL_H264_1;
+ break;
+ case VIDC_1080P_H264_LEVEL1b:
+ *level = VCD_LEVEL_H264_1b;
+ break;
+ case VIDC_1080P_H264_LEVEL1p1:
+ *level = VCD_LEVEL_H264_1p1;
+ break;
+ case VIDC_1080P_H264_LEVEL1p2:
+ *level = VCD_LEVEL_H264_1p2;
+ break;
+ case VIDC_1080P_H264_LEVEL1p3:
+ *level = VCD_LEVEL_H264_1p3;
+ break;
+ case VIDC_1080P_H264_LEVEL2:
+ *level = VCD_LEVEL_H264_2;
+ break;
+ case VIDC_1080P_H264_LEVEL2p1:
+ *level = VCD_LEVEL_H264_2p1;
+ break;
+ case VIDC_1080P_H264_LEVEL2p2:
+ *level = VCD_LEVEL_H264_2p2;
+ break;
+ case VIDC_1080P_H264_LEVEL3:
+ *level = VCD_LEVEL_H264_3;
+ break;
+ case VIDC_1080P_H264_LEVEL3p1:
+ *level = VCD_LEVEL_H264_3p1;
+ break;
+ case VIDC_1080P_H264_LEVEL3p2:
+ *level = VCD_LEVEL_H264_3p2;
+ break;
+ case VIDC_1080P_H264_LEVEL4:
+ *level = VCD_LEVEL_H264_4;
+ break;
+ default:
+ *level = VCD_LEVEL_UNKNOWN;
+ break;
+ }
+}
+
+static void ddl_get_h263_dec_level(enum vcd_codec_level *level,
+ u32 level_codec)
+{
+ switch (level_codec) {
+ case VIDC_1080P_H263_LEVEL10:
+ *level = VCD_LEVEL_H263_10;
+ break;
+ case VIDC_1080P_H263_LEVEL20:
+ *level = VCD_LEVEL_H263_20;
+ break;
+ case VIDC_1080P_H263_LEVEL30:
+ *level = VCD_LEVEL_H263_30;
+ break;
+ case VIDC_1080P_H263_LEVEL40:
+ *level = VCD_LEVEL_H263_40;
+ break;
+ case VIDC_1080P_H263_LEVEL45:
+ *level = VCD_LEVEL_H263_45;
+ break;
+ case VIDC_1080P_H263_LEVEL50:
+ *level = VCD_LEVEL_H263_50;
+ break;
+ case VIDC_1080P_H263_LEVEL60:
+ *level = VCD_LEVEL_H263_60;
+ break;
+ case VIDC_1080P_H263_LEVEL70:
+ *level = VCD_LEVEL_H263_70;
+ break;
+ default:
+ *level = VCD_LEVEL_UNKNOWN;
+ break;
+ }
+}
+
+static void ddl_get_vc1_dec_level(enum vcd_codec_level *level,
+ u32 level_codec, enum vcd_codec_profile vc1_profile)
+{
+ if (vc1_profile == VCD_PROFILE_VC1_ADVANCE) {
+ switch (level_codec) {
+ case VIDC_SM_LEVEL_VC1_ADV_0:
+ *level = VCD_LEVEL_VC1_A_0;
+ break;
+ case VIDC_SM_LEVEL_VC1_ADV_1:
+ *level = VCD_LEVEL_VC1_A_1;
+ break;
+ case VIDC_SM_LEVEL_VC1_ADV_2:
+ *level = VCD_LEVEL_VC1_A_2;
+ break;
+ case VIDC_SM_LEVEL_VC1_ADV_3:
+ *level = VCD_LEVEL_VC1_A_3;
+ break;
+ case VIDC_SM_LEVEL_VC1_ADV_4:
+ *level = VCD_LEVEL_VC1_A_4;
+ break;
+ default:
+ *level = VCD_LEVEL_UNKNOWN;
+ break;
+ }
+ } else if (vc1_profile == VCD_PROFILE_VC1_MAIN) {
+ switch (level_codec) {
+ case VIDC_SM_LEVEL_VC1_LOW:
+ *level = VCD_LEVEL_VC1_M_LOW;
+ break;
+ case VIDC_SM_LEVEL_VC1_MEDIUM:
+ *level = VCD_LEVEL_VC1_M_MEDIUM;
+ break;
+ case VIDC_SM_LEVEL_VC1_HIGH:
+ *level = VCD_LEVEL_VC1_M_HIGH;
+ break;
+ default:
+ *level = VCD_LEVEL_UNKNOWN;
+ break;
+ }
+ } else if (vc1_profile == VCD_PROFILE_VC1_SIMPLE) {
+ switch (level_codec) {
+ case VIDC_SM_LEVEL_VC1_LOW:
+ *level = VCD_LEVEL_VC1_S_LOW;
+ break;
+ case VIDC_SM_LEVEL_VC1_MEDIUM:
+ *level = VCD_LEVEL_VC1_S_MEDIUM;
+ break;
+ default:
+ *level = VCD_LEVEL_UNKNOWN;
+ break;
+ }
+ }
+}
+
+static void ddl_get_mpeg2_dec_level(enum vcd_codec_level *level,
+ u32 level_codec)
+{
+ switch (level_codec) {
+ case VIDC_SM_LEVEL_MPEG2_LOW:
+ *level = VCD_LEVEL_MPEG2_LOW;
+ break;
+ case VIDC_SM_LEVEL_MPEG2_MAIN:
+ *level = VCD_LEVEL_MPEG2_MAIN;
+ break;
+ case VIDC_SM_LEVEL_MPEG2_HIGH_1440:
+ *level = VCD_LEVEL_MPEG2_HIGH_14;
+ break;
+ case VIDC_SM_LEVEL_MPEG2_HIGH:
+ *level = VCD_LEVEL_MPEG2_HIGH;
+ break;
+ default:
+ *level = VCD_LEVEL_UNKNOWN;
+ break;
+ }
+}
+
+static void ddl_get_dec_profile_level(struct ddl_decoder_data *decoder,
+ u32 profile_codec, u32 level_codec)
+{
+ enum vcd_codec_profile profile = VCD_PROFILE_UNKNOWN;
+ enum vcd_codec_level level = VCD_LEVEL_UNKNOWN;
+
+ switch (decoder->codec.codec) {
+ case VCD_CODEC_MPEG4:
+ case VCD_CODEC_XVID:
+ if (profile_codec == VIDC_SM_PROFILE_MPEG4_SIMPLE)
+ profile = VCD_PROFILE_MPEG4_SP;
+ else if (profile_codec == VIDC_SM_PROFILE_MPEG4_ADV_SIMPLE)
+ profile = VCD_PROFILE_MPEG4_ASP;
+ else
+ profile = VCD_PROFILE_UNKNOWN;
+ ddl_get_mpeg4_dec_level(&level, level_codec, profile);
+ break;
+ case VCD_CODEC_H264:
+ if (profile_codec == VIDC_SM_PROFILE_H264_BASELINE)
+ profile = VCD_PROFILE_H264_BASELINE;
+ else if (profile_codec == VIDC_SM_PROFILE_H264_MAIN)
+ profile = VCD_PROFILE_H264_MAIN;
+ else if (profile_codec == VIDC_SM_PROFILE_H264_HIGH)
+ profile = VCD_PROFILE_H264_HIGH;
+ else
+ profile = VCD_PROFILE_UNKNOWN;
+ ddl_get_h264_dec_level(&level, level_codec);
+ break;
+ case VCD_CODEC_H263:
+ if (profile_codec == VIDC_SM_PROFILE_H263_BASELINE)
+ profile = VCD_PROFILE_H263_BASELINE;
+ else
+ profile = VCD_PROFILE_UNKNOWN;
+ ddl_get_h263_dec_level(&level, level_codec);
+ break;
+ case VCD_CODEC_MPEG2:
+ if (profile_codec == VIDC_SM_PROFILE_MPEG2_MAIN)
+ profile = VCD_PROFILE_MPEG2_MAIN;
+ else if (profile_codec == VIDC_SM_PROFILE_MPEG2_SIMPLE)
+ profile = VCD_PROFILE_MPEG2_SIMPLE;
+ else
+ profile = VCD_PROFILE_UNKNOWN;
+ ddl_get_mpeg2_dec_level(&level, level_codec);
+ break;
+ case VCD_CODEC_VC1:
+ case VCD_CODEC_VC1_RCV:
+ if (profile_codec == VIDC_SM_PROFILE_VC1_SIMPLE)
+ profile = VCD_PROFILE_VC1_SIMPLE;
+ else if (profile_codec == VIDC_SM_PROFILE_VC1_MAIN)
+ profile = VCD_PROFILE_VC1_MAIN;
+ else if (profile_codec == VIDC_SM_PROFILE_VC1_ADVANCED)
+ profile = VCD_PROFILE_VC1_ADVANCE;
+ else
+ profile = VCD_PROFILE_UNKNOWN;
+ ddl_get_vc1_dec_level(&level, level_codec, profile);
+ break;
+ default:
+ if (!profile_codec)
+ profile = VCD_PROFILE_UNKNOWN;
+ if (!level)
+ level = VCD_LEVEL_UNKNOWN;
+ break;
+ }
+ decoder->profile.profile = profile;
+ decoder->level.level = level;
+}
+
+static void ddl_handle_enc_frame_done(struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ struct vcd_frame_data *output_frame = &(ddl->output_frame.vcd_frm);
+ u32 bottom_frame_tag;
+ u8 *input_buffer_address = NULL;
+
+ vidc_sm_get_frame_tags(&ddl->shared_mem[ddl->command_channel],
+ &output_frame->ip_frm_tag, &bottom_frame_tag);
+ output_frame->data_len = encoder->enc_frame_info.enc_frame_size;
+ output_frame->flags |= VCD_FRAME_FLAG_ENDOFFRAME;
+ (void)ddl_get_encoded_frame(output_frame,
+ encoder->codec.codec, encoder->enc_frame_info.enc_frame);
+ ddl_process_encoder_metadata(ddl);
+ ddl_vidc_encode_dynamic_property(ddl, false);
+ ddl->input_frame.frm_trans_end = false;
+ input_buffer_address = ddl_context->dram_base_a.align_physical_addr +
+ encoder->enc_frame_info.enc_luma_address;
+ ddl_get_input_frame_from_pool(ddl, input_buffer_address);
+
+ ddl_context->ddl_callback(VCD_EVT_RESP_INPUT_DONE,
+ VCD_S_SUCCESS, &(ddl->input_frame),
+ sizeof(struct ddl_frame_data_tag),
+ (u32 *) ddl, ddl->client_data);
+
+ ddl->output_frame.frm_trans_end =
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_EOS_DONE)
+ ? false : true;
+
+ ddl_context->ddl_callback(VCD_EVT_RESP_OUTPUT_DONE,
+ VCD_S_SUCCESS, &(ddl->output_frame),
+ sizeof(struct ddl_frame_data_tag),
+ (u32 *) ddl, ddl->client_data);
+
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c
new file mode 100644
index 0000000..3f54756
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c
@@ -0,0 +1,505 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "vcd_ddl.h"
+#include "vcd_ddl_shared_mem.h"
+#include "vcd_ddl_metadata.h"
+
+static u32 *ddl_metadata_hdr_entry(struct ddl_client_context *ddl,
+ u32 meta_data)
+{
+ u32 skip_words = 0;
+ u32 *buffer;
+
+ if (ddl->decoding) {
+ buffer = (u32 *) ddl->codec_data.decoder.meta_data_input.
+ align_virtual_addr;
+ skip_words = 32 + 1;
+ buffer += skip_words;
+ switch (meta_data) {
+ default:
+ case VCD_METADATA_DATANONE:
+ skip_words = 0;
+ break;
+ case VCD_METADATA_QPARRAY:
+ skip_words = 3;
+ break;
+ case VCD_METADATA_CONCEALMB:
+ skip_words = 6;
+ break;
+ case VCD_METADATA_VC1:
+ skip_words = 9;
+ break;
+ case VCD_METADATA_SEI:
+ skip_words = 12;
+ break;
+ case VCD_METADATA_VUI:
+ skip_words = 15;
+ break;
+ case VCD_METADATA_PASSTHROUGH:
+ skip_words = 18;
+ break;
+ case VCD_METADATA_QCOMFILLER:
+ skip_words = 21;
+ break;
+ }
+ } else {
+ buffer = (u32 *) ddl->codec_data.encoder.meta_data_input.
+ align_virtual_addr;
+ skip_words = 2;
+ buffer += skip_words;
+ switch (meta_data) {
+ default:
+ case VCD_METADATA_DATANONE:
+ skip_words = 0;
+ break;
+ case VCD_METADATA_ENC_SLICE:
+ skip_words = 3;
+ break;
+ case VCD_METADATA_QCOMFILLER:
+ skip_words = 6;
+ break;
+ }
+ }
+ buffer += skip_words;
+ return buffer;
+}
+
+void ddl_set_default_meta_data_hdr(struct ddl_client_context *ddl)
+{
+ struct ddl_buf_addr *main_buffer =
+ &ddl->ddl_context->metadata_shared_input;
+ struct ddl_buf_addr *client_buffer;
+ u32 *hdr_entry;
+
+ if (ddl->decoding)
+ client_buffer = &(ddl->codec_data.decoder.meta_data_input);
+ else
+ client_buffer = &(ddl->codec_data.encoder.meta_data_input);
+ DDL_METADATA_CLIENT_INPUTBUF(main_buffer, client_buffer,
+ ddl->instance_id);
+ hdr_entry = ddl_metadata_hdr_entry(ddl, VCD_METADATA_QCOMFILLER);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] = VCD_METADATA_QCOMFILLER;
+ hdr_entry = ddl_metadata_hdr_entry(ddl, VCD_METADATA_DATANONE);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] = VCD_METADATA_DATANONE;
+ if (ddl->decoding) {
+ hdr_entry = ddl_metadata_hdr_entry(ddl, VCD_METADATA_QPARRAY);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] = VCD_METADATA_QPARRAY;
+ hdr_entry = ddl_metadata_hdr_entry(ddl, VCD_METADATA_CONCEALMB);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] = VCD_METADATA_CONCEALMB;
+ hdr_entry = ddl_metadata_hdr_entry(ddl, VCD_METADATA_SEI);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] = VCD_METADATA_SEI;
+ hdr_entry = ddl_metadata_hdr_entry(ddl, VCD_METADATA_VUI);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] = VCD_METADATA_VUI;
+ hdr_entry = ddl_metadata_hdr_entry(ddl, VCD_METADATA_VC1);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] = VCD_METADATA_VC1;
+ hdr_entry = ddl_metadata_hdr_entry(ddl,
+ VCD_METADATA_PASSTHROUGH);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] =
+ VCD_METADATA_PASSTHROUGH;
+ } else {
+ hdr_entry = ddl_metadata_hdr_entry(ddl, VCD_METADATA_ENC_SLICE);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] = VCD_METADATA_ENC_SLICE;
+ }
+}
+
+static u32 ddl_supported_metadata_flag(struct ddl_client_context *ddl)
+{
+ u32 flag = 0;
+
+ if (ddl->decoding) {
+ enum vcd_codec codec =
+ ddl->codec_data.decoder.codec.codec;
+
+ flag |= (VCD_METADATA_CONCEALMB | VCD_METADATA_PASSTHROUGH |
+ VCD_METADATA_QPARRAY);
+ if (codec == VCD_CODEC_H264)
+ flag |= (VCD_METADATA_SEI | VCD_METADATA_VUI);
+ else if (codec == VCD_CODEC_VC1 ||
+ codec == VCD_CODEC_VC1_RCV)
+ flag |= VCD_METADATA_VC1;
+ } else
+ flag |= VCD_METADATA_ENC_SLICE;
+ return flag;
+}
+
+void ddl_set_default_metadata_flag(struct ddl_client_context *ddl)
+{
+ if (ddl->decoding)
+ ddl->codec_data.decoder.meta_data_enable_flag = 0;
+ else
+ ddl->codec_data.encoder.meta_data_enable_flag = 0;
+}
+
+void ddl_set_default_decoder_metadata_buffer_size(struct ddl_decoder_data
+ *decoder, struct vcd_property_frame_size *frame_size,
+ struct vcd_buffer_requirement *output_buf_req)
+{
+ u32 flag = decoder->meta_data_enable_flag;
+ u32 suffix = 0, size = 0;
+
+ if (!flag) {
+ decoder->suffix = 0;
+ return;
+ }
+ if (flag & VCD_METADATA_QPARRAY) {
+ u32 num_of_mb = DDL_NO_OF_MB(frame_size->width,
+ frame_size->height);
+
+ size = DDL_METADATA_HDR_SIZE;
+ size += num_of_mb;
+ DDL_METADATA_ALIGNSIZE(size);
+ suffix += size;
+ }
+ if (flag & VCD_METADATA_CONCEALMB) {
+ u32 num_of_mb = DDL_NO_OF_MB(frame_size->width,
+ frame_size->height);
+ size = DDL_METADATA_HDR_SIZE + (num_of_mb >> 3);
+ DDL_METADATA_ALIGNSIZE(size);
+ suffix += size;
+ }
+ if (flag & VCD_METADATA_VC1) {
+ size = DDL_METADATA_HDR_SIZE;
+ size += DDL_METADATA_VC1_PAYLOAD_SIZE;
+ DDL_METADATA_ALIGNSIZE(size);
+ suffix += size;
+ }
+ if (flag & VCD_METADATA_SEI) {
+ size = DDL_METADATA_HDR_SIZE;
+ size += DDL_METADATA_SEI_PAYLOAD_SIZE;
+ DDL_METADATA_ALIGNSIZE(size);
+ suffix += (size * DDL_METADATA_SEI_MAX);
+ }
+ if (flag & VCD_METADATA_VUI) {
+ size = DDL_METADATA_HDR_SIZE;
+ size += DDL_METADATA_VUI_PAYLOAD_SIZE;
+ DDL_METADATA_ALIGNSIZE(size);
+ suffix += (size);
+ }
+ if (flag & VCD_METADATA_PASSTHROUGH) {
+ size = DDL_METADATA_HDR_SIZE;
+ size += DDL_METADATA_PASSTHROUGH_PAYLOAD_SIZE;
+ DDL_METADATA_ALIGNSIZE(size);
+ suffix += (size);
+ }
+ size = DDL_METADATA_EXTRADATANONE_SIZE;
+ DDL_METADATA_ALIGNSIZE(size);
+ suffix += (size);
+ suffix += DDL_METADATA_EXTRAPAD_SIZE;
+ DDL_METADATA_ALIGNSIZE(suffix);
+ decoder->suffix = suffix;
+ output_buf_req->sz += suffix;
+ DDL_MSG_LOW("metadata output buf size : %d", suffix);
+}
+
+void ddl_set_default_encoder_metadata_buffer_size(struct ddl_encoder_data
+ *encoder)
+{
+ u32 flag = encoder->meta_data_enable_flag;
+ u32 suffix = 0, size = 0;
+
+ if (!flag) {
+ encoder->suffix = 0;
+ return;
+ }
+ if (flag & VCD_METADATA_ENC_SLICE) {
+ u32 num_of_mb = DDL_NO_OF_MB(encoder->frame_size.width,
+ encoder->frame_size.height);
+ size = DDL_METADATA_HDR_SIZE;
+ size += 4;
+ size += (num_of_mb << 3);
+ DDL_METADATA_ALIGNSIZE(size);
+ suffix += size;
+ }
+ size = DDL_METADATA_EXTRADATANONE_SIZE;
+ DDL_METADATA_ALIGNSIZE(size);
+ suffix += (size);
+ suffix += DDL_METADATA_EXTRAPAD_SIZE;
+ DDL_METADATA_ALIGNSIZE(suffix);
+ encoder->suffix = suffix;
+ encoder->output_buf_req.sz += suffix;
+}
+
+u32 ddl_set_metadata_params(struct ddl_client_context *ddl,
+ struct vcd_property_hdr *property_hdr, void *property_value)
+{
+ u32 vcd_status = VCD_ERR_ILLEGAL_PARM;
+ if (property_hdr->prop_id == VCD_I_METADATA_ENABLE) {
+ struct vcd_property_meta_data_enable *meta_data_enable =
+ (struct vcd_property_meta_data_enable *) property_value;
+ u32 *meta_data_enable_flag;
+ enum vcd_codec codec;
+
+ if (ddl->decoding) {
+ meta_data_enable_flag =
+ &(ddl->codec_data.decoder.meta_data_enable_flag);
+ codec = ddl->codec_data.decoder.codec.codec;
+ } else {
+ meta_data_enable_flag =
+ &ddl->codec_data.encoder.meta_data_enable_flag;
+ codec = ddl->codec_data.encoder.codec.codec;
+ }
+ if (sizeof(struct vcd_property_meta_data_enable) ==
+ property_hdr->sz &&
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN) && codec) {
+ u32 flag = ddl_supported_metadata_flag(ddl);
+ flag &= (meta_data_enable->meta_data_enable_flag);
+ if (flag)
+ flag |= DDL_METADATA_MANDATORY;
+ if (*meta_data_enable_flag != flag) {
+ *meta_data_enable_flag = flag;
+ if (ddl->decoding)
+ ddl_set_default_decoder_buffer_req(
+ &ddl->codec_data.decoder, true);
+ else
+ ddl_set_default_encoder_buffer_req(
+ &ddl->codec_data.encoder);
+ }
+ vcd_status = VCD_S_SUCCESS;
+ }
+ } else if (property_hdr->prop_id == VCD_I_METADATA_HEADER) {
+ struct vcd_property_metadata_hdr *hdr =
+ (struct vcd_property_metadata_hdr *) property_value;
+
+ if (sizeof(struct vcd_property_metadata_hdr) ==
+ property_hdr->sz) {
+ u32 flag = ddl_supported_metadata_flag(ddl);
+
+ flag |= DDL_METADATA_MANDATORY;
+ flag &= hdr->meta_data_id;
+ if (!(flag & (flag - 1))) {
+ u32 *hdr_entry = ddl_metadata_hdr_entry(ddl,
+ flag);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] =
+ hdr->version;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] =
+ hdr->port_index;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] =
+ hdr->type;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ }
+ return vcd_status;
+}
+
+u32 ddl_get_metadata_params(struct ddl_client_context *ddl,
+ struct vcd_property_hdr *property_hdr, void *property_value)
+{
+ u32 vcd_status = VCD_ERR_ILLEGAL_PARM;
+ if (property_hdr->prop_id == VCD_I_METADATA_ENABLE &&
+ sizeof(struct vcd_property_meta_data_enable) ==
+ property_hdr->sz) {
+ struct vcd_property_meta_data_enable *meta_data_enable =
+ (struct vcd_property_meta_data_enable *) property_value;
+
+ meta_data_enable->meta_data_enable_flag =
+ ((ddl->decoding) ?
+ (ddl->codec_data.decoder.meta_data_enable_flag) :
+ (ddl->codec_data.encoder.meta_data_enable_flag));
+ vcd_status = VCD_S_SUCCESS;
+ } else if (property_hdr->prop_id == VCD_I_METADATA_HEADER &&
+ sizeof(struct vcd_property_metadata_hdr) ==
+ property_hdr->sz) {
+ struct vcd_property_metadata_hdr *hdr =
+ (struct vcd_property_metadata_hdr *) property_value;
+ u32 flag = ddl_supported_metadata_flag(ddl);
+
+ flag |= DDL_METADATA_MANDATORY;
+ flag &= hdr->meta_data_id;
+ if (!(flag & (flag - 1))) {
+ u32 *hdr_entry = ddl_metadata_hdr_entry(ddl, flag);
+ hdr->version =
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX];
+ hdr->port_index =
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX];
+ hdr->type = hdr_entry[DDL_METADATA_HDR_TYPE_INDEX];
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ return vcd_status;
+}
+
+void ddl_vidc_metadata_enable(struct ddl_client_context *ddl)
+{
+ u32 flag, extradata_enable = false;
+ u32 qp_enable = false, concealed_mb_enable = false;
+ u32 vc1_param_enable = false, sei_nal_enable = false;
+ u32 vui_enable = false, enc_slice_size_enable = false;
+
+ if (ddl->decoding)
+ flag = ddl->codec_data.decoder.meta_data_enable_flag;
+ else
+ flag = ddl->codec_data.encoder.meta_data_enable_flag;
+ if (flag) {
+ if (flag & VCD_METADATA_QPARRAY)
+ qp_enable = true;
+ if (flag & VCD_METADATA_CONCEALMB)
+ concealed_mb_enable = true;
+ if (flag & VCD_METADATA_VC1)
+ vc1_param_enable = true;
+ if (flag & VCD_METADATA_SEI)
+ sei_nal_enable = true;
+ if (flag & VCD_METADATA_VUI)
+ vui_enable = true;
+ if (flag & VCD_METADATA_ENC_SLICE)
+ enc_slice_size_enable = true;
+ if (flag & VCD_METADATA_PASSTHROUGH)
+ extradata_enable = true;
+ }
+
+ DDL_MSG_LOW("metadata enable flag : %d", sei_nal_enable);
+ vidc_sm_set_metadata_enable(&ddl->shared_mem
+ [ddl->command_channel], extradata_enable, qp_enable,
+ concealed_mb_enable, vc1_param_enable, sei_nal_enable,
+ vui_enable, enc_slice_size_enable);
+}
+
+u32 ddl_vidc_encode_set_metadata_output_buf(struct ddl_client_context *ddl)
+{
+ struct ddl_encoder_data *encoder = &ddl->codec_data.encoder;
+ struct vcd_frame_data *stream = &ddl->output_frame.vcd_frm;
+ struct ddl_context *ddl_context;
+ u32 ext_buffer_end, hw_metadata_start;
+ u32 *buffer;
+
+ ddl_context = ddl_get_context();
+ ext_buffer_end = (u32) stream->physical + stream->alloc_len;
+ if (!encoder->meta_data_enable_flag) {
+ ext_buffer_end &= ~(DDL_STREAMBUF_ALIGN_GUARD_BYTES);
+ return ext_buffer_end;
+ }
+ hw_metadata_start = (ext_buffer_end - encoder->suffix) &
+ ~(DDL_STREAMBUF_ALIGN_GUARD_BYTES);
+ ext_buffer_end = (hw_metadata_start - 1) &
+ ~(DDL_STREAMBUF_ALIGN_GUARD_BYTES);
+ buffer = (u32 *) encoder->meta_data_input.align_virtual_addr;
+ *buffer++ = encoder->suffix;
+ *buffer = DDL_OFFSET(ddl_context->dram_base_a.align_physical_addr,
+ hw_metadata_start);
+ encoder->meta_data_offset = hw_metadata_start - (u32) stream->physical;
+ return ext_buffer_end;
+}
+
+void ddl_vidc_decode_set_metadata_output(struct ddl_decoder_data *decoder)
+{
+ struct ddl_context *ddl_context;
+ u32 loopc, yuv_size;
+ u32 *buffer;
+
+ if (!decoder->meta_data_enable_flag) {
+ decoder->meta_data_offset = 0;
+ return;
+ }
+ ddl_context = ddl_get_context();
+ yuv_size = ddl_get_yuv_buffer_size(&decoder->client_frame_size,
+ &decoder->buf_format, !decoder->progressive_only,
+ decoder->hdr.decoding, NULL);
+ decoder->meta_data_offset = DDL_ALIGN_SIZE(yuv_size,
+ DDL_LINEAR_BUF_ALIGN_GUARD_BYTES, DDL_LINEAR_BUF_ALIGN_MASK);
+ buffer = (u32 *) decoder->meta_data_input.align_virtual_addr;
+ *buffer++ = decoder->suffix;
+ DDL_MSG_LOW("Metadata offset & size : %d/%d",
+ decoder->meta_data_offset, decoder->suffix);
+ for (loopc = 0; loopc < decoder->dp_buf.no_of_dec_pic_buf;
+ ++loopc) {
+ *buffer++ = (u32)(decoder->meta_data_offset + (u8 *)
+ DDL_OFFSET(ddl_context->dram_base_a.
+ align_physical_addr, decoder->dp_buf.
+ dec_pic_buffers[loopc].vcd_frm.physical));
+ }
+}
+
+void ddl_process_encoder_metadata(struct ddl_client_context *ddl)
+{
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ struct vcd_frame_data *out_frame =
+ &(ddl->output_frame.vcd_frm);
+ u32 *qfiller_hdr, *qfiller, start_addr;
+ u32 qfiller_size;
+ if (!encoder->meta_data_enable_flag) {
+ out_frame->flags &= ~(VCD_FRAME_FLAG_EXTRADATA);
+ return;
+ }
+ if (!encoder->enc_frame_info.meta_data_exists) {
+ out_frame->flags &= ~(VCD_FRAME_FLAG_EXTRADATA);
+ return;
+ }
+ out_frame->flags |= VCD_FRAME_FLAG_EXTRADATA;
+ start_addr = (u32) ((u8 *)out_frame->virtual + out_frame->offset);
+ qfiller = (u32 *)((out_frame->data_len +
+ start_addr + 3) & ~3);
+ qfiller_size = (u32)((encoder->meta_data_offset +
+ (u8 *) out_frame->virtual) - (u8 *) qfiller);
+ qfiller_hdr = ddl_metadata_hdr_entry(ddl, VCD_METADATA_QCOMFILLER);
+ *qfiller++ = qfiller_size;
+ *qfiller++ = qfiller_hdr[DDL_METADATA_HDR_VERSION_INDEX];
+ *qfiller++ = qfiller_hdr[DDL_METADATA_HDR_PORT_INDEX];
+ *qfiller++ = qfiller_hdr[DDL_METADATA_HDR_TYPE_INDEX];
+ *qfiller = (u32)(qfiller_size - DDL_METADATA_HDR_SIZE);
+}
+
+void ddl_process_decoder_metadata(struct ddl_client_context *ddl)
+{
+ struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
+ struct vcd_frame_data *output_frame =
+ &(ddl->output_frame.vcd_frm);
+ u32 *qfiller_hdr, *qfiller;
+ u32 qfiller_size;
+
+ if (!decoder->meta_data_enable_flag) {
+ output_frame->flags &= ~(VCD_FRAME_FLAG_EXTRADATA);
+ return;
+ }
+ if (!decoder->meta_data_exists) {
+ output_frame->flags &= ~(VCD_FRAME_FLAG_EXTRADATA);
+ return;
+ }
+ DDL_MSG_LOW("processing metadata for decoder");
+ DDL_MSG_LOW("data_len/metadata_offset : %d/%d",
+ output_frame->data_len, decoder->meta_data_offset);
+ output_frame->flags |= VCD_FRAME_FLAG_EXTRADATA;
+ if (output_frame->data_len != decoder->meta_data_offset) {
+ qfiller = (u32 *)((u32)((output_frame->data_len +
+ output_frame->offset +
+ (u8 *) output_frame->virtual) + 3) & ~3);
+ qfiller_size = (u32)((decoder->meta_data_offset +
+ (u8 *) output_frame->virtual) -
+ (u8 *) qfiller);
+ qfiller_hdr = ddl_metadata_hdr_entry(ddl,
+ VCD_METADATA_QCOMFILLER);
+ *qfiller++ = qfiller_size;
+ *qfiller++ = qfiller_hdr[DDL_METADATA_HDR_VERSION_INDEX];
+ *qfiller++ = qfiller_hdr[DDL_METADATA_HDR_PORT_INDEX];
+ *qfiller++ = qfiller_hdr[DDL_METADATA_HDR_TYPE_INDEX];
+ *qfiller = (u32)(qfiller_size - DDL_METADATA_HDR_SIZE);
+ }
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.h
new file mode 100644
index 0000000..c63b6a9
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.h
@@ -0,0 +1,66 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _VCD_DDL_METADATA_H_
+#define _VCD_DDL_METADATA_H_
+
+#define DDL_MAX_DEC_METADATATYPE 8
+#define DDL_MAX_ENC_METADATATYPE 3
+#define DDL_METADATA_EXTRAPAD_SIZE 256
+#define DDL_METADATA_HDR_SIZE 20
+#define DDL_METADATA_EXTRADATANONE_SIZE 24
+#define DDL_METADATA_ALIGNSIZE(x) ((x) = (((x) + 0x7) & ~0x7))
+#define DDL_METADATA_MANDATORY \
+ (VCD_METADATA_DATANONE | VCD_METADATA_QCOMFILLER)
+#define DDL_METADATA_VC1_PAYLOAD_SIZE (38*4)
+#define DDL_METADATA_SEI_PAYLOAD_SIZE 100
+#define DDL_METADATA_SEI_MAX 5
+#define DDL_METADATA_VUI_PAYLOAD_SIZE 256
+#define DDL_METADATA_PASSTHROUGH_PAYLOAD_SIZE 68
+#define DDL_METADATA_CLIENT_INPUTBUFSIZE 256
+#define DDL_METADATA_TOTAL_INPUTBUFSIZE \
+ (DDL_METADATA_CLIENT_INPUTBUFSIZE * VCD_MAX_NO_CLIENT)
+
+#define DDL_METADATA_CLIENT_INPUTBUF(main_buffer, client_buffer,\
+ channel_id) { \
+ (client_buffer)->align_physical_addr = (u8 *) \
+ ((u8 *)(main_buffer)->align_physical_addr + \
+ (DDL_METADATA_CLIENT_INPUTBUFSIZE * channel_id)); \
+ (client_buffer)->align_virtual_addr = (u8 *) \
+ ((u8 *)(main_buffer)->align_virtual_addr + \
+ (DDL_METADATA_CLIENT_INPUTBUFSIZE * channel_id)); \
+ (client_buffer)->virtual_base_addr = 0; \
+ }
+
+#define DDL_METADATA_HDR_VERSION_INDEX 0
+#define DDL_METADATA_HDR_PORT_INDEX 1
+#define DDL_METADATA_HDR_TYPE_INDEX 2
+
+void ddl_set_default_meta_data_hdr(struct ddl_client_context *ddl);
+u32 ddl_get_metadata_params(struct ddl_client_context *ddl,
+ struct vcd_property_hdr *property_hdr, void *property_value);
+u32 ddl_set_metadata_params(struct ddl_client_context *ddl,
+ struct vcd_property_hdr *property_hdr, void *property_value);
+void ddl_set_default_metadata_flag(struct ddl_client_context *ddl);
+void ddl_set_default_decoder_metadata_buffer_size(struct ddl_decoder_data
+ *decoder, struct vcd_property_frame_size *frame_size,
+ struct vcd_buffer_requirement *output_buf_req);
+void ddl_set_default_encoder_metadata_buffer_size(
+ struct ddl_encoder_data *encoder);
+void ddl_vidc_metadata_enable(struct ddl_client_context *ddl);
+u32 ddl_vidc_encode_set_metadata_output_buf(struct ddl_client_context *ddl);
+void ddl_vidc_decode_set_metadata_output(struct ddl_decoder_data *decoder);
+void ddl_process_encoder_metadata(struct ddl_client_context *ddl);
+void ddl_process_decoder_metadata(struct ddl_client_context *ddl);
+
+#endif
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
new file mode 100644
index 0000000..b3656cd
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
@@ -0,0 +1,1904 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "vcd_ddl.h"
+#include "vcd_ddl_metadata.h"
+
+static u32 ddl_set_dec_property(struct ddl_client_context *pddl,
+ struct vcd_property_hdr *property_hdr, void *property_value);
+static u32 ddl_set_enc_property(struct ddl_client_context *pddl,
+ struct vcd_property_hdr *property_hdr, void *property_value);
+static u32 ddl_get_dec_property(struct ddl_client_context *pddl,
+ struct vcd_property_hdr *property_hdr, void *property_value);
+static u32 ddl_get_enc_property(struct ddl_client_context *pddl,
+ struct vcd_property_hdr *property_hdr, void *property_value);
+static u32 ddl_set_enc_dynamic_property(struct ddl_client_context *ddl,
+ struct vcd_property_hdr *property_hdr, void *property_value);
+static void ddl_set_default_enc_property(struct ddl_client_context *ddl);
+static void ddl_set_default_enc_profile(
+ struct ddl_encoder_data *encoder);
+static void ddl_set_default_enc_level(struct ddl_encoder_data *encoder);
+static void ddl_set_default_enc_vop_timing(
+ struct ddl_encoder_data *encoder);
+static void ddl_set_default_enc_intra_period(
+ struct ddl_encoder_data *encoder);
+static void ddl_set_default_enc_rc_params(
+ struct ddl_encoder_data *encoder);
+static u32 ddl_valid_buffer_requirement(
+ struct vcd_buffer_requirement *original_buf_req,
+ struct vcd_buffer_requirement *req_buf_req);
+static u32 ddl_decoder_min_num_dpb(struct ddl_decoder_data *decoder);
+static u32 ddl_set_dec_buffers(struct ddl_decoder_data *decoder,
+ struct ddl_property_dec_pic_buffers *dpb);
+
+u32 ddl_set_property(u32 *ddl_handle,
+ struct vcd_property_hdr *property_hdr, void *property_value)
+{
+ struct ddl_context *ddl_context;
+ struct ddl_client_context *ddl =
+ (struct ddl_client_context *) ddl_handle;
+ u32 vcd_status;
+
+ DDL_MSG_HIGH("ddl_set_property");
+ if (!property_hdr || !property_value) {
+ DDL_MSG_ERROR("ddl_set_prop:Bad_argument");
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+ ddl_context = ddl_get_context();
+ if (!DDL_IS_INITIALIZED(ddl_context)) {
+ DDL_MSG_ERROR("ddl_set_prop:Not_inited");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (!ddl) {
+ DDL_MSG_ERROR("ddl_set_prop:Bad_handle");
+ return VCD_ERR_BAD_HANDLE;
+ }
+ if (ddl->decoding)
+ vcd_status = ddl_set_dec_property(ddl, property_hdr,
+ property_value);
+ else
+ vcd_status = ddl_set_enc_property(ddl, property_hdr,
+ property_value);
+ if (vcd_status)
+ DDL_MSG_ERROR("ddl_set_prop:FAILED");
+ return vcd_status;
+}
+
+u32 ddl_get_property(u32 *ddl_handle,
+ struct vcd_property_hdr *property_hdr, void *property_value)
+{
+ struct ddl_context *ddl_context;
+ struct ddl_client_context *ddl =
+ (struct ddl_client_context *) ddl_handle;
+ u32 vcd_status = VCD_ERR_ILLEGAL_PARM;
+
+ DDL_MSG_HIGH("ddl_get_property");
+ if (!property_hdr || !property_value)
+ return VCD_ERR_ILLEGAL_PARM;
+ if (property_hdr->prop_id == DDL_I_CAPABILITY) {
+ if (sizeof(struct ddl_property_capability) ==
+ property_hdr->sz) {
+ struct ddl_property_capability *ddl_capability =
+ (struct ddl_property_capability *)
+ property_value;
+
+ ddl_capability->max_num_client = VCD_MAX_NO_CLIENT;
+ ddl_capability->exclusive = VCD_COMMAND_EXCLUSIVE;
+ ddl_capability->frame_command_depth =
+ VCD_FRAME_COMMAND_DEPTH;
+ ddl_capability->general_command_depth =
+ VCD_GENEVIDC_COMMAND_DEPTH;
+ ddl_capability->ddl_time_out_in_ms =
+ DDL_HW_TIMEOUT_IN_MS;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ return vcd_status;
+ }
+ ddl_context = ddl_get_context();
+ if (!DDL_IS_INITIALIZED(ddl_context))
+ return VCD_ERR_ILLEGAL_OP;
+ if (!ddl)
+ return VCD_ERR_BAD_HANDLE;
+ if (ddl->decoding)
+ vcd_status = ddl_get_dec_property(ddl, property_hdr,
+ property_value);
+ else
+ vcd_status = ddl_get_enc_property(ddl, property_hdr,
+ property_value);
+ if (vcd_status)
+ DDL_MSG_ERROR("ddl_get_prop:FAILED");
+ else
+ DDL_MSG_MED("ddl_get_prop:SUCCESS");
+ return vcd_status;
+}
+
+u32 ddl_decoder_ready_to_start(struct ddl_client_context *ddl,
+ struct vcd_sequence_hdr *header)
+{
+ struct ddl_decoder_data *decoder =
+ &(ddl->codec_data.decoder);
+
+ if (!decoder->codec.codec) {
+ DDL_MSG_ERROR("ddl_dec_start_check:Codec_not_set");
+ return false;
+ }
+ if ((!header) && (!decoder->client_frame_size.height ||
+ !decoder->client_frame_size.width)) {
+ DDL_MSG_ERROR("ddl_dec_start_check:"
+ "Client_height_width_default");
+ return false;
+ }
+ return true;
+}
+
+u32 ddl_encoder_ready_to_start(struct ddl_client_context *ddl)
+{
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+
+ if (!encoder->codec.codec || !encoder->frame_size.height ||
+ !encoder->frame_size.width ||
+ !encoder->frame_rate.fps_denominator ||
+ !encoder->frame_rate.fps_numerator ||
+ !encoder->target_bit_rate.target_bitrate)
+ return false;
+ if (encoder->frame_rate.fps_numerator >
+ (encoder->frame_rate.fps_denominator *
+ encoder->vop_timing.vop_time_resolution)) {
+ DDL_MSG_ERROR("ResVsFrameRateFailed!");
+ return false;
+ }
+ if (encoder->profile.profile == VCD_PROFILE_H264_BASELINE &&
+ encoder->entropy_control.entropy_sel == VCD_ENTROPY_SEL_CABAC) {
+ DDL_MSG_ERROR("H264BaseLineCABAC!!");
+ return false;
+ }
+ return true;
+}
+
+static u32 ddl_set_dec_property(struct ddl_client_context *ddl,
+ struct vcd_property_hdr *property_hdr, void *property_value)
+{
+ struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
+ u32 vcd_status = VCD_ERR_ILLEGAL_PARM ;
+
+ switch (property_hdr->prop_id) {
+ case DDL_I_DPB_RELEASE:
+ if ((sizeof(struct ddl_frame_data_tag) ==
+ property_hdr->sz) &&
+ (decoder->dp_buf.no_of_dec_pic_buf))
+ vcd_status = ddl_decoder_dpb_transact(decoder,
+ (struct ddl_frame_data_tag *)
+ property_value, DDL_DPB_OP_MARK_FREE);
+ break;
+ case DDL_I_DPB:
+ {
+ struct ddl_property_dec_pic_buffers *dpb =
+ (struct ddl_property_dec_pic_buffers *) property_value;
+
+ if ((sizeof(struct ddl_property_dec_pic_buffers) ==
+ property_hdr->sz) &&
+ (DDLCLIENT_STATE_IS(ddl,
+ DDL_CLIENT_WAIT_FOR_INITCODEC) ||
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_DPB)) &&
+ (dpb->no_of_dec_pic_buf ==
+ decoder->client_output_buf_req.actual_count))
+ vcd_status = ddl_set_dec_buffers(decoder, dpb);
+ }
+ break;
+ case DDL_I_REQ_OUTPUT_FLUSH:
+ if (sizeof(u32) == property_hdr->sz) {
+ decoder->dynamic_prop_change |=
+ DDL_DEC_REQ_OUTPUT_FLUSH;
+ decoder->dpb_mask.client_mask = 0;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case DDL_I_INPUT_BUF_REQ:
+ {
+ struct vcd_buffer_requirement *buffer_req =
+ (struct vcd_buffer_requirement *)property_value;
+
+ if (sizeof(struct vcd_buffer_requirement) ==
+ property_hdr->sz &&
+ (DDLCLIENT_STATE_IS(ddl,
+ DDL_CLIENT_WAIT_FOR_INITCODEC) ||
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_DPB) ||
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)) &&
+ (ddl_valid_buffer_requirement(
+ &decoder->min_input_buf_req, buffer_req))) {
+ decoder->client_input_buf_req = *buffer_req;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case DDL_I_OUTPUT_BUF_REQ:
+ {
+ struct vcd_buffer_requirement *buffer_req =
+ (struct vcd_buffer_requirement *)property_value;
+
+ if (sizeof(struct vcd_buffer_requirement) ==
+ property_hdr->sz &&
+ (DDLCLIENT_STATE_IS(ddl,
+ DDL_CLIENT_WAIT_FOR_INITCODEC) ||
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_DPB) ||
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)) &&
+ (ddl_valid_buffer_requirement(
+ &decoder->min_output_buf_req, buffer_req))) {
+ decoder->client_output_buf_req =
+ *buffer_req;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_CODEC:
+ {
+ struct vcd_property_codec *codec =
+ (struct vcd_property_codec *)property_value;
+ if (sizeof(struct vcd_property_codec) ==
+ property_hdr->sz &&
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN) &&
+ ddl_codec_type_transact(ddl, false,
+ codec->codec)) {
+ if (decoder->codec.codec != codec->codec) {
+ decoder->codec = *codec;
+ ddl_set_default_dec_property(ddl);
+ }
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_POST_FILTER:
+ if (sizeof(struct vcd_property_post_filter) ==
+ property_hdr->sz &&
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN) && (
+ decoder->codec.codec == VCD_CODEC_MPEG4 ||
+ decoder->codec.codec == VCD_CODEC_MPEG2)) {
+ decoder->post_filter =
+ *(struct vcd_property_post_filter *)
+ property_value;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_FRAME_SIZE:
+ {
+ struct vcd_property_frame_size *frame_size =
+ (struct vcd_property_frame_size *) property_value;
+ if ((sizeof(struct vcd_property_frame_size) ==
+ property_hdr->sz) &&
+ (DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)) &&
+ (DDL_ALLOW_DEC_FRAMESIZE(frame_size->width,
+ frame_size->height))) {
+ if (decoder->client_frame_size.height !=
+ frame_size->height ||
+ decoder->client_frame_size.width !=
+ frame_size->width) {
+ decoder->client_frame_size = *frame_size;
+ ddl_set_default_decoder_buffer_req(decoder,
+ true);
+ }
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_BUFFER_FORMAT:
+ {
+ struct vcd_property_buffer_format *tile =
+ (struct vcd_property_buffer_format *)
+ property_value;
+ if (sizeof(struct vcd_property_buffer_format) ==
+ property_hdr->sz &&
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN) &&
+ tile->buffer_format == VCD_BUFFER_FORMAT_TILE_4x2) {
+ if (tile->buffer_format !=
+ decoder->buf_format.buffer_format) {
+ decoder->buf_format = *tile;
+ ddl_set_default_decoder_buffer_req(
+ decoder, true);
+ }
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_H264_MV_BUFFER:
+ {
+ int index, buffer_size;
+ u8 *phys_addr;
+ u8 *virt_addr;
+ struct vcd_property_h264_mv_buffer *mv_buff =
+ (struct vcd_property_h264_mv_buffer *)
+ property_value;
+ DDL_MSG_LOW("Entered VCD_I_H264_MV_BUFFER Virt: %p, Phys %p,"
+ "fd: %d size: %d count: %d\n",
+ mv_buff->kernel_virtual_addr,
+ mv_buff->physical_addr,
+ mv_buff->pmem_fd,
+ mv_buff->size, mv_buff->count);
+ if ((property_hdr->sz == sizeof(struct
+ vcd_property_h264_mv_buffer)) &&
+ (DDLCLIENT_STATE_IS(ddl,
+ DDL_CLIENT_WAIT_FOR_INITCODEC) ||
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_DPB) ||
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN))) {
+ phys_addr = mv_buff->physical_addr;
+ virt_addr = mv_buff->kernel_virtual_addr;
+ buffer_size = mv_buff->size/mv_buff->count;
+
+ for (index = 0; index < mv_buff->count; index++) {
+ ddl->codec_data.decoder.hw_bufs.
+ h264_mv[index].align_physical_addr
+ = phys_addr;
+ ddl->codec_data.decoder.hw_bufs.
+ h264_mv[index].align_virtual_addr
+ = virt_addr;
+ ddl->codec_data.decoder.hw_bufs.
+ h264_mv[index].buffer_size
+ = buffer_size;
+ ddl->codec_data.decoder.hw_bufs.
+ h264_mv[index].physical_base_addr
+ = phys_addr;
+ ddl->codec_data.decoder.hw_bufs.
+ h264_mv[index].virtual_base_addr
+ = virt_addr;
+ DDL_MSG_LOW("Assigned %d buffer for "
+ "virt: %p, phys %p for "
+ "h264_mv_buffers "
+ "of size: %d\n",
+ index, virt_addr,
+ phys_addr, buffer_size);
+ phys_addr += buffer_size;
+ virt_addr += buffer_size;
+ }
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_FREE_H264_MV_BUFFER:
+ {
+ memset(&decoder->hw_bufs.h264_mv, 0, sizeof(struct
+ ddl_buf_addr) * DDL_MAX_BUFFER_COUNT);
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_OUTPUT_ORDER:
+ {
+ if (sizeof(u32) == property_hdr->sz &&
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)) {
+ decoder->output_order =
+ *(u32 *)property_value;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_DEC_PICTYPE:
+ {
+ if ((sizeof(u32) == property_hdr->sz) &&
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)) {
+ decoder->idr_only_decoding =
+ *(u32 *)property_value;
+ ddl_set_default_decoder_buffer_req(
+ decoder, true);
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_METADATA_ENABLE:
+ case VCD_I_METADATA_HEADER:
+ DDL_MSG_MED("Meta Data Interface is Requested");
+ vcd_status = ddl_set_metadata_params(ddl, property_hdr,
+ property_value);
+ vcd_status = VCD_S_SUCCESS;
+ break;
+ case VCD_I_FRAME_RATE:
+ vcd_status = VCD_S_SUCCESS;
+ break;
+ case VCD_I_CONT_ON_RECONFIG:
+ {
+ DDL_MSG_LOW("Set property VCD_I_CONT_ON_RECONFIG\n");
+ if (sizeof(u32) == property_hdr->sz &&
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)) {
+ decoder->cont_mode = *(u32 *)property_value;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ default:
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ break;
+ }
+ return vcd_status;
+}
+
+static u32 ddl_check_valid_enc_level(struct vcd_property_codec *codec,
+ struct vcd_property_profile *profile,
+ struct vcd_property_level *level)
+{
+ u32 status = false;
+
+ if (codec && profile && level) {
+ switch (codec->codec) {
+ case VCD_CODEC_MPEG4:
+ status = (profile->profile ==
+ VCD_PROFILE_MPEG4_SP) &&
+ (level->level >= VCD_LEVEL_MPEG4_0) &&
+ (level->level <= VCD_LEVEL_MPEG4_6) &&
+ (VCD_LEVEL_MPEG4_3b != level->level);
+ status = status ||
+ ((profile->profile ==
+ VCD_PROFILE_MPEG4_ASP) &&
+ (level->level >= VCD_LEVEL_MPEG4_0) &&
+ (level->level <= VCD_LEVEL_MPEG4_5));
+ break;
+ case VCD_CODEC_H264:
+ status = (level->level >= VCD_LEVEL_H264_1) &&
+ (level->level <= VCD_LEVEL_H264_4);
+ break;
+ case VCD_CODEC_H263:
+ status = (level->level >= VCD_LEVEL_H263_10) &&
+ (level->level <= VCD_LEVEL_H263_70);
+ break;
+ default:
+ break;
+ }
+ }
+ return status;
+}
+
+static u32 ddl_set_enc_property(struct ddl_client_context *ddl,
+ struct vcd_property_hdr *property_hdr,
+ void *property_value)
+{
+ struct ddl_encoder_data *encoder =
+ &(ddl->codec_data.encoder);
+ u32 vcd_status = VCD_ERR_ILLEGAL_PARM;
+
+ if (DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME) ||
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME_DONE) ||
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)) {
+ vcd_status = ddl_set_enc_dynamic_property(ddl,
+ property_hdr, property_value);
+ }
+ if (vcd_status) {
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN) ||
+ vcd_status != VCD_ERR_ILLEGAL_OP) {
+ DDL_MSG_ERROR("ddl_set_enc_property:"
+ "Fails_as_not_in_open_state");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ } else
+ return vcd_status;
+
+ switch (property_hdr->prop_id) {
+ case VCD_I_FRAME_SIZE:
+ {
+ struct vcd_property_frame_size *frame_size =
+ (struct vcd_property_frame_size *) property_value;
+ if ((sizeof(struct vcd_property_frame_size) ==
+ property_hdr->sz) &&
+ (DDL_ALLOW_ENC_FRAMESIZE(frame_size->width,
+ frame_size->height))) {
+ if (encoder->frame_size.height != frame_size->height ||
+ encoder->frame_size.width !=
+ frame_size->width) {
+ ddl_calculate_stride(frame_size, false);
+ encoder->frame_size = *frame_size;
+ ddl_set_default_encoder_buffer_req(encoder);
+ }
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_CODEC:
+ {
+ struct vcd_property_codec *codec =
+ (struct vcd_property_codec *) property_value;
+ if ((sizeof(struct vcd_property_codec) ==
+ property_hdr->sz) &&
+ (ddl_codec_type_transact(ddl, false, codec->codec))) {
+ if (codec->codec != encoder->codec.codec) {
+ encoder->codec = *codec;
+ ddl_set_default_enc_property(ddl);
+ }
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_REQ_IFRAME:
+ vcd_status = VCD_S_SUCCESS;
+ break;
+ case VCD_I_INTRA_PERIOD:
+ {
+ struct vcd_property_i_period *i_period =
+ (struct vcd_property_i_period *)property_value;
+ if (sizeof(struct vcd_property_i_period) ==
+ property_hdr->sz &&
+ i_period->b_frames <= DDL_MAX_NUM_OF_B_FRAME) {
+ encoder->i_period = *i_period;
+ encoder->client_input_buf_req.min_count =
+ i_period->b_frames + 1;
+ encoder->client_input_buf_req.actual_count =
+ DDL_MAX(encoder->client_input_buf_req.\
+ actual_count, encoder->\
+ client_input_buf_req.min_count);
+ encoder->client_output_buf_req.min_count =
+ i_period->b_frames + 2;
+ encoder->client_output_buf_req.actual_count =
+ DDL_MAX(encoder->client_output_buf_req.\
+ actual_count, encoder->\
+ client_output_buf_req.min_count);
+ ddl->extra_output_buf_count =
+ i_period->b_frames - 1;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_PROFILE:
+ {
+ struct vcd_property_profile *profile =
+ (struct vcd_property_profile *)property_value;
+
+ if ((sizeof(struct vcd_property_profile) ==
+ property_hdr->sz) && ((
+ (encoder->codec.codec == VCD_CODEC_MPEG4) && (
+ profile->profile == VCD_PROFILE_MPEG4_SP ||
+ profile->profile == VCD_PROFILE_MPEG4_ASP)) ||
+ ((encoder->codec.codec == VCD_CODEC_H264) &&
+ (profile->profile >= VCD_PROFILE_H264_BASELINE) &&
+ (profile->profile <= VCD_PROFILE_H264_HIGH)) ||
+ ((encoder->codec.codec == VCD_CODEC_H263) &&
+ (profile->profile == VCD_PROFILE_H263_BASELINE)))) {
+ encoder->profile = *profile;
+ vcd_status = VCD_S_SUCCESS;
+ if (profile->profile == VCD_PROFILE_H264_BASELINE)
+ encoder->entropy_control.entropy_sel =
+ VCD_ENTROPY_SEL_CAVLC;
+ else
+ encoder->entropy_control.entropy_sel =
+ VCD_ENTROPY_SEL_CABAC;
+ }
+ }
+ break;
+ case VCD_I_LEVEL:
+ {
+ struct vcd_property_level *level =
+ (struct vcd_property_level *) property_value;
+
+ if ((sizeof(struct vcd_property_level) ==
+ property_hdr->sz) && (ddl_check_valid_enc_level
+ (&encoder->codec,
+ &encoder->profile, level))) {
+ encoder->level = *level;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_MULTI_SLICE:
+ {
+ struct vcd_property_multi_slice *multi_slice =
+ (struct vcd_property_multi_slice *)
+ property_value;
+
+ switch (multi_slice->m_slice_sel) {
+ case VCD_MSLICE_OFF:
+ vcd_status = VCD_S_SUCCESS;
+ break;
+ case VCD_MSLICE_BY_GOB:
+ if (encoder->codec.codec == VCD_CODEC_H263)
+ vcd_status = VCD_S_SUCCESS;
+ break;
+ case VCD_MSLICE_BY_MB_COUNT:
+ if (multi_slice->m_slice_size >= 1 &&
+ (multi_slice->m_slice_size <=
+ DDL_NO_OF_MB(encoder->frame_size.width,
+ encoder->frame_size.height)))
+ vcd_status = VCD_S_SUCCESS;
+ break;
+ case VCD_MSLICE_BY_BYTE_COUNT:
+ if (multi_slice->m_slice_size > 0)
+ vcd_status = VCD_S_SUCCESS;
+ break;
+ default:
+ break;
+ }
+ if (sizeof(struct vcd_property_multi_slice) ==
+ property_hdr->sz && !vcd_status) {
+ encoder->multi_slice = *multi_slice;
+ if (multi_slice->m_slice_sel == VCD_MSLICE_OFF)
+ encoder->multi_slice.m_slice_size = 0;
+ }
+ }
+ break;
+ case VCD_I_RATE_CONTROL:
+ {
+ struct vcd_property_rate_control *rate_control =
+ (struct vcd_property_rate_control *)
+ property_value;
+ if (sizeof(struct vcd_property_rate_control) ==
+ property_hdr->sz &&
+ rate_control->rate_control >=
+ VCD_RATE_CONTROL_OFF &&
+ rate_control->rate_control <=
+ VCD_RATE_CONTROL_CBR_CFR) {
+ encoder->rc = *rate_control;
+ ddl_set_default_enc_rc_params(encoder);
+ vcd_status = VCD_S_SUCCESS;
+ }
+
+ }
+ break;
+ case VCD_I_SHORT_HEADER:
+ if (sizeof(struct vcd_property_short_header) ==
+ property_hdr->sz &&
+ encoder->codec.codec ==
+ VCD_CODEC_MPEG4) {
+ encoder->short_header =
+ *(struct vcd_property_short_header *)
+ property_value;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_VOP_TIMING:
+ {
+ struct vcd_property_vop_timing *vop_time =
+ (struct vcd_property_vop_timing *)
+ property_value;
+
+ if ((sizeof(struct vcd_property_vop_timing) ==
+ property_hdr->sz) &&
+ (encoder->frame_rate.fps_numerator <=
+ vop_time->vop_time_resolution) &&
+ (encoder->codec.codec == VCD_CODEC_MPEG4)) {
+ encoder->vop_timing = *vop_time;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_HEADER_EXTENSION:
+ if (sizeof(u32) == property_hdr->sz &&
+ encoder->codec.codec == VCD_CODEC_MPEG4) {
+ encoder->hdr_ext_control = *(u32 *)property_value;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_ENTROPY_CTRL:
+ {
+ struct vcd_property_entropy_control *entropy_control =
+ (struct vcd_property_entropy_control *)
+ property_value;
+ if (sizeof(struct vcd_property_entropy_control) ==
+ property_hdr->sz &&
+ encoder->codec.codec == VCD_CODEC_H264 &&
+ entropy_control->entropy_sel >=
+ VCD_ENTROPY_SEL_CAVLC &&
+ entropy_control->entropy_sel <=
+ VCD_ENTROPY_SEL_CABAC) {
+ if ((entropy_control->entropy_sel ==
+ VCD_ENTROPY_SEL_CABAC) &&
+ (encoder->entropy_control.cabac_model ==
+ VCD_CABAC_MODEL_NUMBER_1 ||
+ encoder->entropy_control.cabac_model ==
+ VCD_CABAC_MODEL_NUMBER_2)) {
+ vcd_status = VCD_ERR_ILLEGAL_PARM;
+ } else {
+ encoder->entropy_control = *entropy_control;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ }
+ break;
+ case VCD_I_DEBLOCKING:
+ {
+ struct vcd_property_db_config *db_config =
+ (struct vcd_property_db_config *) property_value;
+ if (sizeof(struct vcd_property_db_config) ==
+ property_hdr->sz &&
+ encoder->codec.codec == VCD_CODEC_H264 &&
+ db_config->db_config >=
+ VCD_DB_ALL_BLOCKING_BOUNDARY &&
+ db_config->db_config <=
+ VCD_DB_SKIP_SLICE_BOUNDARY) {
+ encoder->db_control = *db_config;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_QP_RANGE:
+ {
+ struct vcd_property_qp_range *qp =
+ (struct vcd_property_qp_range *)property_value;
+
+ if ((sizeof(struct vcd_property_qp_range) ==
+ property_hdr->sz) && (qp->min_qp <=
+ qp->max_qp) && ((encoder->codec.codec ==
+ VCD_CODEC_H264 && qp->max_qp <= DDL_MAX_H264_QP) ||
+ (qp->max_qp <= DDL_MAX_MPEG4_QP))) {
+ encoder->qp_range = *qp;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_SESSION_QP:
+ {
+ struct vcd_property_session_qp *qp =
+ (struct vcd_property_session_qp *)property_value;
+ if ((sizeof(struct vcd_property_session_qp) ==
+ property_hdr->sz) &&
+ (qp->i_frame_qp >= encoder->qp_range.min_qp) &&
+ (qp->i_frame_qp <= encoder->qp_range.max_qp) &&
+ (qp->p_frame_qp >= encoder->qp_range.min_qp) &&
+ (qp->p_frame_qp <= encoder->qp_range.max_qp)) {
+ encoder->session_qp = *qp;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_RC_LEVEL_CONFIG:
+ {
+ struct vcd_property_rc_level *rc_level =
+ (struct vcd_property_rc_level *) property_value;
+ if (sizeof(struct vcd_property_rc_level) ==
+ property_hdr->sz &&
+ (encoder->rc.rate_control >=
+ VCD_RATE_CONTROL_VBR_VFR ||
+ encoder->rc.rate_control <=
+ VCD_RATE_CONTROL_CBR_VFR) &&
+ (!rc_level->mb_level_rc ||
+ encoder->codec.codec == VCD_CODEC_H264)) {
+ encoder->rc_level = *rc_level;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_FRAME_LEVEL_RC:
+ {
+ struct vcd_property_frame_level_rc_params
+ *frame_level_rc =
+ (struct vcd_property_frame_level_rc_params *)
+ property_value;
+ if ((sizeof(struct vcd_property_frame_level_rc_params) ==
+ property_hdr->sz) &&
+ (frame_level_rc->reaction_coeff) &&
+ (encoder->rc_level.frame_level_rc)) {
+ encoder->frame_level_rc = *frame_level_rc;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_ADAPTIVE_RC:
+ if ((sizeof(struct vcd_property_adaptive_rc_params) ==
+ property_hdr->sz) &&
+ (encoder->codec.codec == VCD_CODEC_H264) &&
+ (encoder->rc_level.mb_level_rc)) {
+ encoder->adaptive_rc =
+ *(struct vcd_property_adaptive_rc_params *)
+ property_value;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_BUFFER_FORMAT:
+ {
+ struct vcd_property_buffer_format *buffer_format =
+ (struct vcd_property_buffer_format *)
+ property_value;
+
+ if (sizeof(struct vcd_property_buffer_format) ==
+ property_hdr->sz &&
+ ((buffer_format->buffer_format ==
+ VCD_BUFFER_FORMAT_NV12_16M2KA) ||
+ (VCD_BUFFER_FORMAT_TILE_4x2 ==
+ buffer_format->buffer_format))) {
+ if (buffer_format->buffer_format !=
+ encoder->buf_format.buffer_format) {
+ encoder->buf_format = *buffer_format;
+ ddl_set_default_encoder_buffer_req(encoder);
+ }
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case DDL_I_INPUT_BUF_REQ:
+ {
+ struct vcd_buffer_requirement *buffer_req =
+ (struct vcd_buffer_requirement *)property_value;
+ if (sizeof(struct vcd_buffer_requirement) ==
+ property_hdr->sz && (ddl_valid_buffer_requirement(
+ &encoder->input_buf_req, buffer_req))) {
+ encoder->client_input_buf_req = *buffer_req;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case DDL_I_OUTPUT_BUF_REQ:
+ {
+ struct vcd_buffer_requirement *buffer_req =
+ (struct vcd_buffer_requirement *)property_value;
+ if (sizeof(struct vcd_buffer_requirement) ==
+ property_hdr->sz && (ddl_valid_buffer_requirement(
+ &encoder->output_buf_req, buffer_req))) {
+ encoder->client_output_buf_req = *buffer_req;
+ encoder->client_output_buf_req.sz =
+ DDL_ALIGN(buffer_req->sz,
+ DDL_KILO_BYTE(4));
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_RECON_BUFFERS:
+ {
+ int index;
+ struct vcd_property_enc_recon_buffer *recon_buffers =
+ (struct vcd_property_enc_recon_buffer *)property_value;
+ for (index = 0; index < 4; index++) {
+ if (!encoder->hw_bufs.dpb_y[index].align_physical_addr)
+ break;
+ else
+ continue;
+ }
+ if (property_hdr->sz == sizeof(struct
+ vcd_property_enc_recon_buffer)) {
+ encoder->hw_bufs.dpb_y[index].align_physical_addr =
+ recon_buffers->physical_addr;
+ encoder->hw_bufs.dpb_y[index].align_virtual_addr =
+ recon_buffers->kernel_virtual_addr;
+ encoder->hw_bufs.dpb_y[index].buffer_size =
+ recon_buffers->buffer_size;
+ encoder->hw_bufs.dpb_c[index].align_physical_addr =
+ recon_buffers->physical_addr + ddl_get_yuv_buf_size(
+ encoder->frame_size.width, encoder->frame_size.
+ height, DDL_YUV_BUF_TYPE_TILE);
+ encoder->hw_bufs.dpb_c[index].align_virtual_addr =
+ recon_buffers->kernel_virtual_addr +
+ recon_buffers->ysize;
+ DDL_MSG_LOW("Y::KVirt: %p,KPhys: %p"
+ "UV::KVirt: %p,KPhys: %p\n",
+ encoder->hw_bufs.dpb_y[index].align_virtual_addr,
+ encoder->hw_bufs.dpb_y[index].align_physical_addr,
+ encoder->hw_bufs.dpb_c[index].align_virtual_addr,
+ encoder->hw_bufs.dpb_c[index].align_physical_addr);
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_FREE_RECON_BUFFERS:
+ {
+ memset(&encoder->hw_bufs.dpb_y, 0,
+ sizeof(struct ddl_buf_addr) * 4);
+ memset(&encoder->hw_bufs.dpb_c, 0,
+ sizeof(struct ddl_buf_addr) * 4);
+ vcd_status = VCD_S_SUCCESS;
+ break;
+ }
+ case VCD_I_METADATA_ENABLE:
+ case VCD_I_METADATA_HEADER:
+ DDL_MSG_ERROR("Meta Data Interface is Requested");
+ vcd_status = ddl_set_metadata_params(ddl, property_hdr,
+ property_value);
+ vcd_status = VCD_S_SUCCESS;
+ break;
+ default:
+ DDL_MSG_ERROR("INVALID ID %d\n", (int)property_hdr->prop_id);
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ break;
+ }
+ return vcd_status;
+}
+
+static u32 ddl_get_dec_property(struct ddl_client_context *ddl,
+ struct vcd_property_hdr *property_hdr, void *property_value)
+{
+ struct ddl_decoder_data *decoder = &ddl->codec_data.decoder;
+ struct vcd_property_frame_size *fz_size;
+ u32 vcd_status = VCD_ERR_ILLEGAL_PARM;
+ DDL_MSG_HIGH("property_hdr->prop_id:%x\n", property_hdr->prop_id);
+ switch (property_hdr->prop_id) {
+ case VCD_I_FRAME_SIZE:
+ if (sizeof(struct vcd_property_frame_size) ==
+ property_hdr->sz) {
+ ddl_calculate_stride(&decoder->client_frame_size,
+ !decoder->progressive_only);
+ fz_size =
+ &decoder->client_frame_size;
+ fz_size->stride =
+ DDL_TILE_ALIGN(fz_size->width,
+ DDL_TILE_ALIGN_WIDTH);
+ fz_size->scan_lines =
+ DDL_TILE_ALIGN(fz_size->height,
+ DDL_TILE_ALIGN_HEIGHT);
+ *(struct vcd_property_frame_size *)
+ property_value =
+ decoder->client_frame_size;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_PROFILE:
+ if (sizeof(struct vcd_property_profile) ==
+ property_hdr->sz) {
+ *(struct vcd_property_profile *)property_value =
+ decoder->profile;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_LEVEL:
+ if (sizeof(struct vcd_property_level) ==
+ property_hdr->sz) {
+ *(struct vcd_property_level *)property_value =
+ decoder->level;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_PROGRESSIVE_ONLY:
+ if (sizeof(u32) == property_hdr->sz) {
+ *(u32 *)property_value =
+ decoder->progressive_only;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case DDL_I_INPUT_BUF_REQ:
+ if (sizeof(struct vcd_buffer_requirement) ==
+ property_hdr->sz) {
+ *(struct vcd_buffer_requirement *)
+ property_value =
+ decoder->client_input_buf_req;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case DDL_I_OUTPUT_BUF_REQ:
+ if (sizeof(struct vcd_buffer_requirement) ==
+ property_hdr->sz) {
+ *(struct vcd_buffer_requirement *)
+ property_value = decoder->client_output_buf_req;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_CODEC:
+ if (sizeof(struct vcd_property_codec) ==
+ property_hdr->sz) {
+ *(struct vcd_property_codec *) property_value =
+ decoder->codec;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_BUFFER_FORMAT:
+ if (sizeof(struct vcd_property_buffer_format) ==
+ property_hdr->sz) {
+ *(struct vcd_property_buffer_format *)
+ property_value = decoder->buf_format;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_POST_FILTER:
+ if (sizeof(struct vcd_property_post_filter) ==
+ property_hdr->sz) {
+ *(struct vcd_property_post_filter *)
+ property_value =
+ decoder->post_filter;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case DDL_I_SEQHDR_ALIGN_BYTES:
+ if (sizeof(u32) == property_hdr->sz) {
+ *(u32 *)property_value =
+ DDL_LINEAR_BUFFER_ALIGN_BYTES;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case DDL_I_FRAME_PROC_UNITS:
+ if (sizeof(u32) == property_hdr->sz) {
+ if (!decoder->progressive_only &&
+ (decoder->client_frame_size.width *
+ decoder->client_frame_size.height) <=
+ DDL_FRAME_VGA_SIZE) {
+ *(u32 *) property_value = DDL_NO_OF_MB(
+ DDL_FRAME_720P_WIDTH,
+ DDL_FRAME_720P_HEIGHT);
+ } else {
+ *(u32 *) property_value = DDL_NO_OF_MB(
+ decoder->client_frame_size.width,
+ decoder->client_frame_size.height);
+ }
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case DDL_I_DPB_RETRIEVE:
+ if (sizeof(struct ddl_frame_data_tag) ==
+ property_hdr->sz) {
+ vcd_status = ddl_decoder_dpb_transact(decoder,
+ (struct ddl_frame_data_tag *)
+ property_value, DDL_DPB_OP_RETRIEVE);
+ }
+ break;
+ case VCD_I_GET_H264_MV_SIZE:
+ if (property_hdr->sz == sizeof(struct
+ vcd_property_buffer_size)) {
+ struct vcd_property_buffer_size *mv_size =
+ (struct vcd_property_buffer_size *) property_value;
+ mv_size->size = ddl_get_yuv_buf_size(mv_size->width,
+ mv_size->height, DDL_YUV_BUF_TYPE_TILE);
+ mv_size->alignment = DDL_TILE_BUFFER_ALIGN_BYTES;
+ DDL_MSG_LOW("w: %d, h: %d, S: %d, "
+ "A: %d", mv_size->width,
+ mv_size->height, mv_size->size,
+ mv_size->alignment);
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_OUTPUT_ORDER:
+ {
+ if (sizeof(u32) == property_hdr->sz) {
+ *(u32 *)property_value = decoder->output_order;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_METADATA_ENABLE:
+ case VCD_I_METADATA_HEADER:
+ DDL_MSG_ERROR("Meta Data Interface is Requested");
+ vcd_status = ddl_get_metadata_params(ddl, property_hdr,
+ property_value);
+ vcd_status = VCD_S_SUCCESS;
+ break;
+ case VCD_I_CONT_ON_RECONFIG:
+ if (sizeof(u32) == property_hdr->sz) {
+ *(u32 *)property_value = decoder->cont_mode;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ default:
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ break;
+ }
+ return vcd_status;
+}
+
+static u32 ddl_get_enc_property(struct ddl_client_context *ddl,
+ struct vcd_property_hdr *property_hdr, void *property_value)
+{
+ struct ddl_encoder_data *encoder = &ddl->codec_data.encoder;
+ u32 vcd_status = VCD_ERR_ILLEGAL_PARM;
+
+ switch (property_hdr->prop_id) {
+ case VCD_I_CODEC:
+ if (sizeof(struct vcd_property_codec) ==
+ property_hdr->sz) {
+ *(struct vcd_property_codec *) property_value =
+ encoder->codec;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_FRAME_SIZE:
+ if (sizeof(struct vcd_property_frame_size) ==
+ property_hdr->sz) {
+ *(struct vcd_property_frame_size *)
+ property_value = encoder->frame_size;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_FRAME_RATE:
+ if (sizeof(struct vcd_property_frame_rate) ==
+ property_hdr->sz) {
+ *(struct vcd_property_frame_rate *)
+ property_value = encoder->frame_rate;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_TARGET_BITRATE:
+ if (sizeof(struct vcd_property_target_bitrate) ==
+ property_hdr->sz) {
+ *(struct vcd_property_target_bitrate *)
+ property_value = encoder->target_bit_rate;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_RATE_CONTROL:
+ if (sizeof(struct vcd_property_rate_control) ==
+ property_hdr->sz) {
+ *(struct vcd_property_rate_control *)
+ property_value = encoder->rc;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_PROFILE:
+ if (sizeof(struct vcd_property_profile) ==
+ property_hdr->sz) {
+ *(struct vcd_property_profile *) property_value =
+ encoder->profile;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_LEVEL:
+ if (sizeof(struct vcd_property_level) ==
+ property_hdr->sz) {
+ *(struct vcd_property_level *) property_value =
+ encoder->level;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_MULTI_SLICE:
+ if (sizeof(struct vcd_property_multi_slice) ==
+ property_hdr->sz) {
+ *(struct vcd_property_multi_slice *)
+ property_value = encoder->multi_slice;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_SEQ_HEADER:
+ {
+ struct vcd_sequence_hdr *seq_hdr =
+ (struct vcd_sequence_hdr *) property_value;
+
+ if (!encoder->seq_header_length) {
+ seq_hdr->sequence_header_len =
+ encoder->seq_header_length;
+ vcd_status = VCD_ERR_NO_SEQ_HDR;
+ } else if (sizeof(struct vcd_sequence_hdr) ==
+ property_hdr->sz &&
+ encoder->seq_header_length <=
+ seq_hdr->sequence_header_len) {
+ memcpy(seq_hdr->sequence_header,
+ encoder->seq_header.align_virtual_addr,
+ encoder->seq_header_length);
+ seq_hdr->sequence_header_len =
+ encoder->seq_header_length;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case DDL_I_SEQHDR_PRESENT:
+ if (sizeof(u32) == property_hdr->sz) {
+ if ((encoder->codec.codec ==
+ VCD_CODEC_MPEG4 &&
+ !encoder->short_header.short_header) ||
+ encoder->codec.codec == VCD_CODEC_H264)
+ *(u32 *) property_value = 0x1;
+ else
+ *(u32 *) property_value = 0x0;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_VOP_TIMING:
+ if (sizeof(struct vcd_property_vop_timing) ==
+ property_hdr->sz) {
+ *(struct vcd_property_vop_timing *)
+ property_value = encoder->vop_timing;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_SHORT_HEADER:
+ if (sizeof(struct vcd_property_short_header) ==
+ property_hdr->sz) {
+ if (encoder->codec.codec == VCD_CODEC_MPEG4) {
+ *(struct vcd_property_short_header *)
+ property_value =
+ encoder->short_header;
+ vcd_status = VCD_S_SUCCESS;
+ } else
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ }
+ break;
+ case VCD_I_ENTROPY_CTRL:
+ if (sizeof(struct vcd_property_entropy_control) ==
+ property_hdr->sz) {
+ if (encoder->codec.codec == VCD_CODEC_H264) {
+ *(struct vcd_property_entropy_control *)
+ property_value =
+ encoder->entropy_control;
+ vcd_status = VCD_S_SUCCESS;
+ } else
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ }
+ break;
+ case VCD_I_DEBLOCKING:
+ if (sizeof(struct vcd_property_db_config) ==
+ property_hdr->sz) {
+ if (encoder->codec.codec == VCD_CODEC_H264) {
+ *(struct vcd_property_db_config *)
+ property_value =
+ encoder->db_control;
+ vcd_status = VCD_S_SUCCESS;
+ } else
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ }
+ break;
+ case VCD_I_INTRA_PERIOD:
+ if (sizeof(struct vcd_property_i_period) ==
+ property_hdr->sz) {
+ *(struct vcd_property_i_period *)
+ property_value = encoder->i_period;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_QP_RANGE:
+ if (sizeof(struct vcd_property_qp_range) ==
+ property_hdr->sz) {
+ *(struct vcd_property_qp_range *)
+ property_value = encoder->qp_range;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_SESSION_QP:
+ if (sizeof(struct vcd_property_session_qp) ==
+ property_hdr->sz) {
+ *(struct vcd_property_session_qp *)
+ property_value = encoder->session_qp;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_RC_LEVEL_CONFIG:
+ if (sizeof(struct vcd_property_rc_level) ==
+ property_hdr->sz) {
+ *(struct vcd_property_rc_level *)
+ property_value = encoder->rc_level;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_FRAME_LEVEL_RC:
+ if (sizeof(struct vcd_property_frame_level_rc_params) ==
+ property_hdr->sz) {
+ *(struct vcd_property_frame_level_rc_params *)
+ property_value = encoder->frame_level_rc;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_ADAPTIVE_RC:
+ if (sizeof(struct vcd_property_adaptive_rc_params) ==
+ property_hdr->sz) {
+ *(struct vcd_property_adaptive_rc_params *)
+ property_value = encoder->adaptive_rc;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_INTRA_REFRESH:
+ if (sizeof(struct vcd_property_intra_refresh_mb_number) ==
+ property_hdr->sz) {
+ *(struct vcd_property_intra_refresh_mb_number *)
+ property_value = encoder->intra_refresh;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case DDL_I_INPUT_BUF_REQ:
+ if (sizeof(struct vcd_buffer_requirement) ==
+ property_hdr->sz) {
+ *(struct vcd_buffer_requirement *)
+ property_value = encoder->client_input_buf_req;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case DDL_I_OUTPUT_BUF_REQ:
+ if (sizeof(struct vcd_buffer_requirement) ==
+ property_hdr->sz) {
+ *(struct vcd_buffer_requirement *)
+ property_value = encoder->client_output_buf_req;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_BUFFER_FORMAT:
+ if (sizeof(struct vcd_property_buffer_format) ==
+ property_hdr->sz) {
+ *(struct vcd_property_buffer_format *)
+ property_value = encoder->buf_format;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case DDL_I_FRAME_PROC_UNITS:
+ if (sizeof(u32) == property_hdr->sz &&
+ encoder->frame_size.width &&
+ encoder->frame_size.height) {
+ *(u32 *)property_value = DDL_NO_OF_MB(
+ encoder->frame_size.width,
+ encoder->frame_size.height);
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_HEADER_EXTENSION:
+ if (sizeof(u32) == property_hdr->sz &&
+ encoder->codec.codec == VCD_CODEC_MPEG4) {
+ *(u32 *) property_value =
+ encoder->hdr_ext_control;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_GET_RECON_BUFFER_SIZE:
+ {
+ u32 ysize, uvsize;
+ if (property_hdr->sz == sizeof(struct
+ vcd_property_buffer_size)) {
+ struct vcd_property_buffer_size *recon_buff_size =
+ (struct vcd_property_buffer_size *) property_value;
+
+ ysize = ddl_get_yuv_buf_size(recon_buff_size->width,
+ recon_buff_size->height, DDL_YUV_BUF_TYPE_TILE);
+ uvsize = ddl_get_yuv_buf_size(recon_buff_size->width,
+ recon_buff_size->height/2,
+ DDL_YUV_BUF_TYPE_TILE);
+ recon_buff_size->size = ysize + uvsize;
+ recon_buff_size->alignment =
+ DDL_TILE_BUFFER_ALIGN_BYTES;
+ DDL_MSG_LOW("w: %d, h: %d, S: %d, A: %d",
+ recon_buff_size->width, recon_buff_size->height,
+ recon_buff_size->size, recon_buff_size->alignment);
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_METADATA_ENABLE:
+ case VCD_I_METADATA_HEADER:
+ DDL_MSG_ERROR("Meta Data Interface is Requested");
+ vcd_status = ddl_get_metadata_params(ddl, property_hdr,
+ property_value);
+ vcd_status = VCD_S_SUCCESS;
+ break;
+ default:
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ break;
+ }
+ return vcd_status;
+}
+
+static u32 ddl_set_enc_dynamic_property(struct ddl_client_context *ddl,
+ struct vcd_property_hdr *property_hdr, void *property_value)
+{
+ struct ddl_encoder_data *encoder = &ddl->codec_data.encoder;
+ u32 vcd_status = VCD_ERR_ILLEGAL_PARM;
+ u32 dynamic_prop_change = 0x0;
+
+ switch (property_hdr->prop_id) {
+ case VCD_I_REQ_IFRAME:
+ if (sizeof(struct vcd_property_req_i_frame) ==
+ property_hdr->sz) {
+ dynamic_prop_change |= DDL_ENC_REQ_IFRAME;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_TARGET_BITRATE:
+ {
+ struct vcd_property_target_bitrate *bitrate =
+ (struct vcd_property_target_bitrate *)property_value;
+
+ if (sizeof(struct vcd_property_target_bitrate) ==
+ property_hdr->sz && bitrate->target_bitrate &&
+ bitrate->target_bitrate <= DDL_MAX_BIT_RATE) {
+ encoder->target_bit_rate = *bitrate;
+ dynamic_prop_change = DDL_ENC_CHANGE_BITRATE;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_INTRA_PERIOD:
+ {
+ struct vcd_property_i_period *i_period =
+ (struct vcd_property_i_period *)property_value;
+
+ if (sizeof(struct vcd_property_i_period) ==
+ property_hdr->sz) {
+ encoder->i_period = *i_period;
+ dynamic_prop_change = DDL_ENC_CHANGE_IPERIOD;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_FRAME_RATE:
+ {
+ struct vcd_property_frame_rate *frame_rate =
+ (struct vcd_property_frame_rate *)
+ property_value;
+ if (sizeof(struct vcd_property_frame_rate) ==
+ property_hdr->sz &&
+ frame_rate->fps_denominator &&
+ frame_rate->fps_numerator &&
+ frame_rate->fps_denominator <=
+ frame_rate->fps_numerator) {
+ encoder->frame_rate = *frame_rate;
+ dynamic_prop_change = DDL_ENC_CHANGE_FRAMERATE;
+ if (DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN) &&
+ (encoder->codec.codec != VCD_CODEC_MPEG4 ||
+ encoder->short_header.short_header)) {
+ ddl_set_default_enc_vop_timing(encoder);
+ }
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ case VCD_I_INTRA_REFRESH:
+ {
+ struct vcd_property_intra_refresh_mb_number
+ *intra_refresh_mb_num =
+ (struct vcd_property_intra_refresh_mb_number *)
+ property_value;
+ u32 frame_mb_num = DDL_NO_OF_MB(encoder->frame_size.width,
+ encoder->frame_size.height);
+
+ if ((sizeof(struct vcd_property_intra_refresh_mb_number) ==
+ property_hdr->sz) &&
+ (intra_refresh_mb_num->cir_mb_number <= frame_mb_num)) {
+ encoder->intra_refresh = *intra_refresh_mb_num;
+ dynamic_prop_change = DDL_ENC_CHANGE_CIR;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ default:
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ break;
+ }
+
+ if (!vcd_status && (DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME)
+ || DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME_DONE)))
+ encoder->dynamic_prop_change |= dynamic_prop_change;
+
+ return vcd_status;
+}
+
+void ddl_set_default_dec_property(struct ddl_client_context *ddl)
+{
+ struct ddl_decoder_data *decoder =
+ &(ddl->codec_data.decoder);
+
+ if (decoder->codec.codec >= VCD_CODEC_MPEG2 &&
+ decoder->codec.codec <= VCD_CODEC_XVID)
+ decoder->post_filter.post_filter = false;
+ else
+ decoder->post_filter.post_filter = false;
+ decoder->buf_format.buffer_format = VCD_BUFFER_FORMAT_TILE_4x2;
+ decoder->client_frame_size.height = VCD_DDL_TEST_DEFAULT_HEIGHT;
+ decoder->client_frame_size.width = VCD_DDL_TEST_DEFAULT_WIDTH;
+ decoder->client_frame_size.stride = VCD_DDL_TEST_DEFAULT_WIDTH;
+ decoder->client_frame_size.scan_lines = VCD_DDL_TEST_DEFAULT_HEIGHT;
+ decoder->progressive_only = 1;
+ decoder->idr_only_decoding = false;
+ decoder->output_order = VCD_DEC_ORDER_DISPLAY;
+ decoder->field_needed_for_prev_ip = 0;
+ decoder->cont_mode = 0;
+ ddl_set_default_metadata_flag(ddl);
+ ddl_set_default_decoder_buffer_req(decoder, true);
+}
+
+static void ddl_set_default_enc_property(struct ddl_client_context *ddl)
+{
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+
+ ddl_set_default_enc_profile(encoder);
+ ddl_set_default_enc_level(encoder);
+ encoder->rc.rate_control = VCD_RATE_CONTROL_VBR_VFR;
+ ddl_set_default_enc_rc_params(encoder);
+ ddl_set_default_enc_intra_period(encoder);
+ encoder->intra_refresh.cir_mb_number = 0;
+ ddl_set_default_enc_vop_timing(encoder);
+ encoder->multi_slice.m_slice_sel = VCD_MSLICE_OFF;
+ encoder->multi_slice.m_slice_size = 0;
+ ddl->b_count = 0;
+ encoder->short_header.short_header = false;
+ encoder->entropy_control.entropy_sel = VCD_ENTROPY_SEL_CAVLC;
+ encoder->entropy_control.cabac_model = VCD_CABAC_MODEL_NUMBER_0;
+ encoder->db_control.db_config =
+ VCD_DB_ALL_BLOCKING_BOUNDARY;
+ encoder->db_control.slice_alpha_offset = 0;
+ encoder->db_control.slice_beta_offset = 0;
+ encoder->recon_buf_format.buffer_format =
+ VCD_BUFFER_FORMAT_TILE_1x1;
+ encoder->buf_format.buffer_format = VCD_BUFFER_FORMAT_NV12_16M2KA;
+ encoder->hdr_ext_control = 0;
+ encoder->mb_info_enable = false;
+ encoder->num_references_for_p_frame = DDL_MIN_NUM_REF_FOR_P_FRAME;
+ ddl_set_default_metadata_flag(ddl);
+ ddl_set_default_encoder_buffer_req(encoder);
+}
+
+static void ddl_set_default_enc_profile(struct ddl_encoder_data *encoder)
+{
+ enum vcd_codec codec = encoder->codec.codec;
+
+ if (codec == VCD_CODEC_MPEG4)
+ encoder->profile.profile = VCD_PROFILE_MPEG4_SP;
+ else if (codec == VCD_CODEC_H264)
+ encoder->profile.profile = VCD_PROFILE_H264_BASELINE;
+ else
+ encoder->profile.profile = VCD_PROFILE_H263_BASELINE;
+}
+
+static void ddl_set_default_enc_level(struct ddl_encoder_data *encoder)
+{
+ enum vcd_codec codec = encoder->codec.codec;
+
+ if (codec == VCD_CODEC_MPEG4)
+ encoder->level.level = VCD_LEVEL_MPEG4_1;
+ else if (codec == VCD_CODEC_H264)
+ encoder->level.level = VCD_LEVEL_H264_1;
+ else
+ encoder->level.level = VCD_LEVEL_H263_10;
+}
+
+static void ddl_set_default_enc_vop_timing(
+ struct ddl_encoder_data *encoder)
+{
+ if (encoder->codec.codec == VCD_CODEC_MPEG4) {
+ encoder->vop_timing.vop_time_resolution =
+ (encoder->frame_rate.fps_numerator << 1) /
+ encoder->frame_rate.fps_denominator;
+ } else
+ encoder->vop_timing.vop_time_resolution =
+ DDL_FRAMERATE_SCALE(DDL_INITIAL_FRAME_RATE);
+}
+
+static void ddl_set_default_enc_intra_period(
+ struct ddl_encoder_data *encoder)
+{
+ switch (encoder->rc.rate_control) {
+ default:
+ case VCD_RATE_CONTROL_VBR_VFR:
+ case VCD_RATE_CONTROL_VBR_CFR:
+ case VCD_RATE_CONTROL_CBR_VFR:
+ case VCD_RATE_CONTROL_OFF:
+ encoder->i_period.p_frames =
+ ((encoder->frame_rate.fps_numerator << 1) /
+ encoder->frame_rate.fps_denominator) - 1;
+ break;
+ case VCD_RATE_CONTROL_CBR_CFR:
+ encoder->i_period.p_frames =
+ ((encoder->frame_rate.fps_numerator >> 1) /
+ encoder->frame_rate.fps_denominator) - 1;
+ break;
+ }
+ encoder->i_period.b_frames = DDL_DEFAULT_NUM_OF_B_FRAME;
+}
+
+static void ddl_set_default_enc_rc_params(
+ struct ddl_encoder_data *encoder)
+{
+ enum vcd_codec codec = encoder->codec.codec;
+ encoder->rc_level.frame_level_rc = true;
+ encoder->qp_range.min_qp = 0x1;
+ if (codec == VCD_CODEC_H264) {
+ encoder->qp_range.min_qp = 0x1;
+ encoder->qp_range.max_qp = 0x33;
+ encoder->session_qp.i_frame_qp = 0x14;
+ encoder->session_qp.p_frame_qp = 0x14;
+ encoder->session_qp.b_frame_qp = 0x14;
+ encoder->rc_level.mb_level_rc = true;
+ encoder->adaptive_rc.disable_activity_region_flag = true;
+ encoder->adaptive_rc.disable_dark_region_as_flag = true;
+ encoder->adaptive_rc.disable_smooth_region_as_flag = true;
+ encoder->adaptive_rc.disable_static_region_as_flag = true;
+ } else {
+ encoder->qp_range.max_qp = 0x1f;
+ encoder->qp_range.min_qp = 0x1;
+ encoder->session_qp.i_frame_qp = 0xd;
+ encoder->session_qp.p_frame_qp = 0xd;
+ encoder->session_qp.b_frame_qp = 0xd;
+ encoder->rc_level.frame_level_rc = true;
+ encoder->rc_level.mb_level_rc = false;
+ }
+ switch (encoder->rc.rate_control) {
+ case VCD_RATE_CONTROL_VBR_CFR:
+ encoder->r_cframe_skip = 0;
+ encoder->frame_level_rc.reaction_coeff = 0x1f4;
+ break;
+ case VCD_RATE_CONTROL_CBR_VFR:
+ encoder->r_cframe_skip = 1;
+ if (codec != VCD_CODEC_H264) {
+ encoder->session_qp.i_frame_qp = 0xf;
+ encoder->session_qp.p_frame_qp = 0xf;
+ encoder->session_qp.b_frame_qp = 0xf;
+ }
+ encoder->frame_level_rc.reaction_coeff = 0x14;
+ break;
+ case VCD_RATE_CONTROL_CBR_CFR:
+ encoder->r_cframe_skip = 0;
+ encoder->frame_level_rc.reaction_coeff = 0x6;
+ break;
+ case VCD_RATE_CONTROL_OFF:
+ encoder->r_cframe_skip = 0;
+ encoder->rc_level.frame_level_rc = false;
+ encoder->rc_level.mb_level_rc = false;
+ break;
+ case VCD_RATE_CONTROL_VBR_VFR:
+ default:
+ encoder->r_cframe_skip = 1;
+ encoder->frame_level_rc.reaction_coeff = 0x1f4;
+ break;
+ }
+}
+
+void ddl_set_default_encoder_buffer_req(struct ddl_encoder_data *encoder)
+{
+ u32 y_cb_cr_size, y_size;
+ memset(&encoder->hw_bufs.dpb_y, 0, sizeof(struct ddl_buf_addr) * 4);
+ memset(&encoder->hw_bufs.dpb_c, 0, sizeof(struct ddl_buf_addr) * 4);
+
+ y_cb_cr_size = ddl_get_yuv_buffer_size(&encoder->frame_size,
+ &encoder->buf_format, false,
+ encoder->hdr.decoding, &y_size);
+ encoder->input_buf_size.size_yuv = y_cb_cr_size;
+ encoder->input_buf_size.size_y = y_size;
+ encoder->input_buf_size.size_c = y_cb_cr_size - y_size;
+ memset(&encoder->input_buf_req , 0 ,
+ sizeof(struct vcd_buffer_requirement));
+ encoder->input_buf_req.min_count = 3;
+ encoder->input_buf_req.actual_count =
+ encoder->input_buf_req.min_count;
+ encoder->input_buf_req.max_count = DDL_MAX_BUFFER_COUNT;
+ encoder->input_buf_req.sz = y_cb_cr_size;
+ if (encoder->buf_format.buffer_format ==
+ VCD_BUFFER_FORMAT_NV12_16M2KA)
+ encoder->input_buf_req.align =
+ DDL_LINEAR_BUFFER_ALIGN_BYTES;
+ else if (VCD_BUFFER_FORMAT_TILE_4x2 ==
+ encoder->buf_format.buffer_format)
+ encoder->input_buf_req.align = DDL_TILE_BUFFER_ALIGN_BYTES;
+ encoder->client_input_buf_req = encoder->input_buf_req;
+ memset(&encoder->output_buf_req , 0 ,
+ sizeof(struct vcd_buffer_requirement));
+ encoder->output_buf_req.min_count =
+ encoder->i_period.b_frames + 2;
+ encoder->output_buf_req.actual_count =
+ encoder->output_buf_req.min_count + 3;
+ encoder->output_buf_req.max_count = DDL_MAX_BUFFER_COUNT;
+ encoder->output_buf_req.align = DDL_LINEAR_BUFFER_ALIGN_BYTES;
+ if (y_cb_cr_size >= VCD_DDL_720P_YUV_BUF_SIZE)
+ y_cb_cr_size = y_cb_cr_size>>1;
+ encoder->output_buf_req.sz =
+ DDL_ALIGN(y_cb_cr_size, DDL_KILO_BYTE(4));
+ ddl_set_default_encoder_metadata_buffer_size(encoder);
+ encoder->client_output_buf_req = encoder->output_buf_req;
+}
+
+u32 ddl_set_default_decoder_buffer_req(struct ddl_decoder_data *decoder,
+ u32 estimate)
+{
+ struct vcd_property_frame_size *frame_size;
+ struct vcd_buffer_requirement *input_buf_req;
+ struct vcd_buffer_requirement *output_buf_req;
+ u32 min_dpb, y_cb_cr_size;
+
+ if (!decoder->codec.codec)
+ return false;
+ min_dpb = ddl_decoder_min_num_dpb(decoder);
+ if (estimate) {
+ frame_size = &decoder->client_frame_size;
+ output_buf_req = &decoder->client_output_buf_req;
+ input_buf_req = &decoder->client_input_buf_req;
+ y_cb_cr_size = ddl_get_yuv_buffer_size(frame_size,
+ &decoder->buf_format,
+ (!decoder->progressive_only),
+ decoder->hdr.decoding, NULL);
+ } else {
+ if (min_dpb >= decoder->min_dpb_num ||
+ decoder->idr_only_decoding) {
+ frame_size = &decoder->frame_size;
+ output_buf_req = &decoder->actual_output_buf_req;
+ input_buf_req = &decoder->actual_input_buf_req;
+ min_dpb = decoder->min_dpb_num;
+ y_cb_cr_size = decoder->y_cb_cr_size;
+ } else {
+ u32 max_dpb_size;
+
+ max_dpb_size = DDL_NO_OF_MB(
+ decoder->client_frame_size.stride,
+ decoder->client_frame_size.scan_lines);
+ max_dpb_size *= (decoder->min_dpb_num - 2);
+ DDL_MSG_ERROR("Error: H264MaxDpbSizeExceeded: %d > %d",
+ max_dpb_size, MAX_DPB_SIZE_L4PT0_MBS);
+ return false;
+ }
+ }
+ memset(output_buf_req, 0,
+ sizeof(struct vcd_buffer_requirement));
+ if ((!estimate && !decoder->idr_only_decoding) || (decoder->cont_mode))
+ output_buf_req->actual_count = min_dpb + 4;
+ else
+ output_buf_req->actual_count = min_dpb;
+ output_buf_req->min_count = min_dpb;
+ output_buf_req->max_count = DDL_MAX_BUFFER_COUNT;
+ output_buf_req->sz = y_cb_cr_size;
+ DDL_MSG_LOW("output_buf_req->sz : %d", output_buf_req->sz);
+ if (decoder->buf_format.buffer_format != VCD_BUFFER_FORMAT_NV12)
+ output_buf_req->align = DDL_TILE_BUFFER_ALIGN_BYTES;
+ else
+ output_buf_req->align = DDL_LINEAR_BUFFER_ALIGN_BYTES;
+ ddl_set_default_decoder_metadata_buffer_size(decoder, frame_size,
+ output_buf_req);
+
+ decoder->min_output_buf_req = *output_buf_req;
+ memset(input_buf_req, 0,
+ sizeof(struct vcd_buffer_requirement));
+ input_buf_req->min_count = 1;
+ input_buf_req->actual_count = input_buf_req->min_count + 1;
+ input_buf_req->max_count = DDL_MAX_BUFFER_COUNT;
+ input_buf_req->sz = (1024 * 1024);
+ input_buf_req->align = DDL_LINEAR_BUFFER_ALIGN_BYTES;
+ decoder->min_input_buf_req = *input_buf_req;
+ return true;
+}
+
+u32 ddl_get_yuv_buffer_size(struct vcd_property_frame_size *frame_size,
+ struct vcd_property_buffer_format *buf_format,
+ u32 interlace, u32 decoding, u32 *pn_c_offset)
+{
+ struct vcd_property_frame_size frame_sz = *frame_size;
+ u32 total_memory_size = 0, c_offset = 0;
+ ddl_calculate_stride(&frame_sz, interlace);
+ if (buf_format->buffer_format == VCD_BUFFER_FORMAT_TILE_4x2) {
+ u32 component_mem_size, width_round_up;
+ u32 height_round_up, height_chroma = (frame_sz.scan_lines >> 1);
+
+ width_round_up =
+ DDL_ALIGN(frame_sz.stride, DDL_TILE_ALIGN_WIDTH);
+ height_round_up =
+ DDL_ALIGN(frame_sz.scan_lines,
+ DDL_TILE_ALIGN_HEIGHT);
+ component_mem_size = width_round_up * height_round_up;
+ component_mem_size = DDL_ALIGN(component_mem_size,
+ DDL_TILE_MULTIPLY_FACTOR);
+ c_offset = component_mem_size;
+ total_memory_size = ((component_mem_size +
+ DDL_TILE_BUF_ALIGN_GUARD_BYTES) &
+ DDL_TILE_BUF_ALIGN_MASK);
+ height_round_up = DDL_ALIGN(height_chroma,
+ DDL_TILE_ALIGN_HEIGHT);
+ component_mem_size = width_round_up * height_round_up;
+ component_mem_size = DDL_ALIGN(component_mem_size,
+ DDL_TILE_MULTIPLY_FACTOR);
+ total_memory_size += component_mem_size;
+ } else {
+ if (decoding)
+ total_memory_size = frame_sz.scan_lines *
+ frame_sz.stride;
+ else
+ total_memory_size = frame_sz.height * frame_sz.stride;
+ c_offset = DDL_ALIGN(total_memory_size,
+ DDL_LINEAR_MULTIPLY_FACTOR);
+ total_memory_size = c_offset + DDL_ALIGN(
+ total_memory_size >> 1, DDL_LINEAR_MULTIPLY_FACTOR);
+ }
+ if (pn_c_offset)
+ *pn_c_offset = c_offset;
+ return total_memory_size;
+}
+
+
+void ddl_calculate_stride(struct vcd_property_frame_size *frame_size,
+ u32 interlace)
+{
+ frame_size->stride = DDL_ALIGN(frame_size->width,
+ DDL_LINEAR_ALIGN_WIDTH);
+ if (interlace)
+ frame_size->scan_lines = DDL_ALIGN(frame_size->height,
+ DDL_TILE_ALIGN_HEIGHT);
+ else
+ frame_size->scan_lines = DDL_ALIGN(frame_size->height,
+ DDL_LINEAR_ALIGN_HEIGHT);
+}
+
+
+static u32 ddl_valid_buffer_requirement(struct vcd_buffer_requirement
+ *original_buf_req, struct vcd_buffer_requirement *req_buf_req)
+{
+ u32 status = false;
+
+ if (original_buf_req->max_count >= req_buf_req->actual_count &&
+ original_buf_req->min_count <=
+ req_buf_req->actual_count &&
+ !((original_buf_req->align - (u32)0x1) &
+ req_buf_req->align) &&
+ /*original_buf_req->align <= req_buf_req->align,*/
+ original_buf_req->sz <= req_buf_req->sz)
+ status = true;
+ else
+ DDL_MSG_ERROR("ddl_valid_buf_req:Failed");
+ return status;
+}
+
+static u32 ddl_decoder_min_num_dpb(struct ddl_decoder_data *decoder)
+{
+ u32 min_dpb = 0;
+
+ if (decoder->idr_only_decoding) {
+ min_dpb = DDL_MIN_BUFFER_COUNT;
+ if (decoder->post_filter.post_filter)
+ min_dpb *= 2;
+ return min_dpb;
+ }
+
+ switch (decoder->codec.codec) {
+ case VCD_CODEC_H264:
+ {
+ u32 yuv_size_in_mb = DDL_MIN(DDL_NO_OF_MB(
+ decoder->client_frame_size.stride,
+ decoder->client_frame_size.scan_lines),
+ MAX_FRAME_SIZE_L4PT0_MBS);
+ min_dpb = DDL_MIN((MAX_DPB_SIZE_L4PT0_MBS /
+ yuv_size_in_mb), 16);
+ min_dpb += 2;
+ }
+ break;
+ case VCD_CODEC_H263:
+ min_dpb = 3;
+ break;
+ default:
+ case VCD_CODEC_MPEG1:
+ case VCD_CODEC_MPEG2:
+ case VCD_CODEC_MPEG4:
+ case VCD_CODEC_DIVX_3:
+ case VCD_CODEC_DIVX_4:
+ case VCD_CODEC_DIVX_5:
+ case VCD_CODEC_DIVX_6:
+ case VCD_CODEC_XVID:
+ case VCD_CODEC_VC1:
+ case VCD_CODEC_VC1_RCV:
+ min_dpb = 4;
+ if (decoder->post_filter.post_filter)
+ min_dpb *= 2;
+ break;
+ }
+ return min_dpb;
+}
+
+static u32 ddl_set_dec_buffers(struct ddl_decoder_data *decoder,
+ struct ddl_property_dec_pic_buffers *dpb)
+{
+ u32 vcd_status = VCD_S_SUCCESS, loopc;
+
+
+ for (loopc = 0; !vcd_status &&
+ loopc < dpb->no_of_dec_pic_buf; ++loopc) {
+ if ((!DDL_ADDR_IS_ALIGNED(dpb->dec_pic_buffers[loopc].
+ vcd_frm.physical,
+ decoder->client_output_buf_req.align)) ||
+ (dpb->dec_pic_buffers[loopc].vcd_frm.alloc_len <
+ decoder->client_output_buf_req.sz))
+ vcd_status = VCD_ERR_ILLEGAL_PARM;
+ }
+ if (vcd_status) {
+ DDL_MSG_ERROR("ddl_set_prop:"
+ "Dpb_align_fail_or_alloc_size_small");
+ return vcd_status;
+ }
+ if (decoder->dp_buf.no_of_dec_pic_buf) {
+ kfree(decoder->dp_buf.dec_pic_buffers);
+ decoder->dp_buf.no_of_dec_pic_buf = 0;
+ }
+ decoder->dp_buf.dec_pic_buffers =
+ kmalloc(dpb->no_of_dec_pic_buf *
+ sizeof(struct ddl_frame_data_tag), GFP_KERNEL);
+ if (!decoder->dp_buf.dec_pic_buffers) {
+ DDL_MSG_ERROR("ddl_dec_set_prop:Dpb_container_alloc_failed");
+ return VCD_ERR_ALLOC_FAIL;
+ }
+ decoder->dp_buf.no_of_dec_pic_buf = dpb->no_of_dec_pic_buf;
+ for (loopc = 0; loopc < dpb->no_of_dec_pic_buf; ++loopc)
+ decoder->dp_buf.dec_pic_buffers[loopc] =
+ dpb->dec_pic_buffers[loopc];
+ decoder->dpb_mask.client_mask = 0;
+ decoder->dpb_mask.hw_mask = 0;
+ decoder->dynamic_prop_change = 0;
+ return VCD_S_SUCCESS;
+}
+
+void ddl_set_initial_default_values(struct ddl_client_context *ddl)
+{
+
+ if (ddl->decoding) {
+ ddl->codec_data.decoder.codec.codec = VCD_CODEC_MPEG4;
+ ddl_set_default_dec_property(ddl);
+ } else {
+ struct ddl_encoder_data *encoder =
+ &(ddl->codec_data.encoder);
+ encoder->codec.codec = VCD_CODEC_MPEG4;
+ encoder->target_bit_rate.target_bitrate = 64000;
+ encoder->frame_size.width = VCD_DDL_TEST_DEFAULT_WIDTH;
+ encoder->frame_size.height = VCD_DDL_TEST_DEFAULT_HEIGHT;
+ encoder->frame_size.scan_lines =
+ VCD_DDL_TEST_DEFAULT_HEIGHT;
+ encoder->frame_size.stride = VCD_DDL_TEST_DEFAULT_WIDTH;
+ encoder->frame_rate.fps_numerator = DDL_INITIAL_FRAME_RATE;
+ encoder->frame_rate.fps_denominator = 1;
+ ddl_set_default_enc_property(ddl);
+ }
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
new file mode 100644
index 0000000..70e1de1
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
@@ -0,0 +1,678 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "vcd_ddl_shared_mem.h"
+
+#define VIDC_SM_EXTENDED_DECODE_STATUS_ADDR 0x0000
+#define VIDC_SM_EXT_DEC_STATUS_RESOLUTION_CHANGE_BMSK 0x1
+#define VIDC_SM_EXT_DEC_STATUS_RESOLUTION_CHANGE_SHFT 0x0
+#define VIDC_SM_EXT_DEC_STATUS_MORE_FIELD_NEEDED_BMSK 0x4
+#define VIDC_SM_EXT_DEC_STATUS_MORE_FIELD_NEEDED_SHFT 0x2
+
+#define VIDC_SM_SET_FRAME_TAG_ADDR 0x0004
+#define VIDC_SM_GET_FRAME_TAG_TOP_ADDR 0x0008
+#define VIDC_SM_GET_FRAME_TAG_BOTTOM_ADDR 0x000c
+#define VIDC_SM_PIC_TIME_TOP_ADDR 0x0010
+#define VIDC_SM_PIC_TIME_BOTTOM_ADDR 0x0014
+#define VIDC_SM_START_BYTE_NUM_ADDR 0x0018
+
+#define VIDC_SM_CROP_INFO1_ADDR 0x0020
+#define VIDC_SM_CROP_INFO1_RIGHT_OFFSET_BMSK 0xffff0000
+#define VIDC_SM_CROP_INFO1_RIGHT_OFFSET_SHFT 16
+#define VIDC_SM_CROP_INFO1_LEFT_OFFSET_BMSK 0x0000ffff
+#define VIDC_SM_CROP_INFO1_LEFT_OFFSET_SHFT 0
+
+#define VIDC_SM_CROP_INFO2_ADDR 0x0024
+#define VIDC_SM_CROP_INFO2_BOTTOM_OFFSET_BMSK 0xffff0000
+#define VIDC_SM_CROP_INFO2_BOTTOM_OFFSET_SHFT 16
+#define VIDC_SM_CROP_INFO2_TOP_OFFSET_BMSK 0x0000ffff
+#define VIDC_SM_CROP_INFO2_TOP_OFFSET_SHFT 0
+
+#define VIDC_SM_DISP_PIC_PROFILE_ADDR 0x007c
+#define VIDC_SM_DISP_PIC_PROFILE_DISP_PIC_LEVEL_BMASK 0x0000ff00
+#define VIDC_SM_DISP_PIC_PROFILE_DISP_PIC_LEVEL_SHFT 8
+#define VIDC_SM_DISP_PIC_PROFILE_DISP_PIC_PROFILE_BMASK 0x0000001f
+#define VIDC_SM_DISP_PIC_PROFILE_DISP_PIC_PROFILE_SHFT 0
+
+#define VIDC_SM_DISP_PIC_FRAME_TYPE_ADDR 0x00c0
+#define VIDC_SM_DISP_PIC_FRAME_TYPE_BMSK 0x00000003
+#define VIDC_SM_DISP_PIC_FRAME_TYPE_SHFT 0
+
+#define VIDC_SM_FREE_LUMA_DPB_ADDR 0x00c4
+#define VIDC_SM_FREE_LUMA_DPB_BMSK 0xffffffff
+#define VIDC_SM_FREE_LUMA_DPB_SHFT 0
+
+#define VIDC_SM_FREE_LUMA_DPB_DEC_ORDER_ADDR 0x00fc
+#define VIDC_SM_FREE_LUMA_DPB_DEC_ORDER_BMSK 0xffffffff
+#define VIDC_SM_FREE_LUMA_DPB_DEC_ORDER_SHFT 0
+
+#define VIDC_SM_DEC_ORDER_WIDTH_ADDR 0x00e8
+#define VIDC_SM_DEC_ORDER_WIDTH_BMSK 0xffffffff
+#define VIDC_SM_DEC_ORDER_WIDTH_SHFT 0
+
+#define VIDC_SM_DEC_ORDER_HEIGHT_ADDR 0x00ec
+#define VIDC_SM_DEC_ORDER_HEIGHT_BMSK 0xffffffff
+#define VIDC_SM_DEC_ORDER_HEIGHT_SHFT 0
+
+#define VIDC_SM_DEC_CROP_INFO1_ADDR 0x00f4
+#define VIDC_SM_DEC_CROP_INFO1_RIGHT_OFFSET_BMSK 0xffff0000
+#define VIDC_SM_DEC_CROP_INFO1_RIGHT_OFFSET_SHFT 16
+#define VIDC_SM_DEC_CROP_INFO1_LEFT_OFFSET_BMSK 0x0000ffff
+#define VIDC_SM_DEC_CROP_INFO1_LEFT_OFFSET_SHFT 0
+
+#define VIDC_SM_DEC_CROP_INFO2_ADDR 0x00f8
+#define VIDC_SM_DEC_CROP_INFO2_BOTTOM_OFFSET_BMSK 0xffff0000
+#define VIDC_SM_DEC_CROP_INFO2_BOTTOM_OFFSET_SHFT 16
+#define VIDC_SM_DEC_CROP_INFO2_TOP_OFFSET_BMSK 0x0000ffff
+#define VIDC_SM_DEC_CROP_INFO2_TOP_OFFSET_SHFT 0
+
+#define VIDC_SM_IDR_DECODING_ONLY_ADDR 0x0108
+#define VIDC_SM_IDR_DECODING_ONLY_BMSK 0x00000001
+#define VIDC_SM_IDR_DECODING_ONLY_SHIFT 0
+
+#define VIDC_SM_ENC_EXT_CTRL_ADDR 0x0028
+#define VIDC_SM_ENC_EXT_CTRL_VBV_BUFFER_SIZE_BMSK 0xffff0000
+#define VIDC_SM_ENC_EXT_CTRL_VBV_BUFFER_SIZE_SHFT 16
+#define VIDC_SM_ENC_EXT_CTRL_SEQ_HDR_CTRL_BMSK 0x8
+#define VIDC_SM_ENC_EXT_CTRL_SEQ_HDR_CTRL_SHFT 3
+#define VIDC_SM_ENC_EXT_CTRL_FRAME_SKIP_ENABLE_BMSK 0x6
+#define VIDC_SM_ENC_EXT_CTRL_FRAME_SKIP_ENABLE_SHFT 1
+#define VIDC_SM_ENC_EXT_CTRL_HEC_ENABLE_BMSK 0x1
+#define VIDC_SM_ENC_EXT_CTRL_HEC_ENABLE_SHFT 0
+
+#define VIDC_SM_ENC_PARAM_CHANGE_ADDR 0x002c
+#define VIDC_SM_ENC_PARAM_CHANGE_RC_BIT_RATE_BMSK 0x4
+#define VIDC_SM_ENC_PARAM_CHANGE_RC_BIT_RATE_SHFT 2
+#define VIDC_SM_ENC_PARAM_CHANGE_RC_FRAME_RATE_BMSK 0x2
+#define VIDC_SM_ENC_PARAM_CHANGE_RC_FRAME_RATE_SHFT 1
+#define VIDC_SM_ENC_PARAM_CHANGE_I_PERIOD_BMSK 0x1
+#define VIDC_SM_ENC_PARAM_CHANGE_I_PERIOD_SHFT 0
+
+#define VIDC_SM_ENC_VOP_TIMING_ADDR 0x0030
+#define VIDC_SM_ENC_VOP_TIMING_ENABLE_BMSK 0x80000000
+#define VIDC_SM_ENC_VOP_TIMING_ENABLE_SHFT 31
+#define VIDC_SM_ENC_VOP_TIMING_TIME_RESOLUTION_BMSK 0x7fff0000
+#define VIDC_SM_ENC_VOP_TIMING_TIME_RESOLUTION_SHFT 16
+#define VIDC_SM_ENC_VOP_TIMING_FRAME_DELTA_BMSK 0x0000ffff
+#define VIDC_SM_ENC_VOP_TIMING_FRAME_DELTA_SHFT 0
+
+#define VIDC_SM_ENC_HEC_PERIOD_ADDR 0x0034
+
+#define VIDC_SM_H264_REF_L0_ADDR 0x005c
+#define VIDC_SM_H264_REF_L0_CHRO_BTM_FLG_1_BMSK 0x80000000
+#define VIDC_SM_H264_REF_L0_CHRO_BTM_FLG_1_SHFT 31
+#define VIDC_SM_H264_REF_L0_CHRO_REF_1_BMSK 0x7f000000
+#define VIDC_SM_H264_REF_L0_CHRO_REF_1_SHFT 24
+#define VIDC_SM_H264_REF_L0_CHRO_BTM_FLG_0_BMSK 0x00800000
+#define VIDC_SM_H264_REF_L0_CHRO_BTM_FLG_0_SHFT 23
+#define VIDC_SM_H264_REF_L0_CHRO_REF_0_BMSK 0x007f0000
+#define VIDC_SM_H264_REF_L0_CHRO_REF_0_SHFT 16
+#define VIDC_SM_H264_REF_L0_LUMA_BTM_FLG_1_BMSK 0x00008000
+#define VIDC_SM_H264_REF_L0_LUMA_BTM_FLG_1_SHFT 15
+#define VIDC_SM_H264_REF_L0_LUMA_REF_1_BMSK 0x00007f00
+#define VIDC_SM_H264_REF_L0_LUMA_REF_1_SHFT 8
+#define VIDC_SM_H264_REF_L0_LUMA_BTM_FLG_0_BMSK 0x00000080
+#define VIDC_SM_H264_REF_L0_LUMA_BTM_FLG_0_SHFT 7
+#define VIDC_SM_H264_REF_L0_LUMA_REF_0_BMSK 0x0000007f
+#define VIDC_SM_H264_REF_L0_LUMA_REF_0_SHFT 0
+
+#define VIDC_SM_H264_REF_L1_ADDR 0x0060
+#define VIDC_SM_H264_REF_L1_CHRO_BTM_FLG_0_BMSK 0x00800000
+#define VIDC_SM_H264_REF_L1_CHRO_BTM_FLG_0_SHFT 23
+#define VIDC_SM_H264_REF_L1_CHRO_REF_0_BMSK 0x007f0000
+#define VIDC_SM_H264_REF_L1_CHRO_REF_0_SHFT 16
+#define VIDC_SM_H264_REF_L1_LUMA_BTM_FLG_0_BMSK 0x00000080
+#define VIDC_SM_H264_REF_L1_LUMA_BTM_FLG_0_SHFT 7
+#define VIDC_SM_H264_REF_L1_LUMA_REF_0_BMSK 0x0000007f
+#define VIDC_SM_H264_REF_L1_LUMA_REF_0_SHFT 0
+
+#define VIDC_SM_P_B_FRAME_QP_ADDR 0x0070
+#define VIDC_SM_P_B_FRAME_QP_B_FRAME_QP_BMASK 0x00000fc0
+#define VIDC_SM_P_B_FRAME_QP_B_FRAME_QP_SHFT 6
+#define VIDC_SM_P_B_FRAME_QP_P_FRAME_QP_BMASK 0x0000003f
+#define VIDC_SM_P_B_FRAME_QP_P_FRAME_QP_SHFT 0
+
+#define VIDC_SM_NEW_RC_BIT_RATE_ADDR 0x0090
+#define VIDC_SM_NEW_RC_BIT_RATE_VALUE_BMASK 0xffffffff
+#define VIDC_SM_NEW_RC_BIT_RATE_VALUE_SHFT 0
+#define VIDC_SM_NEW_RC_FRAME_RATE_ADDR 0x0094
+#define VIDC_SM_NEW_RC_FRAME_RATE_VALUE_BMASK 0xffffffff
+#define VIDC_SM_NEW_RC_FRAME_RATE_VALUE_SHFT 0
+#define VIDC_SM_NEW_I_PERIOD_ADDR 0x0098
+#define VIDC_SM_NEW_I_PERIOD_VALUE_BMASK 0xffffffff
+#define VIDC_SM_NEW_I_PERIOD_VALUE_SHFT 0
+
+
+#define VIDC_SM_ALLOCATED_LUMA_DPB_SIZE_ADDR 0x0064
+#define VIDC_SM_ALLOCATED_CHROMA_DPB_SIZE_ADDR 0x0068
+#define VIDC_SM_ALLOCATED_MV_SIZE_ADDR 0x006c
+#define VIDC_SM_FLUSH_CMD_TYPE_ADDR 0x0080
+#define VIDC_SM_FLUSH_CMD_INBUF1_ADDR 0x0084
+#define VIDC_SM_FLUSH_CMD_INBUF2_ADDR 0x0088
+#define VIDC_SM_FLUSH_CMD_OUTBUF_ADDR 0x008c
+#define VIDC_SM_MIN_LUMA_DPB_SIZE_ADDR 0x00b0
+#define VIDC_SM_MIN_CHROMA_DPB_SIZE_ADDR 0x00bc
+
+
+#define VIDC_SM_METADATA_ENABLE_ADDR 0x0038
+#define VIDC_SM_METADATA_ENABLE_EXTRADATA_BMSK 0x40
+#define VIDC_SM_METADATA_ENABLE_EXTRADATA_SHFT 6
+#define VIDC_SM_METADATA_ENABLE_ENC_SLICE_SIZE_BMSK 0x20
+#define VIDC_SM_METADATA_ENABLE_ENC_SLICE_SIZE_SHFT 5
+#define VIDC_SM_METADATA_ENABLE_VUI_BMSK 0x10
+#define VIDC_SM_METADATA_ENABLE_VUI_SHFT 4
+#define VIDC_SM_METADATA_ENABLE_SEI_VIDC_BMSK 0x8
+#define VIDC_SM_METADATA_ENABLE_SEI_VIDC_SHFT 3
+#define VIDC_SM_METADATA_ENABLE_VC1_PARAM_BMSK 0x4
+#define VIDC_SM_METADATA_ENABLE_VC1_PARAM_SHFT 2
+#define VIDC_SM_METADATA_ENABLE_CONCEALED_MB_BMSK 0x2
+#define VIDC_SM_METADATA_ENABLE_CONCEALED_MB_SHFT 1
+#define VIDC_SM_METADATA_ENABLE_QP_BMSK 0x1
+#define VIDC_SM_METADATA_ENABLE_QP_SHFT 0
+
+
+#define VIDC_SM_METADATA_STATUS_ADDR 0x003c
+#define VIDC_SM_METADATA_STATUS_STATUS_BMSK 0x1
+#define VIDC_SM_METADATA_STATUS_STATUS_SHFT 0
+
+#define VIDC_SM_METADATA_DISPLAY_INDEX_ADDR 0x0040
+#define VIDC_SM_EXT_METADATA_START_ADDR_ADDR 0x0044
+
+#define VIDC_SM_PUT_EXTRADATA_ADDR 0x0048
+#define VIDC_SM_PUT_EXTRADATA_PUT_BMSK 0x1
+#define VIDC_SM_PUT_EXTRADATA_PUT_SHFT 0
+
+#define VIDC_SM_EXTRADATA_ADDR_ADDR 0x004c
+
+#define VIDC_SM_CHROMA_ADDR_CHANGE_ADDR 0x0148
+#define VIDC_SM_CHROMA_ADDR_CHANGE_BMASK 0x00000001
+#define VIDC_SM_CHROMA_ADDR_CHANGE_SHFT 0
+
+#define DDL_MEM_WRITE_32(base, offset, val) ddl_mem_write_32(\
+ (u32 *) ((u8 *) (base)->align_virtual_addr + (offset)), (val))
+#define DDL_MEM_READ_32(base, offset) ddl_mem_read_32(\
+ (u32 *) ((u8 *) (base)->align_virtual_addr + (offset)))
+
+#define DDL_SHARED_MEM_11BIT_RIGHT_SHIFT 11
+
+static void ddl_mem_write_32(u32 *addr, u32 data)
+{
+ *addr = data;
+}
+
+static u32 ddl_mem_read_32(u32 *addr)
+{
+ return *addr;
+}
+
+void vidc_sm_get_extended_decode_status(struct ddl_buf_addr *shared_mem,
+ u32 *more_field_needed,
+ u32 *resl_change)
+{
+ u32 decode_status = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_EXTENDED_DECODE_STATUS_ADDR);
+ if (more_field_needed)
+ *more_field_needed =
+ VIDC_GETFIELD(decode_status,
+ VIDC_SM_EXT_DEC_STATUS_MORE_FIELD_NEEDED_BMSK,
+ VIDC_SM_EXT_DEC_STATUS_MORE_FIELD_NEEDED_SHFT);
+ if (resl_change)
+ *resl_change =
+ VIDC_GETFIELD(decode_status,
+ VIDC_SM_EXT_DEC_STATUS_RESOLUTION_CHANGE_BMSK,
+ VIDC_SM_EXT_DEC_STATUS_RESOLUTION_CHANGE_SHFT);
+}
+
+void vidc_sm_set_frame_tag(struct ddl_buf_addr *shared_mem,
+ u32 frame_tag)
+{
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_SET_FRAME_TAG_ADDR, frame_tag);
+}
+
+void vidc_sm_get_frame_tags(struct ddl_buf_addr *shared_mem,
+ u32 *pn_frame_tag_top, u32 *pn_frame_tag_bottom)
+{
+ *pn_frame_tag_top = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_GET_FRAME_TAG_TOP_ADDR);
+ *pn_frame_tag_bottom = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_GET_FRAME_TAG_BOTTOM_ADDR);
+}
+
+void vidc_sm_get_picture_times(struct ddl_buf_addr *shared_mem,
+ u32 *pn_time_top, u32 *pn_time_bottom)
+{
+ *pn_time_top = DDL_MEM_READ_32(shared_mem, VIDC_SM_PIC_TIME_TOP_ADDR);
+ *pn_time_bottom = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_PIC_TIME_BOTTOM_ADDR);
+}
+
+void vidc_sm_set_start_byte_number(struct ddl_buf_addr *shared_mem,
+ u32 byte_num)
+{
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_START_BYTE_NUM_ADDR, byte_num);
+}
+
+void vidc_sm_get_crop_info(struct ddl_buf_addr *shared_mem,
+ u32 *pn_left, u32 *pn_right, u32 *pn_top, u32 *pn_bottom)
+{
+ u32 info1, info2;
+
+ info1 = DDL_MEM_READ_32(shared_mem, VIDC_SM_CROP_INFO1_ADDR);
+
+ *pn_left = VIDC_GETFIELD(info1, VIDC_SM_CROP_INFO1_LEFT_OFFSET_BMSK,
+ VIDC_SM_CROP_INFO1_LEFT_OFFSET_SHFT);
+ *pn_right = VIDC_GETFIELD(info1, VIDC_SM_CROP_INFO1_RIGHT_OFFSET_BMSK,
+ VIDC_SM_CROP_INFO1_RIGHT_OFFSET_SHFT);
+ info2 = DDL_MEM_READ_32(shared_mem, VIDC_SM_CROP_INFO2_ADDR);
+ *pn_top = VIDC_GETFIELD(info2, VIDC_SM_CROP_INFO2_TOP_OFFSET_BMSK,
+ VIDC_SM_CROP_INFO2_TOP_OFFSET_SHFT);
+ *pn_bottom = VIDC_GETFIELD(info2,
+ VIDC_SM_CROP_INFO2_BOTTOM_OFFSET_BMSK,
+ VIDC_SM_CROP_INFO2_BOTTOM_OFFSET_SHFT);
+}
+
+void vidc_sm_get_displayed_picture_frame(struct ddl_buf_addr
+ *shared_mem, u32 *n_disp_picture_frame)
+{
+ u32 disp_pict_frame;
+
+ disp_pict_frame = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_DISP_PIC_FRAME_TYPE_ADDR);
+ *n_disp_picture_frame = VIDC_GETFIELD(disp_pict_frame,
+ VIDC_SM_DISP_PIC_FRAME_TYPE_BMSK,
+ VIDC_SM_DISP_PIC_FRAME_TYPE_SHFT);
+}
+void vidc_sm_get_available_luma_dpb_address(struct ddl_buf_addr
+ *shared_mem, u32 *pn_free_luma_dpb_address)
+{
+ *pn_free_luma_dpb_address = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_FREE_LUMA_DPB_ADDR);
+}
+
+void vidc_sm_get_available_luma_dpb_dec_order_address(
+ struct ddl_buf_addr *shared_mem,
+ u32 *pn_free_luma_dpb_address)
+{
+ *pn_free_luma_dpb_address = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_FREE_LUMA_DPB_DEC_ORDER_ADDR);
+}
+
+void vidc_sm_get_dec_order_resl(
+ struct ddl_buf_addr *shared_mem, u32 *width, u32 *height)
+{
+ *width = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_DEC_ORDER_WIDTH_ADDR);
+ *height = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_DEC_ORDER_HEIGHT_ADDR);
+}
+
+void vidc_sm_get_dec_order_crop_info(
+ struct ddl_buf_addr *shared_mem, u32 *left,
+ u32 *right, u32 *top, u32 *bottom)
+{
+ u32 crop_data;
+ crop_data = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_DEC_CROP_INFO1_ADDR);
+ *left = VIDC_GETFIELD(crop_data,
+ VIDC_SM_DEC_CROP_INFO1_LEFT_OFFSET_BMSK,
+ VIDC_SM_DEC_CROP_INFO1_LEFT_OFFSET_SHFT);
+ *right = VIDC_GETFIELD(crop_data,
+ VIDC_SM_DEC_CROP_INFO1_RIGHT_OFFSET_BMSK,
+ VIDC_SM_DEC_CROP_INFO1_RIGHT_OFFSET_SHFT);
+ crop_data = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_DEC_CROP_INFO2_ADDR);
+ *top = VIDC_GETFIELD(crop_data,
+ VIDC_SM_DEC_CROP_INFO2_TOP_OFFSET_BMSK,
+ VIDC_SM_DEC_CROP_INFO2_TOP_OFFSET_SHFT);
+ *bottom = VIDC_GETFIELD(crop_data,
+ VIDC_SM_DEC_CROP_INFO2_BOTTOM_OFFSET_BMSK,
+ VIDC_SM_DEC_CROP_INFO2_BOTTOM_OFFSET_SHFT);
+}
+
+void vidc_sm_set_extended_encoder_control(struct ddl_buf_addr
+ *shared_mem, u32 hec_enable,
+ enum VIDC_SM_frame_skip frame_skip_mode,
+ u32 seq_hdr_in_band, u32 vbv_buffer_size)
+{
+ u32 enc_ctrl;
+
+ enc_ctrl = VIDC_SETFIELD((hec_enable) ? 1 : 0,
+ VIDC_SM_ENC_EXT_CTRL_HEC_ENABLE_SHFT,
+ VIDC_SM_ENC_EXT_CTRL_HEC_ENABLE_BMSK) |
+ VIDC_SETFIELD((u32) frame_skip_mode,
+ VIDC_SM_ENC_EXT_CTRL_FRAME_SKIP_ENABLE_SHFT,
+ VIDC_SM_ENC_EXT_CTRL_FRAME_SKIP_ENABLE_BMSK) |
+ VIDC_SETFIELD((seq_hdr_in_band) ? 1 : 0 ,
+ VIDC_SM_ENC_EXT_CTRL_SEQ_HDR_CTRL_SHFT ,
+ VIDC_SM_ENC_EXT_CTRL_SEQ_HDR_CTRL_BMSK) |
+ VIDC_SETFIELD(vbv_buffer_size,
+ VIDC_SM_ENC_EXT_CTRL_VBV_BUFFER_SIZE_SHFT,
+ VIDC_SM_ENC_EXT_CTRL_VBV_BUFFER_SIZE_BMSK);
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_ENC_EXT_CTRL_ADDR, enc_ctrl);
+}
+
+void vidc_sm_set_encoder_param_change(struct ddl_buf_addr *shared_mem,
+ u32 bit_rate_chg, u32 frame_rate_chg, u32 i_period_chg)
+{
+ u32 enc_param_chg;
+
+ enc_param_chg = VIDC_SETFIELD((bit_rate_chg) ? 1 : 0,
+ VIDC_SM_ENC_PARAM_CHANGE_RC_BIT_RATE_SHFT,
+ VIDC_SM_ENC_PARAM_CHANGE_RC_BIT_RATE_BMSK) |
+ VIDC_SETFIELD((frame_rate_chg) ? 1 : 0,
+ VIDC_SM_ENC_PARAM_CHANGE_RC_FRAME_RATE_SHFT,
+ VIDC_SM_ENC_PARAM_CHANGE_RC_FRAME_RATE_BMSK) |
+ VIDC_SETFIELD((i_period_chg) ? 1 : 0,
+ VIDC_SM_ENC_PARAM_CHANGE_I_PERIOD_SHFT,
+ VIDC_SM_ENC_PARAM_CHANGE_I_PERIOD_BMSK);
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_ENC_PARAM_CHANGE_ADDR,
+ enc_param_chg);
+}
+
+void vidc_sm_set_encoder_vop_time(struct ddl_buf_addr *shared_mem,
+ u32 vop_time_enable, u32 time_resolution, u32 frame_delta)
+{
+ u32 vop_time;
+
+ vop_time = VIDC_SETFIELD((vop_time_enable) ? 1 : 0,
+ VIDC_SM_ENC_VOP_TIMING_ENABLE_SHFT ,
+ VIDC_SM_ENC_VOP_TIMING_ENABLE_BMSK) |
+ VIDC_SETFIELD(time_resolution ,
+ VIDC_SM_ENC_VOP_TIMING_TIME_RESOLUTION_SHFT,
+ VIDC_SM_ENC_VOP_TIMING_TIME_RESOLUTION_BMSK) |
+ VIDC_SETFIELD(frame_delta,
+ VIDC_SM_ENC_VOP_TIMING_FRAME_DELTA_SHFT,
+ VIDC_SM_ENC_VOP_TIMING_FRAME_DELTA_BMSK);
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_ENC_VOP_TIMING_ADDR, vop_time);
+}
+
+void vidc_sm_set_encoder_hec_period(struct ddl_buf_addr *shared_mem,
+ u32 hec_period)
+{
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_ENC_HEC_PERIOD_ADDR,
+ hec_period);
+}
+
+void vidc_sm_get_h264_encoder_reference_list0(struct ddl_buf_addr
+ *shared_mem, enum VIDC_SM_ref_picture *pe_luma_picture0,
+ u32 *pn_luma_picture_index0, enum VIDC_SM_ref_picture
+ *pe_luma_picture1, u32 *pn_luma_picture_index1,
+ enum VIDC_SM_ref_picture *pe_chroma_picture0,
+ u32 *pn_chroma_picture_index0,
+ enum VIDC_SM_ref_picture *pe_chroma_picture1,
+ u32 *pn_chroma_picture_index1)
+{
+ u32 ref_list;
+
+ ref_list = DDL_MEM_READ_32(shared_mem, VIDC_SM_H264_REF_L0_ADDR);
+
+ *pe_luma_picture0 = (enum VIDC_SM_ref_picture)
+ VIDC_GETFIELD(ref_list,
+ VIDC_SM_H264_REF_L0_LUMA_BTM_FLG_0_BMSK,
+ VIDC_SM_H264_REF_L0_LUMA_BTM_FLG_0_SHFT);
+ *pn_luma_picture_index0 =
+ VIDC_GETFIELD(ref_list,
+ VIDC_SM_H264_REF_L0_LUMA_REF_0_BMSK,
+ VIDC_SM_H264_REF_L0_LUMA_REF_0_SHFT);
+ *pe_luma_picture1 = (enum VIDC_SM_ref_picture)
+ VIDC_GETFIELD(ref_list,
+ VIDC_SM_H264_REF_L0_LUMA_BTM_FLG_1_BMSK,
+ VIDC_SM_H264_REF_L0_LUMA_BTM_FLG_1_SHFT);
+ *pn_luma_picture_index1 = VIDC_GETFIELD(ref_list,
+ VIDC_SM_H264_REF_L0_LUMA_REF_1_BMSK,
+ VIDC_SM_H264_REF_L0_LUMA_REF_1_SHFT);
+ *pe_chroma_picture0 = (enum VIDC_SM_ref_picture)
+ VIDC_GETFIELD(ref_list,
+ VIDC_SM_H264_REF_L0_CHRO_BTM_FLG_0_BMSK,
+ VIDC_SM_H264_REF_L0_CHRO_BTM_FLG_0_SHFT);
+ *pn_chroma_picture_index0 = VIDC_GETFIELD(ref_list,
+ VIDC_SM_H264_REF_L0_CHRO_REF_0_BMSK,
+ VIDC_SM_H264_REF_L0_CHRO_REF_0_SHFT);
+ *pe_chroma_picture1 = (enum VIDC_SM_ref_picture)
+ VIDC_GETFIELD(ref_list,
+ VIDC_SM_H264_REF_L0_CHRO_BTM_FLG_1_BMSK,
+ VIDC_SM_H264_REF_L0_CHRO_BTM_FLG_1_SHFT);
+ *pn_chroma_picture_index1 =
+ VIDC_GETFIELD(ref_list,
+ VIDC_SM_H264_REF_L0_CHRO_REF_1_BMSK,
+ VIDC_SM_H264_REF_L0_CHRO_REF_1_SHFT);
+}
+
+void vidc_sm_get_h264_encoder_reference_list1(struct ddl_buf_addr
+ *shared_mem, enum VIDC_SM_ref_picture *pe_luma_picture,
+ u32 *pn_luma_picture_index,
+ enum VIDC_SM_ref_picture *pe_chroma_picture,
+ u32 *pn_chroma_picture_index)
+{
+ u32 ref_list;
+
+ ref_list = DDL_MEM_READ_32(shared_mem, VIDC_SM_H264_REF_L1_ADDR);
+
+ *pe_luma_picture = (enum VIDC_SM_ref_picture)
+ VIDC_GETFIELD(ref_list,
+ VIDC_SM_H264_REF_L1_LUMA_BTM_FLG_0_BMSK,
+ VIDC_SM_H264_REF_L1_LUMA_BTM_FLG_0_SHFT);
+ *pn_luma_picture_index =
+ VIDC_GETFIELD(ref_list,
+ VIDC_SM_H264_REF_L1_LUMA_REF_0_BMSK,
+ VIDC_SM_H264_REF_L1_LUMA_REF_0_SHFT);
+ *pe_chroma_picture = (enum VIDC_SM_ref_picture)
+ VIDC_GETFIELD(ref_list,
+ VIDC_SM_H264_REF_L1_CHRO_BTM_FLG_0_BMSK,
+ VIDC_SM_H264_REF_L1_CHRO_BTM_FLG_0_SHFT);
+ *pn_chroma_picture_index = VIDC_GETFIELD(ref_list,
+ VIDC_SM_H264_REF_L1_CHRO_REF_0_BMSK,
+ VIDC_SM_H264_REF_L1_CHRO_REF_0_SHFT);
+}
+
+void vidc_sm_set_allocated_dpb_size(struct ddl_buf_addr *shared_mem,
+ u32 y_size, u32 c_size)
+{
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_ALLOCATED_LUMA_DPB_SIZE_ADDR,
+ y_size);
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_ALLOCATED_CHROMA_DPB_SIZE_ADDR,
+ c_size);
+}
+
+void vidc_sm_set_allocated_h264_mv_size(struct ddl_buf_addr *shared_mem,
+ u32 mv_size)
+{
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_ALLOCATED_MV_SIZE_ADDR,
+ mv_size);
+}
+
+void vidc_sm_get_min_yc_dpb_sizes(struct ddl_buf_addr *shared_mem,
+ u32 *pn_min_luma_dpb_size, u32 *pn_min_chroma_dpb_size)
+{
+ *pn_min_luma_dpb_size = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_MIN_LUMA_DPB_SIZE_ADDR);
+ *pn_min_chroma_dpb_size = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_MIN_CHROMA_DPB_SIZE_ADDR);
+}
+
+void vidc_sm_set_concealment_color(struct ddl_buf_addr *shared_mem,
+ u32 conceal_ycolor, u32 conceal_ccolor)
+{
+ u32 conceal_color;
+
+ conceal_color = (((conceal_ycolor << 8) & 0xff00) |
+ (conceal_ccolor & 0xff));
+ DDL_MEM_WRITE_32(shared_mem, 0x00f0, conceal_color);
+}
+
+void vidc_sm_set_metadata_enable(struct ddl_buf_addr *shared_mem,
+ u32 extradata_enable, u32 qp_enable, u32 concealed_mb_enable,
+ u32 vc1Param_enable, u32 sei_nal_enable, u32 vui_enable,
+ u32 enc_slice_size_enable)
+{
+ u32 metadata_enable;
+
+ metadata_enable = VIDC_SETFIELD((extradata_enable) ? 1 : 0,
+ VIDC_SM_METADATA_ENABLE_EXTRADATA_SHFT,
+ VIDC_SM_METADATA_ENABLE_EXTRADATA_BMSK) |
+ VIDC_SETFIELD((enc_slice_size_enable) ? 1 : 0,
+ VIDC_SM_METADATA_ENABLE_ENC_SLICE_SIZE_SHFT,
+ VIDC_SM_METADATA_ENABLE_ENC_SLICE_SIZE_BMSK) |
+ VIDC_SETFIELD((vui_enable) ? 1 : 0,
+ VIDC_SM_METADATA_ENABLE_VUI_SHFT,
+ VIDC_SM_METADATA_ENABLE_VUI_BMSK) |
+ VIDC_SETFIELD((sei_nal_enable) ? 1 : 0,
+ VIDC_SM_METADATA_ENABLE_SEI_VIDC_SHFT,
+ VIDC_SM_METADATA_ENABLE_SEI_VIDC_BMSK) |
+ VIDC_SETFIELD((vc1Param_enable) ? 1 : 0,
+ VIDC_SM_METADATA_ENABLE_VC1_PARAM_SHFT,
+ VIDC_SM_METADATA_ENABLE_VC1_PARAM_BMSK) |
+ VIDC_SETFIELD((concealed_mb_enable) ? 1 : 0,
+ VIDC_SM_METADATA_ENABLE_CONCEALED_MB_SHFT,
+ VIDC_SM_METADATA_ENABLE_CONCEALED_MB_BMSK) |
+ VIDC_SETFIELD((qp_enable) ? 1 : 0,
+ VIDC_SM_METADATA_ENABLE_QP_SHFT,
+ VIDC_SM_METADATA_ENABLE_QP_BMSK);
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_METADATA_ENABLE_ADDR,
+ metadata_enable);
+}
+
+void vidc_sm_get_metadata_status(struct ddl_buf_addr
+ *shared_mem, u32 *pb_metadata_present)
+{
+ u32 status;
+
+ status = DDL_MEM_READ_32(shared_mem, VIDC_SM_METADATA_STATUS_ADDR);
+ *pb_metadata_present = (u32) VIDC_GETFIELD(status,
+ VIDC_SM_METADATA_STATUS_STATUS_BMSK,
+ VIDC_SM_METADATA_STATUS_STATUS_SHFT);
+}
+
+void vidc_sm_get_metadata_display_index(struct ddl_buf_addr *shared_mem,
+ u32 *pn_dixplay_index)
+{
+ *pn_dixplay_index = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_METADATA_DISPLAY_INDEX_ADDR);
+}
+
+void vidc_sm_set_metadata_start_address(struct ddl_buf_addr *shared_mem,
+ u32 address)
+{
+ u32 address_shift = address;
+
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_EXT_METADATA_START_ADDR_ADDR,
+ address_shift);
+}
+
+void vidc_sm_set_extradata_presence(struct ddl_buf_addr *shared_mem,
+ u32 extradata_present)
+{
+ u32 put_extradata;
+
+ put_extradata = VIDC_SETFIELD((extradata_present) ? 1 : 0,
+ VIDC_SM_PUT_EXTRADATA_PUT_SHFT,
+ VIDC_SM_PUT_EXTRADATA_PUT_BMSK);
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_PUT_EXTRADATA_ADDR,
+ put_extradata);
+}
+
+void vidc_sm_set_extradata_addr(struct ddl_buf_addr *shared_mem,
+ u32 extradata_addr)
+{
+ u32 address_shift = extradata_addr;
+
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_EXTRADATA_ADDR_ADDR,
+ address_shift);
+}
+
+void vidc_sm_set_pand_b_frame_qp(struct ddl_buf_addr *shared_mem,
+ u32 b_frame_qp, u32 p_frame_qp)
+{
+ u32 nP_B_frame_qp;
+
+ nP_B_frame_qp = VIDC_SETFIELD(b_frame_qp,
+ VIDC_SM_P_B_FRAME_QP_B_FRAME_QP_SHFT,
+ VIDC_SM_P_B_FRAME_QP_B_FRAME_QP_BMASK);
+ nP_B_frame_qp |= VIDC_SETFIELD(p_frame_qp,
+ VIDC_SM_P_B_FRAME_QP_P_FRAME_QP_SHFT,
+ VIDC_SM_P_B_FRAME_QP_P_FRAME_QP_BMASK);
+ DDL_MEM_WRITE_32(shared_mem , VIDC_SM_P_B_FRAME_QP_ADDR,
+ nP_B_frame_qp);
+}
+
+
+void vidc_sm_get_profile_info(struct ddl_buf_addr *shared_mem,
+ struct ddl_profile_info_type *ddl_profile_info)
+{
+ u32 disp_pic_profile;
+
+ disp_pic_profile = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_DISP_PIC_PROFILE_ADDR);
+ ddl_profile_info->bit_depth_chroma_minus8 =
+ (disp_pic_profile & 0x00380000) >> 19;
+ ddl_profile_info->bit_depth_luma_minus8 =
+ (disp_pic_profile & 0x00070000) >> 16;
+ ddl_profile_info->pic_profile = VIDC_GETFIELD(
+ disp_pic_profile,
+ VIDC_SM_DISP_PIC_PROFILE_DISP_PIC_PROFILE_BMASK,
+ VIDC_SM_DISP_PIC_PROFILE_DISP_PIC_PROFILE_SHFT);
+ ddl_profile_info->pic_level = VIDC_GETFIELD(
+ disp_pic_profile,
+ VIDC_SM_DISP_PIC_PROFILE_DISP_PIC_LEVEL_BMASK,
+ VIDC_SM_DISP_PIC_PROFILE_DISP_PIC_LEVEL_SHFT);
+ ddl_profile_info->chroma_format_idc =
+ (disp_pic_profile & 0x60) >> 5;
+}
+
+void vidc_sm_set_encoder_new_bit_rate(struct ddl_buf_addr *shared_mem,
+ u32 new_bit_rate)
+{
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_NEW_RC_BIT_RATE_ADDR,
+ new_bit_rate);
+}
+
+void vidc_sm_set_encoder_new_frame_rate(struct ddl_buf_addr *shared_mem,
+ u32 new_frame_rate)
+{
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_NEW_RC_FRAME_RATE_ADDR,
+ new_frame_rate);
+}
+
+void vidc_sm_set_encoder_new_i_period(struct ddl_buf_addr *shared_mem,
+ u32 new_i_period)
+{
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_NEW_I_PERIOD_ADDR,
+ new_i_period);
+}
+void vidc_sm_set_encoder_init_rc_value(struct ddl_buf_addr *shared_mem,
+ u32 new_rc_value)
+{
+ DDL_MEM_WRITE_32(shared_mem, 0x011C, new_rc_value);
+
+}
+void vidc_sm_set_idr_decode_only(struct ddl_buf_addr *shared_mem,
+ u32 enable)
+{
+ u32 idr_decode_only = VIDC_SETFIELD((enable) ? 1 : 0,
+ VIDC_SM_IDR_DECODING_ONLY_SHIFT,
+ VIDC_SM_IDR_DECODING_ONLY_BMSK
+ );
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_IDR_DECODING_ONLY_ADDR,
+ idr_decode_only);
+}
+
+void vidc_sm_set_chroma_addr_change(struct ddl_buf_addr *shared_mem,
+ u32 addr_change)
+{
+ u32 chroma_addr_change = VIDC_SETFIELD((addr_change) ? 1 : 0,
+ VIDC_SM_CHROMA_ADDR_CHANGE_SHFT,
+ VIDC_SM_CHROMA_ADDR_CHANGE_BMASK);
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_CHROMA_ADDR_CHANGE_ADDR,
+ chroma_addr_change);
+
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
new file mode 100644
index 0000000..99d9651
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
@@ -0,0 +1,157 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _VCD_DDL_SHARED_MEM_H_
+#define _VCD_DDL_SHARED_MEM_H_
+
+#include "vcd_ddl.h"
+
+#define VIDC_SM_PROFILE_MPEG4_SIMPLE (0)
+#define VIDC_SM_PROFILE_MPEG4_ADV_SIMPLE (1)
+
+#define VIDC_SM_PROFILE_H264_BASELINE (0)
+#define VIDC_SM_PROFILE_H264_MAIN (1)
+#define VIDC_SM_PROFILE_H264_HIGH (2)
+
+#define VIDC_SM_PROFILE_H263_BASELINE (0)
+
+#define VIDC_SM_PROFILE_VC1_SIMPLE (0)
+#define VIDC_SM_PROFILE_VC1_MAIN (1)
+#define VIDC_SM_PROFILE_VC1_ADVANCED (2)
+
+#define VIDC_SM_PROFILE_MPEG2_MAIN (4)
+#define VIDC_SM_PROFILE_MPEG2_SIMPLE (5)
+
+#define VIDC_SM_LEVEL_MPEG2_LOW (10)
+#define VIDC_SM_LEVEL_MPEG2_MAIN (8)
+#define VIDC_SM_LEVEL_MPEG2_HIGH_1440 (6)
+#define VIDC_SM_LEVEL_MPEG2_HIGH (4)
+
+#define VIDC_SM_LEVEL_VC1_LOW (0)
+#define VIDC_SM_LEVEL_VC1_MEDIUM (2)
+#define VIDC_SM_LEVEL_VC1_HIGH (4)
+
+#define VIDC_SM_LEVEL_VC1_ADV_0 (0)
+#define VIDC_SM_LEVEL_VC1_ADV_1 (1)
+#define VIDC_SM_LEVEL_VC1_ADV_2 (2)
+#define VIDC_SM_LEVEL_VC1_ADV_3 (3)
+#define VIDC_SM_LEVEL_VC1_ADV_4 (4)
+
+enum VIDC_SM_frame_skip {
+ VIDC_SM_FRAME_SKIP_DISABLE = 0,
+ VIDC_SM_FRAME_SKIP_ENABLE_LEVEL = 1,
+ VIDC_SM_FRAME_SKIP_ENABLE_VBV = 2
+};
+enum VIDC_SM_ref_picture {
+ VIDC_SM_REF_PICT_FRAME_OR_TOP_FIELD = 0,
+ VIDC_SM_REF_PICT_BOTTOM_FIELD = 1
+};
+
+struct ddl_profile_info_type {
+ u32 bit_depth_chroma_minus8;
+ u32 bit_depth_luma_minus8;
+ u32 pic_level;
+ u32 chroma_format_idc;
+ u32 pic_profile;
+};
+
+void vidc_sm_get_extended_decode_status(struct ddl_buf_addr *shared_mem,
+ u32 *more_field_needed,
+ u32 *resl_change);
+void vidc_sm_set_frame_tag(struct ddl_buf_addr *shared_mem,
+ u32 frame_tag);
+void vidc_sm_get_frame_tags(struct ddl_buf_addr *shared_mem,
+ u32 *pn_frame_tag_top, u32 *pn_frame_tag_bottom);
+void vidc_sm_get_picture_times(struct ddl_buf_addr *shared_mem,
+ u32 *pn_time_top, u32 *pn_time_bottom);
+void vidc_sm_set_start_byte_number(struct ddl_buf_addr *shared_mem,
+ u32 byte_num);
+void vidc_sm_get_crop_info(struct ddl_buf_addr *shared_mem, u32 *pn_left,
+ u32 *pn_right, u32 *pn_top, u32 *pn_bottom);
+void vidc_sm_get_displayed_picture_frame(struct ddl_buf_addr
+ *shared_mem, u32 *n_disp_picture_frame);
+void vidc_sm_get_available_luma_dpb_address(
+ struct ddl_buf_addr *shared_mem, u32 *pn_free_luma_dpb_address);
+void vidc_sm_get_available_luma_dpb_dec_order_address(
+ struct ddl_buf_addr *shared_mem, u32 *pn_free_luma_dpb_address);
+void vidc_sm_get_dec_order_resl(
+ struct ddl_buf_addr *shared_mem, u32 *width, u32 *height);
+void vidc_sm_get_dec_order_crop_info(
+ struct ddl_buf_addr *shared_mem, u32 *left,
+ u32 *right, u32 *top, u32 *bottom);
+void vidc_sm_set_extended_encoder_control(
+ struct ddl_buf_addr *shared_mem, u32 hec_enable,
+ enum VIDC_SM_frame_skip frame_skip_mode, u32 seq_hdr_in_band,
+ u32 vbv_buffer_size);
+void vidc_sm_set_encoder_param_change(struct ddl_buf_addr *shared_mem,
+ u32 bit_rate_chg, u32 frame_rate_chg, u32 i_period_chg);
+void vidc_sm_set_encoder_vop_time(struct ddl_buf_addr *shared_mem,
+ u32 vop_time_enable, u32 time_resolution, u32 frame_delta);
+void vidc_sm_set_encoder_hec_period(struct ddl_buf_addr *shared_mem,
+ u32 hec_period);
+void vidc_sm_get_h264_encoder_reference_list0(
+ struct ddl_buf_addr *shared_mem,
+ enum VIDC_SM_ref_picture *pe_luma_picture0,
+ u32 *pn_luma_picture_index0,
+ enum VIDC_SM_ref_picture *pe_luma_picture1,
+ u32 *pn_luma_picture_index1,
+ enum VIDC_SM_ref_picture *pe_chroma_picture0,
+ u32 *pn_chroma_picture_index0,
+ enum VIDC_SM_ref_picture *pe_chroma_picture1,
+ u32 *pn_chroma_picture_index1);
+
+void vidc_sm_get_h264_encoder_reference_list1(
+ struct ddl_buf_addr *shared_mem,
+ enum VIDC_SM_ref_picture *pe_luma_picture,
+ u32 *pn_luma_picture_index,
+ enum VIDC_SM_ref_picture *pe_chroma_picture,
+ u32 *pn_chroma_picture_index);
+void vidc_sm_set_allocated_dpb_size(struct ddl_buf_addr *shared_mem,
+ u32 y_size, u32 c_size);
+void vidc_sm_set_allocated_h264_mv_size(struct ddl_buf_addr *shared_mem,
+ u32 mv_size);
+void vidc_sm_get_min_yc_dpb_sizes(struct ddl_buf_addr *shared_mem,
+ u32 *pn_min_luma_dpb_size, u32 *pn_min_chroma_dpb_size);
+void vidc_sm_set_metadata_enable(struct ddl_buf_addr *shared_mem,
+ u32 extradata_enable, u32 qp_enable, u32 concealed_mb_enable,
+ u32 vc1Param_enable, u32 sei_nal_enable, u32 vui_enable,
+ u32 enc_slice_size_enable);
+void vidc_sm_get_metadata_status(struct ddl_buf_addr *shared_mem,
+ u32 *pb_metadata_present);
+void vidc_sm_get_metadata_display_index(struct ddl_buf_addr *shared_mem,
+ u32 *pn_dixplay_index);
+void vidc_sm_set_metadata_start_address(struct ddl_buf_addr *shared_mem,
+ u32 address);
+void vidc_sm_set_extradata_presence(struct ddl_buf_addr *shared_mem,
+ u32 extradata_present);
+void vidc_sm_set_extradata_addr(struct ddl_buf_addr *shared_mem,
+ u32 extradata_addr);
+void vidc_sm_set_pand_b_frame_qp(struct ddl_buf_addr *shared_mem,
+ u32 b_frame_qp, u32 p_frame_qp);
+void vidc_sm_get_profile_info(struct ddl_buf_addr *shared_mem,
+ struct ddl_profile_info_type *ddl_profile_info);
+void vidc_sm_set_encoder_new_bit_rate(struct ddl_buf_addr *shared_mem,
+ u32 new_bit_rate);
+void vidc_sm_set_encoder_new_frame_rate(struct ddl_buf_addr *shared_mem,
+ u32 new_frame_rate);
+void vidc_sm_set_encoder_new_i_period(struct ddl_buf_addr *shared_mem,
+ u32 new_i_period);
+void vidc_sm_set_encoder_init_rc_value(struct ddl_buf_addr *shared_mem,
+ u32 new_rc_value);
+void vidc_sm_set_idr_decode_only(struct ddl_buf_addr *shared_mem,
+ u32 enable);
+void vidc_sm_set_concealment_color(struct ddl_buf_addr *shared_mem,
+ u32 conceal_ycolor, u32 conceal_ccolor);
+void vidc_sm_set_chroma_addr_change(struct ddl_buf_addr *shared_mem,
+ u32 addr_change);
+#endif
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
new file mode 100644
index 0000000..46337af
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
@@ -0,0 +1,310 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/memory_alloc.h>
+#include "vcd_ddl_utils.h"
+#include "vcd_ddl.h"
+
+struct time_data {
+ unsigned int ddl_t1;
+ unsigned int ddl_ttotal;
+ unsigned int ddl_count;
+};
+static struct time_data proc_time[MAX_TIME_DATA];
+#define DDL_MSG_TIME(x...) printk(KERN_DEBUG x)
+
+#define DDL_FW_CHANGE_ENDIAN
+
+#ifdef DDL_BUF_LOG
+static void ddl_print_buffer(struct ddl_context *ddl_context,
+ struct ddl_buf_addr *buf, u32 idx, u8 *str);
+static void ddl_print_port(struct ddl_context *ddl_context,
+ struct ddl_buf_addr *buf);
+static void ddl_print_buffer_port(struct ddl_context *ddl_context,
+ struct ddl_buf_addr *buf, u32 idx, u8 *str);
+#endif
+
+void *ddl_pmem_alloc(struct ddl_buf_addr *addr, size_t sz, u32 alignment)
+{
+ u32 alloc_size, offset = 0;
+ struct ddl_context *ddl_context;
+ DBG_PMEM("\n%s() IN: Requested alloc size(%u)", __func__, (u32)sz);
+ if (!addr) {
+ DDL_MSG_ERROR("\n%s() Invalid Parameters", __func__);
+ return NULL;
+ }
+ ddl_context = ddl_get_context();
+ alloc_size = (sz + alignment);
+ addr->physical_base_addr = (u8 *) allocate_contiguous_memory_nomap(
+ alloc_size, ddl_context->memtype, SZ_4K);
+ if (!addr->physical_base_addr) {
+ DDL_MSG_ERROR("%s() : pmem alloc failed (%d)\n", __func__,
+ alloc_size);
+ return NULL;
+ }
+ DDL_MSG_LOW("%s() : pmem alloc physical base addr/sz 0x%x / %d\n",\
+ __func__, (u32)addr->physical_base_addr, alloc_size);
+ addr->virtual_base_addr = (u8 *)ioremap((unsigned long)
+ addr->physical_base_addr, alloc_size);
+ if (!addr->virtual_base_addr) {
+ DDL_MSG_ERROR("%s() : ioremap failed, virtual(%x)\n", __func__,
+ (u32)addr->virtual_base_addr);
+ free_contiguous_memory_by_paddr(
+ (unsigned long) addr->physical_base_addr);
+ addr->physical_base_addr = NULL;
+ return NULL;
+ }
+ DDL_MSG_LOW("%s() : pmem alloc virtual base addr/sz 0x%x / %d\n",\
+ __func__, (u32)addr->virtual_base_addr, alloc_size);
+ addr->align_physical_addr = (u8 *) DDL_ALIGN((u32)
+ addr->physical_base_addr, alignment);
+ offset = (u32)(addr->align_physical_addr -
+ addr->physical_base_addr);
+ addr->align_virtual_addr = addr->virtual_base_addr + offset;
+ addr->buffer_size = sz;
+ DDL_MSG_LOW("\n%s() : alig_phy_addr(%p) alig_vir_addr(%p)",
+ __func__, addr->align_physical_addr, addr->align_virtual_addr);
+ DBG_PMEM("\n%s() OUT: phy_addr(%p) vir_addr(%p) size(%u)",
+ __func__, addr->physical_base_addr, addr->virtual_base_addr,
+ addr->buffer_size);
+ return addr->virtual_base_addr;
+}
+
+void ddl_pmem_free(struct ddl_buf_addr *addr)
+{
+ DBG_PMEM("\n%s() IN: phy_addr(%p) vir_addr(%p) size(%u)",
+ __func__, addr->physical_base_addr, addr->virtual_base_addr,
+ addr->buffer_size);
+ if (addr->virtual_base_addr)
+ iounmap((void *)addr->virtual_base_addr);
+ if (addr->physical_base_addr)
+ free_contiguous_memory_by_paddr(
+ (unsigned long) addr->physical_base_addr);
+ DBG_PMEM("\n%s() OUT: phy_addr(%p) vir_addr(%p) size(%u)",
+ __func__, addr->physical_base_addr, addr->virtual_base_addr,
+ addr->buffer_size);
+ addr->physical_base_addr = NULL;
+ addr->virtual_base_addr = NULL;
+ addr->align_virtual_addr = NULL;
+ addr->align_physical_addr = NULL;
+ addr->buffer_size = 0;
+}
+
+#ifdef DDL_BUF_LOG
+
+static void ddl_print_buffer(struct ddl_context *ddl_context,
+ struct ddl_buf_addr *buf, u32 idx, u8 *str)
+{
+ struct ddl_buf_addr *base_ram;
+ s32 offset;
+ size_t sz, KB = 0;
+
+ base_ram = &ddl_context->dram_base_a;
+ offset = (s32) DDL_ADDR_OFFSET(*base_ram, *buf);
+ sz = buf->buffer_size;
+ if (sz > 0) {
+ if (!(sz % 1024)) {
+ sz /= 1024;
+ KB++;
+ if (!(sz % 1024)) {
+ sz /= 1024;
+ KB++;
+ }
+ }
+ }
+ DDL_MSG_LOW("\n%12s [%2d]: 0x%08x [0x%04x], 0x%08x(%d%s), %s",
+ str, idx, (u32) buf->align_physical_addr,
+ (offset > 0) ? offset : 0, buf->buffer_size, sz,
+ ((2 == KB) ? "MB" : (1 == KB) ? "KB" : ""),
+ (((u32) buf->virtual_base_addr) ? "Alloc" : ""));
+}
+
+static void ddl_print_port(struct ddl_context *ddl_context,
+ struct ddl_buf_addr *buf)
+{
+ struct ddl_buf_addr *a = &ddl_context->dram_base_a;
+ struct ddl_buf_addr *b = &ddl_context->dram_base_b;
+
+ if (!buf->align_physical_addr || !buf->buffer_size)
+ return;
+ if (buf->align_physical_addr >= a->align_physical_addr &&
+ buf->align_physical_addr + buf->buffer_size <=
+ a->align_physical_addr + a->buffer_size)
+ DDL_MSG_LOW(" -A [0x%x]-", DDL_ADDR_OFFSET(*a, *buf));
+ else if (buf->align_physical_addr >= b->align_physical_addr &&
+ buf->align_physical_addr + buf->buffer_size <=
+ b->align_physical_addr + b->buffer_size)
+ DDL_MSG_LOW(" -B [0x%x]-", DDL_ADDR_OFFSET(*b, *buf));
+ else
+ DDL_MSG_LOW(" -?-");
+}
+
+static void ddl_print_buffer_port(struct ddl_context *ddl_context,
+ struct ddl_buf_addr *buf, u32 idx, u8 *str)
+{
+ DDL_MSG_LOW("\n");
+ ddl_print_buffer(ddl_context, buf, idx, str);
+ ddl_print_port(ddl_context, buf);
+}
+
+void ddl_list_buffers(struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context;
+ u32 i;
+
+ ddl_context = ddl->ddl_context;
+ DDL_MSG_LOW("\n\n");
+ DDL_MSG_LOW("\n Buffer : Start [offs], Size \
+ (Size), Alloc/Port");
+ DDL_MSG_LOW("\n-------------------------------------------------------\
+ -------------------------");
+ ddl_print_buffer(ddl_context, &ddl_context->dram_base_a, 0,
+ "dram_base_a");
+ ddl_print_buffer(ddl_context, &ddl_context->dram_base_b, 0,
+ "dram_base_b");
+ if (ddl->codec_data.hdr.decoding) {
+ struct ddl_dec_buffers *dec_bufs =
+ &ddl->codec_data.decoder.hw_bufs;
+ for (i = 0; i < 32; i++)
+ ddl_print_buffer_port(ddl_context,
+ &dec_bufs->h264Mv[i], i, "h264Mv");
+ ddl_print_buffer_port(ddl_context,
+ &dec_bufs->h264Vert_nb_mv, 0, "h264Vert_nb_mv");
+ ddl_print_buffer_port(ddl_context,
+ &dec_bufs->h264Nb_ip, 0, "h264Nb_ip");
+ ddl_print_buffer_port(ddl_context,
+ &dec_bufs->nb_dcac, 0, "nb_dcac");
+ ddl_print_buffer_port(ddl_context,
+ &dec_bufs->upnb_mv, 0, "upnb_mv");
+ ddl_print_buffer_port(ddl_context,
+ &dec_bufs->sub_anchor_mv, 0, "sub_anchor_mv");
+ ddl_print_buffer_port(ddl_context,
+ &dec_bufs->overlay_xform, 0, "overlay_xform");
+ ddl_print_buffer_port(ddl_context,
+ &dec_bufs->bit_plane3, 0, "bit_plane3");
+ ddl_print_buffer_port(ddl_context,
+ &dec_bufs->bit_plane2, 0, "bit_plane2");
+ ddl_print_buffer_port(ddl_context,
+ &dec_bufs->bit_plane1, 0, "bit_plane1");
+ ddl_print_buffer_port(ddl_context,
+ dec_bufs->stx_parser, 0, "stx_parser");
+ ddl_print_buffer_port(ddl_context,
+ &dec_bufs->desc, 0, "desc");
+ ddl_print_buffer_port(ddl_context,
+ &dec_bufs->context, 0, "context");
+ } else {
+ struct ddl_enc_buffers *enc_bufs =
+ &ddl->codec_data.encoder.hw_bufs;
+
+ for (i = 0; i < 4; i++)
+ ddl_print_buffer_port(ddl_context,
+ &enc_bufs->dpb_y[i], i, "dpb_y");
+ for (i = 0; i < 4; i++)
+ ddl_print_buffer_port(ddl_context,
+ &enc_bufs->dpb_c[i], i, "dpb_c");
+ ddl_print_buffer_port(ddl_context, &enc_bufs->mv, 0, "mv");
+ ddl_print_buffer_port(ddl_context,
+ &enc_bufs->col_zero, 0, "col_zero");
+ ddl_print_buffer_port(ddl_context, &enc_bufs->md, 0, "md");
+ ddl_print_buffer_port(ddl_context,
+ &enc_bufs->pred, 0, "pred");
+ ddl_print_buffer_port(ddl_context,
+ &enc_bufs->nbor_info, 0, "nbor_info");
+ ddl_print_buffer_port(ddl_context,
+ &enc_bufs->acdc_coef, 0, "acdc_coef");
+ ddl_print_buffer_port(ddl_context,
+ &enc_bufs->context, 0, "context");
+ }
+}
+#endif
+
+#ifdef DDL_FW_CHANGE_ENDIAN
+static void ddl_fw_change_endian(u8 *fw, u32 fw_size)
+{
+ u32 i = 0;
+ u8 temp;
+ for (i = 0; i < fw_size; i = i + 4) {
+ temp = fw[i];
+ fw[i] = fw[i+3];
+ fw[i+3] = temp;
+ temp = fw[i+1];
+ fw[i+1] = fw[i+2];
+ fw[i+2] = temp;
+ }
+ return;
+}
+#endif
+
+u32 ddl_fw_init(struct ddl_buf_addr *dram_base)
+{
+
+ u8 *dest_addr;
+
+ dest_addr = DDL_GET_ALIGNED_VITUAL(*dram_base);
+ if (vidc_video_codec_fw_size > dram_base->buffer_size ||
+ !vidc_video_codec_fw)
+ return false;
+ DDL_MSG_LOW("FW Addr / FW Size : %x/%d", (u32)vidc_video_codec_fw,
+ vidc_video_codec_fw_size);
+ memcpy(dest_addr, vidc_video_codec_fw,
+ vidc_video_codec_fw_size);
+#ifdef DDL_FW_CHANGE_ENDIAN
+ ddl_fw_change_endian(dest_addr, vidc_video_codec_fw_size);
+#endif
+ return true;
+}
+
+void ddl_fw_release(void)
+{
+
+}
+
+void ddl_set_core_start_time(const char *func_name, u32 index)
+{
+ u32 act_time;
+ struct timeval ddl_tv;
+ struct time_data *time_data = &proc_time[index];
+ do_gettimeofday(&ddl_tv);
+ act_time = (ddl_tv.tv_sec * 1000) + (ddl_tv.tv_usec / 1000);
+ if (!time_data->ddl_t1) {
+ time_data->ddl_t1 = act_time;
+ DDL_MSG_LOW("\n%s(): Start Time (%u)", func_name, act_time);
+ } else {
+ DDL_MSG_TIME("\n%s(): Timer already started! St(%u) Act(%u)",
+ func_name, time_data->ddl_t1, act_time);
+ }
+}
+
+void ddl_calc_core_proc_time(const char *func_name, u32 index)
+{
+ struct time_data *time_data = &proc_time[index];
+ if (time_data->ddl_t1) {
+ int ddl_t2;
+ struct timeval ddl_tv;
+ do_gettimeofday(&ddl_tv);
+ ddl_t2 = (ddl_tv.tv_sec * 1000) + (ddl_tv.tv_usec / 1000);
+ time_data->ddl_ttotal += (ddl_t2 - time_data->ddl_t1);
+ time_data->ddl_count++;
+ DDL_MSG_TIME("\n%s(): cnt(%u) End Time (%u) Diff(%u) Avg(%u)",
+ func_name, time_data->ddl_count, ddl_t2,
+ ddl_t2 - time_data->ddl_t1,
+ time_data->ddl_ttotal/time_data->ddl_count);
+ time_data->ddl_t1 = 0;
+ }
+}
+
+void ddl_reset_core_time_variables(u32 index)
+{
+ proc_time[index].ddl_t1 = 0;
+ proc_time[index].ddl_ttotal = 0;
+ proc_time[index].ddl_count = 0;
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
new file mode 100644
index 0000000..42a991c
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
@@ -0,0 +1,73 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _VCD_DDL_UTILS_H_
+#define _VCD_DDL_UTILS_H_
+
+#include <linux/delay.h>
+#include "vidc_type.h"
+
+extern u32 vidc_msg_pmem;
+extern u32 vidc_msg_timing;
+
+enum timing_data {
+ DEC_OP_TIME,
+ DEC_IP_TIME,
+ ENC_OP_TIME,
+ MAX_TIME_DATA
+};
+
+#define DBG_PMEM(x...) \
+do { \
+ if (vidc_msg_pmem) \
+ printk(KERN_DEBUG x); \
+} while (0)
+
+#ifdef DDL_MSG_LOG
+#define DDL_MSG_LOW(x...) printk(KERN_INFO x)
+#define DDL_MSG_MED(x...) printk(KERN_INFO x)
+#define DDL_MSG_HIGH(x...) printk(KERN_INFO x)
+#else
+#define DDL_MSG_LOW(x...)
+#define DDL_MSG_MED(x...)
+#define DDL_MSG_HIGH(x...)
+#endif
+
+#define DDL_MSG_ERROR(x...) printk(KERN_INFO x)
+#define DDL_MSG_FATAL(x...) printk(KERN_INFO x)
+
+#define DDL_ALIGN_SIZE(sz, guard_bytes, align_mask) \
+ (((u32)(sz) + guard_bytes) & align_mask)
+#define DDL_ADDR_IS_ALIGNED(addr, align_bytes) \
+ (!((u32)(addr) & ((align_bytes) - 1)))
+#define DDL_ALIGN(val, grid) ((!(grid)) ? (val) : \
+ ((((val) + (grid) - 1) / (grid)) * (grid)))
+#define DDL_ALIGN_FLOOR(val, grid) ((!(grid)) ? (val) : \
+ (((val) / (grid)) * (grid)))
+#define DDL_OFFSET(base, addr) ((!(addr)) ? 0 : (u32)((u8 *) \
+ (addr) - (u8 *) (base)))
+#define DDL_ADDR_OFFSET(base, addr) DDL_OFFSET((base).align_physical_addr, \
+ (addr).align_physical_addr)
+#define DDL_GET_ALIGNED_VITUAL(x) ((x).align_virtual_addr)
+#define DDL_KILO_BYTE(x) ((x)*1024)
+#define DDL_MEGA_BYTE(x) ((x)*1024*1024)
+#define DDL_FRAMERATE_SCALE(x) ((x) * 1000)
+
+#define DDL_MIN(x, y) ((x < y) ? x : y)
+#define DDL_MAX(x, y) ((x > y) ? x : y)
+
+void ddl_set_core_start_time(const char *func_name, u32 index);
+void ddl_calc_core_proc_time(const char *func_name, u32 index);
+void ddl_reset_core_time_variables(u32 index);
+
+#endif
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
new file mode 100644
index 0000000..2efd211
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
@@ -0,0 +1,925 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "vcd_ddl.h"
+#include "vcd_ddl_metadata.h"
+#include "vcd_ddl_shared_mem.h"
+#include "vcd_core.h"
+
+#if defined(PIX_CACHE_DISABLE)
+#define DDL_PIX_CACHE_ENABLE false
+#else
+#define DDL_PIX_CACHE_ENABLE true
+#endif
+
+void ddl_vidc_core_init(struct ddl_context *ddl_context)
+{
+ struct vidc_1080P_pix_cache_config pixel_cache_config;
+
+ vidc_1080p_do_sw_reset(VIDC_1080P_RESET_IN_SEQ_FIRST_STAGE);
+ msleep(DDL_SW_RESET_SLEEP);
+ vidc_1080p_do_sw_reset(VIDC_1080P_RESET_IN_SEQ_SECOND_STAGE);
+ vidc_1080p_init_memory_controller(
+ (u32) ddl_context->dram_base_a.align_physical_addr,
+ (u32) ddl_context->dram_base_b.align_physical_addr);
+ vidc_1080p_clear_returned_channel_inst_id();
+ ddl_context->vidc_decode_seq_start[0] =
+ vidc_1080p_decode_seq_start_ch0;
+ ddl_context->vidc_decode_seq_start[1] =
+ vidc_1080p_decode_seq_start_ch1;
+ ddl_context->vidc_decode_init_buffers[0] =
+ vidc_1080p_decode_init_buffers_ch0;
+ ddl_context->vidc_decode_init_buffers[1] =
+ vidc_1080p_decode_init_buffers_ch1;
+ ddl_context->vidc_decode_frame_start[0] =
+ vidc_1080p_decode_frame_start_ch0;
+ ddl_context->vidc_decode_frame_start[1] =
+ vidc_1080p_decode_frame_start_ch1;
+ ddl_context->vidc_set_dec_resolution[0] =
+ vidc_1080p_set_dec_resolution_ch0;
+ ddl_context->vidc_set_dec_resolution[1] =
+ vidc_1080p_set_dec_resolution_ch1;
+ ddl_context->vidc_encode_seq_start[0] =
+ vidc_1080p_encode_seq_start_ch0;
+ ddl_context->vidc_encode_seq_start[1] =
+ vidc_1080p_encode_seq_start_ch1;
+ ddl_context->vidc_encode_frame_start[0] =
+ vidc_1080p_encode_frame_start_ch0;
+ ddl_context->vidc_encode_frame_start[1] =
+ vidc_1080p_encode_frame_start_ch1;
+ vidc_1080p_release_sw_reset();
+ ddl_context->pix_cache_enable = DDL_PIX_CACHE_ENABLE;
+ if (ddl_context->pix_cache_enable) {
+ vidc_pix_cache_sw_reset();
+ pixel_cache_config.cache_enable = true;
+ pixel_cache_config.prefetch_en = true;
+ pixel_cache_config.port_select = VIDC_1080P_PIX_CACHE_PORT_B;
+ pixel_cache_config.statistics_off = true;
+ pixel_cache_config.page_size =
+ VIDC_1080P_PIX_CACHE_PAGE_SIZE_1K;
+ vidc_pix_cache_init_config(&pixel_cache_config);
+ }
+}
+
+void ddl_vidc_core_term(struct ddl_context *ddl_context)
+{
+ if (ddl_context->pix_cache_enable) {
+ u32 pix_cache_idle = false;
+ u32 counter = 0;
+
+ vidc_pix_cache_set_halt(true);
+
+ do {
+ msleep(DDL_SW_RESET_SLEEP);
+ vidc_pix_cache_get_status_idle(&pix_cache_idle);
+ counter++;
+ } while (!pix_cache_idle &&
+ counter < DDL_PIXEL_CACHE_STATUS_READ_RETRY);
+
+ if (!pix_cache_idle) {
+ ddl_context->cmd_err_status =
+ DDL_PIXEL_CACHE_NOT_IDLE;
+ ddl_handle_core_errors(ddl_context);
+ }
+ }
+}
+
+void ddl_vidc_channel_set(struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ enum vcd_codec *vcd_codec;
+ enum vidc_1080p_codec codec = VIDC_1080P_H264_DECODE;
+ const enum vidc_1080p_decode_p_cache_enable
+ dec_pix_cache = VIDC_1080P_DECODE_PCACHE_DISABLE;
+ const enum vidc_1080p_encode_p_cache_enable
+ enc_pix_cache = VIDC_1080P_ENCODE_PCACHE_ENABLE;
+ u32 pix_cache_ctrl, ctxt_mem_offset, ctxt_mem_size;
+
+ if (ddl->decoding) {
+ if (vidc_msg_timing)
+ ddl_set_core_start_time(__func__, DEC_OP_TIME);
+ vcd_codec = &(ddl->codec_data.decoder.codec.codec);
+ pix_cache_ctrl = (u32)dec_pix_cache;
+ ctxt_mem_offset = DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ ddl->codec_data.decoder.hw_bufs.context) >> 11;
+ ctxt_mem_size =
+ ddl->codec_data.decoder.hw_bufs.context.buffer_size;
+ } else {
+ vcd_codec = &(ddl->codec_data.encoder.codec.codec);
+ pix_cache_ctrl = (u32)enc_pix_cache;
+ ctxt_mem_offset = DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ ddl->codec_data.encoder.hw_bufs.context) >> 11;
+ ctxt_mem_size =
+ ddl->codec_data.encoder.hw_bufs.context.buffer_size;
+ }
+ switch (*vcd_codec) {
+ default:
+ case VCD_CODEC_MPEG4:
+ if (ddl->decoding)
+ codec = VIDC_1080P_MPEG4_DECODE;
+ else
+ codec = VIDC_1080P_MPEG4_ENCODE;
+ break;
+ case VCD_CODEC_H264:
+ if (ddl->decoding)
+ codec = VIDC_1080P_H264_DECODE;
+ else
+ codec = VIDC_1080P_H264_ENCODE;
+ break;
+ case VCD_CODEC_DIVX_3:
+ if (ddl->decoding)
+ codec = VIDC_1080P_DIVX311_DECODE;
+ break;
+ case VCD_CODEC_DIVX_4:
+ if (ddl->decoding)
+ codec = VIDC_1080P_DIVX412_DECODE;
+ break;
+ case VCD_CODEC_DIVX_5:
+ if (ddl->decoding)
+ codec = VIDC_1080P_DIVX502_DECODE;
+ break;
+ case VCD_CODEC_DIVX_6:
+ if (ddl->decoding)
+ codec = VIDC_1080P_DIVX503_DECODE;
+ break;
+ case VCD_CODEC_XVID:
+ if (ddl->decoding)
+ codec = VIDC_1080P_MPEG4_DECODE;
+ break;
+ case VCD_CODEC_H263:
+ if (ddl->decoding)
+ codec = VIDC_1080P_H263_DECODE;
+ else
+ codec = VIDC_1080P_H263_ENCODE;
+ break;
+ case VCD_CODEC_MPEG1:
+ case VCD_CODEC_MPEG2:
+ if (ddl->decoding)
+ codec = VIDC_1080P_MPEG2_DECODE;
+ break;
+ case VCD_CODEC_VC1:
+ if (ddl->decoding)
+ codec = VIDC_1080P_VC1_DECODE;
+ break;
+ case VCD_CODEC_VC1_RCV:
+ if (ddl->decoding)
+ codec = VIDC_1080P_VC1_RCV_DECODE;
+ break;
+ }
+ ddl->cmd_state = DDL_CMD_CHANNEL_SET;
+ DDL_MSG_LOW("ddl_state_transition: %s ~~> DDL_CLIENT_WAIT_FOR_CHDONE",
+ ddl_get_state_string(ddl->client_state));
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_CHDONE;
+ vidc_1080p_set_host2risc_cmd(VIDC_1080P_HOST2RISC_CMD_OPEN_CH,
+ (u32)codec, pix_cache_ctrl, ctxt_mem_offset,
+ ctxt_mem_size);
+}
+
+void ddl_vidc_decode_init_codec(struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
+ struct vidc_1080p_dec_seq_start_param seq_start_param;
+ u32 seq_size;
+
+ if (vidc_msg_timing)
+ ddl_set_core_start_time(__func__, DEC_OP_TIME);
+ vidc_1080p_set_decode_mpeg4_pp_filter(decoder->post_filter.post_filter);
+ vidc_sm_set_concealment_color(&ddl->shared_mem[ddl->command_channel],
+ DDL_CONCEALMENT_Y_COLOR, DDL_CONCEALMENT_C_COLOR);
+ ddl_vidc_metadata_enable(ddl);
+ vidc_sm_set_metadata_start_address(&ddl->shared_mem
+ [ddl->command_channel],
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ ddl->codec_data.decoder.meta_data_input));
+
+ vidc_sm_set_idr_decode_only(&ddl->shared_mem[ddl->command_channel],
+ decoder->idr_only_decoding);
+
+ if ((decoder->codec.codec == VCD_CODEC_DIVX_3) ||
+ (decoder->codec.codec == VCD_CODEC_VC1_RCV ||
+ decoder->codec.codec == VCD_CODEC_VC1))
+ ddl_context->vidc_set_dec_resolution
+ [ddl->command_channel](decoder->client_frame_size.width,
+ decoder->client_frame_size.height);
+ else
+ ddl_context->vidc_set_dec_resolution
+ [ddl->command_channel](0x0, 0x0);
+ DDL_MSG_LOW("HEADER-PARSE-START");
+ DDL_MSG_LOW("ddl_state_transition: %s ~~>"
+ "DDL_CLIENT_WAIT_FOR_INITCODECDONE",
+ ddl_get_state_string(ddl->client_state));
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_INITCODECDONE;
+ ddl->cmd_state = DDL_CMD_HEADER_PARSE;
+ seq_start_param.cmd_seq_num = ++ddl_context->cmd_seq_num;
+ seq_start_param.inst_id = ddl->instance_id;
+ seq_start_param.shared_mem_addr_offset = DDL_ADDR_OFFSET(
+ ddl_context->dram_base_a, ddl->shared_mem
+ [ddl->command_channel]);
+ seq_start_param.stream_buffer_addr_offset =
+ DDL_OFFSET(ddl_context->dram_base_a.align_physical_addr,
+ decoder->decode_config.sequence_header);
+ seq_start_param.stream_buffersize =
+ decoder->client_input_buf_req.sz;
+ seq_size = decoder->decode_config.sequence_header_len +
+ DDL_LINEAR_BUFFER_ALIGN_BYTES + VCD_SEQ_HDR_PADDING_BYTES;
+ if (seq_start_param.stream_buffersize < seq_size)
+ seq_start_param.stream_buffersize = seq_size;
+ seq_start_param.stream_frame_size =
+ decoder->decode_config.sequence_header_len;
+ seq_start_param.descriptor_buffer_addr_offset =
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ decoder->hw_bufs.desc),
+ seq_start_param.descriptor_buffer_size =
+ decoder->hw_bufs.desc.buffer_size;
+ ddl_context->vidc_decode_seq_start[ddl->command_channel](
+ &seq_start_param);
+}
+
+void ddl_vidc_decode_dynamic_property(struct ddl_client_context *ddl,
+ u32 enable)
+{
+ struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
+ struct vcd_frame_data *bit_stream =
+ &(ddl->input_frame.vcd_frm);
+ struct ddl_context *ddl_context = ddl->ddl_context;
+
+ if (!enable) {
+ if (decoder->dynmic_prop_change_req)
+ decoder->dynmic_prop_change_req = false;
+ return;
+ }
+ if ((decoder->dynamic_prop_change & DDL_DEC_REQ_OUTPUT_FLUSH)) {
+ decoder->dynmic_prop_change_req = true;
+ decoder->dynamic_prop_change &= ~(DDL_DEC_REQ_OUTPUT_FLUSH);
+ decoder->dpb_mask.hw_mask = 0;
+ decoder->flush_pending = true;
+ }
+ if (((decoder->meta_data_enable_flag & VCD_METADATA_PASSTHROUGH)) &&
+ ((VCD_FRAME_FLAG_EXTRADATA & bit_stream->flags))) {
+ u32 extradata_presence = true;
+ u8* tmp = ((u8 *) bit_stream->physical +
+ bit_stream->offset +
+ bit_stream->data_len + 3);
+ u32 extra_data_start = (u32) ((u32)tmp & ~3);
+
+ extra_data_start = extra_data_start -
+ (u32)ddl_context->dram_base_a.align_physical_addr;
+ decoder->dynmic_prop_change_req = true;
+ vidc_sm_set_extradata_addr(&ddl->shared_mem
+ [ddl->command_channel], extra_data_start);
+ vidc_sm_set_extradata_presence(&ddl->shared_mem
+ [ddl->command_channel], extradata_presence);
+ }
+}
+
+void ddl_vidc_encode_dynamic_property(struct ddl_client_context *ddl,
+ u32 enable)
+{
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ u32 frame_rate_change = false, bit_rate_change = false;
+ u32 i_period_change = false, reset_req = false;
+
+ if (!enable) {
+ if (encoder->dynmic_prop_change_req) {
+ reset_req = true;
+ encoder->dynmic_prop_change_req = false;
+ }
+ } else {
+ if ((encoder->dynamic_prop_change & DDL_ENC_REQ_IFRAME)) {
+ encoder->intra_frame_insertion = true;
+ encoder->dynamic_prop_change &=
+ ~(DDL_ENC_REQ_IFRAME);
+ }
+ if ((encoder->dynamic_prop_change &
+ DDL_ENC_CHANGE_BITRATE)) {
+ bit_rate_change = true;
+ vidc_sm_set_encoder_new_bit_rate(
+ &ddl->shared_mem[ddl->command_channel],
+ encoder->target_bit_rate.target_bitrate);
+ encoder->dynamic_prop_change &=
+ ~(DDL_ENC_CHANGE_BITRATE);
+ }
+ if ((encoder->dynamic_prop_change
+ & DDL_ENC_CHANGE_IPERIOD)) {
+ i_period_change = true;
+ vidc_sm_set_encoder_new_i_period(
+ &ddl->shared_mem[ddl->command_channel],
+ encoder->i_period.p_frames);
+ encoder->dynamic_prop_change &=
+ ~(DDL_ENC_CHANGE_IPERIOD);
+ }
+ if ((encoder->dynamic_prop_change
+ & DDL_ENC_CHANGE_FRAMERATE)) {
+ frame_rate_change = true;
+ vidc_sm_set_encoder_new_frame_rate(
+ &ddl->shared_mem[ddl->command_channel],
+ (u32)(DDL_FRAMERATE_SCALE(encoder->\
+ frame_rate.fps_numerator) /
+ encoder->frame_rate.fps_denominator));
+ encoder->dynamic_prop_change &=
+ ~(DDL_ENC_CHANGE_FRAMERATE);
+ }
+ }
+ if ((enable) || (reset_req)) {
+ vidc_sm_set_encoder_param_change(
+ &ddl->shared_mem[ddl->command_channel],
+ bit_rate_change, frame_rate_change,
+ i_period_change);
+ }
+}
+
+static void ddl_vidc_encode_set_profile_level(
+ struct ddl_client_context *ddl)
+{
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ u32 encode_profile, level = 0;
+
+ switch (encoder->profile.profile) {
+ default:
+ case VCD_PROFILE_MPEG4_SP:
+ encode_profile = VIDC_1080P_PROFILE_MPEG4_SIMPLE;
+ break;
+ case VCD_PROFILE_MPEG4_ASP:
+ encode_profile = VIDC_1080P_PROFILE_MPEG4_ADV_SIMPLE;
+ break;
+ case VCD_PROFILE_H264_BASELINE:
+ encode_profile = VIDC_1080P_PROFILE_H264_BASELINE;
+ break;
+ case VCD_PROFILE_H264_MAIN:
+ encode_profile = VIDC_1080P_PROFILE_H264_MAIN;
+ break;
+ case VCD_PROFILE_H264_HIGH:
+ encode_profile = VIDC_1080P_PROFILE_H264_HIGH;
+ break;
+ }
+ switch (encoder->level.level) {
+ default:
+ case VCD_LEVEL_MPEG4_0:
+ level = VIDC_1080P_MPEG4_LEVEL0;
+ break;
+ case VCD_LEVEL_MPEG4_0b:
+ level = VIDC_1080P_MPEG4_LEVEL0b;
+ break;
+ case VCD_LEVEL_MPEG4_1:
+ level = VIDC_1080P_MPEG4_LEVEL1;
+ break;
+ case VCD_LEVEL_MPEG4_2:
+ level = VIDC_1080P_MPEG4_LEVEL2;
+ break;
+ case VCD_LEVEL_MPEG4_3:
+ level = VIDC_1080P_MPEG4_LEVEL3;
+ break;
+ case VCD_LEVEL_MPEG4_3b:
+ level = VIDC_1080P_MPEG4_LEVEL3b;
+ break;
+ case VCD_LEVEL_MPEG4_4:
+ level = VIDC_1080P_MPEG4_LEVEL4;
+ break;
+ case VCD_LEVEL_MPEG4_4a:
+ level = VIDC_1080P_MPEG4_LEVEL4a;
+ break;
+ case VCD_LEVEL_MPEG4_5:
+ level = VIDC_1080P_MPEG4_LEVEL5;
+ break;
+ case VCD_LEVEL_MPEG4_6:
+ level = VIDC_1080P_MPEG4_LEVEL6;
+ break;
+ case VCD_LEVEL_MPEG4_7:
+ level = VIDC_1080P_MPEG4_LEVEL7;
+ break;
+ case VCD_LEVEL_H264_1:
+ level = VIDC_1080P_H264_LEVEL1;
+ break;
+ case VCD_LEVEL_H264_1b:
+ level = VIDC_1080P_H264_LEVEL1b;
+ break;
+ case VCD_LEVEL_H264_1p1:
+ level = VIDC_1080P_H264_LEVEL1p1;
+ break;
+ case VCD_LEVEL_H264_1p2:
+ level = VIDC_1080P_H264_LEVEL1p2;
+ break;
+ case VCD_LEVEL_H264_1p3:
+ level = VIDC_1080P_H264_LEVEL1p3;
+ break;
+ case VCD_LEVEL_H264_2:
+ level = VIDC_1080P_H264_LEVEL2;
+ break;
+ case VCD_LEVEL_H264_2p1:
+ level = VIDC_1080P_H264_LEVEL2p1;
+ break;
+ case VCD_LEVEL_H264_2p2:
+ level = VIDC_1080P_H264_LEVEL2p2;
+ break;
+ case VCD_LEVEL_H264_3:
+ level = VIDC_1080P_H264_LEVEL3;
+ break;
+ case VCD_LEVEL_H264_3p1:
+ level = VIDC_1080P_H264_LEVEL3p1;
+ break;
+ case VCD_LEVEL_H264_3p2:
+ level = VIDC_1080P_H264_LEVEL3p2;
+ break;
+ case VCD_LEVEL_H264_4:
+ level = VIDC_1080P_H264_LEVEL4;
+ break;
+ case VCD_LEVEL_H263_10:
+ level = VIDC_1080P_H263_LEVEL10;
+ break;
+ case VCD_LEVEL_H263_20:
+ level = VIDC_1080P_H263_LEVEL20;
+ break;
+ case VCD_LEVEL_H263_30:
+ level = VIDC_1080P_H263_LEVEL30;
+ break;
+ case VCD_LEVEL_H263_40:
+ level = VIDC_1080P_H263_LEVEL40;
+ break;
+ case VCD_LEVEL_H263_45:
+ level = VIDC_1080P_H263_LEVEL45;
+ break;
+ case VCD_LEVEL_H263_50:
+ level = VIDC_1080P_H263_LEVEL50;
+ break;
+ case VCD_LEVEL_H263_60:
+ level = VIDC_1080P_H263_LEVEL60;
+ break;
+ case VCD_LEVEL_H263_70:
+ level = VIDC_1080P_H263_LEVEL70;
+ break;
+ }
+ vidc_1080p_set_encode_profile_level(encode_profile, level);
+}
+
+static void ddl_vidc_encode_set_multi_slice_info(
+ struct ddl_encoder_data *encoder)
+{
+ enum vidc_1080p_MSlice_selection m_slice_sel;
+ u32 i_multi_slice_size = 0, i_multi_slice_byte = 0;
+
+ if (!encoder) {
+ DDL_MSG_ERROR("Invalid Parameter");
+ return;
+ }
+
+ switch (encoder->multi_slice.m_slice_sel) {
+ default:
+ case VCD_MSLICE_OFF:
+ m_slice_sel = VIDC_1080P_MSLICE_DISABLE;
+ break;
+ case VCD_MSLICE_BY_MB_COUNT:
+ m_slice_sel = VIDC_1080P_MSLICE_BY_MB_COUNT;
+ i_multi_slice_size = encoder->multi_slice.m_slice_size;
+ break;
+ case VCD_MSLICE_BY_BYTE_COUNT:
+ m_slice_sel = VIDC_1080P_MSLICE_BY_BYTE_COUNT;
+ i_multi_slice_byte = encoder->multi_slice.m_slice_size;
+ break;
+ }
+ vidc_1080p_set_encode_multi_slice_control(m_slice_sel,
+ i_multi_slice_size, i_multi_slice_byte);
+}
+
+void ddl_vidc_encode_init_codec(struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ struct ddl_enc_buffers *enc_buffers = &encoder->hw_bufs;
+ struct vidc_1080p_enc_seq_start_param seq_start_param;
+ enum vidc_1080p_memory_access_method mem_access_method;
+ enum vidc_1080p_DBConfig db_config;
+ enum VIDC_SM_frame_skip r_cframe_skip =
+ VIDC_SM_FRAME_SKIP_DISABLE;
+ u32 index, luma[4], chroma[4], hdr_ext_control = false;
+ const u32 recon_bufs = 4;
+
+ ddl_vidc_encode_set_profile_level(ddl);
+ vidc_1080p_set_encode_frame_size(encoder->frame_size.width,
+ encoder->frame_size.height);
+ vidc_1080p_encode_set_qp_params(encoder->qp_range.max_qp,
+ encoder->qp_range.min_qp);
+ vidc_1080p_encode_set_rc_config(encoder->rc_level.frame_level_rc,
+ encoder->rc_level.mb_level_rc,
+ encoder->session_qp.i_frame_qp);
+ if (encoder->hdr_ext_control > 0)
+ hdr_ext_control = true;
+ if (encoder->r_cframe_skip > 0)
+ r_cframe_skip = VIDC_SM_FRAME_SKIP_ENABLE_LEVEL;
+ vidc_sm_set_extended_encoder_control(&ddl->shared_mem
+ [ddl->command_channel], hdr_ext_control,
+ r_cframe_skip, false, 0);
+ vidc_sm_set_encoder_init_rc_value(&ddl->shared_mem
+ [ddl->command_channel],
+ encoder->target_bit_rate.target_bitrate);
+ vidc_sm_set_encoder_hec_period(&ddl->shared_mem
+ [ddl->command_channel], encoder->hdr_ext_control);
+ vidc_sm_set_encoder_vop_time(&ddl->shared_mem
+ [ddl->command_channel], true,
+ encoder->vop_timing.vop_time_resolution, 0);
+ if (encoder->rc_level.frame_level_rc)
+ vidc_1080p_encode_set_frame_level_rc_params((
+ DDL_FRAMERATE_SCALE(encoder->\
+ frame_rate.fps_numerator) /
+ encoder->frame_rate.fps_denominator),
+ encoder->target_bit_rate.target_bitrate,
+ encoder->frame_level_rc.reaction_coeff);
+ if (encoder->rc_level.mb_level_rc)
+ vidc_1080p_encode_set_mb_level_rc_params(
+ encoder->adaptive_rc.disable_dark_region_as_flag,
+ encoder->adaptive_rc.disable_smooth_region_as_flag,
+ encoder->adaptive_rc.disable_static_region_as_flag,
+ encoder->adaptive_rc.disable_activity_region_flag);
+ if ((!encoder->rc_level.frame_level_rc) &&
+ (!encoder->rc_level.mb_level_rc))
+ vidc_sm_set_pand_b_frame_qp(
+ &ddl->shared_mem[ddl->command_channel],
+ encoder->session_qp.b_frame_qp,
+ encoder->session_qp.p_frame_qp);
+ if (encoder->codec.codec == VCD_CODEC_MPEG4) {
+ vidc_1080p_set_mpeg4_encode_quarter_pel_control(false);
+ vidc_1080p_set_encode_field_picture_structure(false);
+ }
+ if (encoder->codec.codec == VCD_CODEC_H264) {
+ enum vidc_1080p_entropy_sel entropy_sel;
+ switch (encoder->entropy_control.entropy_sel) {
+ default:
+ case VCD_ENTROPY_SEL_CAVLC:
+ entropy_sel = VIDC_1080P_ENTROPY_SEL_CAVLC;
+ break;
+ case VCD_ENTROPY_SEL_CABAC:
+ entropy_sel = VIDC_1080P_ENTROPY_SEL_CABAC;
+ break;
+ }
+ vidc_1080p_set_h264_encode_entropy(entropy_sel);
+ switch (encoder->db_control.db_config) {
+ default:
+ case VCD_DB_ALL_BLOCKING_BOUNDARY:
+ db_config = VIDC_1080P_DB_ALL_BLOCKING_BOUNDARY;
+ break;
+ case VCD_DB_DISABLE:
+ db_config = VIDC_1080P_DB_DISABLE;
+ break;
+ case VCD_DB_SKIP_SLICE_BOUNDARY:
+ db_config = VIDC_1080P_DB_SKIP_SLICE_BOUNDARY;
+ break;
+ }
+ vidc_1080p_set_h264_encode_loop_filter(db_config,
+ encoder->db_control.slice_alpha_offset,
+ encoder->db_control.slice_beta_offset);
+ vidc_1080p_set_h264_encoder_p_frame_ref_count(encoder->\
+ num_references_for_p_frame);
+ if (encoder->profile.profile == VCD_PROFILE_H264_HIGH)
+ vidc_1080p_set_h264_encode_8x8transform_control(true);
+ }
+ vidc_1080p_set_encode_picture(encoder->i_period.p_frames,
+ encoder->i_period.b_frames);
+ vidc_1080p_set_encode_circular_intra_refresh(
+ encoder->intra_refresh.cir_mb_number);
+ ddl_vidc_encode_set_multi_slice_info(encoder);
+ ddl_vidc_metadata_enable(ddl);
+ if (encoder->meta_data_enable_flag)
+ vidc_sm_set_metadata_start_address(&ddl->shared_mem
+ [ddl->command_channel], DDL_ADDR_OFFSET(
+ ddl_context->dram_base_a,
+ ddl->codec_data.encoder.meta_data_input));
+ luma[0] = DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ enc_buffers->dpb_y[0]);
+ luma[1] = DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ enc_buffers->dpb_y[1]);
+ if (encoder->hw_bufs.dpb_count == DDL_ENC_MAX_DPB_BUFFERS) {
+ luma[2] = DDL_ADDR_OFFSET(ddl_context->dram_base_b,
+ enc_buffers->dpb_y[2]);
+ luma[3] = DDL_ADDR_OFFSET(ddl_context->dram_base_b,
+ enc_buffers->dpb_y[3]);
+ }
+ for (index = 0; index < recon_bufs; index++)
+ chroma[index] = DDL_ADDR_OFFSET(ddl_context->dram_base_b,
+ enc_buffers->dpb_c[index]);
+ vidc_1080p_set_encode_recon_buffers(recon_bufs, luma, chroma);
+ switch (encoder->codec.codec) {
+ case VCD_CODEC_MPEG4:
+ vidc_1080p_set_mpeg4_encode_work_buffers(
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ enc_buffers->col_zero),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ enc_buffers->acdc_coef),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ enc_buffers->mv));
+ break;
+ case VCD_CODEC_H263:
+ vidc_1080p_set_h263_encode_work_buffers(
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ enc_buffers->mv),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ enc_buffers->acdc_coef));
+ break;
+ case VCD_CODEC_H264:
+ vidc_1080p_set_h264_encode_work_buffers(
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ enc_buffers->mv),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ enc_buffers->col_zero),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ enc_buffers->md),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_b,
+ enc_buffers->pred),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ enc_buffers->nbor_info),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ enc_buffers->mb_info));
+ break;
+ default:
+ break;
+ }
+ if (encoder->buf_format.buffer_format ==
+ VCD_BUFFER_FORMAT_NV12_16M2KA)
+ mem_access_method = VIDC_1080P_TILE_LINEAR;
+ else
+ mem_access_method = VIDC_1080P_TILE_64x32;
+ vidc_1080p_set_encode_input_frame_format(mem_access_method);
+ vidc_1080p_set_encode_padding_control(0, 0, 0, 0);
+ DDL_MSG_LOW("ddl_state_transition: %s ~~>"
+ "DDL_CLIENT_WAIT_FOR_INITCODECDONE",
+ ddl_get_state_string(ddl->client_state));
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_INITCODECDONE;
+ ddl->cmd_state = DDL_CMD_INIT_CODEC;
+ vidc_1080p_set_encode_field_picture_structure(false);
+ seq_start_param.cmd_seq_num = ++ddl_context->cmd_seq_num;
+ seq_start_param.inst_id = ddl->instance_id;
+ seq_start_param.shared_mem_addr_offset = DDL_ADDR_OFFSET(
+ ddl_context->dram_base_a, ddl->shared_mem
+ [ddl->command_channel]);
+ seq_start_param.stream_buffer_addr_offset = DDL_ADDR_OFFSET(
+ ddl_context->dram_base_a, encoder->seq_header);
+ seq_start_param.stream_buffer_size =
+ encoder->seq_header.buffer_size;
+ encoder->seq_header_length = 0;
+ ddl_context->vidc_encode_seq_start[ddl->command_channel](
+ &seq_start_param);
+}
+
+void ddl_vidc_channel_end(struct ddl_client_context *ddl)
+{
+ DDL_MSG_LOW("ddl_state_transition: %s ~~> DDL_CLIENT_WAIT_FOR_CHEND",
+ ddl_get_state_string(ddl->client_state));
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_CHEND;
+ ddl->cmd_state = DDL_CMD_CHANNEL_END;
+ vidc_1080p_set_host2risc_cmd(VIDC_1080P_HOST2RISC_CMD_CLOSE_CH,
+ ddl->instance_id, 0, 0, 0);
+}
+
+void ddl_vidc_encode_frame_run(struct ddl_client_context *ddl)
+{
+ struct vidc_1080p_enc_frame_start_param enc_param;
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ struct ddl_enc_buffers *enc_buffers = &(encoder->hw_bufs);
+ struct vcd_frame_data *stream = &(ddl->output_frame.vcd_frm);
+ struct vcd_frame_data *input_vcd_frm =
+ &(ddl->input_frame.vcd_frm);
+ u32 dpb_addr_y[4], dpb_addr_c[4];
+ u32 index, y_addr, c_addr;
+
+ ddl_vidc_encode_set_metadata_output_buf(ddl);
+
+ encoder->enc_frame_info.meta_data_exists = false;
+
+ y_addr = DDL_OFFSET(ddl_context->dram_base_b.align_physical_addr,
+ input_vcd_frm->physical);
+ c_addr = (y_addr + encoder->input_buf_size.size_y);
+ if (input_vcd_frm->flags & VCD_FRAME_FLAG_EOS) {
+ enc_param.encode = VIDC_1080P_ENC_TYPE_LAST_FRAME_DATA;
+ DDL_MSG_LOW("ddl_state_transition: %s ~~>"
+ "DDL_CLIENT_WAIT_FOR_EOS_DONE",
+ ddl_get_state_string(ddl->client_state));
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_EOS_DONE;
+ } else {
+ enc_param.encode = VIDC_1080P_ENC_TYPE_FRAME_DATA;
+ DDL_MSG_LOW("ddl_state_transition: %s ~~>"
+ "DDL_CLIENT_WAIT_FOR_FRAME_DONE",
+ ddl_get_state_string(ddl->client_state));
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME_DONE;
+ }
+ ddl->cmd_state = DDL_CMD_ENCODE_FRAME;
+ if (encoder->dynamic_prop_change) {
+ encoder->dynmic_prop_change_req = true;
+ ddl_vidc_encode_dynamic_property(ddl, true);
+ }
+
+ vidc_1080p_set_encode_circular_intra_refresh(
+ encoder->intra_refresh.cir_mb_number);
+ ddl_vidc_encode_set_multi_slice_info(encoder);
+ enc_param.cmd_seq_num = ++ddl_context->cmd_seq_num;
+ enc_param.inst_id = ddl->instance_id;
+ enc_param.shared_mem_addr_offset = DDL_ADDR_OFFSET(
+ ddl_context->dram_base_a,
+ ddl->shared_mem[ddl->command_channel]);
+ enc_param.current_y_addr_offset = y_addr;
+ enc_param.current_c_addr_offset = c_addr;
+ enc_param.stream_buffer_addr_offset = DDL_OFFSET(
+ ddl_context->dram_base_a.align_physical_addr, stream->physical);
+ enc_param.stream_buffer_size =
+ encoder->client_output_buf_req.sz;
+
+ enc_param.intra_frame = encoder->intra_frame_insertion;
+ if (encoder->intra_frame_insertion)
+ encoder->intra_frame_insertion = false;
+ enc_param.input_flush = false;
+ vidc_sm_set_encoder_vop_time(
+ &ddl->shared_mem[ddl->command_channel], true,
+ encoder->vop_timing.vop_time_resolution,
+ ddl->input_frame.frm_delta);
+ vidc_sm_set_frame_tag(&ddl->shared_mem[ddl->command_channel],
+ ddl->input_frame.vcd_frm.ip_frm_tag);
+ if (ddl_context->pix_cache_enable) {
+ for (index = 0; index < enc_buffers->dpb_count;
+ index++) {
+ dpb_addr_y[index] =
+ (u32) VIDC_1080P_DEC_DPB_RESET_VALUE;
+ dpb_addr_c[index] = (u32) enc_buffers->dpb_c
+ [index].align_physical_addr;
+ }
+
+ dpb_addr_y[index] = (u32) input_vcd_frm->physical;
+ dpb_addr_c[index] = (u32) input_vcd_frm->physical +
+ encoder->input_buf_size.size_y;
+
+ vidc_pix_cache_init_luma_chroma_base_addr(
+ enc_buffers->dpb_count + 1, dpb_addr_y, dpb_addr_c);
+ vidc_pix_cache_set_frame_size(encoder->frame_size.width,
+ encoder->frame_size.height);
+ vidc_pix_cache_set_frame_range(enc_buffers->sz_dpb_y,
+ enc_buffers->sz_dpb_c);
+ vidc_pix_cache_clear_cache_tags();
+ }
+ ddl_context->vidc_encode_frame_start[ddl->command_channel] (
+ &enc_param);
+}
+
+u32 ddl_vidc_decode_set_buffers(struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
+ u32 vcd_status = VCD_S_SUCCESS;
+ struct vidc_1080p_dec_init_buffers_param init_buf_param;
+
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_DPB)) {
+ DDL_MSG_ERROR("STATE-CRITICAL");
+ return VCD_ERR_FAIL;
+ }
+ ddl_vidc_decode_set_metadata_output(decoder);
+ if (decoder->dp_buf.no_of_dec_pic_buf <
+ decoder->client_output_buf_req.actual_count)
+ return VCD_ERR_BAD_STATE;
+ if (decoder->codec.codec == VCD_CODEC_H264) {
+ vidc_sm_set_allocated_h264_mv_size(
+ &ddl->shared_mem[ddl->command_channel],
+ decoder->hw_bufs.h264_mv[0].buffer_size);
+ }
+ if (vcd_status)
+ return vcd_status;
+#ifdef DDL_BUF_LOG
+ ddl_list_buffers(ddl);
+#endif
+ if (vidc_msg_timing)
+ ddl_set_core_start_time(__func__, DEC_OP_TIME);
+ ddl_decoder_dpb_transact(decoder, NULL, DDL_DPB_OP_INIT);
+ ddl_decoder_dpb_init(ddl);
+ DDL_MSG_LOW("ddl_state_transition: %s ~~> DDL_CLIENT_WAIT_FOR_DPBDONE",
+ ddl_get_state_string(ddl->client_state));
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_DPBDONE;
+ ddl->cmd_state = DDL_CMD_DECODE_SET_DPB;
+ vidc_sm_set_allocated_dpb_size(
+ &ddl->shared_mem[ddl->command_channel],
+ decoder->dpb_buf_size.size_y,
+ decoder->dpb_buf_size.size_c);
+ init_buf_param.cmd_seq_num = ++ddl_context->cmd_seq_num;
+ init_buf_param.inst_id = ddl->instance_id;
+ init_buf_param.shared_mem_addr_offset = DDL_ADDR_OFFSET(
+ ddl_context->dram_base_a, ddl->shared_mem
+ [ddl->command_channel]);
+ init_buf_param.dpb_count = decoder->dp_buf.no_of_dec_pic_buf;
+ ddl_context->vidc_decode_init_buffers[ddl->command_channel] (
+ &init_buf_param);
+ return VCD_S_SUCCESS;
+}
+
+void ddl_vidc_decode_frame_run(struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
+ struct vcd_frame_data *bit_stream =
+ &(ddl->input_frame.vcd_frm);
+ struct ddl_dec_buffers *dec_buffers = &decoder->hw_bufs;
+ struct ddl_mask *dpb_mask = &ddl->codec_data.decoder.dpb_mask;
+ struct vidc_1080p_dec_frame_start_param dec_param;
+ u32 dpb_addr_y[32], index;
+ if (vidc_msg_timing) {
+ ddl_set_core_start_time(__func__, DEC_OP_TIME);
+ ddl_set_core_start_time(__func__, DEC_IP_TIME);
+ }
+ if ((!bit_stream->data_len) || (!bit_stream->physical)) {
+ ddl_vidc_decode_eos_run(ddl);
+ return;
+ }
+ DDL_MSG_LOW("ddl_state_transition: %s ~~"
+ "DDL_CLIENT_WAIT_FOR_FRAME_DONE",
+ ddl_get_state_string(ddl->client_state));
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME_DONE;
+ ddl_vidc_decode_dynamic_property(ddl, true);
+ ddl_decoder_dpb_transact(decoder, NULL, DDL_DPB_OP_SET_MASK);
+ ddl->cmd_state = DDL_CMD_DECODE_FRAME;
+ dec_param.cmd_seq_num = ++ddl_context->cmd_seq_num;
+ dec_param.inst_id = ddl->instance_id;
+ dec_param.shared_mem_addr_offset = DDL_ADDR_OFFSET(
+ ddl_context->dram_base_a, ddl->shared_mem
+ [ddl->command_channel]);
+ dec_param.stream_buffer_addr_offset = DDL_OFFSET(
+ ddl_context->dram_base_a.align_physical_addr,
+ bit_stream->physical);
+ dec_param.stream_frame_size = bit_stream->data_len;
+ dec_param.stream_buffersize = decoder->client_input_buf_req.sz;
+ dec_param.descriptor_buffer_addr_offset = DDL_ADDR_OFFSET(
+ ddl_context->dram_base_a, dec_buffers->desc);
+ dec_param.descriptor_buffer_size = dec_buffers->desc.buffer_size;
+ dec_param.release_dpb_bit_mask = dpb_mask->hw_mask;
+ dec_param.decode = VIDC_1080P_DEC_TYPE_FRAME_DATA;
+ dec_param.dpb_count = decoder->dp_buf.no_of_dec_pic_buf;
+ if (decoder->flush_pending) {
+ dec_param.dpb_flush = true;
+ decoder->flush_pending = false;
+ } else
+ dec_param.dpb_flush = false;
+ vidc_sm_set_frame_tag(&ddl->shared_mem[ddl->command_channel],
+ bit_stream->ip_frm_tag);
+ if (ddl_context->pix_cache_enable) {
+ for (index = 0; index <
+ decoder->dp_buf.no_of_dec_pic_buf; index++) {
+ dpb_addr_y[index] = (u32)
+ decoder->dp_buf.dec_pic_buffers
+ [index].vcd_frm.physical;
+ }
+ vidc_pix_cache_init_luma_chroma_base_addr(
+ decoder->dp_buf.no_of_dec_pic_buf,
+ dpb_addr_y, NULL);
+ vidc_pix_cache_set_frame_range(decoder->dpb_buf_size.size_y,
+ decoder->dpb_buf_size.size_c);
+ vidc_pix_cache_clear_cache_tags();
+ }
+ ddl_context->vidc_decode_frame_start[ddl->command_channel] (
+ &dec_param);
+}
+
+void ddl_vidc_decode_eos_run(struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
+ struct vcd_frame_data *bit_stream =
+ &(ddl->input_frame.vcd_frm);
+ struct ddl_dec_buffers *dec_buffers = &(decoder->hw_bufs);
+ struct ddl_mask *dpb_mask =
+ &(ddl->codec_data.decoder.dpb_mask);
+ struct vidc_1080p_dec_frame_start_param dec_param;
+
+ DDL_MSG_LOW("ddl_state_transition: %s ~~> DDL_CLIENT_WAIT_FOR_EOS_DONE",
+ ddl_get_state_string(ddl->client_state));
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_EOS_DONE;
+ if (decoder->output_order == VCD_DEC_ORDER_DECODE)
+ decoder->dynamic_prop_change |= DDL_DEC_REQ_OUTPUT_FLUSH;
+ ddl_vidc_decode_dynamic_property(ddl, true);
+ ddl_decoder_dpb_transact(decoder, NULL, DDL_DPB_OP_SET_MASK);
+ decoder->dynmic_prop_change_req = true;
+ ddl->cmd_state = DDL_CMD_EOS;
+ memset(&dec_param, 0, sizeof(dec_param));
+ dec_param.cmd_seq_num = ++ddl_context->cmd_seq_num;
+ dec_param.inst_id = ddl->instance_id;
+ dec_param.shared_mem_addr_offset = DDL_ADDR_OFFSET(
+ ddl_context->dram_base_a,
+ ddl->shared_mem[ddl->command_channel]);
+ dec_param.descriptor_buffer_addr_offset = DDL_ADDR_OFFSET(
+ ddl_context->dram_base_a, dec_buffers->desc);
+ dec_param.descriptor_buffer_size = dec_buffers->desc.buffer_size;
+ dec_param.release_dpb_bit_mask = dpb_mask->hw_mask;
+ dec_param.decode = VIDC_1080P_DEC_TYPE_LAST_FRAME_DATA;
+ dec_param.dpb_count = decoder->dp_buf.no_of_dec_pic_buf;
+ if (decoder->flush_pending) {
+ dec_param.dpb_flush = true;
+ decoder->flush_pending = false;
+ } else
+ dec_param.dpb_flush = false;
+ vidc_sm_set_frame_tag(&ddl->shared_mem[ddl->command_channel],
+ bit_stream->ip_frm_tag);
+ ddl_context->vidc_decode_frame_start[ddl->command_channel] (
+ &dec_param);
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc.c b/drivers/video/msm/vidc/1080p/ddl/vidc.c
new file mode 100644
index 0000000..ae918f0
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc.c
@@ -0,0 +1,1007 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "vidc.h"
+#include "vidc_hwio.h"
+
+
+#define VIDC_1080P_INIT_CH_INST_ID 0x0000ffff
+#define VIDC_1080P_RESET_VI 0x3f7
+#define VIDC_1080P_RESET_VI_RISC 0x3f6
+#define VIDC_1080P_RESET_VI_VIDC_RISC 0x3f2
+#define VIDC_1080P_RESET_ALL 0
+#define VIDC_1080P_RESET_RISC 0x3fe
+#define VIDC_1080P_RESET_NONE 0x3ff
+#define VIDC_1080P_INTERRUPT_CLEAR 0
+#define VIDC_1080P_MAX_H264DECODER_DPB 32
+#define VIDC_1080P_MAX_DEC_RECON_BUF 32
+
+#define VIDC_1080P_SI_RG7_DISPLAY_STATUS_MASK 0x00000007
+#define VIDC_1080P_SI_RG7_DISPLAY_STATUS_SHIFT 0
+#define VIDC_1080P_SI_RG7_DISPLAY_CODING_MASK 0x00000008
+#define VIDC_1080P_SI_RG7_DISPLAY_CODING_SHIFT 3
+#define VIDC_1080P_SI_RG7_DISPLAY_RES_MASK 0x00000030
+#define VIDC_1080P_SI_RG7_DISPLAY_RES_SHIFT 4
+
+#define VIDC_1080P_SI_RG7_DISPLAY_CROP_MASK 0x00000040
+#define VIDC_1080P_SI_RG7_DISPLAY_CROP_SHIFT 6
+
+#define VIDC_1080P_SI_RG8_DECODE_FRAMETYPE_MASK 0x00000007
+
+#define VIDC_1080P_SI_RG10_NUM_DPB_BMSK 0x00003fff
+#define VIDC_1080P_SI_RG10_NUM_DPB_SHFT 0
+#define VIDC_1080P_SI_RG10_DPB_FLUSH_BMSK 0x00004000
+#define VIDC_1080P_SI_RG10_DPB_FLUSH_SHFT 14
+#define VIDC_1080P_SI_RG10_DMX_DISABLE_BMSK 0x00008000
+#define VIDC_1080P_SI_RG10_DMX_DISABLE_SHFT 15
+
+#define VIDC_1080P_SI_RG11_DECODE_STATUS_MASK 0x00000007
+#define VIDC_1080P_SI_RG11_DECODE_STATUS_SHIFT 0
+#define VIDC_1080P_SI_RG11_DECODE_CODING_MASK 0x00000008
+#define VIDC_1080P_SI_RG11_DECODE_CODING_SHIFT 3
+#define VIDC_1080P_SI_RG11_DECODE_RES_MASK 0x000000C0
+#define VIDC_1080P_SI_RG11_DECODE_RES_SHIFT 6
+#define VIDC_1080P_SI_RG11_DECODE_CROPP_MASK 0x00000100
+#define VIDC_1080P_SI_RG11_DECODE_CROPP_SHIFT 8
+
+#define VIDC_1080P_BASE_OFFSET_SHIFT 11
+
+
+#define VIDC_1080P_H264DEC_LUMA_ADDR HWIO_REG_759068_ADDR
+#define VIDC_1080P_H264DEC_CHROMA_ADDR HWIO_REG_515200_ADDR
+#define VIDC_1080P_H264DEC_MV_PLANE_ADDR HWIO_REG_466192_ADDR
+
+#define VIDC_1080P_DEC_LUMA_ADDR HWIO_REG_759068_ADDR
+#define VIDC_1080P_DEC_CHROMA_ADDR HWIO_REG_515200_ADDR
+
+#define VIDC_1080P_DEC_TYPE_SEQ_HEADER 0x00010000
+#define VIDC_1080P_DEC_TYPE_FRAME_DATA 0x00020000
+#define VIDC_1080P_DEC_TYPE_LAST_FRAME_DATA 0x00030000
+#define VIDC_1080P_DEC_TYPE_INIT_BUFFERS 0x00040000
+
+#define VIDC_1080P_ENC_TYPE_SEQ_HEADER 0x00010000
+#define VIDC_1080P_ENC_TYPE_FRAME_DATA 0x00020000
+#define VIDC_1080P_ENC_TYPE_LAST_FRAME_DATA 0x00030000
+
+#define VIDC_1080P_MAX_INTRA_PERIOD 0xffff
+
+u8 *VIDC_BASE_PTR;
+
+void vidc_1080p_do_sw_reset(enum vidc_1080p_reset init_flag)
+{
+ if (init_flag == VIDC_1080P_RESET_IN_SEQ_FIRST_STAGE) {
+ u32 sw_reset_value = 0;
+
+ VIDC_HWIO_IN(REG_557899, &sw_reset_value);
+ sw_reset_value &= (~HWIO_REG_557899_RSTN_VI_BMSK);
+ VIDC_HWIO_OUT(REG_557899, sw_reset_value);
+ sw_reset_value &= (~HWIO_REG_557899_RSTN_RISC_BMSK);
+ VIDC_HWIO_OUT(REG_557899, sw_reset_value);
+ sw_reset_value &= (~(HWIO_REG_557899_RSTN_VIDCCORE_BMSK |
+ HWIO_REG_557899_RSTN_DMX_BMSK));
+
+ VIDC_HWIO_OUT(REG_557899, sw_reset_value);
+ } else if (init_flag == VIDC_1080P_RESET_IN_SEQ_SECOND_STAGE) {
+ VIDC_HWIO_OUT(REG_557899, VIDC_1080P_RESET_ALL);
+ VIDC_HWIO_OUT(REG_557899, VIDC_1080P_RESET_RISC);
+ }
+}
+
+void vidc_1080p_release_sw_reset(void)
+{
+ u32 nAxiCtl;
+ u32 nAxiStatus;
+ u32 nRdWrBurst;
+ u32 nOut_Order;
+
+ nOut_Order = VIDC_SETFIELD(1, HWIO_REG_5519_AXI_AOOORD_SHFT,
+ HWIO_REG_5519_AXI_AOOORD_BMSK);
+ VIDC_HWIO_OUT(REG_5519, nOut_Order);
+
+ nOut_Order = VIDC_SETFIELD(1, HWIO_REG_606364_AXI_AOOOWR_SHFT,
+ HWIO_REG_606364_AXI_AOOOWR_BMSK);
+ VIDC_HWIO_OUT(REG_606364, nOut_Order);
+
+ nAxiCtl = VIDC_SETFIELD(1, HWIO_REG_471159_AXI_HALT_REQ_SHFT,
+ HWIO_REG_471159_AXI_HALT_REQ_BMSK);
+
+ VIDC_HWIO_OUT(REG_471159, nAxiCtl);
+
+ do {
+ VIDC_HWIO_IN(REG_437878, &nAxiStatus);
+ nAxiStatus = VIDC_GETFIELD(nAxiStatus,
+ HWIO_REG_437878_AXI_HALT_ACK_BMSK,
+ HWIO_REG_437878_AXI_HALT_ACK_SHFT);
+ } while (0x3 != nAxiStatus);
+
+ nAxiCtl = VIDC_SETFIELD(1,
+ HWIO_REG_471159_AXI_RESET_SHFT,
+ HWIO_REG_471159_AXI_RESET_BMSK);
+
+ VIDC_HWIO_OUT(REG_471159, nAxiCtl);
+ VIDC_HWIO_OUT(REG_471159, 0);
+
+ nRdWrBurst = VIDC_SETFIELD(8,
+ HWIO_REG_922106_XBAR_OUT_MAX_RD_BURST_SHFT,
+ HWIO_REG_922106_XBAR_OUT_MAX_RD_BURST_BMSK) |
+ VIDC_SETFIELD(8, HWIO_REG_922106_XBAR_OUT_MAX_WR_BURST_SHFT,
+ HWIO_REG_922106_XBAR_OUT_MAX_WR_BURST_BMSK);
+
+ VIDC_HWIO_OUT(REG_922106, nRdWrBurst);
+
+ VIDC_HWIO_OUT(REG_666957, VIDC_1080P_INIT_CH_INST_ID);
+ VIDC_HWIO_OUT(REG_313350, VIDC_1080P_INIT_CH_INST_ID);
+ VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
+ VIDC_HWIO_OUT(REG_611794, VIDC_1080P_HOST2RISC_CMD_EMPTY);
+ VIDC_HWIO_OUT(REG_557899, VIDC_1080P_RESET_NONE);
+}
+
+void vidc_1080p_clear_interrupt(void)
+{
+ VIDC_HWIO_OUT(REG_575377, VIDC_1080P_INTERRUPT_CLEAR);
+}
+
+void vidc_1080p_set_host2risc_cmd(enum vidc_1080p_host2risc_cmd
+ host2risc_command, u32 host2risc_arg1, u32 host2risc_arg2,
+ u32 host2risc_arg3, u32 host2risc_arg4)
+{
+ VIDC_HWIO_OUT(REG_611794, VIDC_1080P_HOST2RISC_CMD_EMPTY);
+ VIDC_HWIO_OUT(REG_356340, host2risc_arg1);
+ VIDC_HWIO_OUT(REG_899023, host2risc_arg2);
+ VIDC_HWIO_OUT(REG_987762, host2risc_arg3);
+ VIDC_HWIO_OUT(REG_544000, host2risc_arg4);
+ VIDC_HWIO_OUT(REG_611794, host2risc_command);
+}
+
+void vidc_1080p_get_risc2host_cmd(u32 *pn_risc2host_command,
+ u32 *pn_risc2host_arg1, u32 *pn_risc2host_arg2,
+ u32 *pn_risc2host_arg3, u32 *pn_risc2host_arg4)
+{
+ VIDC_HWIO_IN(REG_695082, pn_risc2host_command);
+ VIDC_HWIO_IN(REG_156596, pn_risc2host_arg1);
+ VIDC_HWIO_IN(REG_222292, pn_risc2host_arg2);
+ VIDC_HWIO_IN(REG_790962, pn_risc2host_arg3);
+ VIDC_HWIO_IN(REG_679882, pn_risc2host_arg4);
+}
+
+void vidc_1080p_get_risc2host_cmd_status(u32 err_status,
+ u32 *dec_err_status, u32 *disp_err_status)
+{
+ *dec_err_status = VIDC_GETFIELD(err_status,
+ VIDC_RISC2HOST_ARG2_VIDC_DEC_ERROR_STATUS_BMSK,
+ VIDC_RISC2HOST_ARG2_VIDC_DEC_ERROR_STATUS_SHFT);
+ *disp_err_status = VIDC_GETFIELD(err_status,
+ VIDC_RISC2HOST_ARG2_VIDC_DISP_ERROR_STATUS_BMSK,
+ VIDC_RISC2HOST_ARG2_VIDC_DISP_ERROR_STATUS_SHFT);
+
+}
+
+void vidc_1080p_clear_risc2host_cmd(void)
+{
+ VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
+}
+
+void vidc_1080p_get_fw_version(u32 *pn_fw_version)
+{
+ VIDC_HWIO_IN(REG_653206, pn_fw_version);
+}
+
+void vidc_1080p_get_fw_status(u32 *pn_fw_status)
+{
+ VIDC_HWIO_IN(REG_350619, pn_fw_status);
+}
+
+void vidc_1080p_init_memory_controller(u32 dram_base_addr_a,
+ u32 dram_base_addr_b)
+{
+ VIDC_HWIO_OUT(REG_64440, dram_base_addr_a);
+ VIDC_HWIO_OUT(REG_675915, dram_base_addr_b);
+}
+
+void vidc_1080p_get_memory_controller_status(u32 *pb_mc_abusy,
+ u32 *pb_mc_bbusy)
+{
+ u32 mc_status = 0;
+
+ VIDC_HWIO_IN(REG_399911, &mc_status);
+ *pb_mc_abusy = (u32) ((mc_status &
+ HWIO_REG_399911_MC_BUSY_A_BMSK) >>
+ HWIO_REG_399911_MC_BUSY_A_SHFT);
+ *pb_mc_bbusy = (u32) ((mc_status &
+ HWIO_REG_399911_MC_BUSY_B_BMSK) >>
+ HWIO_REG_399911_MC_BUSY_B_SHFT);
+}
+
+void vidc_1080p_set_h264_decode_buffers(u32 dpb, u32 dec_vert_nb_mv_offset,
+ u32 dec_nb_ip_offset, u32 *pn_dpb_luma_offset,
+ u32 *pn_dpb_chroma_offset, u32 *pn_mv_buffer_offset)
+{
+ u32 count = 0, num_dpb_used = dpb;
+ u8 *vidc_dpb_luma_reg = (u8 *) VIDC_1080P_H264DEC_LUMA_ADDR;
+ u8 *vidc_dpb_chroma_reg = (u8 *) VIDC_1080P_H264DEC_CHROMA_ADDR;
+ u8 *vidc_mv_buffer_reg = (u8 *) VIDC_1080P_H264DEC_MV_PLANE_ADDR;
+
+ VIDC_HWIO_OUT(REG_931311, (dec_vert_nb_mv_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_16277, (dec_nb_ip_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ if (num_dpb_used > VIDC_1080P_MAX_H264DECODER_DPB)
+ num_dpb_used = VIDC_1080P_MAX_H264DECODER_DPB;
+ for (count = 0; count < num_dpb_used; count++) {
+ VIDC_OUT_DWORD(vidc_dpb_luma_reg,
+ (pn_dpb_luma_offset[count] >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_OUT_DWORD(vidc_dpb_chroma_reg,
+ (pn_dpb_chroma_offset[count] >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_OUT_DWORD(vidc_mv_buffer_reg,
+ (pn_mv_buffer_offset[count] >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ vidc_dpb_luma_reg += 4;
+ vidc_dpb_chroma_reg += 4;
+ vidc_mv_buffer_reg += 4;
+ }
+}
+
+void vidc_1080p_set_decode_recon_buffers(u32 recon_buffer,
+ u32 *pn_dec_luma, u32 *pn_dec_chroma)
+{
+ u32 count = 0, recon_buf_to_program = recon_buffer;
+ u8 *dec_recon_luma_reg = (u8 *) VIDC_1080P_DEC_LUMA_ADDR;
+ u8 *dec_recon_chroma_reg = (u8 *) VIDC_1080P_DEC_CHROMA_ADDR;
+
+ if (recon_buf_to_program > VIDC_1080P_MAX_DEC_RECON_BUF)
+ recon_buf_to_program = VIDC_1080P_MAX_DEC_RECON_BUF;
+ for (count = 0; count < recon_buf_to_program; count++) {
+ VIDC_OUT_DWORD(dec_recon_luma_reg, (pn_dec_luma[count] >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_OUT_DWORD(dec_recon_chroma_reg,
+ (pn_dec_chroma[count] >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ dec_recon_luma_reg += 4;
+ dec_recon_chroma_reg += 4;
+ }
+}
+
+void vidc_1080p_set_mpeg4_divx_decode_work_buffers(u32 nb_dcac_buffer_offset,
+ u32 upnb_mv_buffer_offset, u32 sub_anchor_buffer_offset,
+ u32 overlay_transform_buffer_offset, u32 stx_parser_buffer_offset)
+{
+ VIDC_HWIO_OUT(REG_931311, (nb_dcac_buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_16277, (upnb_mv_buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_654169, (sub_anchor_buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_802794,
+ (overlay_transform_buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_252167, (stx_parser_buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+}
+
+void vidc_1080p_set_h263_decode_work_buffers(u32 nb_dcac_buffer_offset,
+ u32 upnb_mv_buffer_offset, u32 sub_anchor_buffer_offset,
+ u32 overlay_transform_buffer_offset)
+{
+ VIDC_HWIO_OUT(REG_931311, (nb_dcac_buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_16277, (upnb_mv_buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_654169, (sub_anchor_buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_802794,
+ (overlay_transform_buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+}
+
+void vidc_1080p_set_vc1_decode_work_buffers(u32 nb_dcac_buffer_offset,
+ u32 upnb_mv_buffer_offset, u32 sub_anchor_buffer_offset,
+ u32 overlay_transform_buffer_offset, u32 bitplain1Buffer_offset,
+ u32 bitplain2Buffer_offset, u32 bitplain3Buffer_offset)
+{
+ VIDC_HWIO_OUT(REG_931311, (nb_dcac_buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_16277, (upnb_mv_buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_654169, (sub_anchor_buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_802794,
+ (overlay_transform_buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_724376, (bitplain3Buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_551674, (bitplain2Buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_115991, (bitplain1Buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+}
+
+void vidc_1080p_set_encode_recon_buffers(u32 recon_buffer,
+ u32 *pn_enc_luma, u32 *pn_enc_chroma)
+{
+ if (recon_buffer > 0) {
+ VIDC_HWIO_OUT(REG_294579, (pn_enc_luma[0] >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_759068, (pn_enc_chroma[0] >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ }
+ if (recon_buffer > 1) {
+ VIDC_HWIO_OUT(REG_616802, (pn_enc_luma[1] >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_833502, (pn_enc_chroma[1] >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ }
+ if (recon_buffer > 2) {
+ VIDC_HWIO_OUT(REG_61427, (pn_enc_luma[2] >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_68356, (pn_enc_chroma[2] >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ }
+ if (recon_buffer > 3) {
+ VIDC_HWIO_OUT(REG_23318, (pn_enc_luma[3] >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_127855, (pn_enc_chroma[3] >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ }
+}
+
+void vidc_1080p_set_h264_encode_work_buffers(u32 up_row_mv_buffer_offset,
+ u32 direct_colzero_flag_buffer_offset,
+ u32 upper_intra_md_buffer_offset,
+ u32 upper_intra_pred_buffer_offset, u32 nbor_infor_buffer_offset,
+ u32 mb_info_offset)
+{
+ VIDC_HWIO_OUT(REG_515200, (up_row_mv_buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_69832,
+ (direct_colzero_flag_buffer_offset>>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_256132,
+ (upper_intra_md_buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_475648,
+ (upper_intra_pred_buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_29510, (nbor_infor_buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_175929, (mb_info_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+}
+
+void vidc_1080p_set_h263_encode_work_buffers(u32 up_row_mv_buffer_offset,
+ u32 up_row_inv_quanti_coeff_buffer_offset)
+{
+ VIDC_HWIO_OUT(REG_515200, (up_row_mv_buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_29510, (
+ up_row_inv_quanti_coeff_buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+}
+
+void vidc_1080p_set_mpeg4_encode_work_buffers(u32 skip_flag_buffer_offset,
+ u32 up_row_inv_quanti_coeff_buffer_offset, u32 upper_mv_offset)
+{
+ VIDC_HWIO_OUT(REG_69832, (skip_flag_buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_29510, (
+ up_row_inv_quanti_coeff_buffer_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+ VIDC_HWIO_OUT(REG_515200, (upper_mv_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT));
+}
+
+void vidc_1080p_set_encode_frame_size(u32 hori_size, u32 vert_size)
+{
+ VIDC_HWIO_OUT(REG_934655, hori_size);
+ VIDC_HWIO_OUT(REG_179070, vert_size);
+}
+
+void vidc_1080p_set_encode_profile_level(u32 encode_profile, u32 enc_level)
+{
+ u32 profile_level = 0;
+
+ profile_level = VIDC_SETFIELD(enc_level,
+ HWIO_REG_63643_LEVEL_SHFT,
+ HWIO_REG_63643_LEVEL_BMSK) |
+ VIDC_SETFIELD(encode_profile,
+ HWIO_REG_63643_PROFILE_SHFT,
+ HWIO_REG_63643_PROFILE_BMSK);
+ VIDC_HWIO_OUT(REG_63643, profile_level);
+}
+
+void vidc_1080p_set_encode_field_picture_structure(u32 enc_field_picture)
+{
+ VIDC_HWIO_OUT(REG_786024, enc_field_picture);
+}
+
+void vidc_1080p_set_decode_mpeg4_pp_filter(u32 lf_enables)
+{
+ VIDC_HWIO_OUT(REG_152500, lf_enables);
+}
+
+void vidc_1080p_set_decode_qp_save_control(u32 enable_q_pout)
+{
+ VIDC_HWIO_OUT(REG_143629, enable_q_pout);
+}
+
+void vidc_1080p_get_returned_channel_inst_id(u32 *pn_rtn_chid)
+{
+ VIDC_HWIO_IN(REG_607589, pn_rtn_chid);
+}
+
+void vidc_1080p_clear_returned_channel_inst_id(void)
+{
+ VIDC_HWIO_OUT(REG_607589, VIDC_1080P_INIT_CH_INST_ID);
+}
+
+void vidc_1080p_get_decode_seq_start_result(
+ struct vidc_1080p_seq_hdr_info *seq_hdr_info)
+{
+ u32 dec_disp_result;
+ u32 frame = 0;
+ VIDC_HWIO_IN(REG_845544, &seq_hdr_info->img_size_y);
+ VIDC_HWIO_IN(REG_859906, &seq_hdr_info->img_size_x);
+ VIDC_HWIO_IN(REG_490078, &seq_hdr_info->min_num_dpb);
+ VIDC_HWIO_IN(REG_489688, &seq_hdr_info->dec_frm_size);
+ VIDC_HWIO_IN(REG_853667, &dec_disp_result);
+ seq_hdr_info->disp_progressive = VIDC_GETFIELD(dec_disp_result,
+ VIDC_1080P_SI_RG7_DISPLAY_CODING_MASK,
+ VIDC_1080P_SI_RG7_DISPLAY_CODING_SHIFT);
+ seq_hdr_info->disp_crop_exists = VIDC_GETFIELD(dec_disp_result,
+ VIDC_1080P_SI_RG7_DISPLAY_CROP_MASK,
+ VIDC_1080P_SI_RG7_DISPLAY_CROP_SHIFT);
+ VIDC_HWIO_IN(REG_692991, &dec_disp_result);
+ seq_hdr_info->dec_progressive = VIDC_GETFIELD(dec_disp_result,
+ VIDC_1080P_SI_RG11_DECODE_CODING_MASK,
+ VIDC_1080P_SI_RG11_DECODE_CODING_SHIFT);
+ seq_hdr_info->dec_crop_exists = VIDC_GETFIELD(dec_disp_result,
+ VIDC_1080P_SI_RG11_DECODE_CROPP_MASK,
+ VIDC_1080P_SI_RG11_DECODE_CROPP_SHIFT);
+ VIDC_HWIO_IN(REG_760102, &frame);
+ seq_hdr_info->data_partition = ((frame & 0x8) >> 3);
+}
+
+void vidc_1080p_get_decoded_frame_size(u32 *pn_decoded_size)
+{
+ VIDC_HWIO_IN(REG_489688, pn_decoded_size);
+}
+
+void vidc_1080p_get_display_frame_result(
+ struct vidc_1080p_dec_disp_info *dec_disp_info)
+{
+ u32 display_result;
+ VIDC_HWIO_IN(REG_640904, &dec_disp_info->display_y_addr);
+ VIDC_HWIO_IN(REG_60114, &dec_disp_info->display_c_addr);
+ VIDC_HWIO_IN(REG_853667, &display_result);
+ VIDC_HWIO_IN(REG_845544, &dec_disp_info->img_size_y);
+ VIDC_HWIO_IN(REG_859906, &dec_disp_info->img_size_x);
+ dec_disp_info->display_status =
+ (enum vidc_1080p_display_status)
+ VIDC_GETFIELD(display_result,
+ VIDC_1080P_SI_RG7_DISPLAY_STATUS_MASK,
+ VIDC_1080P_SI_RG7_DISPLAY_STATUS_SHIFT);
+ dec_disp_info->display_coding =
+ (enum vidc_1080p_display_coding)
+ VIDC_GETFIELD(display_result, VIDC_1080P_SI_RG7_DISPLAY_CODING_MASK,
+ VIDC_1080P_SI_RG7_DISPLAY_CODING_SHIFT);
+ dec_disp_info->disp_resl_change = VIDC_GETFIELD(display_result,
+ VIDC_1080P_SI_RG7_DISPLAY_RES_MASK,
+ VIDC_1080P_SI_RG7_DISPLAY_RES_SHIFT);
+ dec_disp_info->disp_crop_exists = VIDC_GETFIELD(display_result,
+ VIDC_1080P_SI_RG7_DISPLAY_CROP_MASK,
+ VIDC_1080P_SI_RG7_DISPLAY_CROP_SHIFT);
+}
+
+void vidc_1080p_get_decode_frame(
+ enum vidc_1080p_decode_frame *pe_frame)
+{
+ u32 frame = 0;
+
+ VIDC_HWIO_IN(REG_760102, &frame);
+ *pe_frame = (enum vidc_1080p_decode_frame)
+ (frame & VIDC_1080P_SI_RG8_DECODE_FRAMETYPE_MASK);
+}
+
+void vidc_1080p_get_decode_frame_result(
+ struct vidc_1080p_dec_disp_info *dec_disp_info)
+{
+ u32 decode_result;
+
+ VIDC_HWIO_IN(REG_378318, &dec_disp_info->decode_y_addr);
+ VIDC_HWIO_IN(REG_203487, &dec_disp_info->decode_c_addr);
+ VIDC_HWIO_IN(REG_692991, &decode_result);
+ dec_disp_info->decode_status = (enum vidc_1080p_display_status)
+ VIDC_GETFIELD(decode_result,
+ VIDC_1080P_SI_RG11_DECODE_STATUS_MASK,
+ VIDC_1080P_SI_RG11_DECODE_STATUS_SHIFT);
+ dec_disp_info->decode_coding = (enum vidc_1080p_display_coding)
+ VIDC_GETFIELD(decode_result,
+ VIDC_1080P_SI_RG11_DECODE_CODING_MASK,
+ VIDC_1080P_SI_RG11_DECODE_CODING_SHIFT);
+ dec_disp_info->dec_resl_change = VIDC_GETFIELD(decode_result,
+ VIDC_1080P_SI_RG11_DECODE_RES_MASK,
+ VIDC_1080P_SI_RG11_DECODE_RES_SHIFT);
+ dec_disp_info->dec_crop_exists = VIDC_GETFIELD(decode_result,
+ VIDC_1080P_SI_RG11_DECODE_CROPP_MASK,
+ VIDC_1080P_SI_RG11_DECODE_CROPP_SHIFT);
+}
+
+void vidc_1080p_decode_seq_start_ch0(
+ struct vidc_1080p_dec_seq_start_param *param)
+{
+
+ VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
+ VIDC_HWIO_OUT(REG_666957, VIDC_1080P_INIT_CH_INST_ID);
+ VIDC_HWIO_OUT(REG_117192,
+ param->stream_buffer_addr_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT);
+ VIDC_HWIO_OUT(REG_145068, param->stream_frame_size);
+ VIDC_HWIO_OUT(REG_921356,
+ param->descriptor_buffer_addr_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT);
+ VIDC_HWIO_OUT(REG_190381, param->stream_buffersize);
+ VIDC_HWIO_OUT(REG_85655, param->descriptor_buffer_size);
+ VIDC_HWIO_OUT(REG_889944, param->shared_mem_addr_offset);
+ VIDC_HWIO_OUT(REG_397087, param->cmd_seq_num);
+ VIDC_HWIO_OUT(REG_666957, VIDC_1080P_DEC_TYPE_SEQ_HEADER |
+ param->inst_id);
+}
+
+void vidc_1080p_decode_seq_start_ch1(
+ struct vidc_1080p_dec_seq_start_param *param)
+{
+
+ VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
+ VIDC_HWIO_OUT(REG_313350, VIDC_1080P_INIT_CH_INST_ID);
+ VIDC_HWIO_OUT(REG_980194,
+ param->stream_buffer_addr_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT);
+ VIDC_HWIO_OUT(REG_936704, param->stream_frame_size);
+ VIDC_HWIO_OUT(REG_821977,
+ param->descriptor_buffer_addr_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT);
+ VIDC_HWIO_OUT(REG_887095, param->stream_buffersize);
+ VIDC_HWIO_OUT(REG_576987, param->descriptor_buffer_size);
+ VIDC_HWIO_OUT(REG_652528, param->shared_mem_addr_offset);
+ VIDC_HWIO_OUT(REG_254093, param->cmd_seq_num);
+ VIDC_HWIO_OUT(REG_313350, VIDC_1080P_DEC_TYPE_SEQ_HEADER |
+ param->inst_id);
+}
+
+void vidc_1080p_decode_frame_start_ch0(
+ struct vidc_1080p_dec_frame_start_param *param)
+{
+ u32 dpb_config;
+
+ VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
+ VIDC_HWIO_OUT(REG_666957, VIDC_1080P_INIT_CH_INST_ID);
+ if ((param->decode == VIDC_1080P_DEC_TYPE_LAST_FRAME_DATA) &&
+ ((!param->stream_buffer_addr_offset) ||
+ (!param->stream_frame_size))) {
+ VIDC_HWIO_OUT(REG_117192, 0);
+ VIDC_HWIO_OUT(REG_145068, 0);
+ VIDC_HWIO_OUT(REG_190381, 0);
+ } else {
+ VIDC_HWIO_OUT(REG_117192,
+ param->stream_buffer_addr_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT);
+ VIDC_HWIO_OUT(REG_145068,
+ param->stream_frame_size);
+ VIDC_HWIO_OUT(REG_190381,
+ param->stream_buffersize);
+ }
+ dpb_config = VIDC_SETFIELD(param->dpb_flush,
+ VIDC_1080P_SI_RG10_DPB_FLUSH_SHFT,
+ VIDC_1080P_SI_RG10_DPB_FLUSH_BMSK) |
+ VIDC_SETFIELD(param->dpb_count,
+ VIDC_1080P_SI_RG10_NUM_DPB_SHFT,
+ VIDC_1080P_SI_RG10_NUM_DPB_BMSK);
+ VIDC_HWIO_OUT(REG_921356,
+ param->descriptor_buffer_addr_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT);
+ VIDC_HWIO_OUT(REG_85655, param->descriptor_buffer_size);
+ VIDC_HWIO_OUT(REG_86830, param->release_dpb_bit_mask);
+ VIDC_HWIO_OUT(REG_889944, param->shared_mem_addr_offset);
+ VIDC_HWIO_OUT(REG_404623, dpb_config);
+ VIDC_HWIO_OUT(REG_397087, param->cmd_seq_num);
+ VIDC_HWIO_OUT(REG_666957, (u32)param->decode |
+ param->inst_id);
+}
+
+
+void vidc_1080p_decode_frame_start_ch1(
+ struct vidc_1080p_dec_frame_start_param *param)
+{
+ u32 dpb_config;
+
+ VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
+ VIDC_HWIO_OUT(REG_313350, VIDC_1080P_INIT_CH_INST_ID);
+ if ((param->decode == VIDC_1080P_DEC_TYPE_LAST_FRAME_DATA) &&
+ ((!param->stream_buffer_addr_offset) ||
+ (!param->stream_frame_size))) {
+ VIDC_HWIO_OUT(REG_980194, 0);
+ VIDC_HWIO_OUT(REG_936704, 0);
+ VIDC_HWIO_OUT(REG_887095, 0);
+ } else {
+ VIDC_HWIO_OUT(REG_980194,
+ param->stream_buffer_addr_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT);
+ VIDC_HWIO_OUT(REG_936704,
+ param->stream_frame_size);
+ VIDC_HWIO_OUT(REG_887095,
+ param->stream_buffersize);
+ }
+ dpb_config = VIDC_SETFIELD(param->dpb_flush,
+ VIDC_1080P_SI_RG10_DPB_FLUSH_SHFT,
+ VIDC_1080P_SI_RG10_DPB_FLUSH_BMSK) |
+ VIDC_SETFIELD(param->dpb_count,
+ VIDC_1080P_SI_RG10_NUM_DPB_SHFT,
+ VIDC_1080P_SI_RG10_NUM_DPB_BMSK);
+ VIDC_HWIO_OUT(REG_821977,
+ param->descriptor_buffer_addr_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT);
+ VIDC_HWIO_OUT(REG_576987, param->descriptor_buffer_size);
+ VIDC_HWIO_OUT(REG_70448, param->release_dpb_bit_mask);
+ VIDC_HWIO_OUT(REG_652528, param->shared_mem_addr_offset);
+ VIDC_HWIO_OUT(REG_220637, dpb_config);
+ VIDC_HWIO_OUT(REG_254093, param->cmd_seq_num);
+ VIDC_HWIO_OUT(REG_313350, (u32)param->decode |
+ param->inst_id);
+}
+
+void vidc_1080p_decode_init_buffers_ch0(
+ struct vidc_1080p_dec_init_buffers_param *param)
+{
+ VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
+ VIDC_HWIO_OUT(REG_666957, VIDC_1080P_INIT_CH_INST_ID);
+ VIDC_HWIO_OUT(REG_889944, param->shared_mem_addr_offset);
+ VIDC_HWIO_OUT(REG_404623, param->dpb_count);
+ VIDC_HWIO_OUT(REG_397087, param->cmd_seq_num);
+ VIDC_HWIO_OUT(REG_666957, VIDC_1080P_DEC_TYPE_INIT_BUFFERS |
+ param->inst_id);
+}
+
+void vidc_1080p_decode_init_buffers_ch1(
+ struct vidc_1080p_dec_init_buffers_param *param)
+{
+ VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
+ VIDC_HWIO_OUT(REG_313350, VIDC_1080P_INIT_CH_INST_ID);
+ VIDC_HWIO_OUT(REG_652528, param->shared_mem_addr_offset);
+ VIDC_HWIO_OUT(REG_220637, param->dpb_count);
+ VIDC_HWIO_OUT(REG_254093, param->cmd_seq_num);
+ VIDC_HWIO_OUT(REG_313350, VIDC_1080P_DEC_TYPE_INIT_BUFFERS |
+ param->inst_id);
+}
+
+void vidc_1080p_set_dec_resolution_ch0(u32 width, u32 height)
+{
+ VIDC_HWIO_OUT(REG_612810, height);
+ VIDC_HWIO_OUT(REG_175608, width);
+}
+
+void vidc_1080p_set_dec_resolution_ch1(u32 width, u32 height)
+{
+ VIDC_HWIO_OUT(REG_655721, height);
+ VIDC_HWIO_OUT(REG_548308, width);
+}
+
+void vidc_1080p_get_encode_frame_info(
+ struct vidc_1080p_enc_frame_info *frame_info)
+{
+ VIDC_HWIO_IN(REG_845544, &(frame_info->enc_frame_size));
+ VIDC_HWIO_IN(REG_859906,
+ &(frame_info->enc_picture_count));
+ VIDC_HWIO_IN(REG_490078,
+ &(frame_info->enc_write_pointer));
+ VIDC_HWIO_IN(REG_640904,
+ (u32 *)(&(frame_info->enc_frame)));
+ VIDC_HWIO_IN(REG_60114,
+ &(frame_info->enc_luma_address));
+ frame_info->enc_luma_address = frame_info->enc_luma_address <<
+ VIDC_1080P_BASE_OFFSET_SHIFT;
+ VIDC_HWIO_IN(REG_489688,
+ &(frame_info->enc_chroma_address));
+ frame_info->enc_chroma_address = frame_info->\
+ enc_chroma_address << VIDC_1080P_BASE_OFFSET_SHIFT;
+}
+
+void vidc_1080p_encode_seq_start_ch0(
+ struct vidc_1080p_enc_seq_start_param *param)
+{
+ VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
+ VIDC_HWIO_OUT(REG_666957, VIDC_1080P_INIT_CH_INST_ID);
+ VIDC_HWIO_OUT(REG_117192,
+ param->stream_buffer_addr_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT);
+ VIDC_HWIO_OUT(REG_921356, param->stream_buffer_size);
+ VIDC_HWIO_OUT(REG_889944, param->shared_mem_addr_offset);
+ VIDC_HWIO_OUT(REG_397087, param->cmd_seq_num);
+ VIDC_HWIO_OUT(REG_666957, VIDC_1080P_ENC_TYPE_SEQ_HEADER |
+ param->inst_id);
+}
+
+void vidc_1080p_encode_seq_start_ch1(
+ struct vidc_1080p_enc_seq_start_param *param)
+{
+ VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
+ VIDC_HWIO_OUT(REG_313350, VIDC_1080P_INIT_CH_INST_ID);
+ VIDC_HWIO_OUT(REG_980194,
+ param->stream_buffer_addr_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT);
+ VIDC_HWIO_OUT(REG_821977, param->stream_buffer_size);
+ VIDC_HWIO_OUT(REG_652528, param->shared_mem_addr_offset);
+ VIDC_HWIO_OUT(REG_254093, param->cmd_seq_num);
+ VIDC_HWIO_OUT(REG_313350, VIDC_1080P_ENC_TYPE_SEQ_HEADER |
+ param->inst_id);
+}
+
+void vidc_1080p_encode_frame_start_ch0(
+ struct vidc_1080p_enc_frame_start_param *param)
+{
+ VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
+ VIDC_HWIO_OUT(REG_666957, VIDC_1080P_INIT_CH_INST_ID);
+ VIDC_HWIO_OUT(REG_117192,
+ param->stream_buffer_addr_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT);
+ VIDC_HWIO_OUT(REG_921356, param->stream_buffer_size);
+ VIDC_HWIO_OUT(REG_612810, param->current_y_addr_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT);
+ VIDC_HWIO_OUT(REG_175608, param->current_c_addr_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT);
+ VIDC_HWIO_OUT(REG_190381, param->intra_frame);
+ VIDC_HWIO_OUT(REG_889944, param->shared_mem_addr_offset);
+ VIDC_HWIO_OUT(REG_404623, param->input_flush);
+ VIDC_HWIO_OUT(REG_397087, param->cmd_seq_num);
+ VIDC_HWIO_OUT(REG_666957, (u32)param->encode |
+ param->inst_id);
+}
+
+void vidc_1080p_encode_frame_start_ch1(
+ struct vidc_1080p_enc_frame_start_param *param)
+{
+
+ VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
+ VIDC_HWIO_OUT(REG_313350, VIDC_1080P_INIT_CH_INST_ID);
+ VIDC_HWIO_OUT(REG_980194,
+ param->stream_buffer_addr_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT);
+ VIDC_HWIO_OUT(REG_821977, param->stream_buffer_size);
+ VIDC_HWIO_OUT(REG_655721, param->current_y_addr_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT);
+ VIDC_HWIO_OUT(REG_548308, param->current_c_addr_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT);
+ VIDC_HWIO_OUT(REG_887095, param->intra_frame);
+ VIDC_HWIO_OUT(REG_652528, param->shared_mem_addr_offset);
+ VIDC_HWIO_OUT(REG_404623, param->input_flush);
+ VIDC_HWIO_OUT(REG_254093, param->cmd_seq_num);
+ VIDC_HWIO_OUT(REG_313350, (u32)param->encode |
+ param->inst_id);
+}
+
+void vidc_1080p_set_encode_picture(u32 number_p, u32 number_b)
+{
+ u32 picture, ifrm_ctrl;
+ if (number_p >= VIDC_1080P_MAX_INTRA_PERIOD)
+ ifrm_ctrl = 0;
+ else
+ ifrm_ctrl = number_p + 1;
+ picture = VIDC_SETFIELD(1 ,
+ HWIO_REG_783891_ENC_PIC_TYPE_USE_SHFT,
+ HWIO_REG_783891_ENC_PIC_TYPE_USE_BMSK) |
+ VIDC_SETFIELD(ifrm_ctrl,
+ HWIO_REG_783891_I_FRM_CTRL_SHFT,
+ HWIO_REG_783891_I_FRM_CTRL_BMSK)
+ | VIDC_SETFIELD(number_b ,
+ HWIO_REG_783891_B_FRM_CTRL_SHFT ,
+ HWIO_REG_783891_B_FRM_CTRL_BMSK);
+ VIDC_HWIO_OUT(REG_783891, picture);
+}
+
+void vidc_1080p_set_encode_multi_slice_control(
+ enum vidc_1080p_MSlice_selection multiple_slice_selection,
+ u32 mslice_mb, u32 mslice_byte)
+{
+ VIDC_HWIO_OUT(REG_226332, multiple_slice_selection);
+ VIDC_HWIO_OUT(REG_696136, mslice_mb);
+ VIDC_HWIO_OUT(REG_515564, mslice_byte);
+}
+
+void vidc_1080p_set_encode_circular_intra_refresh(u32 cir_num)
+{
+ VIDC_HWIO_OUT(REG_886210, cir_num);
+}
+
+void vidc_1080p_set_encode_input_frame_format(
+ enum vidc_1080p_memory_access_method memory_format)
+{
+ VIDC_HWIO_OUT(REG_645603, memory_format);
+}
+
+void vidc_1080p_set_encode_padding_control(u32 pad_ctrl_on,
+ u32 cr_pad_val, u32 cb_pad_val, u32 luma_pad_val)
+{
+ u32 padding = VIDC_SETFIELD(pad_ctrl_on ,
+ HWIO_REG_811733_PAD_CTRL_ON_SHFT,
+ HWIO_REG_811733_PAD_CTRL_ON_BMSK) |
+ VIDC_SETFIELD(cr_pad_val ,
+ HWIO_REG_811733_CR_PAD_VIDC_SHFT ,
+ HWIO_REG_811733_CR_PAD_VIDC_BMSK) |
+ VIDC_SETFIELD(cb_pad_val ,
+ HWIO_REG_811733_CB_PAD_VIDC_SHFT ,
+ HWIO_REG_811733_CB_PAD_VIDC_BMSK) |
+ VIDC_SETFIELD(luma_pad_val ,
+ HWIO_REG_811733_LUMA_PAD_VIDC_SHFT ,
+ HWIO_REG_811733_LUMA_PAD_VIDC_BMSK) ;
+ VIDC_HWIO_OUT(REG_811733, padding);
+}
+
+void vidc_1080p_encode_set_rc_config(u32 enable_frame_level_rc,
+ u32 enable_mb_level_rc_flag, u32 frame_qp)
+{
+ u32 rc_config = VIDC_SETFIELD(enable_frame_level_rc ,
+ HWIO_REG_559908_FR_RC_EN_SHFT ,
+ HWIO_REG_559908_FR_RC_EN_BMSK) |
+ VIDC_SETFIELD(enable_mb_level_rc_flag ,
+ HWIO_REG_559908_MB_RC_EN_SHFT,
+ HWIO_REG_559908_MB_RC_EN_BMSK) |
+ VIDC_SETFIELD(frame_qp ,
+ HWIO_REG_559908_FRAME_QP_SHFT ,
+ HWIO_REG_559908_FRAME_QP_BMSK);
+ VIDC_HWIO_OUT(REG_559908, rc_config);
+}
+
+void vidc_1080p_encode_set_frame_level_rc_params(u32 rc_frame_rate,
+ u32 target_bitrate, u32 reaction_coeff)
+{
+ VIDC_HWIO_OUT(REG_977937, rc_frame_rate);
+ VIDC_HWIO_OUT(REG_166135, target_bitrate);
+ VIDC_HWIO_OUT(REG_550322, reaction_coeff);
+}
+
+void vidc_1080p_encode_set_qp_params(u32 max_qp, u32 min_qp)
+{
+ u32 qbound = VIDC_SETFIELD(max_qp , HWIO_REG_109072_MAX_QP_SHFT,
+ HWIO_REG_109072_MAX_QP_BMSK) |
+ VIDC_SETFIELD(min_qp,
+ HWIO_REG_109072_MIN_QP_SHFT ,
+ HWIO_REG_109072_MIN_QP_BMSK);
+ VIDC_HWIO_OUT(REG_109072, qbound);
+}
+
+void vidc_1080p_encode_set_mb_level_rc_params(u32 disable_dark_region_as_flag,
+ u32 disable_smooth_region_as_flag , u32 disable_static_region_as_flag,
+ u32 disable_activity_region_flag)
+{
+ u32 rc_active_feature = VIDC_SETFIELD(
+ disable_dark_region_as_flag,
+ HWIO_REG_949086_DARK_DISABLE_SHFT,
+ HWIO_REG_949086_DARK_DISABLE_BMSK) |
+ VIDC_SETFIELD(
+ disable_smooth_region_as_flag,
+ HWIO_REG_949086_SMOOTH_DISABLE_SHFT,
+ HWIO_REG_949086_SMOOTH_DISABLE_BMSK) |
+ VIDC_SETFIELD(
+ disable_static_region_as_flag,
+ HWIO_REG_949086_STATIC_DISABLE_SHFT,
+ HWIO_REG_949086_STATIC_DISABLE_BMSK) |
+ VIDC_SETFIELD(
+ disable_activity_region_flag,
+ HWIO_REG_949086_ACT_DISABLE_SHFT,
+ HWIO_REG_949086_ACT_DISABLE_BMSK);
+ VIDC_HWIO_OUT(REG_949086, rc_active_feature);
+}
+
+void vidc_1080p_set_h264_encode_entropy(
+ enum vidc_1080p_entropy_sel entropy_sel)
+{
+ VIDC_HWIO_OUT(REG_447796, entropy_sel);
+}
+
+void vidc_1080p_set_h264_encode_loop_filter(
+ enum vidc_1080p_DBConfig db_config, u32 slice_alpha_offset,
+ u32 slice_beta_offset)
+{
+ VIDC_HWIO_OUT(REG_152500, db_config);
+ VIDC_HWIO_OUT(REG_266285, slice_alpha_offset);
+ VIDC_HWIO_OUT(REG_964731, slice_beta_offset);
+}
+
+void vidc_1080p_set_h264_encoder_p_frame_ref_count(u32 max_reference)
+{
+ u32 ref_frames;
+ ref_frames = VIDC_SETFIELD(max_reference,
+ HWIO_REG_744348_P_SHFT,
+ HWIO_REG_744348_P_BMSK);
+ VIDC_HWIO_OUT(REG_744348, ref_frames);
+}
+
+void vidc_1080p_set_h264_encode_8x8transform_control(u32 enable_8x8transform)
+{
+ VIDC_HWIO_OUT(REG_672163, enable_8x8transform);
+}
+
+void vidc_1080p_set_mpeg4_encode_quarter_pel_control(
+ u32 enable_mpeg4_quarter_pel)
+{
+ VIDC_HWIO_OUT(REG_330132, enable_mpeg4_quarter_pel);
+}
+
+void vidc_1080p_set_device_base_addr(u8 *mapped_va)
+{
+ VIDC_BASE_PTR = mapped_va;
+}
+
+void vidc_1080p_get_intra_bias(u32 *bias)
+{
+ u32 intra_bias;
+
+ VIDC_HWIO_IN(REG_676866, &intra_bias);
+ *bias = VIDC_GETFIELD(intra_bias,
+ HWIO_REG_676866_RMSK,
+ HWIO_REG_676866_SHFT);
+}
+
+void vidc_1080p_set_intra_bias(u32 bias)
+{
+ u32 intra_bias;
+
+ intra_bias = VIDC_SETFIELD(bias,
+ HWIO_REG_676866_SHFT,
+ HWIO_REG_676866_RMSK);
+ VIDC_HWIO_OUT(REG_676866, intra_bias);
+}
+
+void vidc_1080p_get_bi_directional_bias(u32 *bi_directional_bias)
+{
+ u32 nbi_direct_bias;
+
+ VIDC_HWIO_IN(REG_54267, &nbi_direct_bias);
+ *bi_directional_bias = VIDC_GETFIELD(nbi_direct_bias,
+ HWIO_REG_54267_RMSK,
+ HWIO_REG_54267_SHFT);
+}
+
+void vidc_1080p_set_bi_directional_bias(u32 bi_directional_bias)
+{
+ u32 nbi_direct_bias;
+
+ nbi_direct_bias = VIDC_SETFIELD(bi_directional_bias,
+ HWIO_REG_54267_SHFT,
+ HWIO_REG_54267_RMSK);
+ VIDC_HWIO_OUT(REG_54267, nbi_direct_bias);
+}
+
+void vidc_1080p_get_encoder_sequence_header_size(u32 *seq_header_size)
+{
+ VIDC_HWIO_IN(REG_845544, seq_header_size);
+}
+
+void vidc_1080p_get_intermedia_stage_debug_counter(
+ u32 *intermediate_stage_counter)
+{
+ VIDC_HWIO_IN(REG_805993, intermediate_stage_counter);
+}
+
+void vidc_1080p_get_exception_status(u32 *exception_status)
+{
+ VIDC_HWIO_IN(REG_493355, exception_status);
+}
+
+void vidc_1080p_frame_start_realloc(u32 instance_id)
+{
+ VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
+ VIDC_HWIO_OUT(REG_666957, VIDC_1080P_INIT_CH_INST_ID);
+ VIDC_HWIO_OUT(REG_666957,
+ VIDC_1080P_DEC_TYPE_FRAME_START_REALLOC | instance_id);
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc.h b/drivers/video/msm/vidc/1080p/ddl/vidc.h
new file mode 100644
index 0000000..f871509
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc.h
@@ -0,0 +1,544 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _VIDC_H_
+#define _VIDC_H_
+
+#include "vidc_hwio_reg.h"
+
+#define VIDC_1080P_RISC2HOST_CMD_EMPTY 0
+#define VIDC_1080P_RISC2HOST_CMD_OPEN_CH_RET 1
+#define VIDC_1080P_RISC2HOST_CMD_CLOSE_CH_RET 2
+#define VIDC_1080P_RISC2HOST_CMD_SEQ_DONE_RET 4
+#define VIDC_1080P_RISC2HOST_CMD_FRAME_DONE_RET 5
+#define VIDC_1080P_RISC2HOST_CMD_ENC_COMPLETE_RET 7
+#define VIDC_1080P_RISC2HOST_CMD_SYS_INIT_RET 8
+#define VIDC_1080P_RISC2HOST_CMD_FW_STATUS_RET 9
+#define VIDC_1080P_RISC2HOST_CMD_FLUSH_COMMAND_RET 12
+#define VIDC_1080P_RISC2HOST_CMD_ABORT_RET 13
+#define VIDC_1080P_RISC2HOST_CMD_INIT_BUFFERS_RET 15
+#define VIDC_1080P_RISC2HOST_CMD_EDFU_INT_RET 16
+#define VIDC_1080P_RISC2HOST_CMD_ERROR_RET 32
+
+#define VIDC_RISC2HOST_ARG2_VIDC_DISP_ERROR_STATUS_BMSK 0xffff0000
+#define VIDC_RISC2HOST_ARG2_VIDC_DISP_ERROR_STATUS_SHFT 16
+#define VIDC_RISC2HOST_ARG2_VIDC_DEC_ERROR_STATUS_BMSK 0x0000ffff
+#define VIDC_RISC2HOST_ARG2_VIDC_DEC_ERROR_STATUS_SHFT 0
+
+#define VIDC_1080P_ERROR_INVALID_CHANNEL_NUMBER 1
+#define VIDC_1080P_ERROR_INVALID_COMMAND_ID 2
+#define VIDC_1080P_ERROR_CHANNEL_ALREADY_IN_USE 3
+#define VIDC_1080P_ERROR_CHANNEL_NOT_OPEN_BEFORE_CHANNEL_CLOSE 4
+#define VIDC_1080P_ERROR_OPEN_CH_ERROR_SEQ_START 5
+#define VIDC_1080P_ERROR_SEQ_START_ALREADY_CALLED 6
+#define VIDC_1080P_ERROR_OPEN_CH_ERROR_INIT_BUFFERS 7
+#define VIDC_1080P_ERROR_SEQ_START_ERROR_INIT_BUFFERS 8
+#define VIDC_1080P_ERROR_INIT_BUFFER_ALREADY_CALLED 9
+#define VIDC_1080P_ERROR_OPEN_CH_ERROR_FRAME_START 10
+#define VIDC_1080P_ERROR_SEQ_START_ERROR_FRAME_START 11
+#define VIDC_1080P_ERROR_INIT_BUFFERS_ERROR_FRAME_START 12
+#define VIDC_1080P_ERROR_RESOLUTION_CHANGED 13
+#define VIDC_1080P_ERROR_INVALID_COMMAND_LAST_FRAME 14
+#define VIDC_1080P_ERROR_INVALID_COMMAND 15
+#define VIDC_1080P_ERROR_INVALID_CODEC_TYPE 16
+
+#define VIDC_1080P_ERROR_MEM_ALLOCATION_FAILED 20
+#define VIDC_1080P_ERROR_INSUFFICIENT_CONTEXT_SIZE 25
+#define VIDC_1080P_ERROR_UNSUPPORTED_FEATURE_IN_PROFILE 27
+#define VIDC_1080P_ERROR_RESOLUTION_NOT_SUPPORTED 28
+
+#define VIDC_1080P_ERROR_HEADER_NOT_FOUND 52
+#define VIDC_1080P_ERROR_VOS_END_CODE_RECEIVED 53
+#define VIDC_1080P_ERROR_FRAME_RATE_NOT_SUPPORTED 62
+#define VIDC_1080P_ERROR_INVALID_QP_VALUE 63
+#define VIDC_1080P_ERROR_INVALID_RC_REACTION_COEFFICIENT 64
+#define VIDC_1080P_ERROR_INVALID_CPB_SIZE_AT_GIVEN_LEVEL 65
+#define VIDC_1080P_ERROR_B_FRAME_NOT_SUPPORTED 66
+#define VIDC_1080P_ERROR_ALLOC_DPB_SIZE_NOT_SUFFICIENT 71
+#define VIDC_1080P_ERROR_NUM_DPB_OUT_OF_RANGE 74
+#define VIDC_1080P_ERROR_NULL_METADATA_INPUT_POINTER 77
+#define VIDC_1080P_ERROR_NULL_DPB_POINTER 78
+#define VIDC_1080P_ERROR_NULL_OTH_EXT_BUFADDR 79
+#define VIDC_1080P_ERROR_NULL_MV_POINTER 80
+#define VIDC_1080P_ERROR_DIVIDE_BY_ZERO 81
+#define VIDC_1080P_ERROR_BIT_STREAM_BUF_EXHAUST 82
+#define VIDC_1080P_ERROR_DESCRIPTOR_BUFFER_EMPTY 83
+#define VIDC_1080P_ERROR_DMA_TX_NOT_COMPLETE 84
+#define VIDC_1080P_ERROR_DESCRIPTOR_TABLE_ENTRY_INVALID 85
+#define VIDC_1080P_ERROR_MB_COEFF_NOT_DONE 86
+#define VIDC_1080P_ERROR_CODEC_SLICE_NOT_DONE 87
+#define VIDC_1080P_ERROR_VIDC_CORE_TIME_OUT 88
+#define VIDC_1080P_ERROR_VC1_BITPLANE_DECODE_ERR 89
+#define VIDC_1080P_ERROR_VSP_NOT_READY 90
+#define VIDC_1080P_ERROR_BUFFER_FULL_STATE 91
+
+#define VIDC_1080P_ERROR_RESOLUTION_MISMATCH 112
+#define VIDC_1080P_ERROR_NV_QUANT_ERR 113
+#define VIDC_1080P_ERROR_SYNC_MARKER_ERR 114
+#define VIDC_1080P_ERROR_FEATURE_NOT_SUPPORTED 115
+#define VIDC_1080P_ERROR_MEM_CORRUPTION 116
+#define VIDC_1080P_ERROR_INVALID_REFERENCE_FRAME 117
+#define VIDC_1080P_ERROR_PICTURE_CODING_TYPE_ERR 118
+#define VIDC_1080P_ERROR_MV_RANGE_ERR 119
+#define VIDC_1080P_ERROR_PICTURE_STRUCTURE_ERR 120
+#define VIDC_1080P_ERROR_SLICE_ADDR_INVALID 121
+#define VIDC_1080P_ERROR_NON_PAIRED_FIELD_NOT_SUPPORTED 122
+#define VIDC_1080P_ERROR_NON_FRAME_DATA_RECEIVED 123
+#define VIDC_1080P_ERROR_INCOMPLETE_FRAME 124
+#define VIDC_1080P_ERROR_NO_BUFFER_RELEASED_FROM_HOST 125
+#define VIDC_1080P_ERROR_NULL_FW_DEBUG_INFO_POINTER 126
+#define VIDC_1080P_ERROR_ALLOC_DEBUG_INFO_SIZE_INSUFFICIENT 127
+#define VIDC_1080P_ERROR_NALU_HEADER_ERROR 128
+#define VIDC_1080P_ERROR_SPS_PARSE_ERROR 129
+#define VIDC_1080P_ERROR_PPS_PARSE_ERROR 130
+#define VIDC_1080P_ERROR_SLICE_PARSE_ERROR 131
+#define VIDC_1080P_ERROR_SYNC_POINT_NOT_RECEIVED 171
+
+#define VIDC_1080P_WARN_COMMAND_FLUSHED 145
+#define VIDC_1080P_WARN_METADATA_NO_SPACE_NUM_CONCEAL_MB 150
+#define VIDC_1080P_WARN_METADATA_NO_SPACE_QP 151
+#define VIDC_1080P_WARN_METADATA_NO_SPACE_CONCEAL_MB 152
+#define VIDC_1080P_WARN_METADATA_NO_SPACE_VC1_PARAM 153
+#define VIDC_1080P_WARN_METADATA_NO_SPACE_SEI 154
+#define VIDC_1080P_WARN_METADATA_NO_SPACE_VUI 155
+#define VIDC_1080P_WARN_METADATA_NO_SPACE_EXTRA 156
+#define VIDC_1080P_WARN_METADATA_NO_SPACE_DATA_NONE 157
+#define VIDC_1080P_WARN_FRAME_RATE_UNKNOWN 158
+#define VIDC_1080P_WARN_ASPECT_RATIO_UNKNOWN 159
+#define VIDC_1080P_WARN_COLOR_PRIMARIES_UNKNOWN 160
+#define VIDC_1080P_WARN_TRANSFER_CHAR_UNKNOWN 161
+#define VIDC_1080P_WARN_MATRIX_COEFF_UNKNOWN 162
+#define VIDC_1080P_WARN_NON_SEQ_SLICE_ADDR 163
+#define VIDC_1080P_WARN_BROKEN_LINK 164
+#define VIDC_1080P_WARN_FRAME_CONCEALED 165
+#define VIDC_1080P_WARN_PROFILE_UNKNOWN 166
+#define VIDC_1080P_WARN_LEVEL_UNKNOWN 167
+#define VIDC_1080P_WARN_BIT_RATE_NOT_SUPPORTED 168
+#define VIDC_1080P_WARN_COLOR_DIFF_FORMAT_NOT_SUPPORTED 169
+#define VIDC_1080P_WARN_NULL_EXTRA_METADATA_POINTER 170
+#define VIDC_1080P_WARN_METADATA_NO_SPACE_MB_INFO 180
+#define VIDC_1080P_WARN_METADATA_NO_SPACE_SLICE_SIZE 181
+#define VIDC_1080P_WARN_RESOLUTION_WARNING 182
+
+#define VIDC_1080P_H264_ENC_TYPE_P 0
+#define VIDC_1080P_H264_ENC_TYPE_B 1
+#define VIDC_1080P_H264_ENC_TYPE_IDR 2
+#define VIDC_1080P_MP4_H263_ENC_TYPE_I 0
+#define VIDC_1080P_MP4_H263_ENC_TYPE_P 1
+#define VIDC_1080P_MP4_H263_ENC_TYPE_B 2
+
+#define VIDC_1080P_MPEG4_LEVEL0 0
+#define VIDC_1080P_MPEG4_LEVEL0b 9
+#define VIDC_1080P_MPEG4_LEVEL1 1
+#define VIDC_1080P_MPEG4_LEVEL2 2
+#define VIDC_1080P_MPEG4_LEVEL3 3
+#define VIDC_1080P_MPEG4_LEVEL3b 7
+#define VIDC_1080P_MPEG4_LEVEL4 4
+#define VIDC_1080P_MPEG4_LEVEL4a 4
+#define VIDC_1080P_MPEG4_LEVEL5 5
+#define VIDC_1080P_MPEG4_LEVEL6 6
+#define VIDC_1080P_MPEG4_LEVEL7 7
+
+#define VIDC_1080P_H264_LEVEL1 10
+#define VIDC_1080P_H264_LEVEL1b 9
+#define VIDC_1080P_H264_LEVEL1p1 11
+#define VIDC_1080P_H264_LEVEL1p2 12
+#define VIDC_1080P_H264_LEVEL1p3 13
+#define VIDC_1080P_H264_LEVEL2 20
+#define VIDC_1080P_H264_LEVEL2p1 21
+#define VIDC_1080P_H264_LEVEL2p2 22
+#define VIDC_1080P_H264_LEVEL3 30
+#define VIDC_1080P_H264_LEVEL3p1 31
+#define VIDC_1080P_H264_LEVEL3p2 32
+#define VIDC_1080P_H264_LEVEL4 40
+#define VIDC_1080P_H264_LEVEL5p1 51
+#define VIDC_1080P_H264_LEVEL_MAX VIDC_1080P_H264_LEVEL5p1
+
+#define VIDC_1080P_H263_LEVEL10 10
+#define VIDC_1080P_H263_LEVEL20 20
+#define VIDC_1080P_H263_LEVEL30 30
+#define VIDC_1080P_H263_LEVEL40 40
+#define VIDC_1080P_H263_LEVEL45 45
+#define VIDC_1080P_H263_LEVEL50 50
+#define VIDC_1080P_H263_LEVEL60 60
+#define VIDC_1080P_H263_LEVEL70 70
+
+#define VIDC_1080P_BUS_ERROR_HANDLER 0x01
+#define VIDC_1080P_ILLEVIDC_INSTRUCTION_HANDLER 0x02
+#define VIDC_1080P_TICK_HANDLER 0x04
+#define VIDC_1080P_TRAP_HANDLER 0x10
+#define VIDC_1080P_ALIGN_HANDLER 0x20
+#define VIDC_1080P_RANGE_HANDLER 0x40
+#define VIDC_1080P_DTLB_MISS_EXCEPTION_HANDLER 0x80
+#define VIDC_1080P_ITLB_MISS_EXCEPTION_HANDLER 0x100
+#define VIDC_1080P_DATA_PAGE_FAULT_EXCEPTION_HANDLER 0x200
+#define VIDC_1080P_INST_PAGE_FAULT_EXCEPTION_HANDLER 0x400
+
+enum vidc_1080p_reset{
+ VIDC_1080P_RESET_IN_SEQ_FIRST_STAGE = 0x0,
+ VIDC_1080P_RESET_IN_SEQ_SECOND_STAGE = 0x1,
+};
+enum vidc_1080p_memory_access_method{
+ VIDC_1080P_TILE_LINEAR = 0,
+ VIDC_1080P_TILE_16x16 = 2,
+ VIDC_1080P_TILE_64x32 = 3,
+ VIDC_1080P_TILE_32BIT = 0x7FFFFFFF
+};
+enum vidc_1080p_host2risc_cmd{
+ VIDC_1080P_HOST2RISC_CMD_EMPTY = 0,
+ VIDC_1080P_HOST2RISC_CMD_OPEN_CH = 1,
+ VIDC_1080P_HOST2RISC_CMD_CLOSE_CH = 2,
+ VIDC_1080P_HOST2RISC_CMD_SYS_INIT = 3,
+ VIDC_1080P_HOST2RISC_CMD_FLUSH_COMMMAND = 4,
+ VIDC_1080P_HOST2RISC_CMD_CONTINUE_ENC = 7,
+ VIDC_1080P_HOST2RISC_CMD_ABORT_ENC = 8,
+ VIDC_1080P_HOST2RISC_CMD_32BIT = 0x7FFFFFFF
+};
+enum vidc_1080p_decode_p_cache_enable{
+ VIDC_1080P_DECODE_PCACHE_ENABLE_P = 0,
+ VIDC_1080P_DECODE_PCACHE_ENABLE_B = 1,
+ VIDC_1080P_DECODE_PCACHE_ENABLE_PB = 2,
+ VIDC_1080P_DECODE_PCACHE_DISABLE = 3,
+ VIDC_1080P_DECODE_PCACHE_32BIT = 0x7FFFFFFF
+};
+enum vidc_1080p_encode_p_cache_enable{
+ VIDC_1080P_ENCODE_PCACHE_ENABLE = 0,
+ VIDC_1080P_ENCODE_PCACHE_DISABLE = 3,
+ VIDC_1080P_ENCODE_PCACHE_32BIT = 0x7FFFFFFF
+};
+enum vidc_1080p_codec{
+ VIDC_1080P_H264_DECODE = 0,
+ VIDC_1080P_VC1_DECODE = 1,
+ VIDC_1080P_MPEG4_DECODE = 2,
+ VIDC_1080P_MPEG2_DECODE = 3,
+ VIDC_1080P_H263_DECODE = 4,
+ VIDC_1080P_VC1_RCV_DECODE = 5,
+ VIDC_1080P_DIVX311_DECODE = 6,
+ VIDC_1080P_DIVX412_DECODE = 7,
+ VIDC_1080P_DIVX502_DECODE = 8,
+ VIDC_1080P_DIVX503_DECODE = 9,
+ VIDC_1080P_H264_ENCODE = 16,
+ VIDC_1080P_MPEG4_ENCODE = 17,
+ VIDC_1080P_H263_ENCODE = 18,
+ VIDC_1080P_CODEC_32BIT = 0x7FFFFFFF
+};
+enum vidc_1080p_entropy_sel{
+ VIDC_1080P_ENTROPY_SEL_CAVLC = 0,
+ VIDC_1080P_ENTROPY_SEL_CABAC = 1,
+ VIDC_1080P_ENTROPY_32BIT = 0x7FFFFFFF
+};
+enum vidc_1080p_DBConfig{
+ VIDC_1080P_DB_ALL_BLOCKING_BOUNDARY = 0,
+ VIDC_1080P_DB_DISABLE = 1,
+ VIDC_1080P_DB_SKIP_SLICE_BOUNDARY = 2,
+ VIDC_1080P_DB_32BIT = 0x7FFFFFFF
+};
+enum vidc_1080p_MSlice_selection{
+ VIDC_1080P_MSLICE_DISABLE = 0,
+ VIDC_1080P_MSLICE_BY_MB_COUNT = 1,
+ VIDC_1080P_MSLICE_BY_BYTE_COUNT = 3,
+ VIDC_1080P_MSLICE_32BIT = 0x7FFFFFFF
+};
+enum vidc_1080p_display_status{
+ VIDC_1080P_DISPLAY_STATUS_DECODE_ONLY = 0,
+ VIDC_1080P_DISPLAY_STATUS_DECODE_AND_DISPLAY = 1,
+ VIDC_1080P_DISPLAY_STATUS_DISPLAY_ONLY = 2,
+ VIDC_1080P_DISPLAY_STATUS_DPB_EMPTY = 3,
+ VIDC_1080P_DISPLAY_STATUS_NOOP = 4,
+ VIDC_1080P_DISPLAY_STATUS_32BIT = 0x7FFFFFFF
+};
+enum vidc_1080p_display_coding{
+ VIDC_1080P_DISPLAY_CODING_PROGRESSIVE_SCAN = 0,
+ VIDC_1080P_DISPLAY_CODING_INTERLACED = 1,
+ VIDC_1080P_DISPLAY_CODING_32BIT = 0x7FFFFFFF
+};
+enum vidc_1080p_decode_frame{
+ VIDC_1080P_DECODE_FRAMETYPE_NOT_CODED = 0,
+ VIDC_1080P_DECODE_FRAMETYPE_I = 1,
+ VIDC_1080P_DECODE_FRAMETYPE_P = 2,
+ VIDC_1080P_DECODE_FRAMETYPE_B = 3,
+ VIDC_1080P_DECODE_FRAMETYPE_OTHERS = 4,
+ VIDC_1080P_DECODE_FRAMETYPE_32BIT = 0x7FFFFFFF
+};
+enum vidc_1080p_encode_frame{
+ VIDC_1080P_ENCODE_FRAMETYPE_NOT_CODED = 0,
+ VIDC_1080P_ENCODE_FRAMETYPE_I = 1,
+ VIDC_1080P_ENCODE_FRAMETYPE_P = 2,
+ VIDC_1080P_ENCODE_FRAMETYPE_B = 3,
+ VIDC_1080P_ENCODE_FRAMETYPE_SKIPPED = 4,
+ VIDC_1080P_ENCODE_FRAMETYPE_OTHERS = 5,
+ VIDC_1080P_ENCODE_FRAMETYPE_32BIT = 0x7FFFFFFF
+
+};
+
+enum vidc_1080p_decode_idc_format {
+ VIDC_1080P_IDCFORMAT_MONOCHROME = 0,
+ VIDC_1080P_IDCFORMAT_420 = 1,
+ VIDC_1080P_IDCFORMAT_422 = 2,
+ VIDC_1080P_IDCFORMAT_444 = 3,
+ VIDC_1080P_IDCFORMAT_OTHERS = 4,
+ VIDC_1080P_IDCFORMAT_32BIT = 0x7FFFFFFF
+};
+
+#define VIDC_1080P_PROFILE_MPEG4_SIMPLE 0x00000000
+#define VIDC_1080P_PROFILE_MPEG4_ADV_SIMPLE 0x00000001
+
+#define VIDC_1080P_PROFILE_H264_MAIN 0x00000000
+#define VIDC_1080P_PROFILE_H264_HIGH 0x00000001
+#define VIDC_1080P_PROFILE_H264_BASELINE 0x00000002
+
+
+enum vidc_1080p_decode{
+ VIDC_1080P_DEC_TYPE_SEQ_HEADER = 0x00010000,
+ VIDC_1080P_DEC_TYPE_FRAME_DATA = 0x00020000,
+ VIDC_1080P_DEC_TYPE_LAST_FRAME_DATA = 0x00030000,
+ VIDC_1080P_DEC_TYPE_INIT_BUFFERS = 0x00040000,
+ VIDC_1080P_DEC_TYPE_FRAME_START_REALLOC = 0x00050000,
+ VIDC_1080P_DEC_TYPE_32BIT = 0x7FFFFFFF
+};
+enum vidc_1080p_encode{
+ VIDC_1080P_ENC_TYPE_SEQ_HEADER = 0x00010000,
+ VIDC_1080P_ENC_TYPE_FRAME_DATA = 0x00020000,
+ VIDC_1080P_ENC_TYPE_LAST_FRAME_DATA = 0x00030000,
+ VIDC_1080P_ENC_TYPE_32BIT = 0x7FFFFFFF
+};
+struct vidc_1080p_dec_seq_start_param{
+ u32 cmd_seq_num;
+ u32 inst_id;
+ u32 shared_mem_addr_offset;
+ u32 stream_buffer_addr_offset;
+ u32 stream_buffersize;
+ u32 stream_frame_size;
+ u32 descriptor_buffer_addr_offset;
+ u32 descriptor_buffer_size;
+};
+struct vidc_1080p_dec_frame_start_param{
+ u32 cmd_seq_num;
+ u32 inst_id;
+ u32 shared_mem_addr_offset;
+ u32 stream_buffer_addr_offset;
+ u32 stream_buffersize;
+ u32 stream_frame_size;
+ u32 descriptor_buffer_addr_offset;
+ u32 descriptor_buffer_size;
+ u32 release_dpb_bit_mask;
+ u32 dpb_count;
+ u32 dpb_flush;
+ enum vidc_1080p_decode decode;
+};
+struct vidc_1080p_dec_init_buffers_param{
+ u32 cmd_seq_num;
+ u32 inst_id;
+ u32 shared_mem_addr_offset;
+ u32 dpb_count;
+};
+struct vidc_1080p_seq_hdr_info{
+ u32 img_size_x;
+ u32 img_size_y;
+ u32 dec_frm_size;
+ u32 min_num_dpb;
+ u32 min_luma_dpb_size;
+ u32 min_chroma_dpb_size;
+ u32 profile;
+ u32 level;
+ u32 disp_progressive;
+ u32 disp_crop_exists;
+ u32 dec_progressive;
+ u32 dec_crop_exists;
+ u32 crop_right_offset;
+ u32 crop_left_offset;
+ u32 crop_bottom_offset;
+ u32 crop_top_offset;
+ u32 data_partition;
+};
+struct vidc_1080p_enc_seq_start_param{
+ u32 cmd_seq_num;
+ u32 inst_id;
+ u32 shared_mem_addr_offset;
+ u32 stream_buffer_addr_offset;
+ u32 stream_buffer_size;
+};
+struct vidc_1080p_enc_frame_start_param{
+ u32 cmd_seq_num;
+ u32 inst_id;
+ u32 shared_mem_addr_offset;
+ u32 current_y_addr_offset;
+ u32 current_c_addr_offset;
+ u32 stream_buffer_addr_offset;
+ u32 stream_buffer_size;
+ u32 intra_frame;
+ u32 input_flush;
+ enum vidc_1080p_encode encode;
+};
+struct vidc_1080p_enc_frame_info{
+ u32 enc_frame_size;
+ u32 enc_picture_count;
+ u32 enc_write_pointer;
+ u32 enc_luma_address;
+ u32 enc_chroma_address;
+ enum vidc_1080p_encode_frame enc_frame;
+ u32 meta_data_exists;
+};
+struct vidc_1080p_dec_disp_info{
+ u32 disp_resl_change;
+ u32 dec_resl_change;
+ u32 reconfig_flush_done;
+ u32 img_size_x;
+ u32 img_size_y;
+ u32 display_y_addr;
+ u32 display_c_addr;
+ u32 decode_y_addr;
+ u32 decode_c_addr;
+ u32 tag_top;
+ u32 pic_time_top;
+ u32 tag_bottom;
+ u32 pic_time_bottom;
+ u32 metadata_exists;
+ u32 disp_crop_exists;
+ u32 dec_crop_exists;
+ u32 crop_right_offset;
+ u32 crop_left_offset;
+ u32 crop_bottom_offset;
+ u32 crop_top_offset;
+ u32 input_bytes_consumed;
+ u32 input_is_interlace;
+ u32 input_frame_num;
+ enum vidc_1080p_display_status display_status;
+ enum vidc_1080p_display_status decode_status;
+ enum vidc_1080p_display_coding display_coding;
+ enum vidc_1080p_display_coding decode_coding;
+ enum vidc_1080p_decode_frame input_frame;
+};
+void vidc_1080p_do_sw_reset(enum vidc_1080p_reset init_flag);
+void vidc_1080p_release_sw_reset(void);
+void vidc_1080p_clear_interrupt(void);
+void vidc_1080p_set_host2risc_cmd(
+ enum vidc_1080p_host2risc_cmd host2risc_command,
+ u32 host2risc_arg1, u32 host2risc_arg2,
+ u32 host2risc_arg3, u32 host2risc_arg4);
+void vidc_1080p_get_risc2host_cmd(u32 *pn_risc2host_command,
+ u32 *pn_risc2host_arg1, u32 *pn_risc2host_arg2,
+ u32 *pn_risc2host_arg3, u32 *pn_risc2host_arg4);
+void vidc_1080p_get_risc2host_cmd_status(u32 err_status,
+ u32 *dec_err_status, u32 *disp_err_status);
+void vidc_1080p_clear_risc2host_cmd(void);
+void vidc_1080p_get_fw_version(u32 *pn_fw_version);
+void vidc_1080p_get_fw_status(u32 *pn_fw_status);
+void vidc_1080p_init_memory_controller(u32 dram_base_addr_a,
+ u32 dram_base_addr_b);
+void vidc_1080p_get_memory_controller_status(u32 *pb_mc_abusy,
+ u32 *pb_mc_bbusy);
+void vidc_1080p_set_h264_decode_buffers(u32 dpb, u32 dec_vert_nb_mv_offset,
+ u32 dec_nb_ip_offset, u32 *pn_dpb_luma_offset,
+ u32 *pn_dpb_chroma_offset, u32 *pn_mv_buffer_offset);
+void vidc_1080p_set_decode_recon_buffers(u32 recon_buffer, u32 *pn_dec_luma,
+ u32 *pn_dec_chroma);
+void vidc_1080p_set_mpeg4_divx_decode_work_buffers(u32 nb_dcac_buffer_offset,
+ u32 upnb_mv_buffer_offset, u32 sub_anchor_buffer_offset,
+ u32 overlay_transform_buffer_offset, u32 stx_parser_buffer_offset);
+void vidc_1080p_set_h263_decode_work_buffers(u32 nb_dcac_buffer_offset,
+ u32 upnb_mv_buffer_offset, u32 sub_anchor_buffer_offset,
+ u32 overlay_transform_buffer_offset);
+void vidc_1080p_set_vc1_decode_work_buffers(u32 nb_dcac_buffer_offset,
+ u32 upnb_mv_buffer_offset, u32 sub_anchor_buffer_offset,
+ u32 overlay_transform_buffer_offset, u32 bitplain1Buffer_offset,
+ u32 bitplain2Buffer_offset, u32 bitplain3Buffer_offset);
+void vidc_1080p_set_encode_recon_buffers(u32 recon_buffer, u32 *pn_enc_luma,
+ u32 *pn_enc_chroma);
+void vidc_1080p_set_h264_encode_work_buffers(u32 up_row_mv_buffer_offset,
+ u32 direct_colzero_flag_buffer_offset,
+ u32 upper_intra_md_buffer_offset,
+ u32 upper_intra_pred_buffer_offset, u32 nbor_infor_buffer_offset,
+ u32 mb_info_offset);
+void vidc_1080p_set_h263_encode_work_buffers(u32 up_row_mv_buffer_offset,
+ u32 up_row_inv_quanti_coeff_buffer_offset);
+void vidc_1080p_set_mpeg4_encode_work_buffers(u32 skip_flag_buffer_offset,
+ u32 up_row_inv_quanti_coeff_buffer_offset, u32 upper_mv_offset);
+void vidc_1080p_set_encode_frame_size(u32 hori_size, u32 vert_size);
+void vidc_1080p_set_encode_profile_level(u32 encode_profile, u32 enc_level);
+void vidc_1080p_set_encode_field_picture_structure(u32 enc_field_picture);
+void vidc_1080p_set_decode_mpeg4_pp_filter(u32 lf_enables);
+void vidc_1080p_set_decode_qp_save_control(u32 enable_q_pout);
+void vidc_1080p_get_returned_channel_inst_id(u32 *pn_rtn_chid);
+void vidc_1080p_clear_returned_channel_inst_id(void);
+void vidc_1080p_get_decode_seq_start_result(
+ struct vidc_1080p_seq_hdr_info *seq_hdr_info);
+void vidc_1080p_get_decoded_frame_size(u32 *pn_decoded_size);
+void vidc_1080p_get_display_frame_result(
+ struct vidc_1080p_dec_disp_info *dec_disp_info);
+void vidc_1080p_get_decode_frame(
+ enum vidc_1080p_decode_frame *pe_frame);
+void vidc_1080p_get_decode_frame_result(
+ struct vidc_1080p_dec_disp_info *dec_disp_info);
+void vidc_1080p_decode_seq_start_ch0(
+ struct vidc_1080p_dec_seq_start_param *param);
+void vidc_1080p_decode_seq_start_ch1(
+ struct vidc_1080p_dec_seq_start_param *param);
+void vidc_1080p_decode_init_buffers_ch0
+ (struct vidc_1080p_dec_init_buffers_param *param);
+void vidc_1080p_decode_init_buffers_ch1(
+ struct vidc_1080p_dec_init_buffers_param *param);
+void vidc_1080p_decode_frame_start_ch0(
+ struct vidc_1080p_dec_frame_start_param *param);
+void vidc_1080p_decode_frame_start_ch1(
+ struct vidc_1080p_dec_frame_start_param *param);
+void vidc_1080p_set_dec_resolution_ch0(u32 width, u32 height);
+void vidc_1080p_set_dec_resolution_ch1(u32 width, u32 height);
+void vidc_1080p_get_encode_frame_info(
+ struct vidc_1080p_enc_frame_info *frame_info);
+void vidc_1080p_encode_seq_start_ch0(
+ struct vidc_1080p_enc_seq_start_param *param);
+void vidc_1080p_encode_seq_start_ch1(
+ struct vidc_1080p_enc_seq_start_param *param);
+void vidc_1080p_encode_frame_start_ch0(
+ struct vidc_1080p_enc_frame_start_param *param);
+void vidc_1080p_encode_frame_start_ch1(
+ struct vidc_1080p_enc_frame_start_param *param);
+void vidc_1080p_set_encode_picture(u32 ifrm_ctrl, u32 number_b);
+void vidc_1080p_set_encode_multi_slice_control(
+ enum vidc_1080p_MSlice_selection multiple_slice_selection,
+ u32 mslice_mb, u32 mslice_byte);
+void vidc_1080p_set_encode_circular_intra_refresh(u32 cir_num);
+void vidc_1080p_set_encode_input_frame_format(
+ enum vidc_1080p_memory_access_method memory_format);
+void vidc_1080p_set_encode_padding_control(u32 pad_ctrl_on,
+ u32 cr_pad_val, u32 cb_pad_val, u32 luma_pad_val);
+void vidc_1080p_encode_set_rc_config(u32 enable_frame_level_rc,
+ u32 enable_mb_level_rc_flag, u32 frame_qp);
+void vidc_1080p_encode_set_frame_level_rc_params(u32 rc_frame_rate,
+ u32 target_bitrate, u32 reaction_coeff);
+void vidc_1080p_encode_set_qp_params(u32 max_qp, u32 min_qp);
+void vidc_1080p_encode_set_mb_level_rc_params(u32 disable_dark_region_as_flag,
+ u32 disable_smooth_region_as_flag , u32 disable_static_region_as_flag,
+ u32 disable_activity_region_flag);
+void vidc_1080p_get_qp(u32 *pn_frame_qp);
+void vidc_1080p_set_h264_encode_entropy(
+ enum vidc_1080p_entropy_sel entropy_sel);
+void vidc_1080p_set_h264_encode_loop_filter(
+ enum vidc_1080p_DBConfig db_config, u32 slice_alpha_offset,
+ u32 slice_beta_offset);
+void vidc_1080p_set_h264_encoder_p_frame_ref_count(u32 max_reference);
+void vidc_1080p_set_h264_encode_8x8transform_control(u32 enable_8x8transform);
+void vidc_1080p_set_mpeg4_encode_quarter_pel_control(
+ u32 enable_mpeg4_quarter_pel);
+void vidc_1080p_set_device_base_addr(u8 *mapped_va);
+void vidc_1080p_get_intra_bias(u32 *intra_bias);
+void vidc_1080p_set_intra_bias(u32 intra_bias);
+void vidc_1080p_get_bi_directional_bias(u32 *bi_directional_bias);
+void vidc_1080p_set_bi_directional_bias(u32 bi_directional_bias);
+void vidc_1080p_get_encoder_sequence_header_size(u32 *seq_header_size);
+void vidc_1080p_get_intermedia_stage_debug_counter(
+ u32 *intermediate_stage_counter);
+void vidc_1080p_get_exception_status(u32 *exception_status);
+void vidc_1080p_frame_start_realloc(u32 instance_id);
+#endif
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc_hwio.h b/drivers/video/msm/vidc/1080p/ddl/vidc_hwio.h
new file mode 100644
index 0000000..f63ebcd
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc_hwio.h
@@ -0,0 +1,115 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _VIDC_HWIO_H_
+#define _VIDC_HWIO_H_
+
+#include "vidc_hwio_reg.h"
+
+#ifdef VIDC_REGISTER_LOG
+#define VIDC_REG_OUT(x...) printk(KERN_DEBUG x)
+#define VIDC_REG_IN(x...) printk(KERN_DEBUG x)
+#else
+#define VIDC_REG_OUT(x...)
+#define VIDC_REG_IN(x...)
+#endif
+
+#define __inpdw(port) (*((u32 *) (port)))
+#define __outpdw(port, val) (*((u32 *) (port)) = ((u32) (val)))
+
+#define in_dword(addr) (__inpdw(addr))
+#define in_dword_masked(addr, mask) (__inpdw(addr) & (mask))
+#define out_dword(addr, val) __outpdw(addr, val)
+
+#define out_dword_masked(io, mask, val, shadow) \
+do { \
+ shadow = (shadow & (u32)(~(mask))) | ((u32)((val) & (mask))); \
+ out_dword(io, shadow); \
+} while (0)
+#define out_dword_masked_ns(io, mask, val, current_reg_content) \
+ out_dword(io, ((current_reg_content & (u32)(~(mask))) | \
+ ((u32)((val) & (mask)))))
+
+#define HWIO_IN(hwiosym) HWIO_##hwiosym##_IN
+#define HWIO_INI(hwiosym, index) HWIO_##hwiosym##_INI(index)
+#define HWIO_INM(hwiosym, mask) HWIO_##hwiosym##_INM(mask)
+#define HWIO_INF(hwiosym, field) (HWIO_INM(hwiosym, \
+ HWIO_FMSK(hwiosym, field)) >> HWIO_SHFT(hwiosym, field))
+
+#define HWIO_OUT(hwiosym, val) HWIO_##hwiosym##_OUT(val)
+#define HWIO_OUTI(hwiosym, index, val) HWIO_##hwiosym##_OUTI(index, val)
+#define HWIO_OUTM(hwiosym, mask, val) HWIO_##hwiosym##_OUTM(mask, val)
+#define HWIO_OUTF(hwiosym, field, val) HWIO_OUTM(hwiosym, \
+ HWIO_FMSK(hwiosym, field), (u32)(val) << HWIO_SHFT(hwiosym, field))
+
+#define HWIO_SHFT(hwio_regsym, hwio_fldsym) \
+ HWIO_##hwiosym##_##hwiofldsym##_SHFT
+#define HWIO_FMSK(hwio_regsym, hwio_fldsym) \
+ HWIO_##hwiosym##_##hwiofldsym##_BMSK
+
+#define VIDC_SETFIELD(val, shift, mask) \
+ (((val) << (shift)) & (mask))
+#define VIDC_GETFIELD(val, mask, shift) \
+ (((val) & (mask)) >> (shift))
+
+#define VIDC_HWIO_OUT(hwiosym, val) \
+do { \
+ VIDC_REG_OUT("\n(0x%x:"#hwiosym"=0x%x)", \
+ HWIO_##hwiosym##_ADDR - VIDC_BASE_PTR, val); \
+ mb(); \
+ HWIO_OUT(hwiosym, val); \
+} while (0)
+#define VIDC_HWIO_OUTI(hwiosym, index, val) \
+do { \
+ VIDC_REG_OUT("\n(0x%x:"#hwiosym"(%d)=0x%x)", \
+ HWIO_##hwiosym##_ADDR(index) - VIDC_BASE_PTR, index, val); \
+ mb(); \
+ HWIO_OUTI(hwiosym, index, val); \
+} while (0)
+#define VIDC_HWIO_OUTF(hwiosym, field, val) \
+do { \
+ VIDC_REG_OUT("\n(0x%x:"#hwiosym":0x%x:=0x%x)" , \
+ HWIO_##hwiosym##_ADDR - VIDC_BASE_PTR, \
+ HWIO_##hwiosym##_##field##_BMSK, val) \
+ mb(); \
+ HWIO_OUTF(hwiosym, field, val); \
+} while (0)
+#define VIDC_OUT_DWORD(addr, val) \
+do { \
+ VIDC_REG_OUT("\n(0x%x:"#addr"=0x%x)", \
+ addr - VIDC_BASE_PTR, val); \
+ mb(); \
+ out_dword(addr, val); \
+} while (0)
+#define VIDC_HWIO_IN(hwiosym, pval) \
+do { \
+ mb(); \
+ *pval = (u32) HWIO_IN(hwiosym); \
+ VIDC_REG_IN("\n(0x%x:"#hwiosym"=0x%x)", \
+ HWIO_##hwiosym##_ADDR - VIDC_BASE_PTR, *pval);\
+} while (0)
+#define VIDC_HWIO_INI(hwiosym, index, pval) \
+do { \
+ mb(); \
+ *pval = (u32) HWIO_INI(hwiosym, index); \
+ VIDC_REG_IN("(0x%x:"#hwiosym"(%d)==0x%x)", \
+ HWIO_##hwiosym##_ADDR(index) - VIDC_BASE_PTR, index, *pval); \
+} while (0)
+#define VIDC_HWIO_INF(hwiosym, mask, pval) \
+do { \
+ mb(); \
+ *pval = HWIO_INF(hwiosym, mask); \
+ VIDC_REG_IN("\n(0x%x:"#hwiosym"=0x%x)", \
+ HWIO_##hwiosym##_ADDR - VIDC_BASE_PTR, *pval); \
+} while (0)
+#endif
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc_hwio_reg.h b/drivers/video/msm/vidc/1080p/ddl/vidc_hwio_reg.h
new file mode 100644
index 0000000..819cd6c
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc_hwio_reg.h
@@ -0,0 +1,4544 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _VIDC_HWIO_REG_H_
+#define _VIDC_HWIO_REG_H_
+
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <asm/system.h>
+#include "vidc.h"
+
+extern u8 *VIDC_BASE_PTR;
+
+#define VIDC_BASE VIDC_BASE_PTR
+
+#define VIDC_BLACKBIRD_REG_BASE (VIDC_BASE + 0x00000000)
+#define VIDC_BLACKBIRD_REG_BASE_PHYS 0x04400000
+
+#define HWIO_REG_557899_ADDR (VIDC_BLACKBIRD_REG_BASE + 00000000)
+#define HWIO_REG_557899_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 00000000)
+#define HWIO_REG_557899_RMSK 0x3ff
+#define HWIO_REG_557899_SHFT 0
+#define HWIO_REG_557899_IN in_dword_masked(HWIO_REG_557899_ADDR,\
+ HWIO_REG_557899_RMSK)
+#define HWIO_REG_557899_INM(m) in_dword_masked(HWIO_REG_557899_ADDR, m)
+#define HWIO_REG_557899_OUT(v) out_dword(HWIO_REG_557899_ADDR, v)
+#define HWIO_REG_557899_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_557899_ADDR, m, v, HWIO_REG_557899_IN);
+#define HWIO_REG_557899_RSTN_RG_MPEG2_BMSK 0x200
+#define HWIO_REG_557899_RSTN_RG_MPEG2_SHFT 0x9
+#define HWIO_REG_557899_RSTN_RG_MPEG4_BMSK 0x100
+#define HWIO_REG_557899_RSTN_RG_MPEG4_SHFT 0x8
+#define HWIO_REG_557899_RSTN_RG_VC1_BMSK 0x80
+#define HWIO_REG_557899_RSTN_RG_VC1_SHFT 0x7
+#define HWIO_REG_557899_RSTN_RG_H264_BMSK 0x40
+#define HWIO_REG_557899_RSTN_RG_H264_SHFT 0x6
+#define HWIO_REG_557899_RSTN_RG_COMMON_BMSK 0x20
+#define HWIO_REG_557899_RSTN_RG_COMMON_SHFT 0x5
+#define HWIO_REG_557899_RSTN_DMX_BMSK 0x10
+#define HWIO_REG_557899_RSTN_DMX_SHFT 0x4
+#define HWIO_REG_557899_RSTN_VI_BMSK 0x8
+#define HWIO_REG_557899_RSTN_VI_SHFT 0x3
+#define HWIO_REG_557899_RSTN_VIDCCORE_BMSK 0x4
+#define HWIO_REG_557899_RSTN_VIDCCORE_SHFT 0x2
+#define HWIO_REG_557899_RSTN_MC_BMSK 0x2
+#define HWIO_REG_557899_RSTN_MC_SHFT 0x1
+#define HWIO_REG_557899_RSTN_RISC_BMSK 0x1
+#define HWIO_REG_557899_RSTN_RISC_SHFT 0
+
+#define HWIO_REG_575377_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000008)
+#define HWIO_REG_575377_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000008)
+#define HWIO_REG_575377_RMSK 0x1
+#define HWIO_REG_575377_SHFT 0
+#define HWIO_REG_575377_IN in_dword_masked(\
+ HWIO_REG_575377_ADDR, HWIO_REG_575377_RMSK)
+#define HWIO_REG_575377_INM(m) \
+ in_dword_masked(HWIO_REG_575377_ADDR, m)
+#define HWIO_REG_575377_OUT(v) \
+ out_dword(HWIO_REG_575377_ADDR, v)
+#define HWIO_REG_575377_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_575377_ADDR, m, v, HWIO_REG_575377_IN);
+#define HWIO_REG_575377_INTERRUPT_BMSK 0x1
+#define HWIO_REG_575377_INTERRUPT_SHFT 0
+
+#define HWIO_REG_611794_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000030)
+#define HWIO_REG_611794_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000030)
+#define HWIO_REG_611794_RMSK 0xffffffff
+#define HWIO_REG_611794_SHFT 0
+#define HWIO_REG_611794_IN in_dword_masked(\
+ HWIO_REG_611794_ADDR, HWIO_REG_611794_RMSK)
+#define HWIO_REG_611794_INM(m) \
+ in_dword_masked(HWIO_REG_611794_ADDR, m)
+#define HWIO_REG_611794_OUT(v) \
+ out_dword(HWIO_REG_611794_ADDR, v)
+#define HWIO_REG_611794_OUTM(m, v) \
+ out_dword_masked_ns(HWIO_REG_611794_ADDR, m, v,\
+ HWIO_REG_611794_IN);
+#define HWIO_REG_611794_HOST2RISC_COMMAND_BMSK 0xffffffff
+#define HWIO_REG_611794_HOST2RISC_COMMAND_SHFT 0
+
+#define HWIO_REG_356340_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000034)
+#define HWIO_REG_356340_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000034)
+#define HWIO_REG_356340_RMSK 0xffffffff
+#define HWIO_REG_356340_SHFT 0
+#define HWIO_REG_356340_IN in_dword_masked(\
+ HWIO_REG_356340_ADDR, HWIO_REG_356340_RMSK)
+#define HWIO_REG_356340_INM(m) \
+ in_dword_masked(HWIO_REG_356340_ADDR, m)
+#define HWIO_REG_356340_OUT(v) \
+ out_dword(HWIO_REG_356340_ADDR, v)
+#define HWIO_REG_356340_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_356340_ADDR, m, v, HWIO_REG_356340_IN);
+#define HWIO_REG_356340_HOST2RISC_ARG1_BMSK 0xffffffff
+#define HWIO_REG_356340_HOST2RISC_ARG1_SHFT 0
+
+#define HWIO_REG_899023_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000038)
+#define HWIO_REG_899023_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000038)
+#define HWIO_REG_899023_RMSK 0xffffffff
+#define HWIO_REG_899023_SHFT 0
+#define HWIO_REG_899023_IN in_dword_masked(\
+ HWIO_REG_899023_ADDR, HWIO_REG_899023_RMSK)
+#define HWIO_REG_899023_INM(m) \
+ in_dword_masked(HWIO_REG_899023_ADDR, m)
+#define HWIO_REG_899023_OUT(v) \
+ out_dword(HWIO_REG_899023_ADDR, v)
+#define HWIO_REG_899023_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_899023_ADDR, m, v, HWIO_REG_899023_IN);
+#define HWIO_REG_899023_HOST2RISC_ARG2_BMSK 0xffffffff
+#define HWIO_REG_899023_HOST2RISC_ARG2_SHFT 0
+
+#define HWIO_REG_987762_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000003c)
+#define HWIO_REG_987762_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000003c)
+#define HWIO_REG_987762_RMSK 0xffffffff
+#define HWIO_REG_987762_SHFT 0
+#define HWIO_REG_987762_IN in_dword_masked(\
+ HWIO_REG_987762_ADDR, HWIO_REG_987762_RMSK)
+#define HWIO_REG_987762_INM(m) \
+ in_dword_masked(HWIO_REG_987762_ADDR, m)
+#define HWIO_REG_987762_OUT(v) \
+ out_dword(HWIO_REG_987762_ADDR, v)
+#define HWIO_REG_987762_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_987762_ADDR, m, v, HWIO_REG_987762_IN);
+#define HWIO_REG_987762_HOST2RISC_ARG3_BMSK 0xffffffff
+#define HWIO_REG_987762_HOST2RISC_ARG3_SHFT 0
+
+#define HWIO_REG_544000_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000040)
+#define HWIO_REG_544000_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000040)
+#define HWIO_REG_544000_RMSK 0xffffffff
+#define HWIO_REG_544000_SHFT 0
+#define HWIO_REG_544000_IN in_dword_masked(\
+ HWIO_REG_544000_ADDR, HWIO_REG_544000_RMSK)
+#define HWIO_REG_544000_INM(m) \
+ in_dword_masked(HWIO_REG_544000_ADDR, m)
+#define HWIO_REG_544000_OUT(v) \
+ out_dword(HWIO_REG_544000_ADDR, v)
+#define HWIO_REG_544000_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_544000_ADDR, m, v, HWIO_REG_544000_IN);
+#define HWIO_REG_544000_HOST2RISC_ARG4_BMSK 0xffffffff
+#define HWIO_REG_544000_HOST2RISC_ARG4_SHFT 0
+
+#define HWIO_REG_695082_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000044)
+#define HWIO_REG_695082_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000044)
+#define HWIO_REG_695082_RMSK 0xffffffff
+#define HWIO_REG_695082_SHFT 0
+#define HWIO_REG_695082_IN in_dword_masked(\
+ HWIO_REG_695082_ADDR, HWIO_REG_695082_RMSK)
+#define HWIO_REG_695082_INM(m) \
+ in_dword_masked(HWIO_REG_695082_ADDR, m)
+#define HWIO_REG_695082_OUT(v) \
+ out_dword(HWIO_REG_695082_ADDR, v)
+#define HWIO_REG_695082_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_695082_ADDR, m, v, HWIO_REG_695082_IN);
+#define HWIO_REG_695082_RISC2HOST_COMMAND_BMSK 0xffffffff
+#define HWIO_REG_695082_RISC2HOST_COMMAND_SHFT 0
+
+#define HWIO_REG_156596_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000048)
+#define HWIO_REG_156596_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000048)
+#define HWIO_REG_156596_RMSK 0xffffffff
+#define HWIO_REG_156596_SHFT 0
+#define HWIO_REG_156596_IN in_dword_masked(\
+ HWIO_REG_156596_ADDR, HWIO_REG_156596_RMSK)
+#define HWIO_REG_156596_INM(m) \
+ in_dword_masked(HWIO_REG_156596_ADDR, m)
+#define HWIO_REG_156596_OUT(v) \
+ out_dword(HWIO_REG_156596_ADDR, v)
+#define HWIO_REG_156596_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_156596_ADDR, m, v, HWIO_REG_156596_IN);
+#define HWIO_REG_156596_REG_156596_BMSK 0xffffffff
+#define HWIO_REG_156596_REG_156596_SHFT 0
+
+#define HWIO_REG_222292_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000004c)
+#define HWIO_REG_222292_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000004c)
+#define HWIO_REG_222292_RMSK 0xffffffff
+#define HWIO_REG_222292_SHFT 0
+#define HWIO_REG_222292_IN in_dword_masked(\
+ HWIO_REG_222292_ADDR, HWIO_REG_222292_RMSK)
+#define HWIO_REG_222292_INM(m) \
+ in_dword_masked(HWIO_REG_222292_ADDR, m)
+#define HWIO_REG_222292_OUT(v) \
+ out_dword(HWIO_REG_222292_ADDR, v)
+#define HWIO_REG_222292_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_222292_ADDR, m, v, HWIO_REG_222292_IN);
+#define HWIO_REG_222292_REG_222292_BMSK 0xffffffff
+#define HWIO_REG_222292_REG_222292_SHFT 0
+
+#define HWIO_REG_790962_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000050)
+#define HWIO_REG_790962_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000050)
+#define HWIO_REG_790962_RMSK 0xffffffff
+#define HWIO_REG_790962_SHFT 0
+#define HWIO_REG_790962_IN in_dword_masked(\
+ HWIO_REG_790962_ADDR, HWIO_REG_790962_RMSK)
+#define HWIO_REG_790962_INM(m) \
+ in_dword_masked(HWIO_REG_790962_ADDR, m)
+#define HWIO_REG_790962_OUT(v) \
+ out_dword(HWIO_REG_790962_ADDR, v)
+#define HWIO_REG_790962_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_790962_ADDR, m, v, HWIO_REG_790962_IN);
+#define HWIO_REG_790962_REG_790962_BMSK 0xffffffff
+#define HWIO_REG_790962_REG_790962_SHFT 0
+
+#define HWIO_REG_679882_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000054)
+#define HWIO_REG_679882_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000054)
+#define HWIO_REG_679882_RMSK 0xffffffff
+#define HWIO_REG_679882_SHFT 0
+#define HWIO_REG_679882_IN in_dword_masked(\
+ HWIO_REG_679882_ADDR, HWIO_REG_679882_RMSK)
+#define HWIO_REG_679882_INM(m) \
+ in_dword_masked(HWIO_REG_679882_ADDR, m)
+#define HWIO_REG_679882_OUT(v) \
+ out_dword(HWIO_REG_679882_ADDR, v)
+#define HWIO_REG_679882_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_679882_ADDR, m, v, HWIO_REG_679882_IN);
+#define HWIO_REG_679882_REG_679882_BMSK 0xffffffff
+#define HWIO_REG_679882_REG_679882_SHFT 0
+
+#define HWIO_REG_653206_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000058)
+#define HWIO_REG_653206_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000058)
+#define HWIO_REG_653206_RMSK 0xffffff
+#define HWIO_REG_653206_SHFT 0
+#define HWIO_REG_653206_IN in_dword_masked(\
+ HWIO_REG_653206_ADDR, HWIO_REG_653206_RMSK)
+#define HWIO_REG_653206_INM(m) \
+ in_dword_masked(HWIO_REG_653206_ADDR, m)
+#define HWIO_REG_653206_YEAR_BMSK 0xff0000
+#define HWIO_REG_653206_YEAR_SHFT 0x10
+#define HWIO_REG_653206_MONTH_BMSK 0xff00
+#define HWIO_REG_653206_MONTH_SHFT 0x8
+#define HWIO_REG_653206_DAY_BMSK 0xff
+#define HWIO_REG_653206_DAY_SHFT 0
+
+#define HWIO_REG_805993_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000064)
+#define HWIO_REG_805993_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000064)
+#define HWIO_REG_805993_RMSK 0xffffffff
+#define HWIO_REG_805993_SHFT 0
+#define HWIO_REG_805993_IN in_dword_masked(\
+ HWIO_REG_805993_ADDR, HWIO_REG_805993_RMSK)
+#define HWIO_REG_805993_INM(m) \
+ in_dword_masked(HWIO_REG_805993_ADDR, m)
+#define HWIO_REG_805993_INTERMEDIATE_STAGE_COUNTER_BMSK 0xffffffff
+#define HWIO_REG_805993_INTERMEDIATE_STAGE_COUNTER_SHFT 0
+
+#define HWIO_REG_493355_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000068)
+#define HWIO_REG_493355_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000068)
+#define HWIO_REG_493355_RMSK 0xffffffff
+#define HWIO_REG_493355_SHFT 0
+#define HWIO_REG_493355_IN in_dword_masked(\
+ HWIO_REG_493355_ADDR, HWIO_REG_493355_RMSK)
+#define HWIO_REG_493355_INM(m) \
+ in_dword_masked(HWIO_REG_493355_ADDR, m)
+#define HWIO_REG_493355_EXCEPTION_STATUS_BMSK 0xffffffff
+#define HWIO_REG_493355_EXCEPTION_STATUS_SHFT 0
+
+#define HWIO_REG_350619_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000080)
+#define HWIO_REG_350619_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000080)
+#define HWIO_REG_350619_RMSK 0x1
+#define HWIO_REG_350619_SHFT 0
+#define HWIO_REG_350619_IN in_dword_masked(\
+ HWIO_REG_350619_ADDR, HWIO_REG_350619_RMSK)
+#define HWIO_REG_350619_INM(m) \
+ in_dword_masked(HWIO_REG_350619_ADDR, m)
+#define HWIO_REG_350619_FIRMWARE_STATUS_BMSK 0x1
+#define HWIO_REG_350619_FIRMWARE_STATUS_SHFT 0
+
+#define HWIO_REG_64440_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000508)
+#define HWIO_REG_64440_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000508)
+#define HWIO_REG_64440_RMSK 0xfffe0000
+#define HWIO_REG_64440_SHFT 0
+#define HWIO_REG_64440_IN in_dword_masked(\
+ HWIO_REG_64440_ADDR, HWIO_REG_64440_RMSK)
+#define HWIO_REG_64440_INM(m) \
+ in_dword_masked(HWIO_REG_64440_ADDR, m)
+#define HWIO_REG_64440_OUT(v) \
+ out_dword(HWIO_REG_64440_ADDR, v)
+#define HWIO_REG_64440_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_64440_ADDR, m, v,\
+ HWIO_REG_64440_IN);
+#define HWIO_REG_64440_MC_DRAMBASE_ADDR_BMSK 0xfffe0000
+#define HWIO_REG_64440_MC_DRAMBASE_ADDR_SHFT 0x11
+
+#define HWIO_REG_675915_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000050c)
+#define HWIO_REG_675915_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000050c)
+#define HWIO_REG_675915_RMSK 0xfffe0000
+#define HWIO_REG_675915_SHFT 0
+#define HWIO_REG_675915_IN in_dword_masked(\
+ HWIO_REG_675915_ADDR, HWIO_REG_675915_RMSK)
+#define HWIO_REG_675915_INM(m) \
+ in_dword_masked(HWIO_REG_675915_ADDR, m)
+#define HWIO_REG_675915_OUT(v) \
+ out_dword(HWIO_REG_675915_ADDR, v)
+#define HWIO_REG_675915_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_675915_ADDR, m, v,\
+ HWIO_REG_675915_IN);
+#define HWIO_REG_675915_MC_DRAMBASE_ADDR_BMSK 0xfffe0000
+#define HWIO_REG_675915_MC_DRAMBASE_ADDR_SHFT 0x11
+
+#define HWIO_REG_399911_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000510)
+#define HWIO_REG_399911_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000510)
+#define HWIO_REG_399911_RMSK 0x3
+#define HWIO_REG_399911_SHFT 0
+#define HWIO_REG_399911_IN in_dword_masked(\
+ HWIO_REG_399911_ADDR, HWIO_REG_399911_RMSK)
+#define HWIO_REG_399911_INM(m) in_dword_masked(HWIO_REG_399911_ADDR, m)
+#define HWIO_REG_399911_MC_BUSY_B_BMSK 0x2
+#define HWIO_REG_399911_MC_BUSY_B_SHFT 0x1
+#define HWIO_REG_399911_MC_BUSY_A_BMSK 0x1
+#define HWIO_REG_399911_MC_BUSY_A_SHFT 0
+
+#define HWIO_REG_515200_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000600)
+#define HWIO_REG_515200_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000600)
+#define HWIO_REG_515200_RMSK 0x1ffff
+#define HWIO_REG_515200_SHFT 0
+#define HWIO_REG_515200_IN in_dword_masked(\
+ HWIO_REG_515200_ADDR, HWIO_REG_515200_RMSK)
+#define HWIO_REG_515200_INM(m) \
+ in_dword_masked(HWIO_REG_515200_ADDR, m)
+#define HWIO_REG_515200_OUT(v) \
+ out_dword(HWIO_REG_515200_ADDR, v)
+#define HWIO_REG_515200_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_515200_ADDR, m, v,\
+ HWIO_REG_515200_IN);
+#define HWIO_REG_515200_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_515200_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_29510_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000604)
+#define HWIO_REG_29510_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000604)
+#define HWIO_REG_29510_RMSK 0x1ffff
+#define HWIO_REG_29510_SHFT 0
+#define HWIO_REG_29510_IN in_dword_masked(\
+ HWIO_REG_29510_ADDR, HWIO_REG_29510_RMSK)
+#define HWIO_REG_29510_INM(m) \
+ in_dword_masked(HWIO_REG_29510_ADDR, m)
+#define HWIO_REG_29510_OUT(v) \
+ out_dword(HWIO_REG_29510_ADDR, v)
+#define HWIO_REG_29510_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_29510_ADDR, m, v,\
+ HWIO_REG_29510_IN);
+#define HWIO_REG_29510_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_29510_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_256132_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000608)
+#define HWIO_REG_256132_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000608)
+#define HWIO_REG_256132_RMSK 0x1ffff
+#define HWIO_REG_256132_SHFT 0
+#define HWIO_REG_256132_IN in_dword_masked(\
+ HWIO_REG_256132_ADDR, HWIO_REG_256132_RMSK)
+#define HWIO_REG_256132_INM(m) \
+ in_dword_masked(HWIO_REG_256132_ADDR, m)
+#define HWIO_REG_256132_OUT(v) \
+ out_dword(HWIO_REG_256132_ADDR, v)
+#define HWIO_REG_256132_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_256132_ADDR, m, v,\
+ HWIO_REG_256132_IN);
+#define HWIO_REG_256132_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_256132_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_885152_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000060c)
+#define HWIO_REG_885152_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000060c)
+#define HWIO_REG_885152_RMSK 0x1ffff
+#define HWIO_REG_885152_SHFT 0
+#define HWIO_REG_885152_IN in_dword_masked(\
+ HWIO_REG_885152_ADDR, HWIO_REG_885152_RMSK)
+#define HWIO_REG_885152_INM(m) \
+ in_dword_masked(HWIO_REG_885152_ADDR, m)
+#define HWIO_REG_885152_OUT(v) \
+ out_dword(HWIO_REG_885152_ADDR, v)
+#define HWIO_REG_885152_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_885152_ADDR, m, v,\
+ HWIO_REG_885152_IN);
+#define HWIO_REG_885152_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_885152_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_69832_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000610)
+#define HWIO_REG_69832_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000610)
+#define HWIO_REG_69832_RMSK 0x1ffff
+#define HWIO_REG_69832_SHFT 0
+#define HWIO_REG_69832_IN in_dword_masked(\
+ HWIO_REG_69832_ADDR, HWIO_REG_69832_RMSK)
+#define HWIO_REG_69832_INM(m) \
+ in_dword_masked(HWIO_REG_69832_ADDR, m)
+#define HWIO_REG_69832_OUT(v) \
+ out_dword(HWIO_REG_69832_ADDR, v)
+#define HWIO_REG_69832_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_69832_ADDR, m, v,\
+ HWIO_REG_69832_IN);
+#define HWIO_REG_69832_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_69832_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_686205_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000614)
+#define HWIO_REG_686205_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000614)
+#define HWIO_REG_686205_RMSK 0x1ffff
+#define HWIO_REG_686205_SHFT 0
+#define HWIO_REG_686205_IN in_dword_masked(\
+ HWIO_REG_686205_ADDR, HWIO_REG_686205_RMSK)
+#define HWIO_REG_686205_INM(m) \
+ in_dword_masked(HWIO_REG_686205_ADDR, m)
+#define HWIO_REG_686205_OUT(v) \
+ out_dword(HWIO_REG_686205_ADDR, v)
+#define HWIO_REG_686205_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_686205_ADDR, m, v,\
+ HWIO_REG_686205_IN);
+#define HWIO_REG_686205_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_686205_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_728036_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000618)
+#define HWIO_REG_728036_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000618)
+#define HWIO_REG_728036_RMSK 0x1ffff
+#define HWIO_REG_728036_SHFT 0
+#define HWIO_REG_728036_IN in_dword_masked(\
+ HWIO_REG_728036_ADDR, HWIO_REG_728036_RMSK)
+#define HWIO_REG_728036_INM(m) \
+ in_dword_masked(HWIO_REG_728036_ADDR, m)
+#define HWIO_REG_728036_OUT(v) \
+ out_dword(HWIO_REG_728036_ADDR, v)
+#define HWIO_REG_728036_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_728036_ADDR, m, v,\
+ HWIO_REG_728036_IN);
+#define HWIO_REG_728036_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_728036_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_294579_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000061c)
+#define HWIO_REG_294579_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000061c)
+#define HWIO_REG_294579_RMSK 0x1ffff
+#define HWIO_REG_294579_SHFT 0
+#define HWIO_REG_294579_IN in_dword_masked(\
+ HWIO_REG_294579_ADDR, HWIO_REG_294579_RMSK)
+#define HWIO_REG_294579_INM(m) \
+ in_dword_masked(HWIO_REG_294579_ADDR, m)
+#define HWIO_REG_294579_OUT(v) \
+ out_dword(HWIO_REG_294579_ADDR, v)
+#define HWIO_REG_294579_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_294579_ADDR, m, v,\
+ HWIO_REG_294579_IN);
+#define HWIO_REG_294579_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_294579_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_61427_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000620)
+#define HWIO_REG_61427_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000620)
+#define HWIO_REG_61427_RMSK 0x1ffff
+#define HWIO_REG_61427_SHFT 0
+#define HWIO_REG_61427_IN in_dword_masked(\
+ HWIO_REG_61427_ADDR, HWIO_REG_61427_RMSK)
+#define HWIO_REG_61427_INM(m) \
+ in_dword_masked(HWIO_REG_61427_ADDR, m)
+#define HWIO_REG_61427_OUT(v) \
+ out_dword(HWIO_REG_61427_ADDR, v)
+#define HWIO_REG_61427_OUTM(m , v) out_dword_masked_ns(\
+ HWIO_REG_61427_ADDR, m, v,\
+ HWIO_REG_61427_IN);
+#define HWIO_REG_61427_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_61427_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_578196_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000624)
+#define HWIO_REG_578196_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000624)
+#define HWIO_REG_578196_RMSK 0x1ffff
+#define HWIO_REG_578196_SHFT 0
+#define HWIO_REG_578196_IN in_dword_masked(\
+ HWIO_REG_578196_ADDR, HWIO_REG_578196_RMSK)
+#define HWIO_REG_578196_INM(m) \
+ in_dword_masked(HWIO_REG_578196_ADDR, m)
+#define HWIO_REG_578196_OUT(v) \
+ out_dword(HWIO_REG_578196_ADDR, v)
+#define HWIO_REG_578196_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_578196_ADDR, m, v,\
+ HWIO_REG_578196_IN);
+#define HWIO_REG_578196_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_578196_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_408588_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000628)
+#define HWIO_REG_408588_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000628)
+#define HWIO_REG_408588_RMSK 0x1ffff
+#define HWIO_REG_408588_SHFT 0
+#define HWIO_REG_408588_IN in_dword_masked(\
+ HWIO_REG_408588_ADDR, HWIO_REG_408588_RMSK)
+#define HWIO_REG_408588_INM(m) \
+ in_dword_masked(HWIO_REG_408588_ADDR, m)
+#define HWIO_REG_408588_OUT(v) \
+ out_dword(HWIO_REG_408588_ADDR, v)
+#define HWIO_REG_408588_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_408588_ADDR, m, v,\
+ HWIO_REG_408588_IN);
+#define HWIO_REG_408588_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_408588_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_55617_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x0000062c)
+#define HWIO_REG_55617_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000062c)
+#define HWIO_REG_55617_RMSK 0x1ffff
+#define HWIO_REG_55617_SHFT 0
+#define HWIO_REG_55617_IN in_dword_masked(\
+ HWIO_REG_55617_ADDR, HWIO_REG_55617_RMSK)
+#define HWIO_REG_55617_INM(m) \
+ in_dword_masked(HWIO_REG_55617_ADDR, m)
+#define HWIO_REG_55617_OUT(v) \
+ out_dword(HWIO_REG_55617_ADDR, v)
+#define HWIO_REG_55617_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_55617_ADDR, m, v,\
+ HWIO_REG_55617_IN);
+#define HWIO_REG_55617_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_55617_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_555239_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000630)
+#define HWIO_REG_555239_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000630)
+#define HWIO_REG_555239_RMSK 0x1ffff
+#define HWIO_REG_555239_SHFT 0
+#define HWIO_REG_555239_IN in_dword_masked(\
+ HWIO_REG_555239_ADDR, HWIO_REG_555239_RMSK)
+#define HWIO_REG_555239_INM(m) \
+ in_dword_masked(HWIO_REG_555239_ADDR, m)
+#define HWIO_REG_555239_OUT(v) \
+ out_dword(HWIO_REG_555239_ADDR, v)
+#define HWIO_REG_555239_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_555239_ADDR, m, v,\
+ HWIO_REG_555239_IN);
+#define HWIO_REG_555239_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_555239_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_515333_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000634)
+#define HWIO_REG_515333_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000634)
+#define HWIO_REG_515333_RMSK 0x1ffff
+#define HWIO_REG_515333_SHFT 0
+#define HWIO_REG_515333_IN in_dword_masked(\
+ HWIO_REG_515333_ADDR, HWIO_REG_515333_RMSK)
+#define HWIO_REG_515333_INM(m) \
+ in_dword_masked(HWIO_REG_515333_ADDR, m)
+#define HWIO_REG_515333_OUT(v) \
+ out_dword(HWIO_REG_515333_ADDR, v)
+#define HWIO_REG_515333_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_515333_ADDR, m, v,\
+ HWIO_REG_515333_IN);
+#define HWIO_REG_515333_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_515333_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_951675_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000638)
+#define HWIO_REG_951675_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000638)
+#define HWIO_REG_951675_RMSK 0x1ffff
+#define HWIO_REG_951675_SHFT 0
+#define HWIO_REG_951675_IN in_dword_masked(\
+ HWIO_REG_951675_ADDR, HWIO_REG_951675_RMSK)
+#define HWIO_REG_951675_INM(m) \
+ in_dword_masked(HWIO_REG_951675_ADDR, m)
+#define HWIO_REG_951675_OUT(v) \
+ out_dword(HWIO_REG_951675_ADDR, v)
+#define HWIO_REG_951675_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_951675_ADDR, m, v,\
+ HWIO_REG_951675_IN);
+#define HWIO_REG_951675_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_951675_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_500775_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x0000063c)
+#define HWIO_REG_500775_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000063c)
+#define HWIO_REG_500775_RMSK 0x1ffff
+#define HWIO_REG_500775_SHFT 0
+#define HWIO_REG_500775_IN in_dword_masked(\
+ HWIO_REG_500775_ADDR, HWIO_REG_500775_RMSK)
+#define HWIO_REG_500775_INM(m) \
+ in_dword_masked(HWIO_REG_500775_ADDR, m)
+#define HWIO_REG_500775_OUT(v) \
+ out_dword(HWIO_REG_500775_ADDR, v)
+#define HWIO_REG_500775_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_500775_ADDR, m, v,\
+ HWIO_REG_500775_IN);
+#define HWIO_REG_500775_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_500775_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_649786_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000640)
+#define HWIO_REG_649786_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000640)
+#define HWIO_REG_649786_RMSK 0x1ffff
+#define HWIO_REG_649786_SHFT 0
+#define HWIO_REG_649786_IN in_dword_masked(\
+ HWIO_REG_649786_ADDR, HWIO_REG_649786_RMSK)
+#define HWIO_REG_649786_INM(m) \
+ in_dword_masked(HWIO_REG_649786_ADDR, m)
+#define HWIO_REG_649786_OUT(v) \
+ out_dword(HWIO_REG_649786_ADDR, v)
+#define HWIO_REG_649786_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_649786_ADDR, m, v,\
+ HWIO_REG_649786_IN);
+#define HWIO_REG_649786_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_649786_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_233366_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000644)
+#define HWIO_REG_233366_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000644)
+#define HWIO_REG_233366_RMSK 0x1ffff
+#define HWIO_REG_233366_SHFT 0
+#define HWIO_REG_233366_IN in_dword_masked(\
+ HWIO_REG_233366_ADDR, HWIO_REG_233366_RMSK)
+#define HWIO_REG_233366_INM(m) \
+ in_dword_masked(HWIO_REG_233366_ADDR, m)
+#define HWIO_REG_233366_OUT(v) \
+ out_dword(HWIO_REG_233366_ADDR, v)
+#define HWIO_REG_233366_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_233366_ADDR, m, v,\
+ HWIO_REG_233366_IN);
+#define HWIO_REG_233366_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_233366_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_366750_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000648)
+#define HWIO_REG_366750_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000648)
+#define HWIO_REG_366750_RMSK 0x1ffff
+#define HWIO_REG_366750_SHFT 0
+#define HWIO_REG_366750_IN in_dword_masked(\
+ HWIO_REG_366750_ADDR, HWIO_REG_366750_RMSK)
+#define HWIO_REG_366750_INM(m) \
+ in_dword_masked(HWIO_REG_366750_ADDR, m)
+#define HWIO_REG_366750_OUT(v) \
+ out_dword(HWIO_REG_366750_ADDR, v)
+#define HWIO_REG_366750_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_366750_ADDR, m, v,\
+ HWIO_REG_366750_IN);
+#define HWIO_REG_366750_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_366750_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_616292_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x0000064c)
+#define HWIO_REG_616292_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000064c)
+#define HWIO_REG_616292_RMSK 0x1ffff
+#define HWIO_REG_616292_SHFT 0
+#define HWIO_REG_616292_IN in_dword_masked(\
+ HWIO_REG_616292_ADDR, HWIO_REG_616292_RMSK)
+#define HWIO_REG_616292_INM(m) \
+ in_dword_masked(HWIO_REG_616292_ADDR, m)
+#define HWIO_REG_616292_OUT(v) \
+ out_dword(HWIO_REG_616292_ADDR, v)
+#define HWIO_REG_616292_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_616292_ADDR, m, v,\
+ HWIO_REG_616292_IN);
+#define HWIO_REG_616292_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_616292_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_666754_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000650)
+#define HWIO_REG_666754_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000650)
+#define HWIO_REG_666754_RMSK 0x1ffff
+#define HWIO_REG_666754_SHFT 0
+#define HWIO_REG_666754_IN in_dword_masked(\
+ HWIO_REG_666754_ADDR, HWIO_REG_666754_RMSK)
+#define HWIO_REG_666754_INM(m) \
+ in_dword_masked(HWIO_REG_666754_ADDR, m)
+#define HWIO_REG_666754_OUT(v) \
+ out_dword(HWIO_REG_666754_ADDR, v)
+#define HWIO_REG_666754_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_666754_ADDR, m, v,\
+ HWIO_REG_666754_IN);
+#define HWIO_REG_666754_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_666754_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_650155_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000654)
+#define HWIO_REG_650155_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000654)
+#define HWIO_REG_650155_RMSK 0x1ffff
+#define HWIO_REG_650155_SHFT 0
+#define HWIO_REG_650155_IN in_dword_masked(\
+ HWIO_REG_650155_ADDR, HWIO_REG_650155_RMSK)
+#define HWIO_REG_650155_INM(m) \
+ in_dword_masked(HWIO_REG_650155_ADDR, m)
+#define HWIO_REG_650155_OUT(v) \
+ out_dword(HWIO_REG_650155_ADDR, v)
+#define HWIO_REG_650155_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_650155_ADDR, m, v,\
+ HWIO_REG_650155_IN);
+#define HWIO_REG_650155_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_650155_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_248198_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000658)
+#define HWIO_REG_248198_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000658)
+#define HWIO_REG_248198_RMSK 0x1ffff
+#define HWIO_REG_248198_SHFT 0
+#define HWIO_REG_248198_IN in_dword_masked(\
+ HWIO_REG_248198_ADDR, HWIO_REG_248198_RMSK)
+#define HWIO_REG_248198_INM(m) \
+ in_dword_masked(HWIO_REG_248198_ADDR, m)
+#define HWIO_REG_248198_OUT(v) \
+ out_dword(HWIO_REG_248198_ADDR, v)
+#define HWIO_REG_248198_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_248198_ADDR, m, v,\
+ HWIO_REG_248198_IN);
+#define HWIO_REG_248198_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_248198_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_389428_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x0000065c)
+#define HWIO_REG_389428_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000065c)
+#define HWIO_REG_389428_RMSK 0x1ffff
+#define HWIO_REG_389428_SHFT 0
+#define HWIO_REG_389428_IN in_dword_masked(\
+ HWIO_REG_389428_ADDR, HWIO_REG_389428_RMSK)
+#define HWIO_REG_389428_INM(m) \
+ in_dword_masked(HWIO_REG_389428_ADDR, m)
+#define HWIO_REG_389428_OUT(v) \
+ out_dword(HWIO_REG_389428_ADDR, v)
+#define HWIO_REG_389428_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_389428_ADDR, m, v,\
+ HWIO_REG_389428_IN);
+#define HWIO_REG_389428_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_389428_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_504308_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000660)
+#define HWIO_REG_504308_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000660)
+#define HWIO_REG_504308_RMSK 0x1ffff
+#define HWIO_REG_504308_SHFT 0
+#define HWIO_REG_504308_IN in_dword_masked(\
+ HWIO_REG_504308_ADDR, HWIO_REG_504308_RMSK)
+#define HWIO_REG_504308_INM(m) \
+ in_dword_masked(HWIO_REG_504308_ADDR, m)
+#define HWIO_REG_504308_OUT(v) \
+ out_dword(HWIO_REG_504308_ADDR, v)
+#define HWIO_REG_504308_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_504308_ADDR, m, v,\
+ HWIO_REG_504308_IN);
+#define HWIO_REG_504308_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_504308_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_280814_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000664)
+#define HWIO_REG_280814_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000664)
+#define HWIO_REG_280814_RMSK 0x1ffff
+#define HWIO_REG_280814_SHFT 0
+#define HWIO_REG_280814_IN in_dword_masked(\
+ HWIO_REG_280814_ADDR, HWIO_REG_280814_RMSK)
+#define HWIO_REG_280814_INM(m) \
+ in_dword_masked(HWIO_REG_280814_ADDR, m)
+#define HWIO_REG_280814_OUT(v) \
+ out_dword(HWIO_REG_280814_ADDR, v)
+#define HWIO_REG_280814_OUTM(m, v) \
+ out_dword_masked_ns(HWIO_REG_280814_ADDR, m, v,\
+ HWIO_REG_280814_IN);
+#define HWIO_REG_280814_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_280814_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_785484_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000668)
+#define HWIO_REG_785484_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000668)
+#define HWIO_REG_785484_RMSK 0x1ffff
+#define HWIO_REG_785484_SHFT 0
+#define HWIO_REG_785484_IN in_dword_masked(\
+ HWIO_REG_785484_ADDR, HWIO_REG_785484_RMSK)
+#define HWIO_REG_785484_INM(m) \
+ in_dword_masked(HWIO_REG_785484_ADDR, m)
+#define HWIO_REG_785484_OUT(v) \
+ out_dword(HWIO_REG_785484_ADDR, v)
+#define HWIO_REG_785484_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_785484_ADDR, m, v,\
+ HWIO_REG_785484_IN);
+#define HWIO_REG_785484_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_785484_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_218455_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x0000066c)
+#define HWIO_REG_218455_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000066c)
+#define HWIO_REG_218455_RMSK 0x1ffff
+#define HWIO_REG_218455_SHFT 0
+#define HWIO_REG_218455_IN in_dword_masked(\
+ HWIO_REG_218455_ADDR, HWIO_REG_218455_RMSK)
+#define HWIO_REG_218455_INM(m) \
+ in_dword_masked(HWIO_REG_218455_ADDR, m)
+#define HWIO_REG_218455_OUT(v) \
+ out_dword(HWIO_REG_218455_ADDR, v)
+#define HWIO_REG_218455_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_218455_ADDR, m, v,\
+ HWIO_REG_218455_IN);
+#define HWIO_REG_218455_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_218455_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_886591_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000670)
+#define HWIO_REG_886591_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000670)
+#define HWIO_REG_886591_RMSK 0x1ffff
+#define HWIO_REG_886591_SHFT 0
+#define HWIO_REG_886591_IN in_dword_masked(\
+ HWIO_REG_886591_ADDR, HWIO_REG_886591_RMSK)
+#define HWIO_REG_886591_INM(m) \
+ in_dword_masked(HWIO_REG_886591_ADDR, m)
+#define HWIO_REG_886591_OUT(v) \
+ out_dword(HWIO_REG_886591_ADDR, v)
+#define HWIO_REG_886591_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_886591_ADDR, m, v,\
+ HWIO_REG_886591_IN);
+#define HWIO_REG_886591_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_886591_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_912449_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000674)
+#define HWIO_REG_912449_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000674)
+#define HWIO_REG_912449_RMSK 0x1ffff
+#define HWIO_REG_912449_SHFT 0
+#define HWIO_REG_912449_IN in_dword_masked(\
+ HWIO_REG_912449_ADDR, HWIO_REG_912449_RMSK)
+#define HWIO_REG_912449_INM(m) \
+ in_dword_masked(HWIO_REG_912449_ADDR, m)
+#define HWIO_REG_912449_OUT(v) \
+ out_dword(HWIO_REG_912449_ADDR, v)
+#define HWIO_REG_912449_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_912449_ADDR, m, v,\
+ HWIO_REG_912449_IN);
+#define HWIO_REG_912449_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_912449_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_1065_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000678)
+#define HWIO_REG_1065_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000678)
+#define HWIO_REG_1065_RMSK 0x1ffff
+#define HWIO_REG_1065_SHFT 0
+#define HWIO_REG_1065_IN in_dword_masked(\
+ HWIO_REG_1065_ADDR, HWIO_REG_1065_RMSK)
+#define HWIO_REG_1065_INM(m) \
+ in_dword_masked(HWIO_REG_1065_ADDR, m)
+#define HWIO_REG_1065_OUT(v) \
+ out_dword(HWIO_REG_1065_ADDR, v)
+#define HWIO_REG_1065_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_1065_ADDR, m, v,\
+ HWIO_REG_1065_IN);
+#define HWIO_REG_1065_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_1065_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_61838_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x0000067c)
+#define HWIO_REG_61838_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000067c)
+#define HWIO_REG_61838_RMSK 0x1ffff
+#define HWIO_REG_61838_SHFT 0
+#define HWIO_REG_61838_IN in_dword_masked(\
+ HWIO_REG_61838_ADDR, HWIO_REG_61838_RMSK)
+#define HWIO_REG_61838_INM(m) \
+ in_dword_masked(HWIO_REG_61838_ADDR, m)
+#define HWIO_REG_61838_OUT(v) \
+ out_dword(HWIO_REG_61838_ADDR, v)
+#define HWIO_REG_61838_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_61838_ADDR, m, v,\
+ HWIO_REG_61838_IN);
+#define HWIO_REG_61838_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_61838_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_169838_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000680)
+#define HWIO_REG_169838_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000680)
+#define HWIO_REG_169838_RMSK 0x1ffff
+#define HWIO_REG_169838_SHFT 0
+#define HWIO_REG_169838_IN in_dword_masked(\
+ HWIO_REG_169838_ADDR, HWIO_REG_169838_RMSK)
+#define HWIO_REG_169838_INM(m) \
+ in_dword_masked(HWIO_REG_169838_ADDR, m)
+#define HWIO_REG_169838_OUT(v) \
+ out_dword(HWIO_REG_169838_ADDR, v)
+#define HWIO_REG_169838_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_169838_ADDR, m, v,\
+ HWIO_REG_169838_IN);
+#define HWIO_REG_169838_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_169838_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_986147_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000684)
+#define HWIO_REG_986147_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000684)
+#define HWIO_REG_986147_RMSK 0x1ffff
+#define HWIO_REG_986147_SHFT 0
+#define HWIO_REG_986147_IN in_dword_masked(\
+ HWIO_REG_986147_ADDR, HWIO_REG_986147_RMSK)
+#define HWIO_REG_986147_INM(m) \
+ in_dword_masked(HWIO_REG_986147_ADDR, m)
+#define HWIO_REG_986147_OUT(v) \
+ out_dword(HWIO_REG_986147_ADDR, v)
+#define HWIO_REG_986147_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_986147_ADDR, m, v,\
+ HWIO_REG_986147_IN);
+#define HWIO_REG_986147_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_986147_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_678637_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000688)
+#define HWIO_REG_678637_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000688)
+#define HWIO_REG_678637_RMSK 0x1ffff
+#define HWIO_REG_678637_SHFT 0
+#define HWIO_REG_678637_IN in_dword_masked(\
+ HWIO_REG_678637_ADDR, HWIO_REG_678637_RMSK)
+#define HWIO_REG_678637_INM(m) \
+ in_dword_masked(HWIO_REG_678637_ADDR, m)
+#define HWIO_REG_678637_OUT(v) \
+ out_dword(HWIO_REG_678637_ADDR, v)
+#define HWIO_REG_678637_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_678637_ADDR, m, v,\
+ HWIO_REG_678637_IN);
+#define HWIO_REG_678637_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_678637_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_931311_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x0000068c)
+#define HWIO_REG_931311_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000068c)
+#define HWIO_REG_931311_RMSK 0x1ffff
+#define HWIO_REG_931311_SHFT 0
+#define HWIO_REG_931311_IN in_dword_masked(\
+ HWIO_REG_931311_ADDR, HWIO_REG_931311_RMSK)
+#define HWIO_REG_931311_INM(m) \
+ in_dword_masked(HWIO_REG_931311_ADDR, m)
+#define HWIO_REG_931311_OUT(v) \
+ out_dword(HWIO_REG_931311_ADDR, v)
+#define HWIO_REG_931311_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_931311_ADDR, m, v,\
+ HWIO_REG_931311_IN);
+#define HWIO_REG_931311_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_931311_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_16277_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000690)
+#define HWIO_REG_16277_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000690)
+#define HWIO_REG_16277_RMSK 0x1ffff
+#define HWIO_REG_16277_SHFT 0
+#define HWIO_REG_16277_IN in_dword_masked(\
+ HWIO_REG_16277_ADDR, HWIO_REG_16277_RMSK)
+#define HWIO_REG_16277_INM(m) \
+ in_dword_masked(HWIO_REG_16277_ADDR, m)
+#define HWIO_REG_16277_OUT(v) \
+ out_dword(HWIO_REG_16277_ADDR, v)
+#define HWIO_REG_16277_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_16277_ADDR, m, v,\
+ HWIO_REG_16277_IN);
+#define HWIO_REG_16277_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_16277_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_654169_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000694)
+#define HWIO_REG_654169_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000694)
+#define HWIO_REG_654169_RMSK 0x1ffff
+#define HWIO_REG_654169_SHFT 0
+#define HWIO_REG_654169_IN in_dword_masked(\
+ HWIO_REG_654169_ADDR, HWIO_REG_654169_RMSK)
+#define HWIO_REG_654169_INM(m) \
+ in_dword_masked(HWIO_REG_654169_ADDR, m)
+#define HWIO_REG_654169_OUT(v) \
+ out_dword(HWIO_REG_654169_ADDR, v)
+#define HWIO_REG_654169_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_654169_ADDR, m, v,\
+ HWIO_REG_654169_IN);
+#define HWIO_REG_654169_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_654169_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_802794_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000698)
+#define HWIO_REG_802794_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000698)
+#define HWIO_REG_802794_RMSK 0x1ffff
+#define HWIO_REG_802794_SHFT 0
+#define HWIO_REG_802794_IN in_dword_masked(\
+ HWIO_REG_802794_ADDR, HWIO_REG_802794_RMSK)
+#define HWIO_REG_802794_INM(m) \
+ in_dword_masked(HWIO_REG_802794_ADDR, m)
+#define HWIO_REG_802794_OUT(v) \
+ out_dword(HWIO_REG_802794_ADDR, v)
+#define HWIO_REG_802794_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_802794_ADDR, m, v,\
+ HWIO_REG_802794_IN);
+#define HWIO_REG_802794_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_802794_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_724376_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x0000069c)
+#define HWIO_REG_724376_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000069c)
+#define HWIO_REG_724376_RMSK 0x1ffff
+#define HWIO_REG_724376_SHFT 0
+#define HWIO_REG_724376_IN in_dword_masked(\
+ HWIO_REG_724376_ADDR, HWIO_REG_724376_RMSK)
+#define HWIO_REG_724376_INM(m) \
+ in_dword_masked(HWIO_REG_724376_ADDR, m)
+#define HWIO_REG_724376_OUT(v) \
+ out_dword(HWIO_REG_724376_ADDR, v)
+#define HWIO_REG_724376_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_724376_ADDR, m, v,\
+ HWIO_REG_724376_IN);
+#define HWIO_REG_724376_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_724376_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_551674_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006a0)
+#define HWIO_REG_551674_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006a0)
+#define HWIO_REG_551674_RMSK 0x1ffff
+#define HWIO_REG_551674_SHFT 0
+#define HWIO_REG_551674_IN in_dword_masked(\
+ HWIO_REG_551674_ADDR, HWIO_REG_551674_RMSK)
+#define HWIO_REG_551674_INM(m) \
+ in_dword_masked(HWIO_REG_551674_ADDR, m)
+#define HWIO_REG_551674_OUT(v) \
+ out_dword(HWIO_REG_551674_ADDR, v)
+#define HWIO_REG_551674_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_551674_ADDR, m, v,\
+ HWIO_REG_551674_IN);
+#define HWIO_REG_551674_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_551674_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_115991_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006a4)
+#define HWIO_REG_115991_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006a4)
+#define HWIO_REG_115991_RMSK 0x1ffff
+#define HWIO_REG_115991_SHFT 0
+#define HWIO_REG_115991_IN in_dword_masked(\
+ HWIO_REG_115991_ADDR, HWIO_REG_115991_RMSK)
+#define HWIO_REG_115991_INM(m) \
+ in_dword_masked(HWIO_REG_115991_ADDR, m)
+#define HWIO_REG_115991_OUT(v) \
+ out_dword(HWIO_REG_115991_ADDR, v)
+#define HWIO_REG_115991_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_115991_ADDR, m, v,\
+ HWIO_REG_115991_IN);
+#define HWIO_REG_115991_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_115991_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_252167_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006a8)
+#define HWIO_REG_252167_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006a8)
+#define HWIO_REG_252167_RMSK 0x1ffff
+#define HWIO_REG_252167_SHFT 0
+#define HWIO_REG_252167_IN in_dword_masked(\
+ HWIO_REG_252167_ADDR, HWIO_REG_252167_RMSK)
+#define HWIO_REG_252167_INM(m) \
+ in_dword_masked(HWIO_REG_252167_ADDR, m)
+#define HWIO_REG_252167_OUT(v) \
+ out_dword(HWIO_REG_252167_ADDR, v)
+#define HWIO_REG_252167_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_252167_ADDR, m, v,\
+ HWIO_REG_252167_IN);
+#define HWIO_REG_252167_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_252167_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_695516_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006ac)
+#define HWIO_REG_695516_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006ac)
+#define HWIO_REG_695516_RMSK 0x1ffff
+#define HWIO_REG_695516_SHFT 0
+#define HWIO_REG_695516_IN in_dword_masked(\
+ HWIO_REG_695516_ADDR, HWIO_REG_695516_RMSK)
+#define HWIO_REG_695516_INM(m) \
+ in_dword_masked(HWIO_REG_695516_ADDR, m)
+#define HWIO_REG_695516_OUT(v) \
+ out_dword(HWIO_REG_695516_ADDR, v)
+#define HWIO_REG_695516_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_695516_ADDR, m, v,\
+ HWIO_REG_695516_IN);
+#define HWIO_REG_695516_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_695516_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_152193_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006b0)
+#define HWIO_REG_152193_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006b0)
+#define HWIO_REG_152193_RMSK 0x1ffff
+#define HWIO_REG_152193_SHFT 0
+#define HWIO_REG_152193_IN in_dword_masked(\
+ HWIO_REG_152193_ADDR, HWIO_REG_152193_RMSK)
+#define HWIO_REG_152193_INM(m) \
+ in_dword_masked(HWIO_REG_152193_ADDR, m)
+#define HWIO_REG_152193_OUT(v) \
+ out_dword(HWIO_REG_152193_ADDR, v)
+#define HWIO_REG_152193_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_152193_ADDR, m, v,\
+ HWIO_REG_152193_IN);
+#define HWIO_REG_152193_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_152193_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_358705_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006b4)
+#define HWIO_REG_358705_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006b4)
+#define HWIO_REG_358705_RMSK 0x1ffff
+#define HWIO_REG_358705_SHFT 0
+#define HWIO_REG_358705_IN in_dword_masked(\
+ HWIO_REG_358705_ADDR, HWIO_REG_358705_RMSK)
+#define HWIO_REG_358705_INM(m) \
+ in_dword_masked(HWIO_REG_358705_ADDR, m)
+#define HWIO_REG_358705_OUT(v) \
+ out_dword(HWIO_REG_358705_ADDR, v)
+#define HWIO_REG_358705_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_358705_ADDR, m, v,\
+ HWIO_REG_358705_IN);
+#define HWIO_REG_358705_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_358705_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_457068_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006b8)
+#define HWIO_REG_457068_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006b8)
+#define HWIO_REG_457068_RMSK 0x1ffff
+#define HWIO_REG_457068_SHFT 0
+#define HWIO_REG_457068_IN in_dword_masked(\
+ HWIO_REG_457068_ADDR, HWIO_REG_457068_RMSK)
+#define HWIO_REG_457068_INM(m) \
+ in_dword_masked(HWIO_REG_457068_ADDR, m)
+#define HWIO_REG_457068_OUT(v) \
+ out_dword(HWIO_REG_457068_ADDR, v)
+#define HWIO_REG_457068_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_457068_ADDR, m, v,\
+ HWIO_REG_457068_IN);
+#define HWIO_REG_457068_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_457068_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_485412_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006bc)
+#define HWIO_REG_485412_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006bc)
+#define HWIO_REG_485412_RMSK 0x1ffff
+#define HWIO_REG_485412_SHFT 0
+#define HWIO_REG_485412_IN in_dword_masked(\
+ HWIO_REG_485412_ADDR, HWIO_REG_485412_RMSK)
+#define HWIO_REG_485412_INM(m) \
+ in_dword_masked(HWIO_REG_485412_ADDR, m)
+#define HWIO_REG_485412_OUT(v) \
+ out_dword(HWIO_REG_485412_ADDR, v)
+#define HWIO_REG_485412_OUTM(m, v) \
+ out_dword_masked_ns(HWIO_REG_485412_ADDR, m, v,\
+ HWIO_REG_485412_IN);
+#define HWIO_REG_485412_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_485412_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_223131_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006c0)
+#define HWIO_REG_223131_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006c0)
+#define HWIO_REG_223131_RMSK 0x1ffff
+#define HWIO_REG_223131_SHFT 0
+#define HWIO_REG_223131_IN in_dword_masked(\
+ HWIO_REG_223131_ADDR, HWIO_REG_223131_RMSK)
+#define HWIO_REG_223131_INM(m) \
+ in_dword_masked(HWIO_REG_223131_ADDR, m)
+#define HWIO_REG_223131_OUT(v) \
+ out_dword(HWIO_REG_223131_ADDR, v)
+#define HWIO_REG_223131_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_223131_ADDR, m, v,\
+ HWIO_REG_223131_IN);
+#define HWIO_REG_223131_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_223131_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_683737_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006c4)
+#define HWIO_REG_683737_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006c4)
+#define HWIO_REG_683737_RMSK 0x1ffff
+#define HWIO_REG_683737_SHFT 0
+#define HWIO_REG_683737_IN in_dword_masked(\
+ HWIO_REG_683737_ADDR, HWIO_REG_683737_RMSK)
+#define HWIO_REG_683737_INM(m) \
+ in_dword_masked(HWIO_REG_683737_ADDR, m)
+#define HWIO_REG_683737_OUT(v) \
+ out_dword(HWIO_REG_683737_ADDR, v)
+#define HWIO_REG_683737_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_683737_ADDR, m, v,\
+ HWIO_REG_683737_IN);
+#define HWIO_REG_683737_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_683737_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_750474_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006c8)
+#define HWIO_REG_750474_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006c8)
+#define HWIO_REG_750474_RMSK 0x1ffff
+#define HWIO_REG_750474_SHFT 0
+#define HWIO_REG_750474_IN in_dword_masked(\
+ HWIO_REG_750474_ADDR, HWIO_REG_750474_RMSK)
+#define HWIO_REG_750474_INM(m) \
+ in_dword_masked(HWIO_REG_750474_ADDR, m)
+#define HWIO_REG_750474_OUT(v) \
+ out_dword(HWIO_REG_750474_ADDR, v)
+#define HWIO_REG_750474_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_750474_ADDR, m, v,\
+ HWIO_REG_750474_IN);
+#define HWIO_REG_750474_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_750474_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_170086_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006cc)
+#define HWIO_REG_170086_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006cc)
+#define HWIO_REG_170086_RMSK 0x1ffff
+#define HWIO_REG_170086_SHFT 0
+#define HWIO_REG_170086_IN in_dword_masked(\
+ HWIO_REG_170086_ADDR, HWIO_REG_170086_RMSK)
+#define HWIO_REG_170086_INM(m) \
+ in_dword_masked(HWIO_REG_170086_ADDR, m)
+#define HWIO_REG_170086_OUT(v) \
+ out_dword(HWIO_REG_170086_ADDR, v)
+#define HWIO_REG_170086_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_170086_ADDR, m, v,\
+ HWIO_REG_170086_IN);
+#define HWIO_REG_170086_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_170086_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_838595_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006d0)
+#define HWIO_REG_838595_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006d0)
+#define HWIO_REG_838595_RMSK 0x1ffff
+#define HWIO_REG_838595_SHFT 0
+#define HWIO_REG_838595_IN in_dword_masked(\
+ HWIO_REG_838595_ADDR, HWIO_REG_838595_RMSK)
+#define HWIO_REG_838595_INM(m) \
+ in_dword_masked(HWIO_REG_838595_ADDR, m)
+#define HWIO_REG_838595_OUT(v) \
+ out_dword(HWIO_REG_838595_ADDR, v)
+#define HWIO_REG_838595_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_838595_ADDR, m, v,\
+ HWIO_REG_838595_IN);
+#define HWIO_REG_838595_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_838595_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_569788_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006d4)
+#define HWIO_REG_569788_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006d4)
+#define HWIO_REG_569788_RMSK 0x1ffff
+#define HWIO_REG_569788_SHFT 0
+#define HWIO_REG_569788_IN in_dword_masked(\
+ HWIO_REG_569788_ADDR, HWIO_REG_569788_RMSK)
+#define HWIO_REG_569788_INM(m) \
+ in_dword_masked(HWIO_REG_569788_ADDR, m)
+#define HWIO_REG_569788_OUT(v) \
+ out_dword(HWIO_REG_569788_ADDR, v)
+#define HWIO_REG_569788_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_569788_ADDR, m, v,\
+ HWIO_REG_569788_IN);
+#define HWIO_REG_569788_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_569788_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_974527_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006d8)
+#define HWIO_REG_974527_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006d8)
+#define HWIO_REG_974527_RMSK 0x1ffff
+#define HWIO_REG_974527_SHFT 0
+#define HWIO_REG_974527_IN in_dword_masked(\
+ HWIO_REG_974527_ADDR, HWIO_REG_974527_RMSK)
+#define HWIO_REG_974527_INM(m) \
+ in_dword_masked(HWIO_REG_974527_ADDR, m)
+#define HWIO_REG_974527_OUT(v) \
+ out_dword(HWIO_REG_974527_ADDR, v)
+#define HWIO_REG_974527_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_974527_ADDR, m, v,\
+ HWIO_REG_974527_IN);
+#define HWIO_REG_974527_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_974527_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_316806_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006dc)
+#define HWIO_REG_316806_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006dc)
+#define HWIO_REG_316806_RMSK 0x1ffff
+#define HWIO_REG_316806_SHFT 0
+#define HWIO_REG_316806_IN in_dword_masked(\
+ HWIO_REG_316806_ADDR, HWIO_REG_316806_RMSK)
+#define HWIO_REG_316806_INM(m) \
+ in_dword_masked(HWIO_REG_316806_ADDR, m)
+#define HWIO_REG_316806_OUT(v) \
+ out_dword(HWIO_REG_316806_ADDR, v)
+#define HWIO_REG_316806_OUTM(m, v) \
+ out_dword_masked_ns(HWIO_REG_316806_ADDR, m, v,\
+ HWIO_REG_316806_IN);
+#define HWIO_REG_316806_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_316806_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_900472_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006e0)
+#define HWIO_REG_900472_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006e0)
+#define HWIO_REG_900472_RMSK 0x1ffff
+#define HWIO_REG_900472_SHFT 0
+#define HWIO_REG_900472_IN in_dword_masked(\
+ HWIO_REG_900472_ADDR, HWIO_REG_900472_RMSK)
+#define HWIO_REG_900472_INM(m) \
+ in_dword_masked(HWIO_REG_900472_ADDR, m)
+#define HWIO_REG_900472_OUT(v) \
+ out_dword(HWIO_REG_900472_ADDR, v)
+#define HWIO_REG_900472_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_900472_ADDR, m, v,\
+ HWIO_REG_900472_IN);
+#define HWIO_REG_900472_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_900472_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_256156_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006e4)
+#define HWIO_REG_256156_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006e4)
+#define HWIO_REG_256156_RMSK 0x1ffff
+#define HWIO_REG_256156_SHFT 0
+#define HWIO_REG_256156_IN in_dword_masked(\
+ HWIO_REG_256156_ADDR, HWIO_REG_256156_RMSK)
+#define HWIO_REG_256156_INM(m) \
+ in_dword_masked(HWIO_REG_256156_ADDR, m)
+#define HWIO_REG_256156_OUT(v) \
+ out_dword(HWIO_REG_256156_ADDR, v)
+#define HWIO_REG_256156_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_256156_ADDR, m, v,\
+ HWIO_REG_256156_IN);
+#define HWIO_REG_256156_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_256156_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_335729_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006e8)
+#define HWIO_REG_335729_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006e8)
+#define HWIO_REG_335729_RMSK 0x1ffff
+#define HWIO_REG_335729_SHFT 0
+#define HWIO_REG_335729_IN in_dword_masked(\
+ HWIO_REG_335729_ADDR, HWIO_REG_335729_RMSK)
+#define HWIO_REG_335729_INM(m) \
+ in_dword_masked(HWIO_REG_335729_ADDR, m)
+#define HWIO_REG_335729_OUT(v) \
+ out_dword(HWIO_REG_335729_ADDR, v)
+#define HWIO_REG_335729_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_335729_ADDR, m, v,\
+ HWIO_REG_335729_IN);
+#define HWIO_REG_335729_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_335729_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_303383_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006ec)
+#define HWIO_REG_303383_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006ec)
+#define HWIO_REG_303383_RMSK 0x1ffff
+#define HWIO_REG_303383_SHFT 0
+#define HWIO_REG_303383_IN in_dword_masked(\
+ HWIO_REG_303383_ADDR, HWIO_REG_303383_RMSK)
+#define HWIO_REG_303383_INM(m) \
+ in_dword_masked(HWIO_REG_303383_ADDR, m)
+#define HWIO_REG_303383_OUT(v) \
+ out_dword(HWIO_REG_303383_ADDR, v)
+#define HWIO_REG_303383_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_303383_ADDR, m, v,\
+ HWIO_REG_303383_IN);
+#define HWIO_REG_303383_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_303383_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_180871_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006f0)
+#define HWIO_REG_180871_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006f0)
+#define HWIO_REG_180871_RMSK 0x1ffff
+#define HWIO_REG_180871_SHFT 0
+#define HWIO_REG_180871_IN in_dword_masked(\
+ HWIO_REG_180871_ADDR, HWIO_REG_180871_RMSK)
+#define HWIO_REG_180871_INM(m) \
+ in_dword_masked(HWIO_REG_180871_ADDR, m)
+#define HWIO_REG_180871_OUT(v) \
+ out_dword(HWIO_REG_180871_ADDR, v)
+#define HWIO_REG_180871_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_180871_ADDR, m, v,\
+ HWIO_REG_180871_IN);
+#define HWIO_REG_180871_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_180871_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_514148_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006f4)
+#define HWIO_REG_514148_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006f4)
+#define HWIO_REG_514148_RMSK 0x1ffff
+#define HWIO_REG_514148_SHFT 0
+#define HWIO_REG_514148_IN in_dword_masked(\
+ HWIO_REG_514148_ADDR, HWIO_REG_514148_RMSK)
+#define HWIO_REG_514148_INM(m) \
+ in_dword_masked(HWIO_REG_514148_ADDR, m)
+#define HWIO_REG_514148_OUT(v) \
+ out_dword(HWIO_REG_514148_ADDR, v)
+#define HWIO_REG_514148_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_514148_ADDR, m, v,\
+ HWIO_REG_514148_IN);
+#define HWIO_REG_514148_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_514148_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_578636_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006f8)
+#define HWIO_REG_578636_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006f8)
+#define HWIO_REG_578636_RMSK 0x1ffff
+#define HWIO_REG_578636_SHFT 0
+#define HWIO_REG_578636_IN in_dword_masked(\
+ HWIO_REG_578636_ADDR, HWIO_REG_578636_RMSK)
+#define HWIO_REG_578636_INM(m) \
+ in_dword_masked(HWIO_REG_578636_ADDR, m)
+#define HWIO_REG_578636_OUT(v) \
+ out_dword(HWIO_REG_578636_ADDR, v)
+#define HWIO_REG_578636_OUTM(m, v) \
+ out_dword_masked_ns(HWIO_REG_578636_ADDR, m, v,\
+ HWIO_REG_578636_IN);
+#define HWIO_REG_578636_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_578636_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_888116_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000006fc)
+#define HWIO_REG_888116_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000006fc)
+#define HWIO_REG_888116_RMSK 0x1ffff
+#define HWIO_REG_888116_SHFT 0
+#define HWIO_REG_888116_IN in_dword_masked(\
+ HWIO_REG_888116_ADDR, HWIO_REG_888116_RMSK)
+#define HWIO_REG_888116_INM(m) \
+ in_dword_masked(HWIO_REG_888116_ADDR, m)
+#define HWIO_REG_888116_OUT(v) \
+ out_dword(HWIO_REG_888116_ADDR, v)
+#define HWIO_REG_888116_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_888116_ADDR, m, v,\
+ HWIO_REG_888116_IN);
+#define HWIO_REG_888116_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_888116_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_759068_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000700)
+#define HWIO_REG_759068_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000700)
+#define HWIO_REG_759068_RMSK 0x1ffff
+#define HWIO_REG_759068_SHFT 0
+#define HWIO_REG_759068_IN in_dword_masked(\
+ HWIO_REG_759068_ADDR, HWIO_REG_759068_RMSK)
+#define HWIO_REG_759068_INM(m) \
+ in_dword_masked(HWIO_REG_759068_ADDR, m)
+#define HWIO_REG_759068_OUT(v) \
+ out_dword(HWIO_REG_759068_ADDR, v)
+#define HWIO_REG_759068_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_759068_ADDR, m, v,\
+ HWIO_REG_759068_IN);
+#define HWIO_REG_759068_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_759068_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_68356_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000704)
+#define HWIO_REG_68356_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000704)
+#define HWIO_REG_68356_RMSK 0x1ffff
+#define HWIO_REG_68356_SHFT 0
+#define HWIO_REG_68356_IN in_dword_masked(\
+ HWIO_REG_68356_ADDR, HWIO_REG_68356_RMSK)
+#define HWIO_REG_68356_INM(m) \
+ in_dword_masked(HWIO_REG_68356_ADDR, m)
+#define HWIO_REG_68356_OUT(v) \
+ out_dword(HWIO_REG_68356_ADDR, v)
+#define HWIO_REG_68356_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_68356_ADDR, m, v,\
+ HWIO_REG_68356_IN);
+#define HWIO_REG_68356_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_68356_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_833502_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000708)
+#define HWIO_REG_833502_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000708)
+#define HWIO_REG_833502_RMSK 0x1ffff
+#define HWIO_REG_833502_SHFT 0
+#define HWIO_REG_833502_IN in_dword_masked(\
+ HWIO_REG_833502_ADDR, HWIO_REG_833502_RMSK)
+#define HWIO_REG_833502_INM(m) \
+ in_dword_masked(HWIO_REG_833502_ADDR, m)
+#define HWIO_REG_833502_OUT(v) \
+ out_dword(HWIO_REG_833502_ADDR, v)
+#define HWIO_REG_833502_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_833502_ADDR, m, v,\
+ HWIO_REG_833502_IN);
+#define HWIO_REG_833502_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_833502_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_127855_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x0000070c)
+#define HWIO_REG_127855_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000070c)
+#define HWIO_REG_127855_RMSK 0x1ffff
+#define HWIO_REG_127855_SHFT 0
+#define HWIO_REG_127855_IN in_dword_masked(\
+ HWIO_REG_127855_ADDR, HWIO_REG_127855_RMSK)
+#define HWIO_REG_127855_INM(m) \
+ in_dword_masked(HWIO_REG_127855_ADDR, m)
+#define HWIO_REG_127855_OUT(v) \
+ out_dword(HWIO_REG_127855_ADDR, v)
+#define HWIO_REG_127855_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_127855_ADDR, m, v,\
+ HWIO_REG_127855_IN);
+#define HWIO_REG_127855_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_127855_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_616802_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000710)
+#define HWIO_REG_616802_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000710)
+#define HWIO_REG_616802_RMSK 0x1ffff
+#define HWIO_REG_616802_SHFT 0
+#define HWIO_REG_616802_IN in_dword_masked(\
+ HWIO_REG_616802_ADDR, HWIO_REG_616802_RMSK)
+#define HWIO_REG_616802_INM(m) \
+ in_dword_masked(HWIO_REG_616802_ADDR, m)
+#define HWIO_REG_616802_OUT(v) \
+ out_dword(HWIO_REG_616802_ADDR, v)
+#define HWIO_REG_616802_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_616802_ADDR, m, v,\
+ HWIO_REG_616802_IN);
+#define HWIO_REG_616802_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_616802_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_23318_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000714)
+#define HWIO_REG_23318_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000714)
+#define HWIO_REG_23318_RMSK 0x1ffff
+#define HWIO_REG_23318_SHFT 0
+#define HWIO_REG_23318_IN in_dword_masked(\
+ HWIO_REG_23318_ADDR, HWIO_REG_23318_RMSK)
+#define HWIO_REG_23318_INM(m) \
+ in_dword_masked(HWIO_REG_23318_ADDR, m)
+#define HWIO_REG_23318_OUT(v) \
+ out_dword(HWIO_REG_23318_ADDR, v)
+#define HWIO_REG_23318_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_23318_ADDR, m, v,\
+ HWIO_REG_23318_IN);
+#define HWIO_REG_23318_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_23318_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_317106_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000718)
+#define HWIO_REG_317106_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000718)
+#define HWIO_REG_317106_RMSK 0x1ffff
+#define HWIO_REG_317106_SHFT 0
+#define HWIO_REG_317106_IN in_dword_masked(\
+ HWIO_REG_317106_ADDR, HWIO_REG_317106_RMSK)
+#define HWIO_REG_317106_INM(m) \
+ in_dword_masked(HWIO_REG_317106_ADDR, m)
+#define HWIO_REG_317106_OUT(v) \
+ out_dword(HWIO_REG_317106_ADDR, v)
+#define HWIO_REG_317106_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_317106_ADDR, m, v,\
+ HWIO_REG_317106_IN);
+#define HWIO_REG_317106_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_317106_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_603772_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x0000071c)
+#define HWIO_REG_603772_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000071c)
+#define HWIO_REG_603772_RMSK 0x1ffff
+#define HWIO_REG_603772_SHFT 0
+#define HWIO_REG_603772_IN in_dword_masked(\
+ HWIO_REG_603772_ADDR, HWIO_REG_603772_RMSK)
+#define HWIO_REG_603772_INM(m) \
+ in_dword_masked(HWIO_REG_603772_ADDR, m)
+#define HWIO_REG_603772_OUT(v) \
+ out_dword(HWIO_REG_603772_ADDR, v)
+#define HWIO_REG_603772_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_603772_ADDR, m, v,\
+ HWIO_REG_603772_IN);
+#define HWIO_REG_603772_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_603772_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_175929_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000720)
+#define HWIO_REG_175929_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000720)
+#define HWIO_REG_175929_RMSK 0x1ffff
+#define HWIO_REG_175929_SHFT 0
+#define HWIO_REG_175929_IN in_dword_masked(\
+ HWIO_REG_175929_ADDR, HWIO_REG_175929_RMSK)
+#define HWIO_REG_175929_INM(m) \
+ in_dword_masked(HWIO_REG_175929_ADDR, m)
+#define HWIO_REG_175929_OUT(v) \
+ out_dword(HWIO_REG_175929_ADDR, v)
+#define HWIO_REG_175929_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_175929_ADDR, m, v,\
+ HWIO_REG_175929_IN);
+#define HWIO_REG_175929_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_175929_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_11928_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000724)
+#define HWIO_REG_11928_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000724)
+#define HWIO_REG_11928_RMSK 0x1ffff
+#define HWIO_REG_11928_SHFT 0
+#define HWIO_REG_11928_IN in_dword_masked(\
+ HWIO_REG_11928_ADDR, HWIO_REG_11928_RMSK)
+#define HWIO_REG_11928_INM(m) \
+ in_dword_masked(HWIO_REG_11928_ADDR, m)
+#define HWIO_REG_11928_OUT(v) \
+ out_dword(HWIO_REG_11928_ADDR, v)
+#define HWIO_REG_11928_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_11928_ADDR, m, v,\
+ HWIO_REG_11928_IN);
+#define HWIO_REG_11928_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_11928_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_772678_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000728)
+#define HWIO_REG_772678_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000728)
+#define HWIO_REG_772678_RMSK 0x1ffff
+#define HWIO_REG_772678_SHFT 0
+#define HWIO_REG_772678_IN in_dword_masked(\
+ HWIO_REG_772678_ADDR, HWIO_REG_772678_RMSK)
+#define HWIO_REG_772678_INM(m) \
+ in_dword_masked(HWIO_REG_772678_ADDR, m)
+#define HWIO_REG_772678_OUT(v) \
+ out_dword(HWIO_REG_772678_ADDR, v)
+#define HWIO_REG_772678_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_772678_ADDR, m, v,\
+ HWIO_REG_772678_IN);
+#define HWIO_REG_772678_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_772678_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_603389_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x0000072c)
+#define HWIO_REG_603389_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000072c)
+#define HWIO_REG_603389_RMSK 0x1ffff
+#define HWIO_REG_603389_SHFT 0
+#define HWIO_REG_603389_IN in_dword_masked(\
+ HWIO_REG_603389_ADDR, HWIO_REG_603389_RMSK)
+#define HWIO_REG_603389_INM(m) \
+ in_dword_masked(HWIO_REG_603389_ADDR, m)
+#define HWIO_REG_603389_OUT(v) \
+ out_dword(HWIO_REG_603389_ADDR, v)
+#define HWIO_REG_603389_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_603389_ADDR, m, v,\
+ HWIO_REG_603389_IN);
+#define HWIO_REG_603389_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_603389_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_989918_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000730)
+#define HWIO_REG_989918_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000730)
+#define HWIO_REG_989918_RMSK 0x1ffff
+#define HWIO_REG_989918_SHFT 0
+#define HWIO_REG_989918_IN in_dword_masked(\
+ HWIO_REG_989918_ADDR, HWIO_REG_989918_RMSK)
+#define HWIO_REG_989918_INM(m) \
+ in_dword_masked(HWIO_REG_989918_ADDR, m)
+#define HWIO_REG_989918_OUT(v) \
+ out_dword(HWIO_REG_989918_ADDR, v)
+#define HWIO_REG_989918_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_989918_ADDR, m, v,\
+ HWIO_REG_989918_IN);
+#define HWIO_REG_989918_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_989918_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_5460_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000734)
+#define HWIO_REG_5460_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000734)
+#define HWIO_REG_5460_RMSK 0x1ffff
+#define HWIO_REG_5460_SHFT 0
+#define HWIO_REG_5460_IN in_dword_masked(\
+ HWIO_REG_5460_ADDR, HWIO_REG_5460_RMSK)
+#define HWIO_REG_5460_INM(m) \
+ in_dword_masked(HWIO_REG_5460_ADDR, m)
+#define HWIO_REG_5460_OUT(v) \
+ out_dword(HWIO_REG_5460_ADDR, v)
+#define HWIO_REG_5460_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_5460_ADDR, m, v,\
+ HWIO_REG_5460_IN);
+#define HWIO_REG_5460_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_5460_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_734724_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000738)
+#define HWIO_REG_734724_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000738)
+#define HWIO_REG_734724_RMSK 0x1ffff
+#define HWIO_REG_734724_SHFT 0
+#define HWIO_REG_734724_IN in_dword_masked(\
+ HWIO_REG_734724_ADDR, HWIO_REG_734724_RMSK)
+#define HWIO_REG_734724_INM(m) \
+ in_dword_masked(HWIO_REG_734724_ADDR, m)
+#define HWIO_REG_734724_OUT(v) \
+ out_dword(HWIO_REG_734724_ADDR, v)
+#define HWIO_REG_734724_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_734724_ADDR, m, v,\
+ HWIO_REG_734724_IN);
+#define HWIO_REG_734724_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_734724_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_451742_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x0000073c)
+#define HWIO_REG_451742_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000073c)
+#define HWIO_REG_451742_RMSK 0x1ffff
+#define HWIO_REG_451742_SHFT 0
+#define HWIO_REG_451742_IN in_dword_masked(\
+ HWIO_REG_451742_ADDR, HWIO_REG_451742_RMSK)
+#define HWIO_REG_451742_INM(m) \
+ in_dword_masked(HWIO_REG_451742_ADDR, m)
+#define HWIO_REG_451742_OUT(v) \
+ out_dword(HWIO_REG_451742_ADDR, v)
+#define HWIO_REG_451742_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_451742_ADDR, m, v,\
+ HWIO_REG_451742_IN);
+#define HWIO_REG_451742_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_451742_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_475648_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000740)
+#define HWIO_REG_475648_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000740)
+#define HWIO_REG_475648_RMSK 0x1ffff
+#define HWIO_REG_475648_SHFT 0
+#define HWIO_REG_475648_IN in_dword_masked(\
+ HWIO_REG_475648_ADDR, HWIO_REG_475648_RMSK)
+#define HWIO_REG_475648_INM(m) \
+ in_dword_masked(HWIO_REG_475648_ADDR, m)
+#define HWIO_REG_475648_OUT(v) \
+ out_dword(HWIO_REG_475648_ADDR, v)
+#define HWIO_REG_475648_OUTM(m, v) \
+ out_dword_masked_ns(HWIO_REG_475648_ADDR, m, v,\
+ HWIO_REG_475648_IN);
+#define HWIO_REG_475648_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_475648_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_284758_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000744)
+#define HWIO_REG_284758_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000744)
+#define HWIO_REG_284758_RMSK 0x1ffff
+#define HWIO_REG_284758_SHFT 0
+#define HWIO_REG_284758_IN in_dword_masked(\
+ HWIO_REG_284758_ADDR, HWIO_REG_284758_RMSK)
+#define HWIO_REG_284758_INM(m) \
+ in_dword_masked(HWIO_REG_284758_ADDR, m)
+#define HWIO_REG_284758_OUT(v) \
+ out_dword(HWIO_REG_284758_ADDR, v)
+#define HWIO_REG_284758_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_284758_ADDR, m, v,\
+ HWIO_REG_284758_IN);
+#define HWIO_REG_284758_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_284758_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_523659_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000748)
+#define HWIO_REG_523659_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000748)
+#define HWIO_REG_523659_RMSK 0x1ffff
+#define HWIO_REG_523659_SHFT 0
+#define HWIO_REG_523659_IN in_dword_masked(\
+ HWIO_REG_523659_ADDR, HWIO_REG_523659_RMSK)
+#define HWIO_REG_523659_INM(m) \
+ in_dword_masked(HWIO_REG_523659_ADDR, m)
+#define HWIO_REG_523659_OUT(v) \
+ out_dword(HWIO_REG_523659_ADDR, v)
+#define HWIO_REG_523659_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_523659_ADDR, m, v,\
+ HWIO_REG_523659_IN);
+#define HWIO_REG_523659_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_523659_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_815580_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x0000074c)
+#define HWIO_REG_815580_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000074c)
+#define HWIO_REG_815580_RMSK 0x1ffff
+#define HWIO_REG_815580_SHFT 0
+#define HWIO_REG_815580_IN in_dword_masked(\
+ HWIO_REG_815580_ADDR, HWIO_REG_815580_RMSK)
+#define HWIO_REG_815580_INM(m) \
+ in_dword_masked(HWIO_REG_815580_ADDR, m)
+#define HWIO_REG_815580_OUT(v) \
+ out_dword(HWIO_REG_815580_ADDR, v)
+#define HWIO_REG_815580_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_815580_ADDR, m, v,\
+ HWIO_REG_815580_IN);
+#define HWIO_REG_815580_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_815580_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_546551_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000750)
+#define HWIO_REG_546551_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000750)
+#define HWIO_REG_546551_RMSK 0x1ffff
+#define HWIO_REG_546551_SHFT 0
+#define HWIO_REG_546551_IN in_dword_masked(\
+ HWIO_REG_546551_ADDR, HWIO_REG_546551_RMSK)
+#define HWIO_REG_546551_INM(m) \
+ in_dword_masked(HWIO_REG_546551_ADDR, m)
+#define HWIO_REG_546551_OUT(v) \
+ out_dword(HWIO_REG_546551_ADDR, v)
+#define HWIO_REG_546551_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_546551_ADDR, m, v,\
+ HWIO_REG_546551_IN);
+#define HWIO_REG_546551_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_546551_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_769851_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000754)
+#define HWIO_REG_769851_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000754)
+#define HWIO_REG_769851_RMSK 0x1ffff
+#define HWIO_REG_769851_SHFT 0
+#define HWIO_REG_769851_IN in_dword_masked(\
+ HWIO_REG_769851_ADDR, HWIO_REG_769851_RMSK)
+#define HWIO_REG_769851_INM(m) \
+ in_dword_masked(HWIO_REG_769851_ADDR, m)
+#define HWIO_REG_769851_OUT(v) \
+ out_dword(HWIO_REG_769851_ADDR, v)
+#define HWIO_REG_769851_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_769851_ADDR, m, v,\
+ HWIO_REG_769851_IN);
+#define HWIO_REG_769851_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_769851_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_205028_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000758)
+#define HWIO_REG_205028_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000758)
+#define HWIO_REG_205028_RMSK 0x1ffff
+#define HWIO_REG_205028_SHFT 0
+#define HWIO_REG_205028_IN in_dword_masked(\
+ HWIO_REG_205028_ADDR, HWIO_REG_205028_RMSK)
+#define HWIO_REG_205028_INM(m) \
+ in_dword_masked(HWIO_REG_205028_ADDR, m)
+#define HWIO_REG_205028_OUT(v) \
+ out_dword(HWIO_REG_205028_ADDR, v)
+#define HWIO_REG_205028_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_205028_ADDR, m, v,\
+ HWIO_REG_205028_IN);
+#define HWIO_REG_205028_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_205028_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_206835_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x0000075c)
+#define HWIO_REG_206835_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000075c)
+#define HWIO_REG_206835_RMSK 0x1ffff
+#define HWIO_REG_206835_SHFT 0
+#define HWIO_REG_206835_IN in_dword_masked(\
+ HWIO_REG_206835_ADDR, HWIO_REG_206835_RMSK)
+#define HWIO_REG_206835_INM(m) \
+ in_dword_masked(HWIO_REG_206835_ADDR, m)
+#define HWIO_REG_206835_OUT(v) \
+ out_dword(HWIO_REG_206835_ADDR, v)
+#define HWIO_REG_206835_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_206835_ADDR, m, v,\
+ HWIO_REG_206835_IN);
+#define HWIO_REG_206835_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_206835_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_582575_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000760)
+#define HWIO_REG_582575_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000760)
+#define HWIO_REG_582575_RMSK 0x1ffff
+#define HWIO_REG_582575_SHFT 0
+#define HWIO_REG_582575_IN in_dword_masked(\
+ HWIO_REG_582575_ADDR, HWIO_REG_582575_RMSK)
+#define HWIO_REG_582575_INM(m) \
+ in_dword_masked(HWIO_REG_582575_ADDR, m)
+#define HWIO_REG_582575_OUT(v) \
+ out_dword(HWIO_REG_582575_ADDR, v)
+#define HWIO_REG_582575_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_582575_ADDR, m, v,\
+ HWIO_REG_582575_IN);
+#define HWIO_REG_582575_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_582575_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_120885_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000764)
+#define HWIO_REG_120885_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000764)
+#define HWIO_REG_120885_RMSK 0x1ffff
+#define HWIO_REG_120885_SHFT 0
+#define HWIO_REG_120885_IN in_dword_masked(\
+ HWIO_REG_120885_ADDR, HWIO_REG_120885_RMSK)
+#define HWIO_REG_120885_INM(m) \
+ in_dword_masked(HWIO_REG_120885_ADDR, m)
+#define HWIO_REG_120885_OUT(v) \
+ out_dword(HWIO_REG_120885_ADDR, v)
+#define HWIO_REG_120885_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_120885_ADDR, m, v,\
+ HWIO_REG_120885_IN);
+#define HWIO_REG_120885_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_120885_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_496067_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000768)
+#define HWIO_REG_496067_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000768)
+#define HWIO_REG_496067_RMSK 0x1ffff
+#define HWIO_REG_496067_SHFT 0
+#define HWIO_REG_496067_IN in_dword_masked(\
+ HWIO_REG_496067_ADDR, HWIO_REG_496067_RMSK)
+#define HWIO_REG_496067_INM(m) \
+ in_dword_masked(HWIO_REG_496067_ADDR, m)
+#define HWIO_REG_496067_OUT(v) \
+ out_dword(HWIO_REG_496067_ADDR, v)
+#define HWIO_REG_496067_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_496067_ADDR, m, v,\
+ HWIO_REG_496067_IN);
+#define HWIO_REG_496067_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_496067_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_472919_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x0000076c)
+#define HWIO_REG_472919_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000076c)
+#define HWIO_REG_472919_RMSK 0x1ffff
+#define HWIO_REG_472919_SHFT 0
+#define HWIO_REG_472919_IN in_dword_masked(\
+ HWIO_REG_472919_ADDR, HWIO_REG_472919_RMSK)
+#define HWIO_REG_472919_INM(m) \
+ in_dword_masked(HWIO_REG_472919_ADDR, m)
+#define HWIO_REG_472919_OUT(v) \
+ out_dword(HWIO_REG_472919_ADDR, v)
+#define HWIO_REG_472919_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_472919_ADDR, m, v,\
+ HWIO_REG_472919_IN);
+#define HWIO_REG_472919_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_472919_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_486985_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000770)
+#define HWIO_REG_486985_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000770)
+#define HWIO_REG_486985_RMSK 0x1ffff
+#define HWIO_REG_486985_SHFT 0
+#define HWIO_REG_486985_IN in_dword_masked(\
+ HWIO_REG_486985_ADDR, HWIO_REG_486985_RMSK)
+#define HWIO_REG_486985_INM(m) \
+ in_dword_masked(HWIO_REG_486985_ADDR, m)
+#define HWIO_REG_486985_OUT(v) \
+ out_dword(HWIO_REG_486985_ADDR, v)
+#define HWIO_REG_486985_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_486985_ADDR, m, v,\
+ HWIO_REG_486985_IN);
+#define HWIO_REG_486985_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_486985_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_964692_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000774)
+#define HWIO_REG_964692_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000774)
+#define HWIO_REG_964692_RMSK 0x1ffff
+#define HWIO_REG_964692_SHFT 0
+#define HWIO_REG_964692_IN in_dword_masked(\
+ HWIO_REG_964692_ADDR, HWIO_REG_964692_RMSK)
+#define HWIO_REG_964692_INM(m) \
+ in_dword_masked(HWIO_REG_964692_ADDR, m)
+#define HWIO_REG_964692_OUT(v) \
+ out_dword(HWIO_REG_964692_ADDR, v)
+#define HWIO_REG_964692_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_964692_ADDR, m, v,\
+ HWIO_REG_964692_IN);
+#define HWIO_REG_964692_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_964692_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_941116_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000778)
+#define HWIO_REG_941116_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000778)
+#define HWIO_REG_941116_RMSK 0x1ffff
+#define HWIO_REG_941116_SHFT 0
+#define HWIO_REG_941116_IN in_dword_masked(\
+ HWIO_REG_941116_ADDR, HWIO_REG_941116_RMSK)
+#define HWIO_REG_941116_INM(m) \
+ in_dword_masked(HWIO_REG_941116_ADDR, m)
+#define HWIO_REG_941116_OUT(v) \
+ out_dword(HWIO_REG_941116_ADDR, v)
+#define HWIO_REG_941116_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_941116_ADDR, m, v,\
+ HWIO_REG_941116_IN);
+#define HWIO_REG_941116_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_941116_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_122567_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x0000077c)
+#define HWIO_REG_122567_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000077c)
+#define HWIO_REG_122567_RMSK 0x1ffff
+#define HWIO_REG_122567_SHFT 0
+#define HWIO_REG_122567_IN in_dword_masked(\
+ HWIO_REG_122567_ADDR, HWIO_REG_122567_RMSK)
+#define HWIO_REG_122567_INM(m) \
+ in_dword_masked(HWIO_REG_122567_ADDR, m)
+#define HWIO_REG_122567_OUT(v) \
+ out_dword(HWIO_REG_122567_ADDR, v)
+#define HWIO_REG_122567_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_122567_ADDR, m, v,\
+ HWIO_REG_122567_IN);
+#define HWIO_REG_122567_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_122567_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_466192_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000780)
+#define HWIO_REG_466192_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000780)
+#define HWIO_REG_466192_RMSK 0x1ffff
+#define HWIO_REG_466192_SHFT 0
+#define HWIO_REG_466192_IN in_dword_masked(\
+ HWIO_REG_466192_ADDR, HWIO_REG_466192_RMSK)
+#define HWIO_REG_466192_INM(m) \
+ in_dword_masked(HWIO_REG_466192_ADDR, m)
+#define HWIO_REG_466192_OUT(v) \
+ out_dword(HWIO_REG_466192_ADDR, v)
+#define HWIO_REG_466192_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_466192_ADDR, m, v,\
+ HWIO_REG_466192_IN);
+#define HWIO_REG_466192_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_466192_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_554890_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000784)
+#define HWIO_REG_554890_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000784)
+#define HWIO_REG_554890_RMSK 0x1ffff
+#define HWIO_REG_554890_SHFT 0
+#define HWIO_REG_554890_IN in_dword_masked(\
+ HWIO_REG_554890_ADDR, HWIO_REG_554890_RMSK)
+#define HWIO_REG_554890_INM(m) \
+ in_dword_masked(HWIO_REG_554890_ADDR, m)
+#define HWIO_REG_554890_OUT(v) \
+ out_dword(HWIO_REG_554890_ADDR, v)
+#define HWIO_REG_554890_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_554890_ADDR, m, v,\
+ HWIO_REG_554890_IN);
+#define HWIO_REG_554890_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_554890_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_295616_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000788)
+#define HWIO_REG_295616_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000788)
+#define HWIO_REG_295616_RMSK 0x1ffff
+#define HWIO_REG_295616_SHFT 0
+#define HWIO_REG_295616_IN in_dword_masked(\
+ HWIO_REG_295616_ADDR, HWIO_REG_295616_RMSK)
+#define HWIO_REG_295616_INM(m) \
+ in_dword_masked(HWIO_REG_295616_ADDR, m)
+#define HWIO_REG_295616_OUT(v) \
+ out_dword(HWIO_REG_295616_ADDR, v)
+#define HWIO_REG_295616_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_295616_ADDR, m, v,\
+ HWIO_REG_295616_IN);
+#define HWIO_REG_295616_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_295616_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_440836_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x0000078c)
+#define HWIO_REG_440836_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000078c)
+#define HWIO_REG_440836_RMSK 0x1ffff
+#define HWIO_REG_440836_SHFT 0
+#define HWIO_REG_440836_IN in_dword_masked(\
+ HWIO_REG_440836_ADDR, HWIO_REG_440836_RMSK)
+#define HWIO_REG_440836_INM(m) \
+ in_dword_masked(HWIO_REG_440836_ADDR, m)
+#define HWIO_REG_440836_OUT(v) \
+ out_dword(HWIO_REG_440836_ADDR, v)
+#define HWIO_REG_440836_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_440836_ADDR, m, v,\
+ HWIO_REG_440836_IN);
+#define HWIO_REG_440836_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_440836_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_741154_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000790)
+#define HWIO_REG_741154_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000790)
+#define HWIO_REG_741154_RMSK 0x1ffff
+#define HWIO_REG_741154_SHFT 0
+#define HWIO_REG_741154_IN in_dword_masked(\
+ HWIO_REG_741154_ADDR,\
+ HWIO_REG_741154_RMSK)
+#define HWIO_REG_741154_INM(m) \
+ in_dword_masked(HWIO_REG_741154_ADDR, m)
+#define HWIO_REG_741154_OUT(v) \
+ out_dword(HWIO_REG_741154_ADDR, v)
+#define HWIO_REG_741154_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_741154_ADDR, m, v,\
+ HWIO_REG_741154_IN);
+#define HWIO_REG_741154_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_741154_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_753139_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000794)
+#define HWIO_REG_753139_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000794)
+#define HWIO_REG_753139_RMSK 0x1ffff
+#define HWIO_REG_753139_SHFT 0
+#define HWIO_REG_753139_IN in_dword_masked(\
+ HWIO_REG_753139_ADDR,\
+ HWIO_REG_753139_RMSK)
+#define HWIO_REG_753139_INM(m) \
+ in_dword_masked(HWIO_REG_753139_ADDR, m)
+#define HWIO_REG_753139_OUT(v) \
+ out_dword(HWIO_REG_753139_ADDR, v)
+#define HWIO_REG_753139_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_753139_ADDR, m, v,\
+ HWIO_REG_753139_IN);
+#define HWIO_REG_753139_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_753139_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_409994_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x00000798)
+#define HWIO_REG_409994_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000798)
+#define HWIO_REG_409994_RMSK 0x1ffff
+#define HWIO_REG_409994_SHFT 0
+#define HWIO_REG_409994_IN in_dword_masked(\
+ HWIO_REG_409994_ADDR,\
+ HWIO_REG_409994_RMSK)
+#define HWIO_REG_409994_INM(m) \
+ in_dword_masked(HWIO_REG_409994_ADDR, m)
+#define HWIO_REG_409994_OUT(v) \
+ out_dword(HWIO_REG_409994_ADDR, v)
+#define HWIO_REG_409994_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_409994_ADDR, m, v,\
+ HWIO_REG_409994_IN);
+#define HWIO_REG_409994_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_409994_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_492611_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x0000079c)
+#define HWIO_REG_492611_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000079c)
+#define HWIO_REG_492611_RMSK 0x1ffff
+#define HWIO_REG_492611_SHFT 0
+#define HWIO_REG_492611_IN in_dword_masked(\
+ HWIO_REG_492611_ADDR,\
+ HWIO_REG_492611_RMSK)
+#define HWIO_REG_492611_INM(m) \
+ in_dword_masked(HWIO_REG_492611_ADDR, m)
+#define HWIO_REG_492611_OUT(v) \
+ out_dword(HWIO_REG_492611_ADDR, v)
+#define HWIO_REG_492611_OUTM(m, v) \
+ out_dword_masked_ns(HWIO_REG_492611_ADDR, m, v,\
+ HWIO_REG_492611_IN);
+#define HWIO_REG_492611_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_492611_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_91427_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007a0)
+#define HWIO_REG_91427_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007a0)
+#define HWIO_REG_91427_RMSK 0x1ffff
+#define HWIO_REG_91427_SHFT 0
+#define HWIO_REG_91427_IN in_dword_masked(\
+ HWIO_REG_91427_ADDR,\
+ HWIO_REG_91427_RMSK)
+#define HWIO_REG_91427_INM(m) \
+ in_dword_masked(HWIO_REG_91427_ADDR, m)
+#define HWIO_REG_91427_OUT(v) \
+ out_dword(HWIO_REG_91427_ADDR, v)
+#define HWIO_REG_91427_OUTM(m, v) \
+ out_dword_masked_ns(HWIO_REG_91427_ADDR, m, v,\
+ HWIO_REG_91427_IN);
+#define HWIO_REG_91427_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_91427_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_617696_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007a4)
+#define HWIO_REG_617696_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007a4)
+#define HWIO_REG_617696_RMSK 0x1ffff
+#define HWIO_REG_617696_SHFT 0
+#define HWIO_REG_617696_IN in_dword_masked(\
+ HWIO_REG_617696_ADDR,\
+ HWIO_REG_617696_RMSK)
+#define HWIO_REG_617696_INM(m) \
+ in_dword_masked(HWIO_REG_617696_ADDR, m)
+#define HWIO_REG_617696_OUT(v) \
+ out_dword(HWIO_REG_617696_ADDR, v)
+#define HWIO_REG_617696_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_617696_ADDR, m, v,\
+ HWIO_REG_617696_IN);
+#define HWIO_REG_617696_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_617696_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_459602_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007a8)
+#define HWIO_REG_459602_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007a8)
+#define HWIO_REG_459602_RMSK 0x1ffff
+#define HWIO_REG_459602_SHFT 0
+#define HWIO_REG_459602_IN in_dword_masked(\
+ HWIO_REG_459602_ADDR,\
+ HWIO_REG_459602_RMSK)
+#define HWIO_REG_459602_INM(m) \
+ in_dword_masked(HWIO_REG_459602_ADDR, m)
+#define HWIO_REG_459602_OUT(v) \
+ out_dword(HWIO_REG_459602_ADDR, v)
+#define HWIO_REG_459602_OUTM(m, v) \
+ out_dword_masked_ns(HWIO_REG_459602_ADDR, m, v,\
+ HWIO_REG_459602_IN);
+#define HWIO_REG_459602_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_459602_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_758_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007ac)
+#define HWIO_REG_758_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007ac)
+#define HWIO_REG_758_RMSK 0x1ffff
+#define HWIO_REG_758_SHFT 0
+#define HWIO_REG_758_IN in_dword_masked(\
+ HWIO_REG_758_ADDR,\
+ HWIO_REG_758_RMSK)
+#define HWIO_REG_758_INM(m) \
+ in_dword_masked(HWIO_REG_758_ADDR, m)
+#define HWIO_REG_758_OUT(v) \
+ out_dword(HWIO_REG_758_ADDR, v)
+#define HWIO_REG_758_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_758_ADDR, m, v,\
+ HWIO_REG_758_IN);
+#define HWIO_REG_758_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_758_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_710606_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007b0)
+#define HWIO_REG_710606_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007b0)
+#define HWIO_REG_710606_RMSK 0x1ffff
+#define HWIO_REG_710606_SHFT 0
+#define HWIO_REG_710606_IN in_dword_masked(\
+ HWIO_REG_710606_ADDR,\
+ HWIO_REG_710606_RMSK)
+#define HWIO_REG_710606_INM(m) \
+ in_dword_masked(HWIO_REG_710606_ADDR, m)
+#define HWIO_REG_710606_OUT(v) \
+ out_dword(HWIO_REG_710606_ADDR, v)
+#define HWIO_REG_710606_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_710606_ADDR, m, v,\
+ HWIO_REG_710606_IN);
+#define HWIO_REG_710606_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_710606_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_122975_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007b4)
+#define HWIO_REG_122975_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007b4)
+#define HWIO_REG_122975_RMSK 0x1ffff
+#define HWIO_REG_122975_SHFT 0
+#define HWIO_REG_122975_IN in_dword_masked(\
+ HWIO_REG_122975_ADDR,\
+ HWIO_REG_122975_RMSK)
+#define HWIO_REG_122975_INM(m)\
+ in_dword_masked(HWIO_REG_122975_ADDR, m)
+#define HWIO_REG_122975_OUT(v)\
+ out_dword(HWIO_REG_122975_ADDR, v)
+#define HWIO_REG_122975_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_122975_ADDR, m, v,\
+ HWIO_REG_122975_IN);
+#define HWIO_REG_122975_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_122975_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_860205_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007b8)
+#define HWIO_REG_860205_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007b8)
+#define HWIO_REG_860205_RMSK 0x1ffff
+#define HWIO_REG_860205_SHFT 0
+#define HWIO_REG_860205_IN in_dword_masked(\
+ HWIO_REG_860205_ADDR,\
+ HWIO_REG_860205_RMSK)
+#define HWIO_REG_860205_INM(m) \
+ in_dword_masked(HWIO_REG_860205_ADDR, m)
+#define HWIO_REG_860205_OUT(v) \
+ out_dword(HWIO_REG_860205_ADDR, v)
+#define HWIO_REG_860205_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_860205_ADDR, m, v,\
+ HWIO_REG_860205_IN);
+#define HWIO_REG_860205_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_860205_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_366154_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007bc)
+#define HWIO_REG_366154_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007bc)
+#define HWIO_REG_366154_RMSK 0x1ffff
+#define HWIO_REG_366154_SHFT 0
+#define HWIO_REG_366154_IN in_dword_masked(\
+ HWIO_REG_366154_ADDR,\
+ HWIO_REG_366154_RMSK)
+#define HWIO_REG_366154_INM(m) \
+ in_dword_masked(HWIO_REG_366154_ADDR, m)
+#define HWIO_REG_366154_OUT(v) \
+ out_dword(HWIO_REG_366154_ADDR, v)
+#define HWIO_REG_366154_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_366154_ADDR, m, v,\
+ HWIO_REG_366154_IN);
+#define HWIO_REG_366154_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_366154_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_632247_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007c0)
+#define HWIO_REG_632247_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007c0)
+#define HWIO_REG_632247_RMSK 0x1ffff
+#define HWIO_REG_632247_SHFT 0
+#define HWIO_REG_632247_IN in_dword_masked(\
+ HWIO_REG_632247_ADDR,\
+ HWIO_REG_632247_RMSK)
+#define HWIO_REG_632247_INM(m) \
+ in_dword_masked(HWIO_REG_632247_ADDR, m)
+#define HWIO_REG_632247_OUT(v) \
+ out_dword(HWIO_REG_632247_ADDR, v)
+#define HWIO_REG_632247_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_632247_ADDR, m, v,\
+ HWIO_REG_632247_IN);
+#define HWIO_REG_632247_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_632247_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_709312_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007c4)
+#define HWIO_REG_709312_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007c4)
+#define HWIO_REG_709312_RMSK 0x1ffff
+#define HWIO_REG_709312_SHFT 0
+#define HWIO_REG_709312_IN in_dword_masked(\
+ HWIO_REG_709312_ADDR,\
+ HWIO_REG_709312_RMSK)
+#define HWIO_REG_709312_INM(m) \
+ in_dword_masked(HWIO_REG_709312_ADDR, m)
+#define HWIO_REG_709312_OUT(v) \
+ out_dword(HWIO_REG_709312_ADDR, v)
+#define HWIO_REG_709312_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_709312_ADDR, m, v,\
+ HWIO_REG_709312_IN);
+#define HWIO_REG_709312_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_709312_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_891367_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007c8)
+#define HWIO_REG_891367_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007c8)
+#define HWIO_REG_891367_RMSK 0x1ffff
+#define HWIO_REG_891367_SHFT 0
+#define HWIO_REG_891367_IN in_dword_masked(\
+ HWIO_REG_891367_ADDR,\
+ HWIO_REG_891367_RMSK)
+#define HWIO_REG_891367_INM(m) \
+ in_dword_masked(HWIO_REG_891367_ADDR, m)
+#define HWIO_REG_891367_OUT(v) \
+ out_dword(HWIO_REG_891367_ADDR, v)
+#define HWIO_REG_891367_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_891367_ADDR, m, v,\
+ HWIO_REG_891367_IN);
+#define HWIO_REG_891367_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_891367_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_628746_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007cc)
+#define HWIO_REG_628746_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007cc)
+#define HWIO_REG_628746_RMSK 0x1ffff
+#define HWIO_REG_628746_SHFT 0
+#define HWIO_REG_628746_IN in_dword_masked(\
+ HWIO_REG_628746_ADDR,\
+ HWIO_REG_628746_RMSK)
+#define HWIO_REG_628746_INM(m) \
+ in_dword_masked(HWIO_REG_628746_ADDR, m)
+#define HWIO_REG_628746_OUT(v) \
+ out_dword(HWIO_REG_628746_ADDR, v)
+#define HWIO_REG_628746_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_628746_ADDR, m, v,\
+ HWIO_REG_628746_IN);
+#define HWIO_REG_628746_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_628746_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_821010_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007d0)
+#define HWIO_REG_821010_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007d0)
+#define HWIO_REG_821010_RMSK 0x1ffff
+#define HWIO_REG_821010_SHFT 0
+#define HWIO_REG_821010_IN in_dword_masked(\
+ HWIO_REG_821010_ADDR,\
+ HWIO_REG_821010_RMSK)
+#define HWIO_REG_821010_INM(m) \
+ in_dword_masked(HWIO_REG_821010_ADDR, m)
+#define HWIO_REG_821010_OUT(v) \
+ out_dword(HWIO_REG_821010_ADDR, v)
+#define HWIO_REG_821010_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_821010_ADDR, m, v,\
+ HWIO_REG_821010_IN);
+#define HWIO_REG_821010_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_821010_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_902098_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007d4)
+#define HWIO_REG_902098_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007d4)
+#define HWIO_REG_902098_RMSK 0x1ffff
+#define HWIO_REG_902098_SHFT 0
+#define HWIO_REG_902098_IN in_dword_masked(\
+ HWIO_REG_902098_ADDR,\
+ HWIO_REG_902098_RMSK)
+#define HWIO_REG_902098_INM(m) \
+ in_dword_masked(HWIO_REG_902098_ADDR, m)
+#define HWIO_REG_902098_OUT(v) \
+ out_dword(HWIO_REG_902098_ADDR, v)
+#define HWIO_REG_902098_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_902098_ADDR, m, v,\
+ HWIO_REG_902098_IN);
+#define HWIO_REG_902098_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_902098_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_939091_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007d8)
+#define HWIO_REG_939091_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007d8)
+#define HWIO_REG_939091_RMSK 0x1ffff
+#define HWIO_REG_939091_SHFT 0
+#define HWIO_REG_939091_IN in_dword_masked(\
+ HWIO_REG_939091_ADDR,\
+ HWIO_REG_939091_RMSK)
+#define HWIO_REG_939091_INM(m) \
+ in_dword_masked(HWIO_REG_939091_ADDR, m)
+#define HWIO_REG_939091_OUT(v) \
+ out_dword(HWIO_REG_939091_ADDR, v)
+#define HWIO_REG_939091_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_939091_ADDR, m, v,\
+ HWIO_REG_939091_IN);
+#define HWIO_REG_939091_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_939091_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_261074_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007dc)
+#define HWIO_REG_261074_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007dc)
+#define HWIO_REG_261074_RMSK 0x1ffff
+#define HWIO_REG_261074_SHFT 0
+#define HWIO_REG_261074_IN in_dword_masked(\
+ HWIO_REG_261074_ADDR,\
+ HWIO_REG_261074_RMSK)
+#define HWIO_REG_261074_INM(m) \
+ in_dword_masked(HWIO_REG_261074_ADDR, m)
+#define HWIO_REG_261074_OUT(v) \
+ out_dword(HWIO_REG_261074_ADDR, v)
+#define HWIO_REG_261074_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_261074_ADDR, m, v,\
+ HWIO_REG_261074_IN);
+#define HWIO_REG_261074_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_261074_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_157718_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007e0)
+#define HWIO_REG_157718_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007e0)
+#define HWIO_REG_157718_RMSK 0x1ffff
+#define HWIO_REG_157718_SHFT 0
+#define HWIO_REG_157718_IN in_dword_masked(\
+ HWIO_REG_157718_ADDR,\
+ HWIO_REG_157718_RMSK)
+#define HWIO_REG_157718_INM(m) \
+ in_dword_masked(HWIO_REG_157718_ADDR, m)
+#define HWIO_REG_157718_OUT(v) \
+ out_dword(HWIO_REG_157718_ADDR, v)
+#define HWIO_REG_157718_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_157718_ADDR, m, v,\
+ HWIO_REG_157718_IN);
+#define HWIO_REG_5552391_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_5552391_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_148889_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007e8)
+#define HWIO_REG_148889_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007e8)
+#define HWIO_REG_148889_RMSK 0x1ffff
+#define HWIO_REG_148889_SHFT 0
+#define HWIO_REG_148889_IN in_dword_masked(\
+ HWIO_REG_148889_ADDR,\
+ HWIO_REG_148889_RMSK)
+#define HWIO_REG_148889_INM(m) \
+ in_dword_masked(HWIO_REG_148889_ADDR, m)
+#define HWIO_REG_148889_OUT(v) \
+ out_dword(HWIO_REG_148889_ADDR, v)
+#define HWIO_REG_148889_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_148889_ADDR, m, v,\
+ HWIO_REG_148889_IN);
+#define HWIO_REG_148889_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_148889_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_396380_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007ec)
+#define HWIO_REG_396380_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007ec)
+#define HWIO_REG_396380_RMSK 0x1ffff
+#define HWIO_REG_396380_SHFT 0
+#define HWIO_REG_396380_IN in_dword_masked(\
+ HWIO_REG_396380_ADDR,\
+ HWIO_REG_396380_RMSK)
+#define HWIO_REG_396380_INM(m) \
+ in_dword_masked(HWIO_REG_396380_ADDR, m)
+#define HWIO_REG_396380_OUT(v) \
+ out_dword(HWIO_REG_396380_ADDR, v)
+#define HWIO_REG_396380_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_396380_ADDR, m, v,\
+ HWIO_REG_396380_IN);
+#define HWIO_REG_396380_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_396380_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_351005_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007f0)
+#define HWIO_REG_351005_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007f0)
+#define HWIO_REG_351005_RMSK 0x1ffff
+#define HWIO_REG_351005_SHFT 0
+#define HWIO_REG_351005_IN in_dword_masked(\
+ HWIO_REG_351005_ADDR,\
+ HWIO_REG_351005_RMSK)
+#define HWIO_REG_351005_INM(m) \
+ in_dword_masked(HWIO_REG_351005_ADDR, m)
+#define HWIO_REG_351005_OUT(v) \
+ out_dword(HWIO_REG_351005_ADDR, v)
+#define HWIO_REG_351005_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_351005_ADDR, m, v,\
+ HWIO_REG_351005_IN);
+#define HWIO_REG_351005_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_351005_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_863263_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007f4)
+#define HWIO_REG_863263_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007f4)
+#define HWIO_REG_863263_RMSK 0x1ffff
+#define HWIO_REG_863263_SHFT 0
+#define HWIO_REG_863263_IN in_dword_masked(\
+ HWIO_REG_863263_ADDR,\
+ HWIO_REG_863263_RMSK)
+#define HWIO_REG_863263_INM(m) \
+ in_dword_masked(HWIO_REG_863263_ADDR, m)
+#define HWIO_REG_863263_OUT(v) \
+ out_dword(HWIO_REG_863263_ADDR, v)
+#define HWIO_REG_863263_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_863263_ADDR, m, v,\
+ HWIO_REG_863263_IN);
+#define HWIO_REG_863263_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_863263_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_135009_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007f8)
+#define HWIO_REG_135009_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007f8)
+#define HWIO_REG_135009_RMSK 0x1ffff
+#define HWIO_REG_135009_SHFT 0
+#define HWIO_REG_135009_IN in_dword_masked(\
+ HWIO_REG_135009_ADDR,\
+ HWIO_REG_135009_RMSK)
+#define HWIO_REG_135009_INM(m) \
+ in_dword_masked(HWIO_REG_135009_ADDR, m)
+#define HWIO_REG_135009_OUT(v) \
+ out_dword(HWIO_REG_135009_ADDR, v)
+#define HWIO_REG_135009_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_135009_ADDR, m, v,\
+ HWIO_REG_135009_IN);
+#define HWIO_REG_135009_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_135009_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_923883_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x000007fc)
+#define HWIO_REG_923883_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000007fc)
+#define HWIO_REG_923883_RMSK 0x1ffff
+#define HWIO_REG_923883_SHFT 0
+#define HWIO_REG_923883_IN in_dword_masked(\
+ HWIO_REG_923883_ADDR,\
+ HWIO_REG_923883_RMSK)
+#define HWIO_REG_923883_INM(m) \
+ in_dword_masked(HWIO_REG_923883_ADDR, m)
+#define HWIO_REG_923883_OUT(v) \
+ out_dword(HWIO_REG_923883_ADDR, v)
+#define HWIO_REG_923883_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_923883_ADDR, m, v,\
+ HWIO_REG_923883_IN);
+#define HWIO_REG_923883_BASE_ADDR_BMSK 0x1ffff
+#define HWIO_REG_923883_BASE_ADDR_SHFT 0
+
+#define HWIO_REG_934655_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000818)
+#define HWIO_REG_934655_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000818)
+#define HWIO_REG_934655_RMSK 0x1fff
+#define HWIO_REG_934655_SHFT 0
+#define HWIO_REG_934655_IN \
+ in_dword_masked(HWIO_REG_934655_ADDR, HWIO_REG_934655_RMSK)
+#define HWIO_REG_934655_INM(m) \
+ in_dword_masked(HWIO_REG_934655_ADDR, m)
+#define HWIO_REG_934655_OUT(v) \
+ out_dword(HWIO_REG_934655_ADDR, v)
+#define HWIO_REG_934655_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_934655_ADDR, m, v, HWIO_REG_934655_IN);
+#define HWIO_REG_934655_FRAME_WIDTH_BMSK 0x1fff
+#define HWIO_REG_934655_FRAME_WIDTH_SHFT 0
+
+#define HWIO_REG_179070_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000081c)
+#define HWIO_REG_179070_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000081c)
+#define HWIO_REG_179070_RMSK 0x1fff
+#define HWIO_REG_179070_SHFT 0
+#define HWIO_REG_179070_IN in_dword_masked(\
+ HWIO_REG_179070_ADDR, HWIO_REG_179070_RMSK)
+#define HWIO_REG_179070_INM(m) \
+ in_dword_masked(HWIO_REG_179070_ADDR, m)
+#define HWIO_REG_179070_OUT(v) \
+ out_dword(HWIO_REG_179070_ADDR, v)
+#define HWIO_REG_179070_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_179070_ADDR, m, v, HWIO_REG_179070_IN);
+#define HWIO_REG_179070_FRAME_HEIGHT_BMSK 0x1fff
+#define HWIO_REG_179070_FRAME_HEIGHT_SHFT 0
+
+#define HWIO_REG_63643_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000830)
+#define HWIO_REG_63643_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000830)
+#define HWIO_REG_63643_RMSK 0xff3f
+#define HWIO_REG_63643_SHFT 0
+#define HWIO_REG_63643_IN in_dword_masked(\
+ HWIO_REG_63643_ADDR, HWIO_REG_63643_RMSK)
+#define HWIO_REG_63643_INM(m) \
+ in_dword_masked(HWIO_REG_63643_ADDR, m)
+#define HWIO_REG_63643_OUT(v) \
+ out_dword(HWIO_REG_63643_ADDR, v)
+#define HWIO_REG_63643_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_63643_ADDR, m, v, HWIO_REG_63643_IN);
+#define HWIO_REG_63643_LEVEL_BMSK 0xff00
+#define HWIO_REG_63643_LEVEL_SHFT 0x8
+#define HWIO_REG_63643_PROFILE_BMSK 0x3f
+#define HWIO_REG_63643_PROFILE_SHFT 0
+
+#define HWIO_REG_786024_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000083c)
+#define HWIO_REG_786024_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000083c)
+#define HWIO_REG_786024_RMSK 0x1
+#define HWIO_REG_786024_SHFT 0
+#define HWIO_REG_786024_IN in_dword_masked(\
+ HWIO_REG_786024_ADDR, HWIO_REG_786024_RMSK)
+#define HWIO_REG_786024_INM(m) \
+ in_dword_masked(HWIO_REG_786024_ADDR, m)
+#define HWIO_REG_786024_OUT(v) \
+ out_dword(HWIO_REG_786024_ADDR, v)
+#define HWIO_REG_786024_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_786024_ADDR, m, v, HWIO_REG_786024_IN);
+#define HWIO_REG_786024_FIELD_BMSK 0x1
+#define HWIO_REG_786024_FIELD_SHFT 0
+
+#define HWIO_REG_152500_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000848)
+#define HWIO_REG_152500_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000848)
+#define HWIO_REG_152500_RMSK 0x3
+#define HWIO_REG_152500_SHFT 0
+#define HWIO_REG_152500_IN in_dword_masked(\
+ HWIO_REG_152500_ADDR, HWIO_REG_152500_RMSK)
+#define HWIO_REG_152500_INM(m) \
+ in_dword_masked(HWIO_REG_152500_ADDR, m)
+#define HWIO_REG_152500_OUT(v) \
+ out_dword(HWIO_REG_152500_ADDR, v)
+#define HWIO_REG_152500_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_152500_ADDR, m, v, HWIO_REG_152500_IN);
+#define HWIO_REG_152500_LF_CONTROL_BMSK 0x3
+#define HWIO_REG_152500_LF_CONTROL_SHFT 0
+
+#define HWIO_REG_266285_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000084c)
+#define HWIO_REG_266285_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000084c)
+#define HWIO_REG_266285_RMSK 0x1f
+#define HWIO_REG_266285_SHFT 0
+#define HWIO_REG_266285_IN in_dword_masked(\
+ HWIO_REG_266285_ADDR, HWIO_REG_266285_RMSK)
+#define HWIO_REG_266285_INM(m) \
+ in_dword_masked(HWIO_REG_266285_ADDR, m)
+#define HWIO_REG_266285_OUT(v) \
+ out_dword(HWIO_REG_266285_ADDR, v)
+#define HWIO_REG_266285_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_266285_ADDR, m, v, HWIO_REG_266285_IN);
+#define HWIO_REG_266285_LF_ALPHAS_OFF_BMSK 0x1f
+#define HWIO_REG_266285_LF_ALPHAS_OFF_SHFT 0
+
+#define HWIO_REG_964731_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000850)
+#define HWIO_REG_964731_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000850)
+#define HWIO_REG_964731_RMSK 0x1f
+#define HWIO_REG_964731_SHFT 0
+#define HWIO_REG_964731_IN in_dword_masked(\
+ HWIO_REG_964731_ADDR, HWIO_REG_964731_RMSK)
+#define HWIO_REG_964731_INM(m) \
+ in_dword_masked(HWIO_REG_964731_ADDR, m)
+#define HWIO_REG_964731_OUT(v) \
+ out_dword(HWIO_REG_964731_ADDR, v)
+#define HWIO_REG_964731_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_964731_ADDR, m, v, HWIO_REG_964731_IN);
+#define HWIO_REG_964731_LF_BETA_OFF_BMSK 0x1f
+#define HWIO_REG_964731_LF_BETA_OFF_SHFT 0
+
+#define HWIO_REG_919924_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000c30)
+#define HWIO_REG_919924_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000c30)
+#define HWIO_REG_919924_RMSK 0xffffffff
+#define HWIO_REG_919924_SHFT 0
+#define HWIO_REG_919924_IN in_dword_masked(\
+ HWIO_REG_919924_ADDR, HWIO_REG_919924_RMSK)
+#define HWIO_REG_919924_INM(m) \
+ in_dword_masked(HWIO_REG_919924_ADDR, m)
+#define HWIO_REG_919924_OUT(v) \
+ out_dword(HWIO_REG_919924_ADDR, v)
+#define HWIO_REG_919924_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_919924_ADDR, m, v, HWIO_REG_919924_IN);
+#define HWIO_REG_919924_VIDC_QP_OFFSET_BMSK 0xffffffff
+#define HWIO_REG_919924_VIDC_QP_OFFSET_SHFT 0
+
+#define HWIO_REG_143629_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00000c34)
+#define HWIO_REG_143629_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00000c34)
+#define HWIO_REG_143629_RMSK 0x1
+#define HWIO_REG_143629_SHFT 0
+#define HWIO_REG_143629_IN in_dword_masked(\
+ HWIO_REG_143629_ADDR, HWIO_REG_143629_RMSK)
+#define HWIO_REG_143629_INM(m) \
+ in_dword_masked(HWIO_REG_143629_ADDR, m)
+#define HWIO_REG_143629_OUT(v) \
+ out_dword(HWIO_REG_143629_ADDR, v)
+#define HWIO_REG_143629_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_143629_ADDR, m, v, HWIO_REG_143629_IN);
+#define HWIO_REG_143629_REG_143629_BMSK 0x1
+#define HWIO_REG_143629_REG_143629_SHFT 0
+
+#define HWIO_REG_607589_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002000)
+#define HWIO_REG_607589_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002000)
+#define HWIO_REG_607589_RMSK 0xffffffff
+#define HWIO_REG_607589_SHFT 0
+#define HWIO_REG_607589_IN in_dword_masked(\
+ HWIO_REG_607589_ADDR, HWIO_REG_607589_RMSK)
+#define HWIO_REG_607589_INM(m) \
+ in_dword_masked(HWIO_REG_607589_ADDR, m)
+#define HWIO_REG_607589_OUT(v) \
+ out_dword(HWIO_REG_607589_ADDR, v)
+#define HWIO_REG_607589_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_607589_ADDR, m, v, HWIO_REG_607589_IN);
+#define HWIO_REG_607589_RTN_CHID_BMSK 0xffffffff
+#define HWIO_REG_607589_RTN_CHID_SHFT 0
+
+#define HWIO_REG_845544_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002004)
+#define HWIO_REG_845544_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002004)
+#define HWIO_REG_845544_RMSK 0xffffffff
+#define HWIO_REG_845544_SHFT 0
+#define HWIO_REG_845544_IN in_dword_masked(\
+ HWIO_REG_845544_ADDR, HWIO_REG_845544_RMSK)
+#define HWIO_REG_845544_INM(m) \
+ in_dword_masked(HWIO_REG_845544_ADDR, m)
+#define HWIO_REG_845544_OUT(v) \
+ out_dword(HWIO_REG_845544_ADDR, v)
+#define HWIO_REG_845544_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_845544_ADDR, m, v, HWIO_REG_845544_IN);
+#define HWIO_REG_845544_REG_845544_BMSK 0xffffffff
+#define HWIO_REG_845544_REG_845544_SHFT 0
+
+#define HWIO_REG_859906_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002008)
+#define HWIO_REG_859906_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002008)
+#define HWIO_REG_859906_RMSK 0xffffffff
+#define HWIO_REG_859906_SHFT 0
+#define HWIO_REG_859906_IN in_dword_masked(\
+ HWIO_REG_859906_ADDR, HWIO_REG_859906_RMSK)
+#define HWIO_REG_859906_INM(m) \
+ in_dword_masked(HWIO_REG_859906_ADDR, m)
+#define HWIO_REG_859906_OUT(v) \
+ out_dword(HWIO_REG_859906_ADDR, v)
+#define HWIO_REG_859906_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_859906_ADDR, m, v, HWIO_REG_859906_IN);
+#define HWIO_REG_859906_REG_859906_BMSK 0xffffffff
+#define HWIO_REG_859906_REG_859906_SHFT 0
+
+#define HWIO_REG_490078_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000200c)
+#define HWIO_REG_490078_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000200c)
+#define HWIO_REG_490078_RMSK 0xffffffff
+#define HWIO_REG_490078_SHFT 0
+#define HWIO_REG_490078_IN in_dword_masked(\
+ HWIO_REG_490078_ADDR, HWIO_REG_490078_RMSK)
+#define HWIO_REG_490078_INM(m) \
+ in_dword_masked(HWIO_REG_490078_ADDR, m)
+#define HWIO_REG_490078_OUT(v) \
+ out_dword(HWIO_REG_490078_ADDR, v)
+#define HWIO_REG_490078_OUTM(m, v) \
+ out_dword_masked_ns(HWIO_REG_490078_ADDR, m, v,\
+ HWIO_REG_490078_IN);
+#define HWIO_REG_490078_REG_490078_BMSK 0xffffffff
+#define HWIO_REG_490078_REG_490078_SHFT 0
+
+#define HWIO_REG_640904_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002010)
+#define HWIO_REG_640904_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002010)
+#define HWIO_REG_640904_RMSK 0xffffffff
+#define HWIO_REG_640904_SHFT 0
+#define HWIO_REG_640904_IN in_dword_masked(\
+ HWIO_REG_640904_ADDR, HWIO_REG_640904_RMSK)
+#define HWIO_REG_640904_INM(m) \
+ in_dword_masked(HWIO_REG_640904_ADDR, m)
+#define HWIO_REG_640904_OUT(v) \
+ out_dword(HWIO_REG_640904_ADDR, v)
+#define HWIO_REG_640904_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_640904_ADDR, m, v, HWIO_REG_640904_IN);
+#define HWIO_REG_640904_REG_640904_BMSK 0xffffffff
+#define HWIO_REG_640904_REG_640904_SHFT 0
+
+#define HWIO_REG_60114_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002014)
+#define HWIO_REG_60114_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002014)
+#define HWIO_REG_60114_RMSK 0xffffffff
+#define HWIO_REG_60114_SHFT 0
+#define HWIO_REG_60114_IN in_dword_masked(\
+ HWIO_REG_60114_ADDR, HWIO_REG_60114_RMSK)
+#define HWIO_REG_60114_INM(m) \
+ in_dword_masked(HWIO_REG_60114_ADDR, m)
+#define HWIO_REG_60114_OUT(v) \
+ out_dword(HWIO_REG_60114_ADDR, v)
+#define HWIO_REG_60114_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_60114_ADDR, m, v, HWIO_REG_60114_IN);
+#define HWIO_REG_60114_REG_60114_BMSK 0xffffffff
+#define HWIO_REG_60114_REG_60114_SHFT 0
+
+#define HWIO_REG_489688_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002018)
+#define HWIO_REG_489688_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002018)
+#define HWIO_REG_489688_RMSK 0xffffffff
+#define HWIO_REG_489688_SHFT 0
+#define HWIO_REG_489688_IN in_dword_masked(\
+ HWIO_REG_489688_ADDR, HWIO_REG_489688_RMSK)
+#define HWIO_REG_489688_INM(m) \
+ in_dword_masked(HWIO_REG_489688_ADDR, m)
+#define HWIO_REG_489688_OUT(v) \
+ out_dword(HWIO_REG_489688_ADDR, v)
+#define HWIO_REG_489688_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_489688_ADDR, m, v, HWIO_REG_489688_IN);
+#define HWIO_REG_489688_REG_489688_BMSK 0xffffffff
+#define HWIO_REG_489688_REG_489688_SHFT 0
+
+#define HWIO_REG_853667_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000201c)
+#define HWIO_REG_853667_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000201c)
+#define HWIO_REG_853667_RMSK 0xffffffff
+#define HWIO_REG_853667_SHFT 0
+#define HWIO_REG_853667_IN in_dword_masked(\
+ HWIO_REG_853667_ADDR, HWIO_REG_853667_RMSK)
+#define HWIO_REG_853667_INM(m) \
+ in_dword_masked(HWIO_REG_853667_ADDR, m)
+#define HWIO_REG_853667_OUT(v) \
+ out_dword(HWIO_REG_853667_ADDR, v)
+#define HWIO_REG_853667_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_853667_ADDR, m, v, HWIO_REG_853667_IN);
+#define HWIO_REG_853667_REG_853667_BMSK 0xffffffff
+#define HWIO_REG_853667_REG_853667_SHFT 0
+
+#define HWIO_REG_760102_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002020)
+#define HWIO_REG_760102_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002020)
+#define HWIO_REG_760102_RMSK 0xffffffff
+#define HWIO_REG_760102_SHFT 0
+#define HWIO_REG_760102_IN in_dword_masked(\
+ HWIO_REG_760102_ADDR, HWIO_REG_760102_RMSK)
+#define HWIO_REG_760102_INM(m) \
+ in_dword_masked(HWIO_REG_760102_ADDR, m)
+#define HWIO_REG_760102_OUT(v) \
+ out_dword(HWIO_REG_760102_ADDR, v)
+#define HWIO_REG_760102_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_760102_ADDR, m, v, HWIO_REG_760102_IN);
+#define HWIO_REG_760102_REG_760102_BMSK 0xffffffff
+#define HWIO_REG_760102_REG_760102_SHFT 0
+
+#define HWIO_REG_378318_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002024)
+#define HWIO_REG_378318_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002024)
+#define HWIO_REG_378318_RMSK 0xffffffff
+#define HWIO_REG_378318_SHFT 0
+#define HWIO_REG_378318_IN in_dword_masked(\
+ HWIO_REG_378318_ADDR, HWIO_REG_378318_RMSK)
+#define HWIO_REG_378318_INM(m) \
+ in_dword_masked(HWIO_REG_378318_ADDR, m)
+#define HWIO_REG_378318_OUT(v) \
+ out_dword(HWIO_REG_378318_ADDR, v)
+#define HWIO_REG_378318_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_378318_ADDR, m, v, HWIO_REG_378318_IN);
+#define HWIO_REG_378318_REG_378318_BMSK 0xffffffff
+#define HWIO_REG_378318_REG_378318_SHFT 0
+
+#define HWIO_REG_203487_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002028)
+#define HWIO_REG_203487_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002028)
+#define HWIO_REG_203487_RMSK 0xffffffff
+#define HWIO_REG_203487_SHFT 0
+#define HWIO_REG_203487_IN in_dword_masked(\
+ HWIO_REG_203487_ADDR, HWIO_REG_203487_RMSK)
+#define HWIO_REG_203487_INM(m) \
+ in_dword_masked(HWIO_REG_203487_ADDR, m)
+#define HWIO_REG_203487_OUT(v) \
+ out_dword(HWIO_REG_203487_ADDR, v)
+#define HWIO_REG_203487_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_203487_ADDR, m, v, HWIO_REG_203487_IN);
+#define HWIO_REG_203487_REG_203487_BMSK 0xffffffff
+#define HWIO_REG_203487_REG_203487_SHFT 0
+
+#define HWIO_REG_692991_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000202c)
+#define HWIO_REG_692991_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000202c)
+#define HWIO_REG_692991_RMSK 0xffffffff
+#define HWIO_REG_692991_SHFT 0
+#define HWIO_REG_692991_IN in_dword_masked(\
+ HWIO_REG_692991_ADDR, HWIO_REG_692991_RMSK)
+#define HWIO_REG_692991_INM(m) \
+ in_dword_masked(HWIO_REG_692991_ADDR, m)
+#define HWIO_REG_692991_OUT(v) \
+ out_dword(HWIO_REG_692991_ADDR, v)
+#define HWIO_REG_692991_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_692991_ADDR, m, v, HWIO_REG_692991_IN);
+#define HWIO_REG_692991_REG_692991_BMSK 0xffffffff
+#define HWIO_REG_692991_REG_692991_SHFT 0
+
+#define HWIO_REG_161740_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002030)
+#define HWIO_REG_161740_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002030)
+#define HWIO_REG_161740_RMSK 0xffffffff
+#define HWIO_REG_161740_SHFT 0
+#define HWIO_REG_161740_IN in_dword_masked(\
+ HWIO_REG_161740_ADDR, HWIO_REG_161740_RMSK)
+#define HWIO_REG_161740_INM(m) \
+ in_dword_masked(HWIO_REG_161740_ADDR, m)
+#define HWIO_REG_161740_OUT(v) \
+ out_dword(HWIO_REG_161740_ADDR, v)
+#define HWIO_REG_161740_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_161740_ADDR, m, v, HWIO_REG_161740_IN);
+#define HWIO_REG_161740_REG_161740_BMSK 0xffffffff
+#define HWIO_REG_161740_REG_161740_SHFT 0
+
+#define HWIO_REG_930239_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002034)
+#define HWIO_REG_930239_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002034)
+#define HWIO_REG_930239_RMSK 0xffffffff
+#define HWIO_REG_930239_SHFT 0
+#define HWIO_REG_930239_IN in_dword_masked(\
+ HWIO_REG_930239_ADDR, HWIO_REG_930239_RMSK)
+#define HWIO_REG_930239_INM(m) \
+ in_dword_masked(HWIO_REG_930239_ADDR, m)
+#define HWIO_REG_930239_OUT(v) \
+ out_dword(HWIO_REG_930239_ADDR, v)
+#define HWIO_REG_930239_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_930239_ADDR, m, v, HWIO_REG_930239_IN);
+#define HWIO_REG_930239_REG_930239_BMSK 0xffffffff
+#define HWIO_REG_930239_REG_930239_SHFT 0
+
+#define HWIO_REG_567827_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002038)
+#define HWIO_REG_567827_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002038)
+#define HWIO_REG_567827_RMSK 0xffffffff
+#define HWIO_REG_567827_SHFT 0
+#define HWIO_REG_567827_IN in_dword_masked(\
+ HWIO_REG_567827_ADDR, HWIO_REG_567827_RMSK)
+#define HWIO_REG_567827_INM(m) \
+ in_dword_masked(HWIO_REG_567827_ADDR, m)
+#define HWIO_REG_567827_OUT(v) \
+ out_dword(HWIO_REG_567827_ADDR, v)
+#define HWIO_REG_567827_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_567827_ADDR, m, v, HWIO_REG_567827_IN);
+#define HWIO_REG_567827_REG_567827_BMSK 0xffffffff
+#define HWIO_REG_567827_REG_567827_SHFT 0
+
+#define HWIO_REG_542997_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000203c)
+#define HWIO_REG_542997_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000203c)
+#define HWIO_REG_542997_RMSK 0xffffffff
+#define HWIO_REG_542997_SHFT 0
+#define HWIO_REG_542997_IN in_dword_masked(\
+ HWIO_REG_542997_ADDR, HWIO_REG_542997_RMSK)
+#define HWIO_REG_542997_INM(m) \
+ in_dword_masked(HWIO_REG_542997_ADDR, m)
+#define HWIO_REG_542997_OUT(v) \
+ out_dword(HWIO_REG_542997_ADDR, v)
+#define HWIO_REG_542997_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_542997_ADDR, m, v, HWIO_REG_542997_IN);
+#define HWIO_REG_542997_REG_542997_BMSK 0xffffffff
+#define HWIO_REG_542997_REG_542997_SHFT 0
+
+#define HWIO_REG_666957_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002040)
+#define HWIO_REG_666957_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002040)
+#define HWIO_REG_666957_RMSK 0x7ffff
+#define HWIO_REG_666957_SHFT 0
+#define HWIO_REG_666957_IN in_dword_masked(\
+ HWIO_REG_666957_ADDR, HWIO_REG_666957_RMSK)
+#define HWIO_REG_666957_INM(m) \
+ in_dword_masked(HWIO_REG_666957_ADDR, m)
+#define HWIO_REG_666957_OUT(v) \
+ out_dword(HWIO_REG_666957_ADDR, v)
+#define HWIO_REG_666957_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_666957_ADDR, m, v, HWIO_REG_666957_IN);
+#define HWIO_REG_666957_CH_DEC_TYPE_BMSK 0x70000
+#define HWIO_REG_666957_CH_DEC_TYPE_SHFT 0x10
+#define HWIO_REG_666957_CH_INST_ID_BMSK 0xffff
+#define HWIO_REG_666957_CH_INST_ID_SHFT 0
+
+#define HWIO_REG_117192_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002044)
+#define HWIO_REG_117192_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002044)
+#define HWIO_REG_117192_RMSK 0xffffffff
+#define HWIO_REG_117192_SHFT 0
+#define HWIO_REG_117192_IN in_dword_masked(\
+ HWIO_REG_117192_ADDR, HWIO_REG_117192_RMSK)
+#define HWIO_REG_117192_INM(m) \
+ in_dword_masked(HWIO_REG_117192_ADDR, m)
+#define HWIO_REG_117192_OUT(v) \
+ out_dword(HWIO_REG_117192_ADDR, v)
+#define HWIO_REG_117192_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_117192_ADDR, m, v, HWIO_REG_117192_IN);
+#define HWIO_REG_117192_REG_117192_BMSK 0xffffffff
+#define HWIO_REG_117192_REG_117192_SHFT 0
+
+#define HWIO_REG_145068_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002048)
+#define HWIO_REG_145068_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002048)
+#define HWIO_REG_145068_RMSK 0xffffffff
+#define HWIO_REG_145068_SHFT 0
+#define HWIO_REG_145068_IN in_dword_masked(\
+ HWIO_REG_145068_ADDR, HWIO_REG_145068_RMSK)
+#define HWIO_REG_145068_INM(m) \
+ in_dword_masked(HWIO_REG_145068_ADDR, m)
+#define HWIO_REG_145068_OUT(v) \
+ out_dword(HWIO_REG_145068_ADDR, v)
+#define HWIO_REG_145068_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_145068_ADDR, m, v, HWIO_REG_145068_IN);
+#define HWIO_REG_145068_REG_145068_BMSK 0xffffffff
+#define HWIO_REG_145068_REG_145068_SHFT 0
+
+#define HWIO_REG_921356_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000204c)
+#define HWIO_REG_921356_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000204c)
+#define HWIO_REG_921356_RMSK 0xffffffff
+#define HWIO_REG_921356_SHFT 0
+#define HWIO_REG_921356_IN in_dword_masked(\
+ HWIO_REG_921356_ADDR, HWIO_REG_921356_RMSK)
+#define HWIO_REG_921356_INM(m) \
+ in_dword_masked(HWIO_REG_921356_ADDR, m)
+#define HWIO_REG_921356_OUT(v) \
+ out_dword(HWIO_REG_921356_ADDR, v)
+#define HWIO_REG_921356_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_921356_ADDR, m, v, HWIO_REG_921356_IN);
+#define HWIO_REG_921356_REG_921356_BMSK 0xffffffff
+#define HWIO_REG_921356_REG_921356_SHFT 0
+
+#define HWIO_REG_612810_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002050)
+#define HWIO_REG_612810_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002050)
+#define HWIO_REG_612810_RMSK 0xffffffff
+#define HWIO_REG_612810_SHFT 0
+#define HWIO_REG_612810_IN in_dword_masked(\
+ HWIO_REG_612810_ADDR, HWIO_REG_612810_RMSK)
+#define HWIO_REG_612810_INM(m) \
+ in_dword_masked(HWIO_REG_612810_ADDR, m)
+#define HWIO_REG_612810_OUT(v) \
+ out_dword(HWIO_REG_612810_ADDR, v)
+#define HWIO_REG_612810_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_612810_ADDR, m, v, HWIO_REG_612810_IN);
+#define HWIO_REG_612810_REG_612810_BMSK 0xffffffff
+#define HWIO_REG_612810_REG_612810_SHFT 0
+
+#define HWIO_REG_175608_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002054)
+#define HWIO_REG_175608_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002054)
+#define HWIO_REG_175608_RMSK 0xffffffff
+#define HWIO_REG_175608_SHFT 0
+#define HWIO_REG_175608_IN in_dword_masked(\
+ HWIO_REG_175608_ADDR, HWIO_REG_175608_RMSK)
+#define HWIO_REG_175608_INM(m) \
+ in_dword_masked(HWIO_REG_175608_ADDR, m)
+#define HWIO_REG_175608_OUT(v) \
+ out_dword(HWIO_REG_175608_ADDR, v)
+#define HWIO_REG_175608_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_175608_ADDR, m, v, HWIO_REG_175608_IN);
+#define HWIO_REG_175608_REG_175608_BMSK 0xffffffff
+#define HWIO_REG_175608_REG_175608_SHFT 0
+
+#define HWIO_REG_190381_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002058)
+#define HWIO_REG_190381_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002058)
+#define HWIO_REG_190381_RMSK 0xffffffff
+#define HWIO_REG_190381_SHFT 0
+#define HWIO_REG_190381_IN in_dword_masked(\
+ HWIO_REG_190381_ADDR, HWIO_REG_190381_RMSK)
+#define HWIO_REG_190381_INM(m) \
+ in_dword_masked(HWIO_REG_190381_ADDR, m)
+#define HWIO_REG_190381_OUT(v) \
+ out_dword(HWIO_REG_190381_ADDR, v)
+#define HWIO_REG_190381_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_190381_ADDR, m, v, HWIO_REG_190381_IN);
+#define HWIO_REG_190381_REG_190381_BMSK 0xffffffff
+#define HWIO_REG_190381_REG_190381_SHFT 0
+
+#define HWIO_REG_85655_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000205c)
+#define HWIO_REG_85655_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000205c)
+#define HWIO_REG_85655_RMSK 0xffffffff
+#define HWIO_REG_85655_SHFT 0
+#define HWIO_REG_85655_IN in_dword_masked(\
+ HWIO_REG_85655_ADDR, HWIO_REG_85655_RMSK)
+#define HWIO_REG_85655_INM(m) \
+ in_dword_masked(HWIO_REG_85655_ADDR, m)
+#define HWIO_REG_85655_OUT(v) \
+ out_dword(HWIO_REG_85655_ADDR, v)
+#define HWIO_REG_85655_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_85655_ADDR, m, v, HWIO_REG_85655_IN);
+#define HWIO_REG_85655_REG_85655_BMSK 0xffffffff
+#define HWIO_REG_85655_REG_85655_SHFT 0
+
+#define HWIO_REG_86830_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002060)
+#define HWIO_REG_86830_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002060)
+#define HWIO_REG_86830_RMSK 0xffffffff
+#define HWIO_REG_86830_SHFT 0
+#define HWIO_REG_86830_IN in_dword_masked(\
+ HWIO_REG_86830_ADDR, HWIO_REG_86830_RMSK)
+#define HWIO_REG_86830_INM(m) \
+ in_dword_masked(HWIO_REG_86830_ADDR, m)
+#define HWIO_REG_86830_OUT(v) \
+ out_dword(HWIO_REG_86830_ADDR, v)
+#define HWIO_REG_86830_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_86830_ADDR, m, v, HWIO_REG_86830_IN);
+#define HWIO_REG_86830_REG_86830_BMSK 0xffffffff
+#define HWIO_REG_86830_REG_86830_SHFT 0
+
+#define HWIO_REG_889944_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002064)
+#define HWIO_REG_889944_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002064)
+#define HWIO_REG_889944_RMSK 0xffffffff
+#define HWIO_REG_889944_SHFT 0
+#define HWIO_REG_889944_IN in_dword_masked(\
+ HWIO_REG_889944_ADDR, HWIO_REG_889944_RMSK)
+#define HWIO_REG_889944_INM(m) \
+ in_dword_masked(HWIO_REG_889944_ADDR, m)
+#define HWIO_REG_889944_OUT(v) \
+ out_dword(HWIO_REG_889944_ADDR, v)
+#define HWIO_REG_889944_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_889944_ADDR, m, v, HWIO_REG_889944_IN);
+#define HWIO_REG_889944_HOST_WR_ADDR_BMSK 0xffffffff
+#define HWIO_REG_889944_HOST_WR_ADSR_SHFT 0
+
+#define HWIO_REG_404623_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002068)
+#define HWIO_REG_404623_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002068)
+#define HWIO_REG_404623_RMSK 0xffffffff
+#define HWIO_REG_404623_SHFT 0
+#define HWIO_REG_404623_IN in_dword_masked(\
+ HWIO_REG_404623_ADDR, HWIO_REG_404623_RMSK)
+#define HWIO_REG_404623_INM(m) \
+ in_dword_masked(HWIO_REG_404623_ADDR, m)
+#define HWIO_REG_404623_OUT(v) \
+ out_dword(HWIO_REG_404623_ADDR, v)
+#define HWIO_REG_404623_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_404623_ADDR, m, v, HWIO_REG_404623_IN);
+#define HWIO_REG_404623_REG_404623_BMSK 0xffffffff
+#define HWIO_REG_404623_REG_404623_SHFT 0
+
+#define HWIO_REG_397087_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000206c)
+#define HWIO_REG_397087_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000206c)
+#define HWIO_REG_397087_RMSK 0xffffffff
+#define HWIO_REG_397087_SHFT 0
+#define HWIO_REG_397087_IN in_dword_masked(\
+ HWIO_REG_397087_ADDR, HWIO_REG_397087_RMSK)
+#define HWIO_REG_397087_INM(m) \
+ in_dword_masked(HWIO_REG_397087_ADDR, m)
+#define HWIO_REG_397087_OUT(v) \
+ out_dword(HWIO_REG_397087_ADDR, v)
+#define HWIO_REG_397087_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_397087_ADDR, m, v, HWIO_REG_397087_IN);
+#define HWIO_REG_397087_CMD_SEQ_NUM_BMSK 0xffffffff
+#define HWIO_REG_397087_CMD_SEQ_NUM_SHFT 0
+
+#define HWIO_REG_212613_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002070)
+#define HWIO_REG_212613_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002070)
+#define HWIO_REG_212613_RMSK 0xffffffff
+#define HWIO_REG_212613_SHFT 0
+#define HWIO_REG_212613_IN in_dword_masked(\
+ HWIO_REG_212613_ADDR, HWIO_REG_212613_RMSK)
+#define HWIO_REG_212613_INM(m) \
+ in_dword_masked(HWIO_REG_212613_ADDR, m)
+#define HWIO_REG_212613_OUT(v) \
+ out_dword(HWIO_REG_212613_ADDR, v)
+#define HWIO_REG_212613_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_212613_ADDR, m, v, HWIO_REG_212613_IN);
+#define HWIO_REG_212613_REG_212613_BMSK 0xffffffff
+#define HWIO_REG_212613_REG_212613_SHFT 0
+
+#define HWIO_REG_840123_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002074)
+#define HWIO_REG_840123_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002074)
+#define HWIO_REG_840123_RMSK 0xffffffff
+#define HWIO_REG_840123_SHFT 0
+#define HWIO_REG_840123_IN in_dword_masked(\
+ HWIO_REG_840123_ADDR, HWIO_REG_840123_RMSK)
+#define HWIO_REG_840123_INM(m) \
+ in_dword_masked(HWIO_REG_840123_ADDR, m)
+#define HWIO_REG_840123_OUT(v) \
+ out_dword(HWIO_REG_840123_ADDR, v)
+#define HWIO_REG_840123_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_840123_ADDR, m, v, HWIO_REG_840123_IN);
+#define HWIO_REG_840123_REG_840123_BMSK 0xffffffff
+#define HWIO_REG_840123_REG_840123_SHFT 0
+
+#define HWIO_REG_520335_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002078)
+#define HWIO_REG_520335_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002078)
+#define HWIO_REG_520335_RMSK 0xffffffff
+#define HWIO_REG_520335_SHFT 0
+#define HWIO_REG_520335_IN in_dword_masked(\
+ HWIO_REG_520335_ADDR, HWIO_REG_520335_RMSK)
+#define HWIO_REG_520335_INM(m) \
+ in_dword_masked(HWIO_REG_520335_ADDR, m)
+#define HWIO_REG_520335_OUT(v) \
+ out_dword(HWIO_REG_520335_ADDR, v)
+#define HWIO_REG_520335_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_520335_ADDR, m, v, HWIO_REG_520335_IN);
+#define HWIO_REG_520335_REG_196943_BMSK 0xffffffff
+#define HWIO_REG_520335_REG_196943_SHFT 0
+
+#define HWIO_REG_196943_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000207c)
+#define HWIO_REG_196943_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000207c)
+#define HWIO_REG_196943_RMSK 0xffffffff
+#define HWIO_REG_196943_SHFT 0
+#define HWIO_REG_196943_IN in_dword_masked(\
+ HWIO_REG_196943_ADDR, HWIO_REG_196943_RMSK)
+#define HWIO_REG_196943_INM(m) \
+ in_dword_masked(HWIO_REG_196943_ADDR, m)
+#define HWIO_REG_196943_OUT(v) \
+ out_dword(HWIO_REG_196943_ADDR, v)
+#define HWIO_REG_196943_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_196943_ADDR, m, v, HWIO_REG_196943_IN);
+#define HWIO_REG_196943_REG_196943_BMSK 0xffffffff
+#define HWIO_REG_196943_REG_196943_SHFT 0
+
+#define HWIO_REG_313350_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002080)
+#define HWIO_REG_313350_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002080)
+#define HWIO_REG_313350_RMSK 0x7ffff
+#define HWIO_REG_313350_SHFT 0
+#define HWIO_REG_313350_IN in_dword_masked(\
+ HWIO_REG_313350_ADDR, HWIO_REG_313350_RMSK)
+#define HWIO_REG_313350_INM(m) \
+ in_dword_masked(HWIO_REG_313350_ADDR, m)
+#define HWIO_REG_313350_OUT(v) \
+ out_dword(HWIO_REG_313350_ADDR, v)
+#define HWIO_REG_313350_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_313350_ADDR, m, v, HWIO_REG_313350_IN);
+#define HWIO_REG_313350_CH_DEC_TYPE_BMSK 0x70000
+#define HWIO_REG_313350_CH_DEC_TYPE_SHFT 0x10
+#define HWIO_REG_313350_CH_INST_ID_BMSK 0xffff
+#define HWIO_REG_313350_CH_INST_ID_SHFT 0
+
+#define HWIO_REG_980194_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002084)
+#define HWIO_REG_980194_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002084)
+#define HWIO_REG_980194_RMSK 0xffffffff
+#define HWIO_REG_980194_SHFT 0
+#define HWIO_REG_980194_IN in_dword_masked(\
+ HWIO_REG_980194_ADDR, HWIO_REG_980194_RMSK)
+#define HWIO_REG_980194_INM(m) \
+ in_dword_masked(HWIO_REG_980194_ADDR, m)
+#define HWIO_REG_980194_OUT(v) \
+ out_dword(HWIO_REG_980194_ADDR, v)
+#define HWIO_REG_980194_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_980194_ADDR, m, v, HWIO_REG_980194_IN);
+#define HWIO_REG_980194_REG_980194_BMSK 0xffffffff
+#define HWIO_REG_980194_REG_980194_SHFT 0
+
+#define HWIO_REG_936704_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002088)
+#define HWIO_REG_936704_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002088)
+#define HWIO_REG_936704_RMSK 0xffffffff
+#define HWIO_REG_936704_SHFT 0
+#define HWIO_REG_936704_IN in_dword_masked(\
+ HWIO_REG_936704_ADDR, HWIO_REG_936704_RMSK)
+#define HWIO_REG_936704_INM(m) \
+ in_dword_masked(HWIO_REG_936704_ADDR, m)
+#define HWIO_REG_936704_OUT(v) \
+ out_dword(HWIO_REG_936704_ADDR, v)
+#define HWIO_REG_936704_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_936704_ADDR, m, v, HWIO_REG_936704_IN);
+#define HWIO_REG_936704_REG_936704_BMSK 0xffffffff
+#define HWIO_REG_936704_REG_936704_SHFT 0
+
+#define HWIO_REG_821977_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000208c)
+#define HWIO_REG_821977_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000208c)
+#define HWIO_REG_821977_RMSK 0xffffffff
+#define HWIO_REG_821977_SHFT 0
+#define HWIO_REG_821977_IN in_dword_masked(\
+ HWIO_REG_821977_ADDR, HWIO_REG_821977_RMSK)
+#define HWIO_REG_821977_INM(m) \
+ in_dword_masked(HWIO_REG_821977_ADDR, m)
+#define HWIO_REG_821977_OUT(v) \
+ out_dword(HWIO_REG_821977_ADDR, v)
+#define HWIO_REG_821977_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_821977_ADDR, m, v, HWIO_REG_821977_IN);
+#define HWIO_REG_821977_REG_821977_BMSK 0xffffffff
+#define HWIO_REG_821977_REG_821977_SHFT 0
+
+#define HWIO_REG_655721_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002090)
+#define HWIO_REG_655721_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002090)
+#define HWIO_REG_655721_RMSK 0xffffffff
+#define HWIO_REG_655721_SHFT 0
+#define HWIO_REG_655721_IN in_dword_masked(\
+ HWIO_REG_655721_ADDR, HWIO_REG_655721_RMSK)
+#define HWIO_REG_655721_INM(m) \
+ in_dword_masked(HWIO_REG_655721_ADDR, m)
+#define HWIO_REG_655721_OUT(v) \
+ out_dword(HWIO_REG_655721_ADDR, v)
+#define HWIO_REG_655721_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_655721_ADDR, m, v, HWIO_REG_655721_IN);
+#define HWIO_REG_655721_REG_655721_BMSK 0xffffffff
+#define HWIO_REG_655721_REG_655721_SHFT 0
+
+#define HWIO_REG_548308_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002094)
+#define HWIO_REG_548308_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002094)
+#define HWIO_REG_548308_RMSK 0xffffffff
+#define HWIO_REG_548308_SHFT 0
+#define HWIO_REG_548308_IN in_dword_masked(\
+ HWIO_REG_548308_ADDR, HWIO_REG_548308_RMSK)
+#define HWIO_REG_548308_INM(m) \
+ in_dword_masked(HWIO_REG_548308_ADDR, m)
+#define HWIO_REG_548308_OUT(v) \
+ out_dword(HWIO_REG_548308_ADDR, v)
+#define HWIO_REG_548308_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_548308_ADDR, m, v, HWIO_REG_548308_IN);
+#define HWIO_REG_548308_REG_548308_BMSK 0xffffffff
+#define HWIO_REG_548308_REG_548308_SHFT 0
+
+#define HWIO_REG_887095_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x00002098)
+#define HWIO_REG_887095_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x00002098)
+#define HWIO_REG_887095_RMSK 0xffffffff
+#define HWIO_REG_887095_SHFT 0
+#define HWIO_REG_887095_IN in_dword_masked(\
+ HWIO_REG_887095_ADDR, HWIO_REG_887095_RMSK)
+#define HWIO_REG_887095_INM(m) \
+ in_dword_masked(HWIO_REG_887095_ADDR, m)
+#define HWIO_REG_887095_OUT(v) \
+ out_dword(HWIO_REG_887095_ADDR, v)
+#define HWIO_REG_887095_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_887095_ADDR, m, v, HWIO_REG_887095_IN);
+#define HWIO_REG_887095_REG_887095_BMSK 0xffffffff
+#define HWIO_REG_887095_REG_887095_SHFT 0
+
+#define HWIO_REG_576987_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000209c)
+#define HWIO_REG_576987_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000209c)
+#define HWIO_REG_576987_RMSK 0xffffffff
+#define HWIO_REG_576987_SHFT 0
+#define HWIO_REG_576987_IN in_dword_masked(\
+ HWIO_REG_576987_ADDR, HWIO_REG_576987_RMSK)
+#define HWIO_REG_576987_INM(m) \
+ in_dword_masked(HWIO_REG_576987_ADDR, m)
+#define HWIO_REG_576987_OUT(v) \
+ out_dword(HWIO_REG_576987_ADDR, v)
+#define HWIO_REG_576987_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_576987_ADDR, m, v, HWIO_REG_576987_IN);
+#define HWIO_REG_576987_REG_576987_BMSK 0xffffffff
+#define HWIO_REG_576987_REG_576987_SHFT 0
+
+#define HWIO_REG_70448_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x000020a0)
+#define HWIO_REG_70448_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000020a0)
+#define HWIO_REG_70448_RMSK 0xffffffff
+#define HWIO_REG_70448_SHFT 0
+#define HWIO_REG_70448_IN in_dword_masked(\
+ HWIO_REG_70448_ADDR, HWIO_REG_70448_RMSK)
+#define HWIO_REG_70448_INM(m) \
+ in_dword_masked(HWIO_REG_70448_ADDR, m)
+#define HWIO_REG_70448_OUT(v) \
+ out_dword(HWIO_REG_70448_ADDR, v)
+#define HWIO_REG_70448_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_70448_ADDR, m, v, HWIO_REG_70448_IN);
+#define HWIO_REG_70448_REG_70448_BMSK 0xffffffff
+#define HWIO_REG_70448_REG_70448_SHFT 0
+
+#define HWIO_REG_652528_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x000020a4)
+#define HWIO_REG_652528_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000020a4)
+#define HWIO_REG_652528_RMSK 0xffffffff
+#define HWIO_REG_652528_SHFT 0
+#define HWIO_REG_652528_IN in_dword_masked(\
+ HWIO_REG_652528_ADDR, HWIO_REG_652528_RMSK)
+#define HWIO_REG_652528_INM(m) \
+ in_dword_masked(HWIO_REG_652528_ADDR, m)
+#define HWIO_REG_652528_OUT(v) \
+ out_dword(HWIO_REG_652528_ADDR, v)
+#define HWIO_REG_652528_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_652528_ADDR, m, v , HWIO_REG_652528_IN);
+#define HWIO_REG_652528_REG_652528_BMSK 0xffffffff
+#define HWIO_REG_652528_REG_652528_SHFT 0
+
+#define HWIO_REG_220637_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x000020a8)
+#define HWIO_REG_220637_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000020a8)
+#define HWIO_REG_220637_RMSK 0xffffffff
+#define HWIO_REG_220637_SHFT 0
+#define HWIO_REG_220637_IN in_dword_masked(\
+ HWIO_REG_220637_ADDR, HWIO_REG_220637_RMSK)
+#define HWIO_REG_220637_INM(m) \
+ in_dword_masked(HWIO_REG_220637_ADDR, m)
+#define HWIO_REG_220637_OUT(v) \
+ out_dword(HWIO_REG_220637_ADDR, v)
+#define HWIO_REG_220637_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_220637_ADDR, m, v, HWIO_REG_220637_IN);
+#define HWIO_REG_220637_REG_220637_BMSK 0xffffffff
+#define HWIO_REG_220637_REG_220637_SHFT 0
+
+#define HWIO_REG_254093_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x000020ac)
+#define HWIO_REG_254093_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000020ac)
+#define HWIO_REG_254093_RMSK 0xffffffff
+#define HWIO_REG_254093_SHFT 0
+#define HWIO_REG_254093_IN in_dword_masked(\
+ HWIO_REG_254093_ADDR, HWIO_REG_254093_RMSK)
+#define HWIO_REG_254093_INM(m) \
+ in_dword_masked(HWIO_REG_254093_ADDR, m)
+#define HWIO_REG_254093_OUT(v) \
+ out_dword(HWIO_REG_254093_ADDR, v)
+#define HWIO_REG_254093_OUTM(m, v) out_dword_masked_ns\
+ (HWIO_REG_254093_ADDR, m, v, HWIO_REG_254093_IN);
+#define HWIO_REG_254093_REG_254093_BMSK 0xffffffff
+#define HWIO_REG_254093_REG_254093_SHFT 0
+
+#define HWIO_REG_160474_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x000020b0)
+#define HWIO_REG_160474_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000020b0)
+#define HWIO_REG_160474_RMSK 0xffffffff
+#define HWIO_REG_160474_SHFT 0
+#define HWIO_REG_160474_IN in_dword_masked(\
+ HWIO_REG_160474_ADDR, HWIO_REG_160474_RMSK)
+#define HWIO_REG_160474_INM(m) \
+ in_dword_masked(HWIO_REG_160474_ADDR, m)
+#define HWIO_REG_160474_OUT(v) \
+ out_dword(HWIO_REG_160474_ADDR, v)
+#define HWIO_REG_160474_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_160474_ADDR, m, v, HWIO_REG_160474_IN);
+#define HWIO_REG_160474_REG_160474_BMSK 0xffffffff
+#define HWIO_REG_160474_REG_160474_SHFT 0
+
+#define HWIO_REG_39027_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x000020b4)
+#define HWIO_REG_39027_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000020b4)
+#define HWIO_REG_39027_RMSK 0xffffffff
+#define HWIO_REG_39027_SHFT 0
+#define HWIO_REG_39027_IN in_dword_masked(\
+ HWIO_REG_39027_ADDR, HWIO_REG_39027_RMSK)
+#define HWIO_REG_39027_INM(m) \
+ in_dword_masked(HWIO_REG_39027_ADDR, m)
+#define HWIO_REG_39027_OUT(v) \
+ out_dword(HWIO_REG_39027_ADDR, v)
+#define HWIO_REG_39027_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_39027_ADDR, m, v, HWIO_REG_39027_IN);
+#define HWIO_REG_39027_REG_39027_BMSK 0xffffffff
+#define HWIO_REG_39027_REG_39027_SHFT 0
+
+#define HWIO_REG_74049_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x000020b8)
+#define HWIO_REG_74049_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000020b8)
+#define HWIO_REG_74049_RMSK 0xffffffff
+#define HWIO_REG_74049_SHFT 0
+#define HWIO_REG_74049_IN in_dword_masked(\
+ HWIO_REG_74049_ADDR, HWIO_REG_74049_RMSK)
+#define HWIO_REG_74049_INM(m) \
+ in_dword_masked(HWIO_REG_74049_ADDR, m)
+#define HWIO_REG_74049_OUT(v) \
+ out_dword(HWIO_REG_74049_ADDR, v)
+#define HWIO_REG_74049_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_74049_ADDR, m, v, HWIO_REG_74049_IN);
+#define HWIO_REG_74049_REG_74049_BMSK 0xffffffff
+#define HWIO_REG_74049_REG_74049_SHFT 0
+
+#define HWIO_REG_697870_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x000020bc)
+#define HWIO_REG_697870_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x000020bc)
+#define HWIO_REG_697870_RMSK 0xffffffff
+#define HWIO_REG_697870_SHFT 0
+#define HWIO_REG_697870_IN in_dword_masked(\
+ HWIO_REG_697870_ADDR, HWIO_REG_697870_RMSK)
+#define HWIO_REG_697870_INM(m) \
+ in_dword_masked(HWIO_REG_697870_ADDR, m)
+#define HWIO_REG_697870_OUT(v) \
+ out_dword(HWIO_REG_697870_ADDR, v)
+#define HWIO_REG_697870_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_697870_ADDR, m, v, HWIO_REG_697870_IN);
+#define HWIO_REG_697870_REG_697870_BMSK 0xffffffff
+#define HWIO_REG_697870_REG_697870_SHFT 0
+
+#define HWIO_REG_783891_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000c504)
+#define HWIO_REG_783891_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000c504)
+#define HWIO_REG_783891_RMSK 0x7ffff
+#define HWIO_REG_783891_SHFT 0
+#define HWIO_REG_783891_IN in_dword_masked(\
+ HWIO_REG_783891_ADDR, HWIO_REG_783891_RMSK)
+#define HWIO_REG_783891_INM(m) \
+ in_dword_masked(HWIO_REG_783891_ADDR, m)
+#define HWIO_REG_783891_OUT(v) \
+ out_dword(HWIO_REG_783891_ADDR, v)
+#define HWIO_REG_783891_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_783891_ADDR, m, v, HWIO_REG_783891_IN);
+#define HWIO_REG_783891_ENC_PIC_TYPE_USE_BMSK 0x40000
+#define HWIO_REG_783891_ENC_PIC_TYPE_USE_SHFT 0x12
+#define HWIO_REG_783891_B_FRM_CTRL_BMSK 0x30000
+#define HWIO_REG_783891_B_FRM_CTRL_SHFT 0x10
+#define HWIO_REG_783891_I_FRM_CTRL_BMSK 0xffff
+#define HWIO_REG_783891_I_FRM_CTRL_SHFT 0
+
+#define HWIO_REG_226332_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000c50c)
+#define HWIO_REG_226332_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000c50c)
+#define HWIO_REG_226332_RMSK 0x7
+#define HWIO_REG_226332_SHFT 0
+#define HWIO_REG_226332_IN in_dword_masked(\
+ HWIO_REG_226332_ADDR, HWIO_REG_226332_RMSK)
+#define HWIO_REG_226332_INM(m) in_dword_masked(HWIO_REG_226332_ADDR, m)
+#define HWIO_REG_226332_OUT(v) out_dword(HWIO_REG_226332_ADDR, v)
+#define HWIO_REG_226332_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_226332_ADDR, m, v, HWIO_REG_226332_IN);
+#define HWIO_REG_226332_MSLICE_MODE_BMSK 0x6
+#define HWIO_REG_226332_MSLICE_MODE_SHFT 0x1
+#define HWIO_REG_226332_MSLICE_ENA_BMSK 0x1
+#define HWIO_REG_226332_MSLICE_ENA_SHFT 0
+
+#define HWIO_REG_696136_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000c510)
+#define HWIO_REG_696136_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000c510)
+#define HWIO_REG_696136_RMSK 0xffff
+#define HWIO_REG_696136_SHFT 0
+#define HWIO_REG_696136_IN in_dword_masked(\
+ HWIO_REG_696136_ADDR, HWIO_REG_696136_RMSK)
+#define HWIO_REG_696136_INM(m) in_dword_masked(HWIO_REG_696136_ADDR, m)
+#define HWIO_REG_696136_OUT(v) out_dword(HWIO_REG_696136_ADDR, v)
+#define HWIO_REG_696136_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_696136_ADDR, m, v, HWIO_REG_696136_IN);
+#define HWIO_REG_696136_MSLICE_MB_BMSK 0xffff
+#define HWIO_REG_696136_MSLICE_MB_SHFT 0
+
+#define HWIO_REG_515564_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000c514)
+#define HWIO_REG_515564_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000c514)
+#define HWIO_REG_515564_RMSK 0xffffffff
+#define HWIO_REG_515564_SHFT 0
+#define HWIO_REG_515564_IN in_dword_masked(\
+ HWIO_REG_515564_ADDR, HWIO_REG_515564_RMSK)
+#define HWIO_REG_515564_INM(m) \
+ in_dword_masked(HWIO_REG_515564_ADDR, m)
+#define HWIO_REG_515564_OUT(v) out_dword(HWIO_REG_515564_ADDR, v)
+#define HWIO_REG_515564_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_515564_ADDR, m, v, HWIO_REG_515564_IN);
+#define HWIO_REG_515564_MSLICE_BIT_BMSK 0xffffffff
+#define HWIO_REG_515564_MSLICE_BIT_SHFT 0
+
+#define HWIO_REG_886210_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000c518)
+#define HWIO_REG_886210_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000c518)
+#define HWIO_REG_886210_RMSK 0xffff
+#define HWIO_REG_886210_SHFT 0
+#define HWIO_REG_886210_IN in_dword_masked(\
+ HWIO_REG_886210_ADDR, HWIO_REG_886210_RMSK)
+#define HWIO_REG_886210_INM(m) in_dword_masked(HWIO_REG_886210_ADDR, m)
+#define HWIO_REG_886210_OUT(v) out_dword(HWIO_REG_886210_ADDR, v)
+#define HWIO_REG_886210_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_886210_ADDR, m, v, HWIO_REG_886210_IN);
+#define HWIO_REG_886210_CIR_NUM_BMSK 0xffff
+#define HWIO_REG_886210_CIR_NUM_SHFT 0
+
+#define HWIO_REG_645603_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000c51c)
+#define HWIO_REG_645603_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000c51c)
+#define HWIO_REG_645603_RMSK 0x3
+#define HWIO_REG_645603_SHFT 0
+#define HWIO_REG_645603_IN in_dword_masked(\
+ HWIO_REG_645603_ADDR, HWIO_REG_645603_RMSK)
+#define HWIO_REG_645603_INM(m) \
+ in_dword_masked(HWIO_REG_645603_ADDR, m)
+#define HWIO_REG_645603_OUT(v) out_dword(HWIO_REG_645603_ADDR, v)
+#define HWIO_REG_645603_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_645603_ADDR, m, v, HWIO_REG_645603_IN);
+#define HWIO_REG_645603_REG_645603_BMSK 0x3
+#define HWIO_REG_645603_REG_645603_SHFT 0
+
+#define HWIO_REG_811733_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000c520)
+#define HWIO_REG_811733_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000c520)
+#define HWIO_REG_811733_RMSK 0x80ffffff
+#define HWIO_REG_811733_SHFT 0
+#define HWIO_REG_811733_IN in_dword_masked(\
+ HWIO_REG_811733_ADDR, HWIO_REG_811733_RMSK)
+#define HWIO_REG_811733_INM(m) \
+ in_dword_masked(HWIO_REG_811733_ADDR, m)
+#define HWIO_REG_811733_OUT(v) out_dword(HWIO_REG_811733_ADDR, v)
+#define HWIO_REG_811733_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_811733_ADDR, m, v, HWIO_REG_811733_IN);
+#define HWIO_REG_811733_PAD_CTRL_ON_BMSK 0x80000000
+#define HWIO_REG_811733_PAD_CTRL_ON_SHFT 0x1f
+#define HWIO_REG_811733_CR_PAD_VIDC_BMSK 0xff0000
+#define HWIO_REG_811733_CR_PAD_VIDC_SHFT 0x10
+#define HWIO_REG_811733_CB_PAD_VIDC_BMSK 0xff00
+#define HWIO_REG_811733_CB_PAD_VIDC_SHFT 0x8
+#define HWIO_REG_811733_LUMA_PAD_VIDC_BMSK 0xff
+#define HWIO_REG_811733_LUMA_PAD_VIDC_SHFT 0
+
+#define HWIO_REG_676866_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000c588)
+#define HWIO_REG_676866_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000c588)
+#define HWIO_REG_676866_RMSK 0xffff
+#define HWIO_REG_676866_SHFT 0
+#define HWIO_REG_676866_IN in_dword_masked(\
+ HWIO_REG_676866_ADDR, HWIO_REG_676866_RMSK)
+#define HWIO_REG_676866_INM(m) \
+ in_dword_masked(HWIO_REG_676866_ADDR, m)
+#define HWIO_REG_676866_OUT(v) \
+ out_dword(HWIO_REG_676866_ADDR, v)
+#define HWIO_REG_676866_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_676866_ADDR, m, v, HWIO_REG_676866_IN);
+#define HWIO_REG_676866_REG_676866_BMSK 0xffff
+#define HWIO_REG_676866_REG_676866_SHFT 0
+
+#define HWIO_REG_54267_ADDR \
+ (VIDC_BLACKBIRD_REG_BASE + 0x0000c58c)
+#define HWIO_REG_54267_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000c58c)
+#define HWIO_REG_54267_RMSK 0xffff
+#define HWIO_REG_54267_SHFT 0
+#define HWIO_REG_54267_IN in_dword_masked(\
+ HWIO_REG_54267_ADDR,\
+ HWIO_REG_54267_RMSK)
+#define HWIO_REG_54267_INM(m) \
+ in_dword_masked(HWIO_REG_54267_ADDR, m)
+#define HWIO_REG_54267_OUT(v) \
+ out_dword(HWIO_REG_54267_ADDR, v)
+#define HWIO_REG_54267_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_54267_ADDR, m, v,\
+ HWIO_REG_54267_IN);
+#define HWIO_REG_54267_REG_54267_BMSK 0xffff
+#define HWIO_REG_54267_REG_54267_SHFT 0
+
+#define HWIO_REG_559908_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000c5a0)
+#define HWIO_REG_559908_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000c5a0)
+#define HWIO_REG_559908_RMSK 0x33f
+#define HWIO_REG_559908_SHFT 0
+#define HWIO_REG_559908_IN in_dword_masked(\
+ HWIO_REG_559908_ADDR, HWIO_REG_559908_RMSK)
+#define HWIO_REG_559908_INM(m) in_dword_masked(HWIO_REG_559908_ADDR, m)
+#define HWIO_REG_559908_OUT(v) out_dword(HWIO_REG_559908_ADDR, v)
+#define HWIO_REG_559908_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_559908_ADDR, m, v, HWIO_REG_559908_IN);
+#define HWIO_REG_559908_FR_RC_EN_BMSK 0x200
+#define HWIO_REG_559908_FR_RC_EN_SHFT 0x9
+#define HWIO_REG_559908_MB_RC_EN_BMSK 0x100
+#define HWIO_REG_559908_MB_RC_EN_SHFT 0x8
+#define HWIO_REG_559908_FRAME_QP_BMSK 0x3f
+#define HWIO_REG_559908_FRAME_QP_SHFT 0
+
+#define HWIO_REG_977937_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000d0d0)
+#define HWIO_REG_977937_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000d0d0)
+#define HWIO_REG_977937_RMSK 0xff
+#define HWIO_REG_977937_SHFT 0
+#define HWIO_REG_977937_IN in_dword_masked(\
+ HWIO_REG_977937_ADDR, HWIO_REG_977937_RMSK)
+#define HWIO_REG_977937_INM(m) in_dword_masked(HWIO_REG_977937_ADDR, m)
+#define HWIO_REG_977937_OUT(v) out_dword(HWIO_REG_977937_ADDR, v)
+#define HWIO_REG_977937_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_977937_ADDR, m, v, HWIO_REG_977937_IN);
+#define HWIO_REG_977937_FRAME_RATE_BMSK 0xff
+#define HWIO_REG_977937_FRAME_RATE_SHFT 0
+
+#define HWIO_REG_166135_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000c5a8)
+#define HWIO_REG_166135_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000c5a8)
+#define HWIO_REG_166135_RMSK 0xffffffff
+#define HWIO_REG_166135_SHFT 0
+#define HWIO_REG_166135_IN in_dword_masked(\
+ HWIO_REG_166135_ADDR, HWIO_REG_166135_RMSK)
+#define HWIO_REG_166135_INM(m) in_dword_masked(HWIO_REG_166135_ADDR, m)
+#define HWIO_REG_166135_OUT(v) out_dword(HWIO_REG_166135_ADDR, v)
+#define HWIO_REG_166135_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_166135_ADDR, m, v, HWIO_REG_166135_IN);
+#define HWIO_REG_166135_BIT_RATE_BMSK 0xffffffff
+#define HWIO_REG_166135_BIT_RATE_SHFT 0
+
+#define HWIO_REG_109072_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000c5ac)
+#define HWIO_REG_109072_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000c5ac)
+#define HWIO_REG_109072_RMSK 0x3fff
+#define HWIO_REG_109072_SHFT 0
+#define HWIO_REG_109072_IN in_dword_masked(\
+ HWIO_REG_109072_ADDR, HWIO_REG_109072_RMSK)
+#define HWIO_REG_109072_INM(m) in_dword_masked(HWIO_REG_109072_ADDR, m)
+#define HWIO_REG_109072_OUT(v) out_dword(HWIO_REG_109072_ADDR, v)
+#define HWIO_REG_109072_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_109072_ADDR, m, v, HWIO_REG_109072_IN);
+#define HWIO_REG_109072_MAX_QP_BMSK 0x3f00
+#define HWIO_REG_109072_MAX_QP_SHFT 0x8
+#define HWIO_REG_109072_MIN_QP_BMSK 0x3f
+#define HWIO_REG_109072_MIN_QP_SHFT 0
+
+#define HWIO_REG_550322_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000c5b0)
+#define HWIO_REG_550322_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000c5b0)
+#define HWIO_REG_550322_RMSK 0xffff
+#define HWIO_REG_550322_SHFT 0
+#define HWIO_REG_550322_IN in_dword_masked(\
+ HWIO_REG_550322_ADDR, HWIO_REG_550322_RMSK)
+#define HWIO_REG_550322_INM(m) in_dword_masked(HWIO_REG_550322_ADDR, m)
+#define HWIO_REG_550322_OUT(v) out_dword(HWIO_REG_550322_ADDR, v)
+#define HWIO_REG_550322_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_550322_ADDR, m, v, HWIO_REG_550322_IN);
+#define HWIO_REG_550322_REACT_PARA_BMSK 0xffff
+#define HWIO_REG_550322_REACT_PARA_SHFT 0
+
+#define HWIO_REG_949086_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000c5b4)
+#define HWIO_REG_949086_PHYS (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000c5b4)
+#define HWIO_REG_949086_RMSK 0xf
+#define HWIO_REG_949086_SHFT 0
+#define HWIO_REG_949086_IN in_dword_masked(\
+ HWIO_REG_949086_ADDR, HWIO_REG_949086_RMSK)
+#define HWIO_REG_949086_INM(m) in_dword_masked(HWIO_REG_949086_ADDR, m)
+#define HWIO_REG_949086_OUT(v) out_dword(HWIO_REG_949086_ADDR, v)
+#define HWIO_REG_949086_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_949086_ADDR, m, v, HWIO_REG_949086_IN);
+#define HWIO_REG_949086_DARK_DISABLE_BMSK 0x8
+#define HWIO_REG_949086_DARK_DISABLE_SHFT 0x3
+#define HWIO_REG_949086_SMOOTH_DISABLE_BMSK 0x4
+#define HWIO_REG_949086_SMOOTH_DISABLE_SHFT 0x2
+#define HWIO_REG_949086_STATIC_DISABLE_BMSK 0x2
+#define HWIO_REG_949086_STATIC_DISABLE_SHFT 0x1
+#define HWIO_REG_949086_ACT_DISABLE_BMSK 0x1
+#define HWIO_REG_949086_ACT_DISABLE_SHFT 0
+
+#define HWIO_REG_447796_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000d004)
+#define HWIO_REG_447796_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000d004)
+#define HWIO_REG_447796_RMSK 0x1
+#define HWIO_REG_447796_SHFT 0
+#define HWIO_REG_447796_IN in_dword_masked(\
+ HWIO_REG_447796_ADDR, HWIO_REG_447796_RMSK)
+#define HWIO_REG_447796_INM(m) \
+ in_dword_masked(HWIO_REG_447796_ADDR, m)
+#define HWIO_REG_447796_OUT(v) \
+ out_dword(HWIO_REG_447796_ADDR, v)
+#define HWIO_REG_447796_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_447796_ADDR, m, v, HWIO_REG_447796_IN);
+#define HWIO_REG_447796_REG_447796_BMSK 0x1
+#define HWIO_REG_447796_REG_447796_SHFT 0
+
+#define HWIO_REG_744348_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000d010)
+#define HWIO_REG_744348_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000d010)
+#define HWIO_REG_744348_RMSK 0x7f
+#define HWIO_REG_744348_SHFT 0
+#define HWIO_REG_744348_IN in_dword_masked(\
+ HWIO_REG_744348_ADDR, HWIO_REG_744348_RMSK)
+#define HWIO_REG_744348_INM(m) \
+ in_dword_masked(HWIO_REG_744348_ADDR, m)
+#define HWIO_REG_744348_OUT(v) \
+ out_dword(HWIO_REG_744348_ADDR, v)
+#define HWIO_REG_744348_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_744348_ADDR, m, v, HWIO_REG_744348_IN);
+#define HWIO_REG_744348_P_BMSK 0x60
+#define HWIO_REG_744348_P_SHFT 0x5
+#define HWIO_REG_744348_BMSK 0x1f
+#define HWIO_REG_744348_SHFT 0
+
+#define HWIO_REG_672163_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000d034)
+#define HWIO_REG_672163_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000d034)
+#define HWIO_REG_672163_RMSK 0x1
+#define HWIO_REG_672163_SHFT 0
+#define HWIO_REG_672163_IN in_dword_masked(\
+ HWIO_REG_672163_ADDR, HWIO_REG_672163_RMSK)
+#define HWIO_REG_672163_INM(m) \
+ in_dword_masked(HWIO_REG_672163_ADDR, m)
+#define HWIO_REG_672163_OUT(v) \
+ out_dword(HWIO_REG_672163_ADDR, v)
+#define HWIO_REG_672163_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_672163_ADDR, m, v,\
+ HWIO_REG_672163_IN);
+#define HWIO_REG_672163_ENC_TRANS_8X8_FLAG_BMSK 0x1
+#define HWIO_REG_672163_ENC_TRANS_8X8_FLAG_SHFT 0
+
+#define HWIO_REG_780908_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000d140)
+#define HWIO_REG_780908_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000d140)
+#define HWIO_REG_780908_RMSK 0x1
+#define HWIO_REG_780908_SHFT 0
+#define HWIO_REG_780908_IN in_dword_masked(\
+ HWIO_REG_780908_ADDR, HWIO_REG_780908_RMSK)
+#define HWIO_REG_780908_INM(m) in_dword_masked(\
+ HWIO_REG_780908_ADDR, m)
+#define HWIO_REG_780908_OUT(v) out_dword(\
+ HWIO_REG_780908_ADDR, v)
+#define HWIO_REG_780908_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_780908_ADDR, m, v,\
+ HWIO_REG_780908_IN)
+#define HWIO_REG_780908_REG_780908_BMSK 0x1
+#define HWIO_REG_780908_REG_780908_SHFT 0
+
+#define HWIO_REG_330132_ADDR (VIDC_BLACKBIRD_REG_BASE + 0x0000e008)
+#define HWIO_REG_330132_PHYS \
+ (VIDC_BLACKBIRD_REG_BASE_PHYS + 0x0000e008)
+#define HWIO_REG_330132_RMSK 0x1
+#define HWIO_REG_330132_SHFT 0
+#define HWIO_REG_330132_IN in_dword_masked(\
+ HWIO_REG_330132_ADDR, HWIO_REG_330132_RMSK)
+#define HWIO_REG_330132_INM(m) \
+ in_dword_masked(HWIO_REG_330132_ADDR, m)
+#define HWIO_REG_330132_OUT(v) \
+ out_dword(HWIO_REG_330132_ADDR, v)
+#define HWIO_REG_330132_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_330132_ADDR, m, v, HWIO_REG_330132_IN);
+#define HWIO_REG_330132_MPEG4_QUART_PXL_BMSK 0x1
+#define HWIO_REG_330132_MPEG4_QUART_PXL_SHFT 0
+
+
+#define VIDC_MGEN2MAXI_REG_BASE (VIDC_BASE + 0x00080000)
+#define VIDC_MGEN2MAXI_REG_BASE_PHYS 0x04480000
+
+#define HWIO_REG_916352_ADDR (VIDC_MGEN2MAXI_REG_BASE + 00000000)
+#define HWIO_REG_916352_PHYS (VIDC_MGEN2MAXI_REG_BASE_PHYS + 00000000)
+#define HWIO_REG_916352_RMSK 0xff
+#define HWIO_REG_916352_SHFT 0
+#define HWIO_REG_916352_IN in_dword_masked(\
+ HWIO_REG_916352_ADDR, HWIO_REG_916352_RMSK)
+#define HWIO_REG_916352_INM(m) \
+ in_dword_masked(HWIO_REG_916352_ADDR, m)
+#define HWIO_REG_916352_VERSION_BMSK 0xff
+#define HWIO_REG_916352_VERSION_SHFT 0
+
+#define HWIO_REG_5519_ADDR (VIDC_MGEN2MAXI_REG_BASE + 0x00000004)
+#define HWIO_REG_5519_PHYS \
+ (VIDC_MGEN2MAXI_REG_BASE_PHYS + 0x00000004)
+#define HWIO_REG_5519_RMSK 0x1
+#define HWIO_REG_5519_SHFT 0
+#define HWIO_REG_5519_IN in_dword_masked(\
+ HWIO_REG_5519_ADDR, HWIO_REG_5519_RMSK)
+#define HWIO_REG_5519_INM(m) \
+ in_dword_masked(HWIO_REG_5519_ADDR, m)
+#define HWIO_REG_5519_OUT(v) \
+ out_dword(HWIO_REG_5519_ADDR, v)
+#define HWIO_REG_5519_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_5519_ADDR, m, v, HWIO_REG_5519_IN);
+#define HWIO_REG_5519_AXI_AOOORD_BMSK 0x1
+#define HWIO_REG_5519_AXI_AOOORD_SHFT 0
+
+#define HWIO_REG_606364_ADDR (VIDC_MGEN2MAXI_REG_BASE + 0x00000008)
+#define HWIO_REG_606364_PHYS \
+ (VIDC_MGEN2MAXI_REG_BASE_PHYS + 0x00000008)
+#define HWIO_REG_606364_RMSK 0x1
+#define HWIO_REG_606364_SHFT 0
+#define HWIO_REG_606364_IN in_dword_masked(\
+ HWIO_REG_606364_ADDR, HWIO_REG_606364_RMSK)
+#define HWIO_REG_606364_INM(m) \
+ in_dword_masked(HWIO_REG_606364_ADDR, m)
+#define HWIO_REG_606364_OUT(v) \
+ out_dword(HWIO_REG_606364_ADDR, v)
+#define HWIO_REG_606364_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_606364_ADDR, m, v, HWIO_REG_606364_IN);
+#define HWIO_REG_606364_AXI_AOOOWR_BMSK 0x1
+#define HWIO_REG_606364_AXI_AOOOWR_SHFT 0
+
+#define HWIO_REG_821472_ADDR (VIDC_MGEN2MAXI_REG_BASE + 0x0000000c)
+#define HWIO_REG_821472_PHYS \
+ (VIDC_MGEN2MAXI_REG_BASE_PHYS + 0x0000000c)
+#define HWIO_REG_821472_RMSK 0xf
+#define HWIO_REG_821472_SHFT 0
+#define HWIO_REG_821472_IN in_dword_masked(\
+ HWIO_REG_821472_ADDR, HWIO_REG_821472_RMSK)
+#define HWIO_REG_821472_INM(m) \
+ in_dword_masked(HWIO_REG_821472_ADDR, m)
+#define HWIO_REG_821472_OUT(v) \
+ out_dword(HWIO_REG_821472_ADDR, v)
+#define HWIO_REG_821472_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_821472_ADDR, m, v, HWIO_REG_821472_IN);
+#define HWIO_REG_821472_AXI_TYPE_BMSK 0xf
+#define HWIO_REG_821472_AXI_TYPE_SHFT 0
+
+#define HWIO_REG_988424_ADDR \
+ (VIDC_MGEN2MAXI_REG_BASE + 0x00000010)
+#define HWIO_REG_988424_PHYS \
+ (VIDC_MGEN2MAXI_REG_BASE_PHYS + 0x00000010)
+#define HWIO_REG_988424_RMSK 0x3
+#define HWIO_REG_988424_SHFT 0
+#define HWIO_REG_988424_IN in_dword_masked(\
+ HWIO_REG_988424_ADDR,\
+ HWIO_REG_988424_RMSK)
+#define HWIO_REG_988424_INM(m) \
+ in_dword_masked(HWIO_REG_988424_ADDR, m)
+#define HWIO_REG_988424_OUT(v) \
+ out_dword(HWIO_REG_988424_ADDR, v)
+#define HWIO_REG_988424_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_988424_ADDR, m, v,\
+ HWIO_REG_988424_IN);
+#define HWIO_REG_988424_AXI_AREQPRIORITY_BMSK 0x3
+#define HWIO_REG_988424_AXI_AREQPRIORITY_SHFT 0
+
+#define HWIO_REG_471159_ADDR (VIDC_MGEN2MAXI_REG_BASE + 0x00000014)
+#define HWIO_REG_471159_PHYS (VIDC_MGEN2MAXI_REG_BASE_PHYS + 0x00000014)
+#define HWIO_REG_471159_RMSK 0x801f1111
+#define HWIO_REG_471159_SHFT 0
+#define HWIO_REG_471159_IN in_dword_masked(\
+ HWIO_REG_471159_ADDR, HWIO_REG_471159_RMSK)
+#define HWIO_REG_471159_INM(m) \
+ in_dword_masked(HWIO_REG_471159_ADDR, m)
+#define HWIO_REG_471159_OUT(v) \
+ out_dword(HWIO_REG_471159_ADDR, v)
+#define HWIO_REG_471159_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_471159_ADDR, m, v, HWIO_REG_471159_IN);
+#define HWIO_REG_471159_AXI_INTR_CLR_BMSK 0x80000000
+#define HWIO_REG_471159_AXI_INTR_CLR_SHFT 0x1f
+#define HWIO_REG_471159_AXI_WDTIMEOUT_LOG2_BMSK 0x1e0000
+#define HWIO_REG_471159_AXI_WDTIMEOUT_LOG2_SHFT 0x11
+#define HWIO_REG_471159_AXI_HALT_ON_WDTIMEOUT_BMSK 0x10000
+#define HWIO_REG_471159_AXI_HALT_ON_WDTIMEOUT_SHFT 0x10
+#define HWIO_REG_471159_AXI_HALT_ON_WR_ERR_BMSK 0x1000
+#define HWIO_REG_471159_AXI_HALT_ON_WR_ERR_SHFT 0xc
+#define HWIO_REG_471159_AXI_HALT_ON_RD_ERR_BMSK 0x100
+#define HWIO_REG_471159_AXI_HALT_ON_RD_ERR_SHFT 0x8
+#define HWIO_REG_471159_AXI_RESET_BMSK 0x10
+#define HWIO_REG_471159_AXI_RESET_SHFT 0x4
+#define HWIO_REG_471159_AXI_HALT_REQ_BMSK 0x1
+#define HWIO_REG_471159_AXI_HALT_REQ_SHFT 0
+
+#define HWIO_REG_437878_ADDR (VIDC_MGEN2MAXI_REG_BASE + 0x00000018)
+#define HWIO_REG_437878_PHYS \
+ (VIDC_MGEN2MAXI_REG_BASE_PHYS + 0x00000018)
+#define HWIO_REG_437878_RMSK 0x3333
+#define HWIO_REG_437878_SHFT 0
+#define HWIO_REG_437878_IN in_dword_masked(\
+ HWIO_REG_437878_ADDR, HWIO_REG_437878_RMSK)
+#define HWIO_REG_437878_INM(m) \
+ in_dword_masked(HWIO_REG_437878_ADDR, m)
+#define HWIO_REG_437878_AXI_WDTIMEOUT_INTR_BMSK 0x3000
+#define HWIO_REG_437878_AXI_WDTIMEOUT_INTR_SHFT 0xc
+#define HWIO_REG_437878_AXI_ERR_INTR_BMSK 0x300
+#define HWIO_REG_437878_AXI_ERR_INTR_SHFT 0x8
+#define HWIO_REG_437878_AXI_IDLE_BMSK 0x30
+#define HWIO_REG_437878_AXI_IDLE_SHFT 0x4
+#define HWIO_REG_437878_AXI_HALT_ACK_BMSK 0x3
+#define HWIO_REG_437878_AXI_HALT_ACK_SHFT 0
+
+#define HWIO_REG_736158_ADDR \
+ (VIDC_MGEN2MAXI_REG_BASE + 0x0000001c)
+#define HWIO_REG_736158_PHYS \
+ (VIDC_MGEN2MAXI_REG_BASE_PHYS + 0x0000001c)
+#define HWIO_REG_736158_RMSK 0x10fff
+#define HWIO_REG_736158_SHFT 0
+#define HWIO_REG_736158_IN in_dword_masked(\
+ HWIO_REG_736158_ADDR,\
+ HWIO_REG_736158_RMSK)
+#define HWIO_REG_736158_INM(m) \
+ in_dword_masked(HWIO_REG_736158_ADDR, m)
+#define HWIO_REG_736158_AXI_WDTIMEOUT_BMSK 0x10000
+#define HWIO_REG_736158_AXI_WDTIMEOUT_SHFT 0x10
+#define HWIO_REG_736158_AXI_ERR_BMSK 0x800
+#define HWIO_REG_736158_AXI_ERR_SHFT 0xb
+#define HWIO_REG_736158_AXI_ERR_TYPE_BMSK 0x400
+#define HWIO_REG_736158_AXI_ERR_TYPE_SHFT 0xa
+#define HWIO_REG_736158_AXI_RESP_BMSK 0x300
+#define HWIO_REG_736158_AXI_RESP_SHFT 0x8
+#define HWIO_REG_736158_AXI_MID_BMSK 0xf0
+#define HWIO_REG_736158_AXI_MID_SHFT 0x4
+#define HWIO_REG_736158_AXI_TID_BMSK 0xf
+#define HWIO_REG_736158_AXI_TID_SHFT 0
+
+#define HWIO_REG_598415_ADDR \
+ (VIDC_MGEN2MAXI_REG_BASE + 0x00000020)
+#define HWIO_REG_598415_PHYS \
+ (VIDC_MGEN2MAXI_REG_BASE_PHYS + 0x00000020)
+#define HWIO_REG_598415_RMSK 0x10fff
+#define HWIO_REG_598415_SHFT 0
+#define HWIO_REG_598415_IN in_dword_masked(\
+ HWIO_REG_598415_ADDR,\
+ HWIO_REG_598415_RMSK)
+#define HWIO_REG_598415_INM(m) \
+ in_dword_masked(HWIO_REG_598415_ADDR, m)
+#define HWIO_REG_598415_AXI_WDTIMEOUT_BMSK 0x10000
+#define HWIO_REG_598415_AXI_WDTIMEOUT_SHFT 0x10
+#define HWIO_REG_598415_AXI_ERR_BMSK 0x800
+#define HWIO_REG_598415_AXI_ERR_SHFT 0xb
+#define HWIO_REG_598415_AXI_ERR_TYPE_BMSK 0x400
+#define HWIO_REG_598415_AXI_ERR_TYPE_SHFT 0xa
+#define HWIO_REG_598415_AXI_RESP_BMSK 0x300
+#define HWIO_REG_598415_AXI_RESP_SHFT 0x8
+#define HWIO_REG_598415_AXI_MID_BMSK 0xf0
+#define HWIO_REG_598415_AXI_MID_SHFT 0x4
+#define HWIO_REG_598415_AXI_TID_BMSK 0xf
+#define HWIO_REG_598415_AXI_TID_SHFT 0
+
+#define HWIO_REG_439061_ADDR (VIDC_MGEN2MAXI_REG_BASE + 0x00000024)
+#define HWIO_REG_439061_PHYS \
+ (VIDC_MGEN2MAXI_REG_BASE_PHYS + 0x00000024)
+#define HWIO_REG_439061_RMSK 0x11111ff
+#define HWIO_REG_439061_SHFT 0
+#define HWIO_REG_439061_IN in_dword_masked(\
+ HWIO_REG_439061_ADDR, HWIO_REG_439061_RMSK)
+#define HWIO_REG_439061_INM(m) \
+ in_dword_masked(HWIO_REG_439061_ADDR, m)
+#define HWIO_REG_439061_OUT(v) \
+ out_dword(HWIO_REG_439061_ADDR, v)
+#define HWIO_REG_439061_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_439061_ADDR, m, v, HWIO_REG_439061_IN);
+#define HWIO_REG_439061_AXI_RD_LAT_REP_EN_BMSK 0x1000000
+#define HWIO_REG_439061_AXI_RD_LAT_REP_EN_SHFT 0x18
+#define HWIO_REG_439061_AXI_LSFR_EN_BMSK 0x100000
+#define HWIO_REG_439061_AXI_LSFR_EN_SHFT 0x14
+#define HWIO_REG_439061_AXI_MISR_RES_BMSK 0x10000
+#define HWIO_REG_439061_AXI_MISR_RES_SHFT 0x10
+#define HWIO_REG_439061_AXI_MISR_EN_BMSK 0x1000
+#define HWIO_REG_439061_AXI_MISR_EN_SHFT 0xc
+#define HWIO_REG_439061_AXI_MISR_WD_BMSK 0x100
+#define HWIO_REG_439061_AXI_MISR_WD_SHFT 0x8
+#define HWIO_REG_439061_AXI_CTR_EN_BMSK 0x80
+#define HWIO_REG_439061_AXI_CTR_EN_SHFT 0x7
+#define HWIO_REG_439061_AXI_CTR_RES_BMSK 0x40
+#define HWIO_REG_439061_AXI_CTR_RES_SHFT 0x6
+#define HWIO_REG_439061_AXI_TEST_ARB_SEL_BMSK 0x30
+#define HWIO_REG_439061_AXI_TEST_ARB_SEL_SHFT 0x4
+#define HWIO_REG_439061_AXI_TEST_OUT_SEL_BMSK 0xf
+#define HWIO_REG_439061_AXI_TEST_OUT_SEL_SHFT 0
+
+#define HWIO_REG_573121_ADDR \
+ (VIDC_MGEN2MAXI_REG_BASE + 0x00000028)
+#define HWIO_REG_573121_PHYS \
+ (VIDC_MGEN2MAXI_REG_BASE_PHYS + 0x00000028)
+#define HWIO_REG_573121_RMSK 0xffffffff
+#define HWIO_REG_573121_SHFT 0
+#define HWIO_REG_573121_IN in_dword_masked(\
+ HWIO_REG_573121_ADDR,\
+ HWIO_REG_573121_RMSK)
+#define HWIO_REG_573121_INM(m) \
+ in_dword_masked(HWIO_REG_573121_ADDR, m)
+#define HWIO_REG_573121_AXI_TEST_OUT_BMSK 0xffffffff
+#define HWIO_REG_573121_AXI_TEST_OUT_SHFT 0
+
+#define HWIO_REG_806413_ADDR \
+ (VIDC_MGEN2MAXI_REG_BASE + 0x0000002c)
+#define HWIO_REG_806413_PHYS \
+ (VIDC_MGEN2MAXI_REG_BASE_PHYS + 0x0000002c)
+#define HWIO_REG_806413_RMSK 0xffffffff
+#define HWIO_REG_806413_SHFT 0
+#define HWIO_REG_806413_IN in_dword_masked(\
+ HWIO_REG_806413_ADDR,\
+ HWIO_REG_806413_RMSK)
+#define HWIO_REG_806413_INM(m) \
+ in_dword_masked(HWIO_REG_806413_ADDR, m)
+#define HWIO_REG_806413_AXI_TEST_OUT_BMSK 0xffffffff
+#define HWIO_REG_806413_AXI_TEST_OUT_SHFT 0
+
+#define HWIO_REG_804110_ADDR (VIDC_MGEN2MAXI_REG_BASE + 0x00000030)
+#define HWIO_REG_804110_PHYS (VIDC_MGEN2MAXI_REG_BASE_PHYS + 0x00000030)
+#define HWIO_REG_804110_RMSK 0xc00fffff
+#define HWIO_REG_804110_SHFT 0
+#define HWIO_REG_804110_IN in_dword_masked(\
+ HWIO_REG_804110_ADDR, HWIO_REG_804110_RMSK)
+#define HWIO_REG_804110_INM(m) \
+ in_dword_masked(HWIO_REG_804110_ADDR, m)
+#define HWIO_REG_804110_OUT(v) out_dword(HWIO_REG_804110_ADDR, v)
+#define HWIO_REG_804110_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_804110_ADDR, m, v, HWIO_REG_804110_IN);
+#define HWIO_REG_804110_ENABLE_BMSK 0x80000000
+#define HWIO_REG_804110_ENABLE_SHFT 0x1f
+#define HWIO_REG_804110_CONST_VIDC_BMSK 0x40000000
+#define HWIO_REG_804110_CONST_VIDC_SHFT 0x1e
+#define HWIO_REG_804110_VIDCV_1080P_VERSION_BMSK 0xff000
+#define HWIO_REG_804110_VIDCV_1080P_VERSION_SHFT 0xc
+#define HWIO_REG_804110_MGEN2MAXI_DATA_SEL_BMSK 0xf00
+#define HWIO_REG_804110_MGEN2MAXI_DATA_SEL_SHFT 0x8
+#define HWIO_REG_804110_MGEN2MAXI_XIN_SEL_BMSK 0x80
+#define HWIO_REG_804110_MGEN2MAXI_XIN_SEL_SHFT 0x7
+#define HWIO_REG_804110_MGEN2MAXI_ARB_SEL_BMSK 0x40
+#define HWIO_REG_804110_MGEN2MAXI_ARB_SEL_SHFT 0x6
+#define HWIO_REG_804110_MGEN2MAXI_TESTBUS_SEL_BMSK 0x30
+#define HWIO_REG_804110_MGEN2MAXI_TESTBUS_SEL_SHFT 0x4
+#define HWIO_REG_804110_AHB2AHB_TESTBUS_SEL_BMSK 0x8
+#define HWIO_REG_804110_AHB2AHB_TESTBUS_SEL_SHFT 0x3
+#define HWIO_REG_804110_MGEN2MAXI_AXI_SEL_BMSK 0x4
+#define HWIO_REG_804110_MGEN2MAXI_AXI_SEL_SHFT 0x2
+#define HWIO_REG_804110_SELECT_BMSK 0x3
+#define HWIO_REG_804110_SELECT_SHFT 0
+
+#define HWIO_REG_616440_ADDR \
+ (VIDC_MGEN2MAXI_REG_BASE + 0x00000034)
+#define HWIO_REG_616440_PHYS \
+ (VIDC_MGEN2MAXI_REG_BASE_PHYS + 0x00000034)
+#define HWIO_REG_616440_RMSK 0xffff
+#define HWIO_REG_616440_SHFT 0
+#define HWIO_REG_616440_IN in_dword_masked(\
+ HWIO_REG_616440_ADDR,\
+ HWIO_REG_616440_RMSK)
+#define HWIO_REG_616440_INM(m) \
+ in_dword_masked(HWIO_REG_616440_ADDR, m)
+#define HWIO_REG_616440_OUT(v) \
+ out_dword(HWIO_REG_616440_ADDR, v)
+#define HWIO_REG_616440_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_616440_ADDR, m, v,\
+ HWIO_REG_616440_IN);
+#define HWIO_REG_616440_XBAR_IN_RD_LIM_BMSK 0xff00
+#define HWIO_REG_616440_XBAR_IN_RD_LIM_SHFT 0x8
+#define HWIO_REG_616440_XBAR_IN_WR_LIM_BMSK 0xff
+#define HWIO_REG_616440_XBAR_IN_WR_LIM_SHFT 0
+
+#define HWIO_REG_527219_ADDR \
+ (VIDC_MGEN2MAXI_REG_BASE + 0x00000038)
+#define HWIO_REG_527219_PHYS \
+ (VIDC_MGEN2MAXI_REG_BASE_PHYS + 0x00000038)
+#define HWIO_REG_527219_RMSK 0xffff
+#define HWIO_REG_527219_SHFT 0
+#define HWIO_REG_527219_IN in_dword_masked(\
+ HWIO_REG_527219_ADDR,\
+ HWIO_REG_527219_RMSK)
+#define HWIO_REG_527219_INM(m) \
+ in_dword_masked(HWIO_REG_527219_ADDR, m)
+#define HWIO_REG_527219_OUT(v) \
+ out_dword(HWIO_REG_527219_ADDR, v)
+#define HWIO_REG_527219_OUTM(m, v) \out_dword_masked_ns(\
+ HWIO_REG_527219_ADDR, m, v,\
+ HWIO_REG_527219_IN);
+#define HWIO_REG_527219_XBAR_OUT_RD_LIM_BMSK 0xff00
+#define HWIO_REG_527219_XBAR_OUT_RD_LIM_SHFT 0x8
+#define HWIO_REG_527219_XBAR_OUT_WR_LIM_BMSK 0xff
+#define HWIO_REG_527219_XBAR_OUT_WR_LIM_SHFT 0
+
+#define HWIO_REG_922106_ADDR \
+ (VIDC_MGEN2MAXI_REG_BASE + 0x0000003c)
+#define HWIO_REG_922106_PHYS \
+ (VIDC_MGEN2MAXI_REG_BASE_PHYS + 0x0000003c)
+#define HWIO_REG_922106_RMSK 0xffff
+#define HWIO_REG_922106_SHFT 0
+#define HWIO_REG_922106_IN in_dword_masked(\
+ HWIO_REG_922106_ADDR,\
+ HWIO_REG_922106_RMSK)
+#define HWIO_REG_922106_INM(m) \
+ in_dword_masked(HWIO_REG_922106_ADDR, m)
+#define HWIO_REG_922106_OUT(v) \
+ out_dword(HWIO_REG_922106_ADDR, v)
+#define HWIO_REG_922106_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_922106_ADDR, m, v,\
+ HWIO_REG_922106_IN);
+#define HWIO_REG_922106_XBAR_OUT_MAX_RD_BURST_BMSK 0xff00
+#define HWIO_REG_922106_XBAR_OUT_MAX_RD_BURST_SHFT 0x8
+#define HWIO_REG_922106_XBAR_OUT_MAX_WR_BURST_BMSK 0xff
+#define HWIO_REG_922106_XBAR_OUT_MAX_WR_BURST_SHFT 0
+
+#define VIDC_ENHANCE_REG_BASE (VIDC_BASE + 0x000c0000)
+#define VIDC_ENHANCE_REG_BASE_PHYS 0x044c0000
+
+#define HWIO_REG_261029_ADDR (VIDC_ENHANCE_REG_BASE + 00000000)
+#define HWIO_REG_261029_PHYS (VIDC_ENHANCE_REG_BASE_PHYS + 00000000)
+#define HWIO_REG_261029_RMSK 0x10f
+#define HWIO_REG_261029_SHFT 0
+#define HWIO_REG_261029_IN in_dword_masked(\
+ HWIO_REG_261029_ADDR, HWIO_REG_261029_RMSK)
+#define HWIO_REG_261029_INM(m) \
+ in_dword_masked(HWIO_REG_261029_ADDR, m)
+#define HWIO_REG_261029_OUT(v) \
+ out_dword(HWIO_REG_261029_ADDR, v)
+#define HWIO_REG_261029_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_261029_ADDR, m, v, HWIO_REG_261029_IN);
+#define HWIO_REG_261029_AUTO_INC_EN_BMSK 0x100
+#define HWIO_REG_261029_AUTO_INC_EN_SHFT 0x8
+#define HWIO_REG_261029_DMI_RAM_SEL_BMSK 0xf
+#define HWIO_REG_261029_DMI_RAM_SEL_SHFT 0
+
+#define HWIO_REG_576200_ADDR (VIDC_ENHANCE_REG_BASE + 0x00000004)
+#define HWIO_REG_576200_PHYS (VIDC_ENHANCE_REG_BASE_PHYS + 0x00000004)
+#define HWIO_REG_576200_RMSK 0x7ff
+#define HWIO_REG_576200_SHFT 0
+#define HWIO_REG_576200_IN in_dword_masked(\
+ HWIO_REG_576200_ADDR, HWIO_REG_576200_RMSK)
+#define HWIO_REG_576200_INM(m) \
+ in_dword_masked(HWIO_REG_576200_ADDR, m)
+#define HWIO_REG_576200_OUT(v) \
+ out_dword(HWIO_REG_576200_ADDR, v)
+#define HWIO_REG_576200_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_576200_ADDR, m, v, HWIO_REG_576200_IN);
+#define HWIO_REG_576200_DMI_ADDR_BMSK 0x7ff
+#define HWIO_REG_576200_DMI_ADDR_SHFT 0
+
+#define HWIO_REG_917583_ADDR (VIDC_ENHANCE_REG_BASE + 0x00000008)
+#define HWIO_REG_917583_PHYS (VIDC_ENHANCE_REG_BASE_PHYS + 0x00000008)
+#define HWIO_REG_917583_RMSK 0xffffffff
+#define HWIO_REG_917583_SHFT 0
+#define HWIO_REG_917583_IN in_dword_masked(\
+ HWIO_REG_917583_ADDR, HWIO_REG_917583_RMSK)
+#define HWIO_REG_917583_INM(m) \
+ in_dword_masked(HWIO_REG_917583_ADDR, m)
+#define HWIO_REG_917583_OUT(v) \
+ out_dword(HWIO_REG_917583_ADDR, v)
+#define HWIO_REG_917583_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_917583_ADDR, m, v, HWIO_REG_917583_IN);
+#define HWIO_REG_917583_DMI_DATA_HI_BMSK 0xffffffff
+#define HWIO_REG_917583_DMI_DATA_HI_SHFT 0
+
+#define HWIO_REG_556274_ADDR (VIDC_ENHANCE_REG_BASE + 0x0000000c)
+#define HWIO_REG_556274_PHYS (VIDC_ENHANCE_REG_BASE_PHYS + 0x0000000c)
+#define HWIO_REG_556274_RMSK 0xffffffff
+#define HWIO_REG_556274_SHFT 0
+#define HWIO_REG_556274_IN in_dword_masked(\
+ HWIO_REG_556274_ADDR, HWIO_REG_556274_RMSK)
+#define HWIO_REG_556274_INM(m) \
+ in_dword_masked(HWIO_REG_556274_ADDR, m)
+#define HWIO_REG_556274_OUT(v) \
+ out_dword(HWIO_REG_556274_ADDR, v)
+#define HWIO_REG_556274_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_556274_ADDR, m, v, HWIO_REG_556274_IN);
+#define HWIO_REG_556274_DMI_DATA_LO_BMSK 0xffffffff
+#define HWIO_REG_556274_DMI_DATA_LO_SHFT 0
+
+#define HWIO_REG_39703_ADDR (VIDC_ENHANCE_REG_BASE + 0x00000010)
+#define HWIO_REG_39703_PHYS \
+ (VIDC_ENHANCE_REG_BASE_PHYS + 0x00000010)
+#define HWIO_REG_39703_RMSK 0x1f
+#define HWIO_REG_39703_SHFT 0
+#define HWIO_REG_39703_IN in_dword_masked(\
+ HWIO_REG_39703_ADDR, HWIO_REG_39703_RMSK)
+#define HWIO_REG_39703_INM(m) \
+ in_dword_masked(HWIO_REG_39703_ADDR, m)
+#define HWIO_REG_39703_OUT(v) \
+ out_dword(HWIO_REG_39703_ADDR, v)
+#define HWIO_REG_39703_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_39703_ADDR, m, v, HWIO_REG_39703_IN);
+#define HWIO_REG_39703_PIX_CACHE_TB_SEL_BMSK 0x1f
+#define HWIO_REG_39703_PIX_CACHE_TB_SEL_SHFT 0
+
+#define HWIO_REG_169013_ADDR (VIDC_ENHANCE_REG_BASE + 0x00000014)
+#define HWIO_REG_169013_PHYS (VIDC_ENHANCE_REG_BASE_PHYS + 0x00000014)
+#define HWIO_REG_169013_RMSK 0x3
+#define HWIO_REG_169013_SHFT 0
+#define HWIO_REG_169013_IN in_dword_masked(\
+ HWIO_REG_169013_ADDR, HWIO_REG_169013_RMSK)
+#define HWIO_REG_169013_INM(m) \
+ in_dword_masked(HWIO_REG_169013_ADDR, m)
+#define HWIO_REG_169013_OUT(v) \
+ out_dword(HWIO_REG_169013_ADDR, v)
+#define HWIO_REG_169013_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_169013_ADDR, m, v, HWIO_REG_169013_IN);
+#define HWIO_REG_169013_PIX_CACHE_SW_RESET_BMSK 0x2
+#define HWIO_REG_169013_PIX_CACHE_SW_RESET_SHFT 0x1
+#define HWIO_REG_169013_CRIF_RESET_BMSK 0x1
+#define HWIO_REG_169013_CRIF_RESET_SHFT 0
+
+#define HWIO_REG_22756_ADDR (VIDC_ENHANCE_REG_BASE + 0x00000018)
+#define HWIO_REG_22756_PHYS \
+ (VIDC_ENHANCE_REG_BASE_PHYS + 0x00000018)
+#define HWIO_REG_22756_RMSK 0x133f
+#define HWIO_REG_22756_SHFT 0
+#define HWIO_REG_22756_IN in_dword_masked(\
+ HWIO_REG_22756_ADDR, HWIO_REG_22756_RMSK)
+#define HWIO_REG_22756_INM(m) \
+ in_dword_masked(HWIO_REG_22756_ADDR, m)
+#define HWIO_REG_22756_OUT(v) \
+ out_dword(HWIO_REG_22756_ADDR, v)
+#define HWIO_REG_22756_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_22756_ADDR, m, v, HWIO_REG_22756_IN);
+#define HWIO_REG_22756_CACHE_HALT_BMSK 0x1000
+#define HWIO_REG_22756_CACHE_HALT_SHFT 0xc
+#define HWIO_REG_22756_PAGE_SIZE_BMSK 0x300
+#define HWIO_REG_22756_PAGE_SIZE_SHFT 0x8
+#define HWIO_REG_22756_STATISTICS_OFF_BMSK 0x20
+#define HWIO_REG_22756_STATISTICS_OFF_SHFT 0x5
+#define HWIO_REG_22756_CACHE_PORT_SELECT_BMSK 0x10
+#define HWIO_REG_22756_CACHE_PORT_SELECT_SHFT 0x4
+#define HWIO_REG_22756_PREFETCH_EN_BMSK 0x8
+#define HWIO_REG_22756_PREFETCH_EN_SHFT 0x3
+#define HWIO_REG_22756_SS_TILE_FORMAT_BMSK 0x4
+#define HWIO_REG_22756_SS_TILE_FORMAT_SHFT 0x2
+#define HWIO_REG_22756_CACHE_EN_BMSK 0x2
+#define HWIO_REG_22756_CACHE_EN_SHFT 0x1
+#define HWIO_REG_22756_CACHE_TAG_CLEAR_BMSK 0x1
+#define HWIO_REG_22756_CACHE_TAG_CLEAR_SHFT 0
+
+#define HWIO_REG_951731_ADDR \
+ (VIDC_ENHANCE_REG_BASE + 0x0000001c)
+#define HWIO_REG_951731_PHYS \
+ (VIDC_ENHANCE_REG_BASE_PHYS + 0x0000001c)
+#define HWIO_REG_951731_RMSK 0x7ff07ff
+#define HWIO_REG_951731_SHFT 0
+#define HWIO_REG_951731_IN in_dword_masked(\
+ HWIO_REG_951731_ADDR,\
+ HWIO_REG_951731_RMSK)
+#define HWIO_REG_951731_INM(m) \
+ in_dword_masked(HWIO_REG_951731_ADDR, m)
+#define HWIO_REG_951731_OUT(v) \
+ out_dword(HWIO_REG_951731_ADDR, v)
+#define HWIO_REG_951731_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_951731_ADDR, m, v,\
+ HWIO_REG_951731_IN);
+#define HWIO_REG_951731_FRAME_HEIGHT_BMSK 0x7ff0000
+#define HWIO_REG_951731_FRAME_HEIGHT_SHFT 0x10
+#define HWIO_REG_951731_FRAME_WIDTH_BMSK 0x7ff
+#define HWIO_REG_951731_FRAME_WIDTH_SHFT 0
+
+#define HWIO_REG_905239_ADDR \
+ (VIDC_ENHANCE_REG_BASE + 0x00000020)
+#define HWIO_REG_905239_PHYS \
+ (VIDC_ENHANCE_REG_BASE_PHYS + 0x00000020)
+#define HWIO_REG_905239_RMSK 0x3ffff
+#define HWIO_REG_905239_SHFT 0
+#define HWIO_REG_905239_IN in_dword_masked(\
+ HWIO_REG_905239_ADDR,\
+ HWIO_REG_905239_RMSK)
+#define HWIO_REG_905239_INM(m) \
+ in_dword_masked(HWIO_REG_905239_ADDR, m)
+#define HWIO_REG_905239_OUT(v) \
+ out_dword(HWIO_REG_905239_ADDR, v)
+#define HWIO_REG_905239_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_905239_ADDR, m, v,\
+ HWIO_REG_905239_IN);
+#define HWIO_REG_905239_LINEAR_LUMA_BMSK 0x3ffff
+#define HWIO_REG_905239_LINEAR_LUMA_SHFT 0
+#define HWIO_REG_905239_TILE_LUMA_BMSK 0xff00
+#define HWIO_REG_905239_TILE_LUMA_SHFT 0x8
+#define HWIO_REG_905239_TILE_CHROMA_BMSK 0xff
+#define HWIO_REG_905239_TILE_CHROMA_SHFT 0
+
+#define HWIO_REG_804925_ADDR(n) \
+ (VIDC_ENHANCE_REG_BASE + 0x00000024 + 4 * (n))
+#define HWIO_REG_804925_PHYS(n) \
+ (VIDC_ENHANCE_REG_BASE_PHYS + 0x00000024 + 4 * (n))
+#define HWIO_REG_804925_RMSK 0xfffffff8
+#define HWIO_REG_804925_SHFT 0
+#define HWIO_REG_804925_MAXn 0x12
+#define HWIO_REG_804925_INI(n) \
+ in_dword(HWIO_REG_804925_ADDR(n))
+#define HWIO_REG_804925_INMI(n, mask) \
+ in_dword_masked(HWIO_REG_804925_ADDR(n), mask)
+#define HWIO_REG_804925_OUTI(n, val) \
+ out_dword(HWIO_REG_804925_ADDR(n), val)
+#define HWIO_REG_804925_OUTMI(n, mask, val) \
+ out_dword_masked_ns(HWIO_REG_804925_ADDR(n),\
+ mask, val, HWIO_REG_804925_INI(n));
+#define HWIO_REG_804925_ADDR_BMSK 0xfffffff8
+#define HWIO_REG_804925_ADDR_SHFT 0x3
+
+#define HWIO_REG_41909_ADDR(n) \
+ (VIDC_ENHANCE_REG_BASE + 0x00000070 + 4 * (n))
+#define HWIO_REG_41909_PHYS(n) \
+ (VIDC_ENHANCE_REG_BASE_PHYS + 0x00000070 + 4 * (n))
+#define HWIO_REG_41909_RMSK 0xfffffff8
+#define HWIO_REG_41909_SHFT 0
+#define HWIO_REG_41909_MAXn 0x12
+#define HWIO_REG_41909_INI(n) \
+ in_dword(HWIO_REG_41909_ADDR(n))
+#define HWIO_REG_41909_INMI(n, mask) \
+ in_dword_masked(HWIO_REG_41909_ADDR(n), mask)
+#define HWIO_REG_41909_OUTI(n, val) \
+ out_dword(HWIO_REG_41909_ADDR(n), val)
+#define HWIO_REG_41909_OUTMI(n, mask, val) \
+ out_dword_masked_ns(HWIO_REG_41909_ADDR(n),\
+ mask, val, HWIO_REG_41909_INI(n));
+#define HWIO_REG_41909_ADDR_BMSK 0xfffffff8
+#define HWIO_REG_41909_ADDR_SHFT 0x3
+
+#define HWIO_REG_919904_ADDR (VIDC_ENHANCE_REG_BASE + 0x000000bc)
+#define HWIO_REG_919904_PHYS \
+ (VIDC_ENHANCE_REG_BASE_PHYS + 0x000000bc)
+#define HWIO_REG_919904_RMSK 0x1
+#define HWIO_REG_919904_SHFT 0
+#define HWIO_REG_919904_IN in_dword_masked(\
+ HWIO_REG_919904_ADDR,\
+ HWIO_REG_919904_RMSK)
+#define HWIO_REG_919904_INM(m) \
+ in_dword_masked(HWIO_REG_919904_ADDR, m)
+#define HWIO_REG_919904_IDLE_BMSK 0x1
+#define HWIO_REG_919904_IDLE_SHFT 0
+
+#define HWIO_REG_278310_ADDR \
+ (VIDC_ENHANCE_REG_BASE + 0x000000c0)
+#define HWIO_REG_278310_PHYS \
+ (VIDC_ENHANCE_REG_BASE_PHYS + 0x000000c0)
+#define HWIO_REG_278310_RMSK 0xffffffff
+#define HWIO_REG_278310_SHFT 0
+#define HWIO_REG_278310_IN in_dword_masked(\
+ HWIO_REG_278310_ADDR,\
+ HWIO_REG_278310_RMSK)
+#define HWIO_REG_278310_INM(m) \
+ in_dword_masked(HWIO_REG_278310_ADDR, m)
+#define HWIO_REG_278310_MISS_COUNT_BMSK 0xffffffff
+#define HWIO_REG_278310_MISS_COUNT_SHFT 0
+
+#define HWIO_REG_421222_ADDR \
+ (VIDC_ENHANCE_REG_BASE + 0x000000c4)
+#define HWIO_REG_421222_PHYS \
+ (VIDC_ENHANCE_REG_BASE_PHYS + 0x000000c4)
+#define HWIO_REG_421222_RMSK 0xffffffff
+#define HWIO_REG_421222_SHFT 0
+#define HWIO_REG_421222_IN in_dword_masked(\
+ HWIO_REG_421222_ADDR,\
+ HWIO_REG_421222_RMSK)
+#define HWIO_REG_421222_INM(m) \
+ in_dword_masked(HWIO_REG_421222_ADDR, m)
+#define HWIO_REG_421222_HIT_COUNT_BMSK 0xffffffff
+#define HWIO_REG_421222_HIT_COUNT_SHFT 0
+
+#define HWIO_REG_609607_ADDR \
+ (VIDC_ENHANCE_REG_BASE + 0x000000c8)
+#define HWIO_REG_609607_PHYS \
+ (VIDC_ENHANCE_REG_BASE_PHYS + 0x000000c8)
+#define HWIO_REG_609607_RMSK 0xffffffff
+#define HWIO_REG_609607_SHFT 0
+#define HWIO_REG_609607_IN in_dword_masked(\
+ HWIO_REG_609607_ADDR,\
+ HWIO_REG_609607_RMSK)
+#define HWIO_REG_609607_INM(m) \
+ in_dword_masked(HWIO_REG_609607_ADDR, m)
+#define HWIO_REG_609607_AXI_REQUEST_COUNT_BMSK 0xffffffff
+#define HWIO_REG_609607_AXI_REQUEST_COUNT_SHFT 0
+
+#define HWIO_REG_395232_ADDR \
+ (VIDC_ENHANCE_REG_BASE + 0x000000cc)
+#define HWIO_REG_395232_PHYS \
+ (VIDC_ENHANCE_REG_BASE_PHYS + 0x000000cc)
+#define HWIO_REG_395232_RMSK 0xffffffff
+#define HWIO_REG_395232_SHFT 0
+#define HWIO_REG_395232_IN in_dword_masked(\
+ HWIO_REG_395232_ADDR,\
+ HWIO_REG_395232_RMSK)
+#define HWIO_REG_395232_INM(m) \
+ in_dword_masked(HWIO_REG_395232_ADDR, m)
+#define HWIO_REG_395232_CORE_REQUEST_COUNT_BMSK \
+ 0xffffffff
+#define HWIO_REG_395232_CORE_REQUEST_COUNT_SHFT 0
+
+#define HWIO_REG_450146_ADDR \
+ (VIDC_ENHANCE_REG_BASE + 0x000000d0)
+#define HWIO_REG_450146_PHYS \
+ (VIDC_ENHANCE_REG_BASE_PHYS + 0x000000d0)
+#define HWIO_REG_450146_RMSK 0xffffffff
+#define HWIO_REG_450146_SHFT 0
+#define HWIO_REG_450146_IN in_dword_masked(\
+ HWIO_REG_450146_ADDR,\
+ HWIO_REG_450146_RMSK)
+#define HWIO_REG_450146_INM(m) \
+ in_dword_masked(HWIO_REG_450146_ADDR, m)
+#define HWIO_REG_450146_AXI_BEAT_COUNT_BMSK 0xffffffff
+#define HWIO_REG_450146_AXI_BEAT_COUNT_SHFT 0
+
+#define HWIO_REG_610651_ADDR \
+ (VIDC_ENHANCE_REG_BASE + 0x000000d4)
+#define HWIO_REG_610651_PHYS \
+ (VIDC_ENHANCE_REG_BASE_PHYS + 0x000000d4)
+#define HWIO_REG_610651_RMSK 0xffffffff
+#define HWIO_REG_610651_SHFT 0
+#define HWIO_REG_610651_IN in_dword_masked(\
+ HWIO_REG_610651_ADDR,\
+ HWIO_REG_610651_RMSK)
+#define HWIO_REG_610651_INM(m) \
+ in_dword_masked(HWIO_REG_610651_ADDR, m)
+#define HWIO_REG_610651_CORE_BEAT_COUNT_BMSK 0xffffffff
+#define HWIO_REG_610651_CORE_BEAT_COUNT_SHFT 0
+
+#define HWIO_REG_883784_ADDR \
+ (VIDC_ENHANCE_REG_BASE + 0x000000d8)
+#define HWIO_REG_883784_PHYS \
+ (VIDC_ENHANCE_REG_BASE_PHYS + 0x000000d8)
+#define HWIO_REG_883784_RMSK 0xffffffff
+#define HWIO_REG_883784_SHFT 0
+#define HWIO_REG_883784_IN in_dword_masked(\
+ HWIO_REG_883784_ADDR,\
+ HWIO_REG_883784_RMSK)
+#define HWIO_REG_883784_INM(m) \
+ in_dword_masked(HWIO_REG_883784_ADDR, m)
+#define HWIO_REG_883784_OUT(v) \
+ out_dword(HWIO_REG_883784_ADDR, v)
+#define HWIO_REG_883784_OUTM(m, v) out_dword_masked_ns(\
+ HWIO_REG_883784_ADDR, m, v,\
+ HWIO_REG_883784_IN);
+#define HWIO_REG_883784_COUNTER_BMSK 0xffffff00
+#define HWIO_REG_883784_COUNTER_SHFT 0x8
+#define HWIO_REG_883784_ID_BMSK 0xf0
+#define HWIO_REG_883784_ID_SHFT 0x4
+#define HWIO_REG_883784_IGNORE_ID_BMSK 0x8
+#define HWIO_REG_883784_IGNORE_ID_SHFT 0x3
+#define HWIO_REG_883784_INPUT_SEL_BMSK 0x6
+#define HWIO_REG_883784_INPUT_SEL_SHFT 0x1
+#define HWIO_REG_883784_MISR_EN_BMSK 0x1
+#define HWIO_REG_883784_MISR_EN_SHFT 0
+
+#define HWIO_REG_651391_ADDR(n) \
+ (VIDC_ENHANCE_REG_BASE + 0x000000dc + 4 * (n))
+#define HWIO_REG_651391_PHYS(n) \
+ (VIDC_ENHANCE_REG_BASE_PHYS + 0x000000dc + 4 * (n))
+#define HWIO_REG_651391_RMSK 0xffffffff
+#define HWIO_REG_651391_SHFT 0
+#define HWIO_REG_651391_MAXn 0x1
+#define HWIO_REG_651391_INI(n) \
+ in_dword(HWIO_REG_651391_ADDR(n))
+#define HWIO_REG_651391_INMI(n, mask) \
+ in_dword_masked(HWIO_REG_651391_ADDR(n), mask)
+#define HWIO_REG_651391_OUTI(n, val) \
+ out_dword(HWIO_REG_651391_ADDR(n), val)
+#define HWIO_REG_651391_SIGNATURE_BMSK 0xffffffff
+#define HWIO_REG_651391_SIGNATURE_SHFT 0
+
+#endif
+
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc_pix_cache.c b/drivers/video/msm/vidc/1080p/ddl/vidc_pix_cache.c
new file mode 100644
index 0000000..6870525
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc_pix_cache.c
@@ -0,0 +1,349 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "vidc_hwio_reg.h"
+#include "vidc_hwio.h"
+#include "vidc_pix_cache.h"
+
+
+#define VIDC_1080P_MAX_DEC_DPB 19
+#define VIDC_TILE_MULTIPLY_FACTOR 8192
+
+void vidc_pix_cache_sw_reset(void)
+{
+ u32 sw_reset_value = 0;
+
+ VIDC_HWIO_IN(REG_169013, &sw_reset_value);
+ sw_reset_value |= HWIO_REG_169013_PIX_CACHE_SW_RESET_BMSK;
+ VIDC_HWIO_OUT(REG_169013, sw_reset_value);
+ VIDC_HWIO_IN(REG_169013, &sw_reset_value);
+ sw_reset_value &= (~HWIO_REG_169013_PIX_CACHE_SW_RESET_BMSK);
+ VIDC_HWIO_OUT(REG_169013, sw_reset_value);
+}
+
+void vidc_pix_cache_init_luma_chroma_base_addr(u32 dpb,
+ u32 *pn_dpb_luma_offset, u32 *pn_dpb_chroma_offset)
+{
+ u32 count, num_dpb_used = dpb;
+ u32 dpb_reset_value = VIDC_1080P_DEC_DPB_RESET_VALUE;
+
+ if (num_dpb_used > VIDC_1080P_MAX_DEC_DPB)
+ num_dpb_used = VIDC_1080P_MAX_DEC_DPB;
+ for (count = 0; count < VIDC_1080P_MAX_DEC_DPB; count++) {
+ if (count < num_dpb_used) {
+ if (pn_dpb_luma_offset) {
+ VIDC_HWIO_OUTI(
+ REG_804925,
+ count, pn_dpb_luma_offset[count]);
+ } else {
+ VIDC_HWIO_OUTI(
+ REG_804925,
+ count, dpb_reset_value);
+ }
+ if (pn_dpb_chroma_offset) {
+ VIDC_HWIO_OUTI(
+ REG_41909,
+ count, pn_dpb_chroma_offset[count]);
+ } else {
+ VIDC_HWIO_OUTI(
+ REG_41909,
+ count, dpb_reset_value);
+ }
+ } else {
+ VIDC_HWIO_OUTI(REG_804925,
+ count, dpb_reset_value);
+ VIDC_HWIO_OUTI(REG_41909,
+ count, dpb_reset_value);
+ }
+ }
+}
+
+void vidc_pix_cache_set_frame_range(u32 luma_size, u32 chroma_size)
+{
+ u32 frame_range;
+
+ frame_range =
+ (((luma_size / VIDC_TILE_MULTIPLY_FACTOR) & 0xFF) << 8)|
+ ((chroma_size / VIDC_TILE_MULTIPLY_FACTOR) & 0xFF);
+ VIDC_HWIO_OUT(REG_905239, frame_range);
+}
+void vidc_pix_cache_set_frame_size(u32 frame_width, u32 frame_height)
+{
+ u32 frame_size;
+ frame_size = (((u32) (frame_height << HWIO_REG_951731_FRAME_HEIGHT_SHFT) &
+ HWIO_REG_951731_FRAME_HEIGHT_BMSK) |
+ ((u32) (frame_width << HWIO_REG_951731_FRAME_WIDTH_SHFT) &
+ HWIO_REG_951731_FRAME_WIDTH_BMSK));
+ VIDC_HWIO_OUT(REG_951731, frame_size);
+}
+
+void vidc_pix_cache_init_config(
+ struct vidc_1080P_pix_cache_config *config)
+{
+ u32 cfg_reg = 0;
+
+ if (config->cache_enable)
+ cfg_reg |= HWIO_REG_22756_CACHE_EN_BMSK;
+ else
+ cfg_reg &= (~HWIO_REG_22756_CACHE_EN_BMSK);
+ if (config->port_select == VIDC_1080P_PIX_CACHE_PORT_A)
+ cfg_reg &=
+ (~HWIO_REG_22756_CACHE_PORT_SELECT_BMSK);
+ else
+ cfg_reg |= HWIO_REG_22756_CACHE_PORT_SELECT_BMSK;
+ if (!config->statistics_off)
+ cfg_reg |= HWIO_REG_22756_STATISTICS_OFF_BMSK;
+ else
+ cfg_reg &= (~HWIO_REG_22756_STATISTICS_OFF_BMSK);
+ if (config->prefetch_en)
+ cfg_reg |= HWIO_REG_22756_PREFETCH_EN_BMSK;
+ else
+ cfg_reg &= (~HWIO_REG_22756_PREFETCH_EN_BMSK);
+ cfg_reg &= (~HWIO_REG_22756_PAGE_SIZE_BMSK);
+ cfg_reg |= VIDC_SETFIELD(config->page_size,
+ HWIO_REG_22756_PAGE_SIZE_SHFT,
+ HWIO_REG_22756_PAGE_SIZE_BMSK);
+ VIDC_HWIO_OUT(REG_22756, cfg_reg);
+}
+
+void vidc_pix_cache_set_prefetch_page_limit(u32 page_size_limit)
+{
+ u32 cfg_reg = 0;
+
+ VIDC_HWIO_IN(REG_22756, &cfg_reg);
+ cfg_reg &= (~HWIO_REG_22756_PAGE_SIZE_BMSK);
+ cfg_reg |= VIDC_SETFIELD(page_size_limit,
+ HWIO_REG_22756_PAGE_SIZE_SHFT,
+ HWIO_REG_22756_PAGE_SIZE_BMSK);
+ VIDC_HWIO_OUT(REG_22756, cfg_reg);
+}
+
+void vidc_pix_cache_enable_prefetch(u32 prefetch_enable)
+{
+ u32 cfg_reg = 0;
+
+ VIDC_HWIO_IN(REG_22756, &cfg_reg);
+ if (prefetch_enable)
+ cfg_reg |= HWIO_REG_22756_PREFETCH_EN_BMSK;
+ else
+ cfg_reg &= (~HWIO_REG_22756_PREFETCH_EN_BMSK);
+ VIDC_HWIO_OUT(REG_22756, cfg_reg);
+}
+
+void vidc_pix_cache_disable_statistics(u32 statistics_off)
+{
+ u32 cfg_reg = 0;
+
+ VIDC_HWIO_IN(REG_22756, &cfg_reg);
+ if (!statistics_off)
+ cfg_reg |= HWIO_REG_22756_STATISTICS_OFF_BMSK;
+ else
+ cfg_reg &= (~HWIO_REG_22756_STATISTICS_OFF_BMSK);
+ VIDC_HWIO_OUT(REG_22756, cfg_reg);
+}
+
+void vidc_pix_cache_set_port(
+ enum vidc_1080P_pix_cache_port_sel port_select)
+{
+ u32 cfg_reg = 0;
+
+ VIDC_HWIO_IN(REG_22756, &cfg_reg);
+ if (port_select == VIDC_1080P_PIX_CACHE_PORT_A)
+ cfg_reg &=
+ (~HWIO_REG_22756_CACHE_PORT_SELECT_BMSK);
+ else
+ cfg_reg |= HWIO_REG_22756_CACHE_PORT_SELECT_BMSK;
+ VIDC_HWIO_OUT(REG_22756, cfg_reg);
+}
+
+void vidc_pix_cache_enable_cache(u32 cache_enable)
+{
+ u32 cfg_reg = 0;
+
+ VIDC_HWIO_IN(REG_22756, &cfg_reg);
+ if (cache_enable)
+ cfg_reg |= HWIO_REG_22756_CACHE_EN_BMSK;
+ else
+ cfg_reg &= (~HWIO_REG_22756_CACHE_EN_BMSK);
+ VIDC_HWIO_OUT(REG_22756, cfg_reg);
+}
+
+void vidc_pix_cache_clear_cache_tags(void)
+{
+ u32 cfg_reg = 0;
+
+ VIDC_HWIO_IN(REG_22756, &cfg_reg);
+ cfg_reg |= HWIO_REG_22756_CACHE_TAG_CLEAR_BMSK;
+ VIDC_HWIO_OUT(REG_22756, cfg_reg);
+ VIDC_HWIO_IN(REG_22756, &cfg_reg);
+ cfg_reg &= (~HWIO_REG_22756_CACHE_TAG_CLEAR_BMSK);
+ VIDC_HWIO_OUT(REG_22756, cfg_reg);
+}
+
+void vidc_pix_cache_set_halt(u32 halt_enable)
+{
+ u32 cfg_reg = 0;
+
+ VIDC_HWIO_IN(REG_22756, &cfg_reg);
+ if (halt_enable)
+ cfg_reg |= HWIO_REG_22756_CACHE_HALT_BMSK;
+ else
+ cfg_reg &= (~HWIO_REG_22756_CACHE_HALT_BMSK);
+ VIDC_HWIO_OUT(REG_22756, cfg_reg);
+}
+
+void vidc_pix_cache_get_status_idle(u32 *idle_status)
+{
+ VIDC_HWIO_IN(REG_919904, idle_status);
+}
+
+void vidc_pix_cache_set_ram(u32 ram_select)
+{
+ u32 dmi_cfg_reg = 0;
+
+ VIDC_HWIO_IN(REG_261029, &dmi_cfg_reg);
+ dmi_cfg_reg &= (~HWIO_REG_261029_DMI_RAM_SEL_BMSK);
+ dmi_cfg_reg |= VIDC_SETFIELD(ram_select,
+ HWIO_REG_261029_AUTO_INC_EN_SHFT,
+ HWIO_REG_261029_DMI_RAM_SEL_BMSK);
+ VIDC_HWIO_OUT(REG_261029, dmi_cfg_reg);
+}
+
+void vidc_pix_cache_set_auto_inc_ram_addr(u32 auto_inc_enable)
+{
+ u32 dmi_cfg_reg = 0;
+
+ VIDC_HWIO_IN(REG_261029, &dmi_cfg_reg);
+ if (auto_inc_enable)
+ dmi_cfg_reg |= HWIO_REG_261029_AUTO_INC_EN_BMSK;
+ else
+ dmi_cfg_reg &= (~HWIO_REG_261029_AUTO_INC_EN_BMSK);
+ VIDC_HWIO_OUT(REG_261029, dmi_cfg_reg);
+}
+
+
+void vidc_pix_cache_read_ram_data(u32 src_ram_address,
+ u32 ram_size, u32 *dest_address)
+{
+ u32 count, dmi_cfg_reg = 0;
+
+ VIDC_HWIO_IN(REG_261029, &dmi_cfg_reg);
+ VIDC_HWIO_OUT(REG_576200, src_ram_address);
+ vidc_pix_cache_set_auto_inc_ram_addr(1);
+ for (count = 0; count < ram_size; count++) {
+ VIDC_HWIO_IN(REG_556274, dest_address);
+ dest_address++;
+ VIDC_HWIO_IN(REG_917583, dest_address);
+ dest_address++;
+ }
+ VIDC_HWIO_OUT(REG_261029, dmi_cfg_reg);
+}
+
+void vidc_pix_cache_write_ram_data(u32 *src_address,
+ u32 ram_size, u32 dest_ram_address)
+{
+ u32 count, dmi_cfg_reg = 0;
+
+ VIDC_HWIO_IN(REG_261029, &dmi_cfg_reg);
+ VIDC_HWIO_OUT(REG_576200, dest_ram_address);
+ vidc_pix_cache_set_auto_inc_ram_addr(1);
+ for (count = 0; count < ram_size; count++) {
+ VIDC_HWIO_OUT(REG_917583, *src_address);
+ src_address++;
+ VIDC_HWIO_OUT(REG_556274, *src_address);
+ src_address++;
+ }
+ VIDC_HWIO_OUT(REG_261029, dmi_cfg_reg);
+}
+
+void vidc_pix_cache_get_statistics(
+ struct vidc_1080P_pix_cache_statistics *statistics)
+{
+ VIDC_HWIO_IN(REG_278310,
+ &statistics->access_miss);
+ VIDC_HWIO_IN(REG_421222,
+ &statistics->access_hit);
+ VIDC_HWIO_IN(REG_609607,
+ &statistics->axi_req);
+ VIDC_HWIO_IN(REG_395232,
+ &statistics->core_req);
+ VIDC_HWIO_IN(REG_450146,
+ &statistics->axi_bus);
+ VIDC_HWIO_IN(REG_610651,
+ &statistics->core_bus);
+}
+
+void vidc_pix_cache_enable_misr(u32 misr_enable)
+{
+ u32 misr_cfg_reg = 0;
+
+ VIDC_HWIO_IN(REG_883784, &misr_cfg_reg);
+ if (misr_enable)
+ misr_cfg_reg |= HWIO_REG_883784_MISR_EN_BMSK;
+ else
+ misr_cfg_reg &=
+ (~HWIO_REG_883784_MISR_EN_BMSK);
+ VIDC_HWIO_OUT(REG_261029, misr_cfg_reg);
+}
+
+void vidc_pix_cache_set_misr_interface(u32 input_select)
+{
+ u32 misr_cfg_reg = 0;
+
+ VIDC_HWIO_IN(REG_883784, &misr_cfg_reg);
+ misr_cfg_reg &= (~HWIO_REG_883784_INPUT_SEL_BMSK);
+ misr_cfg_reg |= VIDC_SETFIELD(input_select,
+ HWIO_REG_883784_INPUT_SEL_SHFT,
+ HWIO_REG_883784_INPUT_SEL_BMSK);
+ VIDC_HWIO_OUT(REG_261029, misr_cfg_reg);
+}
+
+void vidc_pix_cache_set_misr_id_filtering(
+ struct vidc_1080P_pix_cache_misr_id_filtering *filter_id)
+{
+ u32 misr_cfg_reg = 0;
+
+ VIDC_HWIO_IN(REG_883784, &misr_cfg_reg);
+ if (filter_id->ignore_id)
+ misr_cfg_reg |=
+ HWIO_REG_883784_IGNORE_ID_BMSK;
+ else
+ misr_cfg_reg &=
+ (~HWIO_REG_883784_IGNORE_ID_BMSK);
+ misr_cfg_reg &= (~HWIO_REG_883784_ID_BMSK);
+ misr_cfg_reg |= VIDC_SETFIELD(filter_id->id,
+ HWIO_REG_883784_ID_SHFT,
+ HWIO_REG_883784_ID_BMSK);
+ VIDC_HWIO_OUT(REG_261029, misr_cfg_reg);
+}
+
+void vidc_pix_cache_set_misr_filter_trans(u32 no_of_trans)
+{
+ u32 misr_cfg_reg = 0;
+
+ VIDC_HWIO_IN(REG_883784, &misr_cfg_reg);
+ misr_cfg_reg &= (~HWIO_REG_883784_COUNTER_BMSK);
+ misr_cfg_reg |= VIDC_SETFIELD(no_of_trans,
+ HWIO_REG_883784_COUNTER_SHFT,
+ HWIO_REG_883784_COUNTER_BMSK);
+ VIDC_HWIO_OUT(REG_261029, misr_cfg_reg);
+}
+
+void vidc_pix_cache_get_misr_signatures(
+ struct vidc_1080P_pix_cache_misr_signature *signatures)
+{
+ VIDC_HWIO_INI(REG_651391, 0,
+ &signatures->signature0);
+ VIDC_HWIO_INI(REG_651391, 1,
+ &signatures->signature1);
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc_pix_cache.h b/drivers/video/msm/vidc/1080p/ddl/vidc_pix_cache.h
new file mode 100644
index 0000000..e8a93a1
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc_pix_cache.h
@@ -0,0 +1,87 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _VIDEO_CORE_PIXCACHE_
+#define _VIDEO_CORE_PIXCACHE_
+
+
+#include "vidc.h"
+
+#define VIDC_1080P_DEC_DPB_RESET_VALUE 0xFFFFFFF8
+
+enum vidc_1080P_pix_cache_port_sel{
+ VIDC_1080P_PIX_CACHE_PORT_A = 0,
+ VIDC_1080P_PIX_CACHE_PORT_B = 1,
+ VIDC_1080P_PIX_CACHE_PORT_32BIT = 0x7FFFFFFF
+};
+enum vidc_1080P_pix_cache_page_size{
+ VIDC_1080P_PIX_CACHE_PAGE_SIZE_1K = 0,
+ VIDC_1080P_PIX_CACHE_PAGE_SIZE_2K = 1,
+ VIDC_1080P_PIX_CACHE_PAGE_SIZE_4K = 2
+};
+struct vidc_1080P_pix_cache_config{
+ u32 cache_enable;
+ u32 prefetch_en;
+ enum vidc_1080P_pix_cache_port_sel port_select;
+ u32 statistics_off;
+ enum vidc_1080P_pix_cache_page_size page_size;
+};
+struct vidc_1080P_pix_cache_statistics{
+ u32 access_miss;
+ u32 access_hit;
+ u32 axi_req;
+ u32 core_req;
+ u32 axi_bus;
+ u32 core_bus;
+};
+struct vidc_1080P_pix_cache_misr_id_filtering{
+ u32 ignore_id;
+ u32 id;
+};
+struct vidc_1080P_pix_cache_misr_signature{
+ u32 signature0;
+ u32 signature1;
+};
+
+void vidc_pix_cache_sw_reset(void);
+void vidc_pix_cache_init_luma_chroma_base_addr(u32 dpb,
+ u32 *pn_dpb_luma_offset, u32 *pn_dpb_chroma_offset);
+void vidc_pix_cache_set_frame_range(u32 luma_size, u32 chroma_size);
+void vidc_pix_cache_set_frame_size(u32 frame_width, u32 frame_height);
+void vidc_pix_cache_init_config(
+ struct vidc_1080P_pix_cache_config *config);
+void vidc_pix_cache_set_prefetch_page_limit(u32 page_size_limit);
+void vidc_pix_cache_enable_prefetch(u32 prefetch_enable);
+void vidc_pix_cache_disable_statistics(u32 statistics_off);
+void vidc_pix_cache_set_port(
+ enum vidc_1080P_pix_cache_port_sel port_select);
+void vidc_pix_cache_enable_cache(u32 cache_enable);
+void vidc_pix_cache_clear_cache_tags(void);
+void vidc_pix_cache_set_halt(u32 halt_enable);
+void vidc_pix_cache_get_status_idle(u32 *idle_status);
+void vidc_pix_cache_set_ram(u32 ram_select);
+void vidc_pix_cache_set_auto_inc_ram_addr(u32 auto_inc_enable);
+void vidc_pix_cache_read_ram_data(u32 src_ram_address, u32 ram_size,
+ u32 *dest_address);
+void vidc_pix_cache_write_ram_data(u32 *src_address, u32 ram_size,
+ u32 dest_ram_address);
+void vidc_pix_cache_get_statistics(
+ struct vidc_1080P_pix_cache_statistics *statistics);
+void vidc_pix_cache_enable_misr(u32 misr_enable);
+void vidc_pix_cache_set_misr_interface(u32 input_select);
+void vidc_pix_cache_set_misr_id_filtering(
+ struct vidc_1080P_pix_cache_misr_id_filtering *filter_id);
+void vidc_pix_cache_set_misr_filter_trans(u32 no_of_trans);
+void vidc_pix_cache_get_misr_signatures(
+ struct vidc_1080P_pix_cache_misr_signature *signatures);
+#endif
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
new file mode 100644
index 0000000..ec6c39a
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
@@ -0,0 +1,508 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/firmware.h>
+#include <linux/pm_qos_params.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
+#include <mach/clk.h>
+#include <mach/msm_reqs.h>
+#include <mach/msm_memtypes.h>
+#include <linux/interrupt.h>
+#include <linux/memory_alloc.h>
+#include <asm/sizes.h>
+#include "vidc.h"
+#include "vcd_res_tracker.h"
+#include "vidc_init.h"
+
+static unsigned int vidc_clk_table[3] = {
+ 48000000, 133330000, 200000000
+};
+static struct res_trk_context resource_context;
+
+#define VIDC_FW "vidc_1080p.fw"
+#define VIDC_FW_SIZE SZ_1M
+
+unsigned char *vidc_video_codec_fw;
+u32 vidc_video_codec_fw_size;
+static u32 res_trk_get_clk(void);
+static void res_trk_put_clk(void);
+
+static u32 res_trk_get_clk()
+{
+ if (resource_context.vcodec_clk ||
+ resource_context.vcodec_pclk) {
+ VCDRES_MSG_ERROR("%s() Clock reference exists\n",
+ __func__);
+ goto bail_out;
+ }
+ resource_context.vcodec_clk = clk_get(resource_context.device,
+ "vcodec_clk");
+ if (IS_ERR(resource_context.vcodec_clk)) {
+ VCDRES_MSG_ERROR("%s(): vcodec_clk get failed\n",
+ __func__);
+ goto bail_out;
+ }
+ resource_context.vcodec_pclk = clk_get(resource_context.device,
+ "vcodec_pclk");
+ if (IS_ERR(resource_context.vcodec_pclk)) {
+ VCDRES_MSG_ERROR("%s(): vcodec_pclk get failed\n",
+ __func__);
+ goto release_vcodec_clk;
+ }
+ resource_context.vcodec_axi_a_clk = clk_get(resource_context.device,
+ "vcodec_axi_a_clk");
+ if (IS_ERR(resource_context.vcodec_axi_a_clk)) {
+ VCDRES_MSG_ERROR("%s(): vcodec_axi_a_clk get failed\n",
+ __func__);
+ resource_context.vcodec_axi_a_clk = NULL;
+ }
+ resource_context.vcodec_axi_b_clk = clk_get(resource_context.device,
+ "vcodec_axi_b_clk");
+ if (IS_ERR(resource_context.vcodec_axi_b_clk)) {
+ VCDRES_MSG_ERROR("%s(): vcodec_axi_b_clk get failed\n",
+ __func__);
+ resource_context.vcodec_axi_b_clk = NULL;
+ }
+ if (clk_set_rate(resource_context.vcodec_clk,
+ vidc_clk_table[0])) {
+ VCDRES_MSG_ERROR("%s(): set rate failed in power up\n",
+ __func__);
+ goto release_vcodec_pclk;
+ }
+ return true;
+release_vcodec_pclk:
+ if (resource_context.vcodec_axi_a_clk)
+ clk_put(resource_context.vcodec_axi_a_clk);
+ if (resource_context.vcodec_axi_b_clk)
+ clk_put(resource_context.vcodec_axi_b_clk);
+ clk_put(resource_context.vcodec_pclk);
+ resource_context.vcodec_pclk = NULL;
+ resource_context.vcodec_axi_a_clk = NULL;
+ resource_context.vcodec_axi_b_clk = NULL;
+release_vcodec_clk:
+ clk_put(resource_context.vcodec_clk);
+ resource_context.vcodec_clk = NULL;
+bail_out:
+ return false;
+}
+
+static void res_trk_put_clk()
+{
+ if (resource_context.vcodec_clk)
+ clk_put(resource_context.vcodec_clk);
+ if (resource_context.vcodec_pclk)
+ clk_put(resource_context.vcodec_pclk);
+ if (resource_context.vcodec_axi_a_clk)
+ clk_put(resource_context.vcodec_axi_a_clk);
+ if (resource_context.vcodec_axi_b_clk)
+ clk_put(resource_context.vcodec_axi_b_clk);
+ resource_context.vcodec_axi_b_clk = NULL;
+ resource_context.vcodec_axi_a_clk = NULL;
+ resource_context.vcodec_clk = NULL;
+ resource_context.vcodec_pclk = NULL;
+}
+
+static u32 res_trk_shutdown_vidc(void)
+{
+ mutex_lock(&resource_context.lock);
+ if (resource_context.clock_enabled) {
+ mutex_unlock(&resource_context.lock);
+ VCDRES_MSG_LOW("\n Calling CLK disable in Power Down\n");
+ res_trk_disable_clocks();
+ mutex_lock(&resource_context.lock);
+ }
+ res_trk_put_clk();
+ if (resource_context.footswitch) {
+ if (regulator_disable(resource_context.footswitch))
+ VCDRES_MSG_ERROR("Regulator disable failed\n");
+ regulator_put(resource_context.footswitch);
+ resource_context.footswitch = NULL;
+ }
+ if (pm_runtime_put(resource_context.device) < 0)
+ VCDRES_MSG_ERROR("Error : pm_runtime_put failed");
+ mutex_unlock(&resource_context.lock);
+ return true;
+}
+
+u32 res_trk_enable_clocks(void)
+{
+ VCDRES_MSG_LOW("\n in res_trk_enable_clocks()");
+ mutex_lock(&resource_context.lock);
+ if (!resource_context.clock_enabled) {
+ VCDRES_MSG_LOW("Enabling IRQ in %s()\n", __func__);
+ enable_irq(resource_context.irq_num);
+ VCDRES_MSG_LOW("%s(): Enabling the clocks\n", __func__);
+ if (resource_context.vcodec_clk &&
+ resource_context.vcodec_pclk) {
+ if (clk_enable(resource_context.vcodec_pclk)) {
+ VCDRES_MSG_ERROR("vidc pclk Enable fail\n");
+ goto bail_out;
+ }
+ if (clk_enable(resource_context.vcodec_clk)) {
+ VCDRES_MSG_ERROR("vidc core clk Enable fail\n");
+ goto vidc_disable_pclk;
+ }
+ if (resource_context.vcodec_axi_a_clk &&
+ resource_context.vcodec_axi_b_clk) {
+ if (clk_enable(resource_context.
+ vcodec_axi_a_clk))
+ VCDRES_MSG_ERROR("a_clk Enable fail\n");
+ if (clk_enable(resource_context.
+ vcodec_axi_b_clk))
+ VCDRES_MSG_ERROR("b_clk Enable fail\n");
+ }
+
+ VCDRES_MSG_LOW("%s(): Clocks enabled!\n", __func__);
+ } else {
+ VCDRES_MSG_ERROR("%s(): Clocks enable failed!\n",
+ __func__);
+ goto bail_out;
+ }
+ }
+ resource_context.clock_enabled = 1;
+ mutex_unlock(&resource_context.lock);
+ return true;
+vidc_disable_pclk:
+ clk_disable(resource_context.vcodec_pclk);
+bail_out:
+ mutex_unlock(&resource_context.lock);
+ return false;
+}
+
+static u32 res_trk_sel_clk_rate(unsigned long hclk_rate)
+{
+ u32 status = true;
+ mutex_lock(&resource_context.lock);
+ if (clk_set_rate(resource_context.vcodec_clk,
+ hclk_rate)) {
+ VCDRES_MSG_ERROR("vidc hclk set rate failed\n");
+ status = false;
+ } else
+ resource_context.vcodec_clk_rate = hclk_rate;
+ mutex_unlock(&resource_context.lock);
+ return status;
+}
+
+static u32 res_trk_get_clk_rate(unsigned long *phclk_rate)
+{
+ u32 status = true;
+ mutex_lock(&resource_context.lock);
+ if (phclk_rate) {
+ *phclk_rate = clk_get_rate(resource_context.vcodec_clk);
+ if (!(*phclk_rate)) {
+ VCDRES_MSG_ERROR("vidc hclk get rate failed\n");
+ status = false;
+ }
+ } else
+ status = false;
+ mutex_unlock(&resource_context.lock);
+ return status;
+}
+
+u32 res_trk_disable_clocks(void)
+{
+ u32 status = false;
+ VCDRES_MSG_LOW("in res_trk_disable_clocks()\n");
+ mutex_lock(&resource_context.lock);
+ if (resource_context.clock_enabled) {
+ VCDRES_MSG_LOW("Disabling IRQ in %s()\n", __func__);
+ disable_irq_nosync(resource_context.irq_num);
+ VCDRES_MSG_LOW("%s(): Disabling the clocks ...\n", __func__);
+ resource_context.clock_enabled = 0;
+ if (resource_context.vcodec_clk)
+ clk_disable(resource_context.vcodec_clk);
+ if (resource_context.vcodec_pclk)
+ clk_disable(resource_context.vcodec_pclk);
+ if (resource_context.vcodec_axi_a_clk)
+ clk_disable(resource_context.vcodec_axi_a_clk);
+ if (resource_context.vcodec_axi_b_clk)
+ clk_disable(resource_context.vcodec_axi_b_clk);
+ status = true;
+ }
+ mutex_unlock(&resource_context.lock);
+ return status;
+}
+
+static u32 res_trk_vidc_pwr_up(void)
+{
+ mutex_lock(&resource_context.lock);
+
+ if (pm_runtime_get(resource_context.device) < 0) {
+ VCDRES_MSG_ERROR("Error : pm_runtime_get failed\n");
+ goto bail_out;
+ }
+ resource_context.footswitch = regulator_get(NULL, "fs_ved");
+ if (IS_ERR(resource_context.footswitch)) {
+ VCDRES_MSG_ERROR("foot switch get failed\n");
+ resource_context.footswitch = NULL;
+ } else
+ regulator_enable(resource_context.footswitch);
+ if (!res_trk_get_clk())
+ goto rel_vidc_pm_runtime;
+ mutex_unlock(&resource_context.lock);
+ return true;
+
+rel_vidc_pm_runtime:
+ if (pm_runtime_put(resource_context.device) < 0)
+ VCDRES_MSG_ERROR("Error : pm_runtime_put failed");
+bail_out:
+ mutex_unlock(&resource_context.lock);
+ return false;
+}
+
+u32 res_trk_power_up(void)
+{
+ VCDRES_MSG_LOW("clk_regime_rail_enable");
+ VCDRES_MSG_LOW("clk_regime_sel_rail_control");
+#ifdef CONFIG_MSM_BUS_SCALING
+ resource_context.pcl = 0;
+ if (resource_context.vidc_bus_client_pdata) {
+ resource_context.pcl = msm_bus_scale_register_client(
+ resource_context.vidc_bus_client_pdata);
+ VCDRES_MSG_LOW("%s(), resource_context.pcl = %x", __func__,
+ resource_context.pcl);
+ }
+ if (resource_context.pcl == 0) {
+ dev_err(resource_context.device,
+ "register bus client returned NULL\n");
+ return false;
+ }
+#endif
+ return res_trk_vidc_pwr_up();
+}
+
+u32 res_trk_power_down(void)
+{
+ VCDRES_MSG_LOW("clk_regime_rail_disable");
+#ifdef CONFIG_MSM_BUS_SCALING
+ msm_bus_scale_client_update_request(resource_context.pcl, 0);
+ msm_bus_scale_unregister_client(resource_context.pcl);
+#endif
+ VCDRES_MSG_MED("res_trk_power_down():: Calling "
+ "res_trk_shutdown_vidc()\n");
+ return res_trk_shutdown_vidc();
+}
+
+u32 res_trk_get_max_perf_level(u32 *pn_max_perf_lvl)
+{
+ if (!pn_max_perf_lvl) {
+ VCDRES_MSG_ERROR("%s(): pn_max_perf_lvl is NULL\n",
+ __func__);
+ return false;
+ }
+ *pn_max_perf_lvl = RESTRK_1080P_MAX_PERF_LEVEL;
+ return true;
+}
+
+#ifdef CONFIG_MSM_BUS_SCALING
+int res_trk_update_bus_perf_level(struct vcd_dev_ctxt *dev_ctxt, u32 perf_level)
+{
+ struct vcd_clnt_ctxt *cctxt_itr = NULL;
+ u32 enc_perf_level = 0, dec_perf_level = 0;
+ u32 bus_clk_index, client_type = 0;
+ int rc = 0;
+
+ cctxt_itr = dev_ctxt->cctxt_list_head;
+ while (cctxt_itr) {
+ if (cctxt_itr->decoding)
+ dec_perf_level += cctxt_itr->reqd_perf_lvl;
+ else
+ enc_perf_level += cctxt_itr->reqd_perf_lvl;
+ cctxt_itr = cctxt_itr->next;
+ }
+ if (!enc_perf_level)
+ client_type = 1;
+ if (perf_level <= RESTRK_1080P_VGA_PERF_LEVEL)
+ bus_clk_index = 0;
+ else if (perf_level <= RESTRK_1080P_720P_PERF_LEVEL)
+ bus_clk_index = 1;
+ else
+ bus_clk_index = 2;
+
+ if (dev_ctxt->reqd_perf_lvl + dev_ctxt->curr_perf_lvl == 0)
+ bus_clk_index = 2;
+
+ bus_clk_index = (bus_clk_index << 1) + (client_type + 1);
+ VCDRES_MSG_LOW("%s(), bus_clk_index = %d", __func__, bus_clk_index);
+ VCDRES_MSG_LOW("%s(),context.pcl = %x", __func__, resource_context.pcl);
+ VCDRES_MSG_LOW("%s(), bus_perf_level = %x", __func__, perf_level);
+ rc = msm_bus_scale_client_update_request(resource_context.pcl,
+ bus_clk_index);
+ return rc;
+}
+#endif
+
+u32 res_trk_set_perf_level(u32 req_perf_lvl, u32 *pn_set_perf_lvl,
+ struct vcd_dev_ctxt *dev_ctxt)
+{
+ u32 vidc_freq = 0;
+ if (!pn_set_perf_lvl || !dev_ctxt) {
+ VCDRES_MSG_ERROR("%s(): NULL pointer! dev_ctxt(%p)\n",
+ __func__, dev_ctxt);
+ return false;
+ }
+ VCDRES_MSG_LOW("%s(), req_perf_lvl = %d", __func__, req_perf_lvl);
+#ifdef CONFIG_MSM_BUS_SCALING
+ if (!res_trk_update_bus_perf_level(dev_ctxt, req_perf_lvl) < 0) {
+ VCDRES_MSG_ERROR("%s(): update buf perf level failed\n",
+ __func__);
+ return false;
+ }
+
+#endif
+ if (dev_ctxt->reqd_perf_lvl + dev_ctxt->curr_perf_lvl == 0)
+ req_perf_lvl = RESTRK_1080P_MAX_PERF_LEVEL;
+
+ if (req_perf_lvl <= RESTRK_1080P_VGA_PERF_LEVEL) {
+ vidc_freq = vidc_clk_table[0];
+ *pn_set_perf_lvl = RESTRK_1080P_VGA_PERF_LEVEL;
+ } else if (req_perf_lvl <= RESTRK_1080P_720P_PERF_LEVEL) {
+ vidc_freq = vidc_clk_table[1];
+ *pn_set_perf_lvl = RESTRK_1080P_720P_PERF_LEVEL;
+ } else {
+ vidc_freq = vidc_clk_table[2];
+ *pn_set_perf_lvl = RESTRK_1080P_MAX_PERF_LEVEL;
+ }
+ resource_context.perf_level = *pn_set_perf_lvl;
+ VCDRES_MSG_MED("VIDC: vidc_freq = %u, req_perf_lvl = %u\n",
+ vidc_freq, req_perf_lvl);
+#ifdef USE_RES_TRACKER
+ if (req_perf_lvl != RESTRK_1080P_MIN_PERF_LEVEL) {
+ VCDRES_MSG_MED("%s(): Setting vidc freq to %u\n",
+ __func__, vidc_freq);
+ if (!res_trk_sel_clk_rate(vidc_freq)) {
+ VCDRES_MSG_ERROR("%s(): res_trk_sel_clk_rate FAILED\n",
+ __func__);
+ *pn_set_perf_lvl = 0;
+ return false;
+ }
+ }
+#endif
+ VCDRES_MSG_MED("%s() set perl level : %d", __func__, *pn_set_perf_lvl);
+ return true;
+}
+
+u32 res_trk_get_curr_perf_level(u32 *pn_perf_lvl)
+{
+ unsigned long freq;
+
+ if (!pn_perf_lvl) {
+ VCDRES_MSG_ERROR("%s(): pn_perf_lvl is NULL\n",
+ __func__);
+ return false;
+ }
+ VCDRES_MSG_LOW("clk_regime_msm_get_clk_freq_hz");
+ if (!res_trk_get_clk_rate(&freq)) {
+ VCDRES_MSG_ERROR("%s(): res_trk_get_clk_rate FAILED\n",
+ __func__);
+ *pn_perf_lvl = 0;
+ return false;
+ }
+ *pn_perf_lvl = resource_context.perf_level;
+ VCDRES_MSG_MED("%s(): freq = %lu, *pn_perf_lvl = %u", __func__,
+ freq, *pn_perf_lvl);
+ return true;
+}
+
+u32 res_trk_download_firmware(void)
+{
+ const struct firmware *fw_video = NULL;
+ int rc = 0;
+ u32 status = true;
+
+ VCDRES_MSG_HIGH("%s(): Request firmware download\n",
+ __func__);
+ mutex_lock(&resource_context.lock);
+ rc = request_firmware(&fw_video, VIDC_FW,
+ resource_context.device);
+ if (rc) {
+ VCDRES_MSG_ERROR("request_firmware for %s error %d\n",
+ VIDC_FW, rc);
+ status = false;
+ goto bail_out;
+ }
+ vidc_video_codec_fw = (unsigned char *)fw_video->data;
+ vidc_video_codec_fw_size = (u32) fw_video->size;
+bail_out:
+ mutex_unlock(&resource_context.lock);
+ return status;
+}
+
+void res_trk_init(struct device *device, u32 irq)
+{
+ if (resource_context.device || resource_context.irq_num ||
+ !device) {
+ VCDRES_MSG_ERROR("%s() Resource Tracker Init error\n",
+ __func__);
+ } else {
+ memset(&resource_context, 0, sizeof(resource_context));
+ mutex_init(&resource_context.lock);
+ resource_context.device = device;
+ resource_context.irq_num = irq;
+ resource_context.vidc_platform_data =
+ (struct msm_vidc_platform_data *) device->platform_data;
+ if (resource_context.vidc_platform_data) {
+ resource_context.memtype =
+ resource_context.vidc_platform_data->memtype;
+#ifdef CONFIG_MSM_BUS_SCALING
+ resource_context.vidc_bus_client_pdata =
+ resource_context.vidc_platform_data->
+ vidc_bus_client_pdata;
+#endif
+ } else {
+ resource_context.memtype = -1;
+ }
+ resource_context.core_type = VCD_CORE_1080P;
+ if (resource_context.memtype == MEMTYPE_EBI1) {
+ resource_context.device_addr =
+ (phys_addr_t)
+ allocate_contiguous_memory_nomap(VIDC_FW_SIZE,
+ resource_context.memtype, SZ_4K);
+ if (resource_context.device_addr) {
+ resource_context.base_addr = (u8 *)
+ ioremap((unsigned long)
+ resource_context.device_addr, VIDC_FW_SIZE);
+ if (!resource_context.base_addr) {
+ free_contiguous_memory_by_paddr(
+ (unsigned long)
+ resource_context.device_addr);
+ resource_context.device_addr =
+ (phys_addr_t)NULL;
+ }
+ }
+ }
+ }
+}
+
+u32 res_trk_get_core_type(void){
+ return resource_context.core_type;
+}
+
+u32 res_trk_get_firmware_addr(struct res_trk_firmware_addr *firm_addr)
+{
+ int status = -1;
+ if (firm_addr && resource_context.base_addr &&
+ resource_context.device_addr) {
+ firm_addr->base_addr = resource_context.base_addr;
+ firm_addr->device_addr = resource_context.device_addr;
+ firm_addr->buf_size = VIDC_FW_SIZE;
+ status = 0;
+ }
+ return status;
+}
+
+u32 res_trk_get_mem_type(void){
+ return resource_context.memtype;
+}
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h
new file mode 100644
index 0000000..16680ad
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h
@@ -0,0 +1,69 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _VIDEO_720P_RESOURCE_TRACKER_H_
+#define _VIDEO_720P_RESOURCE_TRACKER_H_
+
+#include <linux/regulator/consumer.h>
+#include "vcd_res_tracker_api.h"
+#ifdef CONFIG_MSM_BUS_SCALING
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+#endif
+#include <mach/board.h>
+
+#define RESTRK_1080P_VGA_PERF_LEVEL VCD_MIN_PERF_LEVEL
+#define RESTRK_1080P_720P_PERF_LEVEL 108000
+#define RESTRK_1080P_1080P_PERF_LEVEL 244800
+
+#define RESTRK_1080P_MIN_PERF_LEVEL RESTRK_1080P_VGA_PERF_LEVEL
+#define RESTRK_1080P_MAX_PERF_LEVEL RESTRK_1080P_1080P_PERF_LEVEL
+struct res_trk_context {
+ struct device *device;
+ u32 irq_num;
+ struct mutex lock;
+ struct clk *vcodec_clk;
+ struct clk *vcodec_pclk;
+ struct clk *vcodec_axi_a_clk;
+ struct clk *vcodec_axi_b_clk;
+ unsigned long vcodec_clk_rate;
+ unsigned int clock_enabled;
+ unsigned int perf_level;
+ struct regulator *footswitch;
+ struct msm_vidc_platform_data *vidc_platform_data;
+ int memtype;
+#ifdef CONFIG_MSM_BUS_SCALING
+ struct msm_bus_scale_pdata *vidc_bus_client_pdata;
+ uint32_t pcl;
+#endif
+ u32 core_type;
+ u8 *base_addr;
+ phys_addr_t device_addr;
+};
+
+#if DEBUG
+
+#define VCDRES_MSG_LOW(xx_fmt...) printk(KERN_INFO "\n\t* " xx_fmt)
+#define VCDRES_MSG_MED(xx_fmt...) printk(KERN_INFO "\n * " xx_fmt)
+
+#else
+
+#define VCDRES_MSG_LOW(xx_fmt...)
+#define VCDRES_MSG_MED(xx_fmt...)
+
+#endif
+
+#define VCDRES_MSG_HIGH(xx_fmt...) printk(KERN_WARNING "\n" xx_fmt)
+#define VCDRES_MSG_ERROR(xx_fmt...) printk(KERN_ERR "\n err: " xx_fmt)
+#define VCDRES_MSG_FATAL(xx_fmt...) printk(KERN_ERR "\n<FATAL> " xx_fmt)
+
+#endif
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h
new file mode 100644
index 0000000..95cddd9
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h
@@ -0,0 +1,37 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _VIDEO_720P_RESOURCE_TRACKER_API_H_
+#define _VIDEO_720P_RESOURCE_TRACKER_API_H_
+
+#include "vcd_core.h"
+
+struct res_trk_firmware_addr {
+ u8 *base_addr;
+ phys_addr_t device_addr;
+ u32 buf_size;
+};
+void res_trk_init(struct device *device, u32 irq);
+u32 res_trk_power_up(void);
+u32 res_trk_power_down(void);
+u32 res_trk_enable_clocks(void);
+u32 res_trk_disable_clocks(void);
+u32 res_trk_get_max_perf_level(u32 *pn_max_perf_lvl);
+u32 res_trk_set_perf_level(u32 req_perf_lvl, u32 *pn_set_perf_lvl,
+ struct vcd_dev_ctxt *dev_ctxt);
+u32 res_trk_get_curr_perf_level(u32 *pn_perf_lvl);
+u32 res_trk_download_firmware(void);
+u32 res_trk_get_core_type(void);
+u32 res_trk_get_firmware_addr(struct res_trk_firmware_addr *firm_addr);
+u32 res_trk_get_mem_type(void);
+
+#endif
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c
new file mode 100644
index 0000000..d27b354
--- /dev/null
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c
@@ -0,0 +1,629 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "vidc_type.h"
+#include "vcd_ddl_utils.h"
+#include "vcd_ddl_metadata.h"
+#include "vcd_res_tracker_api.h"
+
+u32 ddl_device_init(struct ddl_init_config *ddl_init_config,
+ void *client_data)
+{
+ struct ddl_context *ddl_context;
+ u32 status = VCD_S_SUCCESS;
+
+ if ((!ddl_init_config) ||
+ (!ddl_init_config->ddl_callback) ||
+ (!ddl_init_config->core_virtual_base_addr)
+ ) {
+ VIDC_LOGERR_STRING("ddl_dev_init:Bad_argument");
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+
+ ddl_context = ddl_get_context();
+
+ if (DDL_IS_INITIALIZED(ddl_context)) {
+ VIDC_LOGERR_STRING("ddl_dev_init:Multiple_init");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (DDL_IS_BUSY(ddl_context)) {
+ VIDC_LOGERR_STRING("ddl_dev_init:Ddl_busy");
+ return VCD_ERR_BUSY;
+ }
+
+ DDL_MEMSET(ddl_context, 0, sizeof(struct ddl_context));
+
+ DDL_BUSY(ddl_context);
+ ddl_context->memtype = res_trk_get_mem_type();
+ if (ddl_context->memtype == -1) {
+ VIDC_LOGERR_STRING("ddl_dev_init:Invalid Memtype");
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+ ddl_context->ddl_callback = ddl_init_config->ddl_callback;
+ ddl_context->interrupt_clr = ddl_init_config->interrupt_clr;
+ ddl_context->core_virtual_base_addr =
+ ddl_init_config->core_virtual_base_addr;
+ ddl_context->client_data = client_data;
+
+ vidc_720p_set_device_virtual_base(ddl_context->
+ core_virtual_base_addr);
+
+ ddl_context->current_ddl = NULL;
+ ddl_move_command_state(ddl_context, DDL_CMD_INVALID);
+
+ ddl_client_transact(DDL_INIT_CLIENTS, NULL);
+
+ ddl_pmem_alloc(&ddl_context->context_buf_addr,
+ DDL_CONTEXT_MEMORY, DDL_LINEAR_BUFFER_ALIGN_BYTES);
+ if (!ddl_context->context_buf_addr.virtual_base_addr) {
+ VIDC_LOGERR_STRING("ddl_dev_init:Context_alloc_fail");
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (!status) {
+ ddl_pmem_alloc(&ddl_context->db_line_buffer,
+ DDL_DB_LINE_BUF_SIZE,
+ DDL_TILE_BUFFER_ALIGN_BYTES);
+ if (!ddl_context->db_line_buffer.virtual_base_addr) {
+ VIDC_LOGERR_STRING("ddl_dev_init:Line_buf_alloc_fail");
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ }
+
+ if (!status) {
+ ddl_pmem_alloc(&ddl_context->data_partition_tempbuf,
+ DDL_MPEG4_DATA_PARTITION_BUF_SIZE,
+ DDL_TILE_BUFFER_ALIGN_BYTES);
+ if (ddl_context->data_partition_tempbuf.virtual_base_addr \
+ == NULL) {
+ VIDC_LOGERR_STRING
+ ("ddl_dev_init:Data_partition_buf_alloc_fail");
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ }
+
+ if (!status) {
+
+ ddl_pmem_alloc(&ddl_context->metadata_shared_input,
+ DDL_METADATA_TOTAL_INPUTBUFSIZE,
+ DDL_LINEAR_BUFFER_ALIGN_BYTES);
+ if (!ddl_context->metadata_shared_input.virtual_base_addr) {
+ VIDC_LOGERR_STRING
+ ("ddl_dev_init:metadata_shared_input_alloc_fail");
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ }
+
+ if (!status) {
+ ddl_pmem_alloc(&ddl_context->dbg_core_dump, \
+ DDL_DBG_CORE_DUMP_SIZE, \
+ DDL_LINEAR_BUFFER_ALIGN_BYTES);
+ if (!ddl_context->dbg_core_dump.virtual_base_addr) {
+ VIDC_LOGERR_STRING
+ ("ddl_dev_init:dbg_core_dump_alloc_failed");
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ ddl_context->enable_dbg_core_dump = 0;
+ }
+
+ if (!status && !vcd_fw_init()) {
+ VIDC_LOGERR_STRING("ddl_dev_init:fw_init_failed");
+ status = VCD_ERR_ALLOC_FAIL;
+ }
+ if (status) {
+ ddl_release_context_buffers(ddl_context);
+ DDL_IDLE(ddl_context);
+ return status;
+ }
+
+ ddl_move_command_state(ddl_context, DDL_CMD_DMA_INIT);
+
+ ddl_core_init(ddl_context);
+
+ return status;
+}
+
+u32 ddl_device_release(void *client_data)
+{
+ struct ddl_context *ddl_context;
+
+ ddl_context = ddl_get_context();
+
+ if (DDL_IS_BUSY(ddl_context)) {
+ VIDC_LOGERR_STRING("ddl_dev_rel:Ddl_busy");
+ return VCD_ERR_BUSY;
+ }
+
+ if (!DDL_IS_INITIALIZED(ddl_context)) {
+ VIDC_LOGERR_STRING("ddl_dev_rel:Not_inited");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+
+ if (!ddl_client_transact(DDL_ACTIVE_CLIENT, NULL)) {
+ VIDC_LOGERR_STRING("ddl_dev_rel:Client_present_err");
+ return VCD_ERR_CLIENT_PRESENT;
+ }
+ DDL_BUSY(ddl_context);
+
+ ddl_context->device_state = DDL_DEVICE_NOTINIT;
+ ddl_context->client_data = client_data;
+ ddl_move_command_state(ddl_context, DDL_CMD_INVALID);
+ vidc_720p_stop_fw();
+
+ VIDC_LOG_STRING("FW_ENDDONE");
+ ddl_release_context_buffers(ddl_context);
+
+ DDL_IDLE(ddl_context);
+
+ return VCD_S_SUCCESS;
+}
+
+u32 ddl_open(u32 **ddl_handle, u32 decoding)
+{
+ struct ddl_context *ddl_context;
+ struct ddl_client_context *ddl;
+ u32 status;
+
+ if (!ddl_handle) {
+ VIDC_LOGERR_STRING("ddl_open:Bad_handle");
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ ddl_context = ddl_get_context();
+
+ if (!DDL_IS_INITIALIZED(ddl_context)) {
+ VIDC_LOGERR_STRING("ddl_open:Not_inited");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+
+ status = ddl_client_transact(DDL_GET_CLIENT, &ddl);
+
+ if (status) {
+ VIDC_LOGERR_STRING("ddl_open:Client_trasac_failed");
+ return status;
+ }
+
+ ddl_move_client_state(ddl, DDL_CLIENT_OPEN);
+
+ ddl->codec_data.hdr.decoding = decoding;
+ ddl->decoding = decoding;
+
+ ddl_set_default_meta_data_hdr(ddl);
+
+ ddl_set_initial_default_values(ddl);
+
+ *ddl_handle = (u32 *) ddl;
+ return VCD_S_SUCCESS;
+}
+
+u32 ddl_close(u32 **ddl_handle)
+{
+ struct ddl_context *ddl_context;
+ struct ddl_client_context **ddl =
+ (struct ddl_client_context **)ddl_handle;
+
+ if (!ddl || !*ddl) {
+ VIDC_LOGERR_STRING("ddl_close:Bad_handle");
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ ddl_context = ddl_get_context();
+
+ if (!DDL_IS_INITIALIZED(ddl_context)) {
+ VIDC_LOGERR_STRING("ddl_close:Not_inited");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+
+ if (!DDLCLIENT_STATE_IS(*ddl, DDL_CLIENT_OPEN)) {
+ VIDC_LOGERR_STRING("ddl_close:Not_in_open_state");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+
+ ddl_move_client_state(*ddl, DDL_CLIENT_INVALID);
+ if ((*ddl)->decoding) {
+ vcd_fw_transact(false, true,
+ (*ddl)->codec_data.decoder.codec.codec);
+ } else {
+ vcd_fw_transact(false, false,
+ (*ddl)->codec_data.encoder.codec.codec);
+ }
+ ddl_client_transact(DDL_FREE_CLIENT, ddl);
+
+ return VCD_S_SUCCESS;
+}
+
+u32 ddl_encode_start(u32 *ddl_handle, void *client_data)
+{
+ struct ddl_client_context *ddl =
+ (struct ddl_client_context *)ddl_handle;
+ struct ddl_context *ddl_context;
+ struct ddl_encoder_data *encoder;
+ u32 dpb_size;
+
+ ddl_context = ddl_get_context();
+
+ if (!DDL_IS_INITIALIZED(ddl_context)) {
+ VIDC_LOGERR_STRING("ddl_enc_start:Not_inited");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (DDL_IS_BUSY(ddl_context)) {
+ VIDC_LOGERR_STRING("ddl_enc_start:Ddl_busy");
+ return VCD_ERR_BUSY;
+ }
+ if (!ddl || ddl->decoding) {
+ VIDC_LOGERR_STRING("ddl_enc_start:Bad_handle");
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)) {
+ VIDC_LOGERR_STRING("ddl_enc_start:Not_opened");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+
+ if (!ddl_encoder_ready_to_start(ddl)) {
+ VIDC_LOGERR_STRING("ddl_enc_start:Err_param_settings");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+
+ encoder = &ddl->codec_data.encoder;
+
+ dpb_size = ddl_get_yuv_buffer_size(&encoder->frame_size,
+ &encoder->re_con_buf_format, false,
+ encoder->codec.codec);
+
+ dpb_size *= DDL_ENC_NUM_DPB_BUFFERS;
+ ddl_pmem_alloc(&encoder->enc_dpb_addr,
+ dpb_size, DDL_TILE_BUFFER_ALIGN_BYTES);
+ if (!encoder->enc_dpb_addr.virtual_base_addr) {
+ VIDC_LOGERR_STRING("ddl_enc_start:Dpb_alloc_failed");
+ return VCD_ERR_ALLOC_FAIL;
+ }
+
+ if ((encoder->codec.codec == VCD_CODEC_MPEG4 &&
+ !encoder->short_header.short_header) ||
+ encoder->codec.codec == VCD_CODEC_H264) {
+ ddl_pmem_alloc(&encoder->seq_header,
+ DDL_ENC_SEQHEADER_SIZE,
+ DDL_LINEAR_BUFFER_ALIGN_BYTES);
+ if (!encoder->seq_header.virtual_base_addr) {
+ ddl_pmem_free(&encoder->enc_dpb_addr);
+ VIDC_LOGERR_STRING
+ ("ddl_enc_start:Seq_hdr_alloc_failed");
+ return VCD_ERR_ALLOC_FAIL;
+ }
+ } else {
+ encoder->seq_header.buffer_size = 0;
+ encoder->seq_header.virtual_base_addr = 0;
+ }
+
+ DDL_BUSY(ddl_context);
+
+ ddl_context->current_ddl = ddl;
+ ddl_context->client_data = client_data;
+ ddl_channel_set(ddl);
+ return VCD_S_SUCCESS;
+}
+
+u32 ddl_decode_start(u32 *ddl_handle,
+ struct vcd_sequence_hdr *header, void *client_data)
+{
+ struct ddl_client_context *ddl =
+ (struct ddl_client_context *)ddl_handle;
+ struct ddl_context *ddl_context;
+ struct ddl_decoder_data *decoder;
+
+ ddl_context = ddl_get_context();
+
+ if (!DDL_IS_INITIALIZED(ddl_context)) {
+ VIDC_LOGERR_STRING("ddl_dec_start:Not_inited");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (DDL_IS_BUSY(ddl_context)) {
+ VIDC_LOGERR_STRING("ddl_dec_start:Ddl_busy");
+ return VCD_ERR_BUSY;
+ }
+ if (!ddl || !ddl->decoding) {
+ VIDC_LOGERR_STRING("ddl_dec_start:Bad_handle");
+ return VCD_ERR_BAD_HANDLE;
+ }
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)) {
+ VIDC_LOGERR_STRING("ddl_dec_start:Not_in_opened_state");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+
+ if ((header) &&
+ ((!header->sequence_header_len) ||
+ (!header->sequence_header)
+ )
+ ) {
+ VIDC_LOGERR_STRING("ddl_dec_start:Bad_param_seq_header");
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+
+ if (!ddl_decoder_ready_to_start(ddl, header)) {
+ VIDC_LOGERR_STRING("ddl_dec_start:Err_param_settings");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+
+ DDL_BUSY(ddl_context);
+
+ decoder = &ddl->codec_data.decoder;
+ if (header) {
+ decoder->header_in_start = true;
+ decoder->decode_config = *header;
+ } else {
+ decoder->header_in_start = false;
+ decoder->decode_config.sequence_header_len = 0;
+ }
+
+ if (decoder->codec.codec == VCD_CODEC_H264) {
+ ddl_pmem_alloc(&decoder->h264Vsp_temp_buffer,
+ DDL_DECODE_H264_VSPTEMP_BUFSIZE,
+ DDL_LINEAR_BUFFER_ALIGN_BYTES);
+ if (!decoder->h264Vsp_temp_buffer.virtual_base_addr) {
+ DDL_IDLE(ddl_context);
+ VIDC_LOGERR_STRING
+ ("ddl_dec_start:H264Sps_alloc_failed");
+ return VCD_ERR_ALLOC_FAIL;
+ }
+ }
+
+ ddl_context->current_ddl = ddl;
+ ddl_context->client_data = client_data;
+
+ ddl_channel_set(ddl);
+ return VCD_S_SUCCESS;
+}
+
+u32 ddl_decode_frame(u32 *ddl_handle,
+ struct ddl_frame_data_tag *input_bits, void *client_data)
+{
+ u32 vcd_status = VCD_S_SUCCESS;
+ struct ddl_client_context *ddl =
+ (struct ddl_client_context *)ddl_handle;
+ struct ddl_context *ddl_context = ddl_get_context();
+
+ if (!DDL_IS_INITIALIZED(ddl_context)) {
+ VIDC_LOGERR_STRING("ddl_dec_frame:Not_inited");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (DDL_IS_BUSY(ddl_context)) {
+ VIDC_LOGERR_STRING("ddl_dec_frame:Ddl_busy");
+ return VCD_ERR_BUSY;
+ }
+ if (!ddl || !ddl->decoding) {
+ VIDC_LOGERR_STRING("ddl_dec_frame:Bad_handle");
+ return VCD_ERR_BAD_HANDLE;
+ }
+ if (!input_bits ||
+ ((!input_bits->vcd_frm.physical ||
+ !input_bits->vcd_frm.data_len) &&
+ (!(VCD_FRAME_FLAG_EOS & input_bits->vcd_frm.flags))
+ )
+ ) {
+ VIDC_LOGERR_STRING("ddl_dec_frame:Bad_input_param");
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+
+ DDL_BUSY(ddl_context);
+
+ ddl_context->current_ddl = ddl;
+ ddl_context->client_data = client_data;
+
+ ddl->input_frame = *input_bits;
+
+ if (DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME)) {
+ ddl_decode_frame_run(ddl);
+ } else {
+ if (!ddl->codec_data.decoder.dp_buf.no_of_dec_pic_buf) {
+ VIDC_LOGERR_STRING("ddl_dec_frame:Dpbs_requied");
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ } else if (DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_DPB)) {
+ vcd_status = ddl_decode_set_buffers(ddl);
+ } else
+ if (DDLCLIENT_STATE_IS
+ (ddl, DDL_CLIENT_WAIT_FOR_INITCODEC)) {
+ ddl->codec_data.decoder.decode_config.
+ sequence_header =
+ ddl->input_frame.vcd_frm.physical;
+ ddl->codec_data.decoder.decode_config.
+ sequence_header_len =
+ ddl->input_frame.vcd_frm.data_len;
+ ddl_decode_init_codec(ddl);
+ } else {
+ VIDC_LOGERR_STRING("Dec_frame:Wrong_state");
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ }
+ if (vcd_status)
+ DDL_IDLE(ddl_context);
+ }
+ return vcd_status;
+}
+
+u32 ddl_encode_frame(u32 *ddl_handle,
+ struct ddl_frame_data_tag *input_frame,
+ struct ddl_frame_data_tag *output_bit, void *client_data)
+{
+ struct ddl_client_context *ddl =
+ (struct ddl_client_context *)ddl_handle;
+ struct ddl_context *ddl_context = ddl_get_context();
+
+ if (vidc_msg_timing)
+ ddl_set_core_start_time(__func__, ENC_OP_TIME);
+
+ if (!DDL_IS_INITIALIZED(ddl_context)) {
+ VIDC_LOGERR_STRING("ddl_enc_frame:Not_inited");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (DDL_IS_BUSY(ddl_context)) {
+ VIDC_LOGERR_STRING("ddl_enc_frame:Ddl_busy");
+ return VCD_ERR_BUSY;
+ }
+ if (!ddl || ddl->decoding) {
+ VIDC_LOGERR_STRING("ddl_enc_frame:Bad_handle");
+ return VCD_ERR_BAD_HANDLE;
+ }
+ if (!input_frame ||
+ !input_frame->vcd_frm.physical ||
+ ddl->codec_data.encoder.input_buf_req.sz !=
+ input_frame->vcd_frm.data_len) {
+ VIDC_LOGERR_STRING("ddl_enc_frame:Bad_input_params");
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+ if ((((u32) input_frame->vcd_frm.physical +
+ input_frame->vcd_frm.offset) &
+ (DDL_STREAMBUF_ALIGN_GUARD_BYTES)
+ )
+ ) {
+ VIDC_LOGERR_STRING
+ ("ddl_enc_frame:Un_aligned_yuv_start_address");
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+ if (!output_bit ||
+ !output_bit->vcd_frm.physical ||
+ !output_bit->vcd_frm.alloc_len) {
+ VIDC_LOGERR_STRING("ddl_enc_frame:Bad_output_params");
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+ if ((ddl->codec_data.encoder.output_buf_req.sz +
+ output_bit->vcd_frm.offset) >
+ output_bit->vcd_frm.alloc_len) {
+ VIDC_LOGERR_STRING
+ ("ddl_enc_frame:offset_large, Exceeds_min_buf_size");
+ }
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME)) {
+ VIDC_LOGERR_STRING("ddl_enc_frame:Wrong_state");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+
+ DDL_BUSY(ddl_context);
+
+ ddl_context->current_ddl = ddl;
+ ddl_context->client_data = client_data;
+
+ ddl->input_frame = *input_frame;
+ ddl->output_frame = *output_bit;
+
+ ddl_encode_frame_run(ddl);
+ return VCD_S_SUCCESS;
+}
+
+u32 ddl_decode_end(u32 *ddl_handle, void *client_data)
+{
+ struct ddl_client_context *ddl =
+ (struct ddl_client_context *)ddl_handle;
+ struct ddl_context *ddl_context;
+
+ ddl_context = ddl_get_context();
+
+ if (vidc_msg_timing) {
+ ddl_reset_core_time_variables(DEC_OP_TIME);
+ ddl_reset_core_time_variables(DEC_IP_TIME);
+ }
+
+ if (!DDL_IS_INITIALIZED(ddl_context)) {
+ VIDC_LOGERR_STRING("ddl_dec_end:Not_inited");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (DDL_IS_BUSY(ddl_context)) {
+ VIDC_LOGERR_STRING("ddl_dec_end:Ddl_busy");
+ return VCD_ERR_BUSY;
+ }
+ if (!ddl || !ddl->decoding) {
+ VIDC_LOGERR_STRING("ddl_dec_end:Bad_handle");
+ return VCD_ERR_BAD_HANDLE;
+ }
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME) &&
+ !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_INITCODEC) &&
+ !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_DPB) &&
+ !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_FATAL_ERROR)
+ ) {
+ VIDC_LOGERR_STRING("ddl_dec_end:Wrong_state");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ DDL_BUSY(ddl_context);
+
+ ddl_context->current_ddl = ddl;
+ ddl_context->client_data = client_data;
+
+ ddl_channel_end(ddl);
+ return VCD_S_SUCCESS;
+}
+
+u32 ddl_encode_end(u32 *ddl_handle, void *client_data)
+{
+ struct ddl_client_context *ddl =
+ (struct ddl_client_context *)ddl_handle;
+ struct ddl_context *ddl_context;
+
+ ddl_context = ddl_get_context();
+
+ if (vidc_msg_timing)
+ ddl_reset_core_time_variables(ENC_OP_TIME);
+
+ if (!DDL_IS_INITIALIZED(ddl_context)) {
+ VIDC_LOGERR_STRING("ddl_enc_end:Not_inited");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (DDL_IS_BUSY(ddl_context)) {
+ VIDC_LOGERR_STRING("ddl_enc_end:Ddl_busy");
+ return VCD_ERR_BUSY;
+ }
+ if (!ddl || ddl->decoding) {
+ VIDC_LOGERR_STRING("ddl_enc_end:Bad_handle");
+ return VCD_ERR_BAD_HANDLE;
+ }
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME) &&
+ !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_INITCODEC) &&
+ !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_FATAL_ERROR)) {
+ VIDC_LOGERR_STRING("ddl_enc_end:Wrong_state");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ DDL_BUSY(ddl_context);
+
+ ddl_context->current_ddl = ddl;
+ ddl_context->client_data = client_data;
+
+ ddl_channel_end(ddl);
+ return VCD_S_SUCCESS;
+}
+
+u32 ddl_reset_hw(u32 mode)
+{
+ struct ddl_context *ddl_context;
+ struct ddl_client_context *ddl;
+ int i_client_num;
+
+ VIDC_LOG_STRING("ddl_reset_hw:called");
+ ddl_context = ddl_get_context();
+ ddl_move_command_state(ddl_context, DDL_CMD_INVALID);
+ DDL_BUSY(ddl_context);
+
+ if (ddl_context->core_virtual_base_addr)
+ vidc_720p_do_sw_reset();
+
+ ddl_context->device_state = DDL_DEVICE_NOTINIT;
+ for (i_client_num = 0; i_client_num < VCD_MAX_NO_CLIENT;
+ ++i_client_num) {
+ ddl = ddl_context->ddl_clients[i_client_num];
+ ddl_context->ddl_clients[i_client_num] = NULL;
+ if (ddl) {
+ ddl_release_client_internal_buffers(ddl);
+ ddl_client_transact(DDL_FREE_CLIENT, &ddl);
+ }
+ }
+
+ ddl_release_context_buffers(ddl_context);
+ DDL_MEMSET(ddl_context, 0, sizeof(struct ddl_context));
+
+ return true;
+}
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
new file mode 100644
index 0000000..157b556
--- /dev/null
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
@@ -0,0 +1,282 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _VCD_DDL_H_
+#define _VCD_DDL_H_
+#include "vcd_ddl_api.h"
+#include "vcd_ddl_utils.h"
+#include "vcd_ddl_firmware.h"
+#include "vidc.h"
+
+#undef DDL_INLINE
+#define DDL_INLINE
+
+#define DDL_BUSY_STATE 1
+#define DDL_IDLE_STATE 0
+#define DDL_ERROR_STATE 2
+#define DDL_IS_BUSY(ddl_context) \
+ (((ddl_context)->ddl_busy != DDL_IDLE_STATE))
+#define DDL_BUSY(ddl_context) \
+ ((ddl_context)->ddl_busy = DDL_BUSY_STATE)
+#define DDL_IDLE(ddl_context) \
+ ((ddl_context)->ddl_busy = DDL_IDLE_STATE)
+#define DDL_ERROR(ddl_context) \
+ ((ddl_context)->ddl_busy = DDL_ERROR_STATE)
+
+#define DDL_DEVICE_NOTINIT 0
+#define DDL_DEVICE_INITED 1
+#define DDL_DEVICE_HWFATAL 2
+#define DDL_IS_INITIALIZED(ddl_context) \
+(ddl_context->device_state == DDL_DEVICE_INITED)
+
+#define DDLCOMMAND_STATE_IS(ddl_context, command_state) \
+(command_state == (ddl_context)->cmd_state)
+
+#define DDLCLIENT_STATE_IS(ddl, current_state) \
+(current_state == (ddl)->client_state)
+
+#define DDL_DPB_OP_INIT 1
+#define DDL_DPB_OP_MARK_FREE 2
+#define DDL_DPB_OP_MARK_BUSY 3
+#define DDL_DPB_OP_SET_MASK 4
+#define DDL_DPB_OP_RETRIEVE 5
+
+#define DDL_INIT_CLIENTS 0
+#define DDL_GET_CLIENT 1
+#define DDL_FREE_CLIENT 2
+#define DDL_ACTIVE_CLIENT 3
+
+#define DDL_INVALID_CHANNEL_ID ((u32)~0)
+#define DDL_INVALID_CODEC_TYPE ((u32)~0)
+
+#define DDL_ENC_REQ_IFRAME 0x01
+#define DDL_ENC_CHANGE_IPERIOD 0x02
+#define DDL_ENC_CHANGE_BITRATE 0x04
+#define DDL_ENC_CHANGE_FRAMERATE 0x08
+#define DDL_ENC_CHANGE_CIR 0x10
+
+#define DDL_DEC_REQ_OUTPUT_FLUSH 0x1
+
+struct ddl_buf_addr {
+ u32 *physical_base_addr;
+ u32 *virtual_base_addr;
+ u32 *align_physical_addr;
+ u32 *align_virtual_addr;
+ u32 buffer_size;
+};
+
+enum ddl_cmd_state {
+ DDL_CMD_INVALID = 0x0,
+ DDL_CMD_DMA_INIT = 0x1,
+ DDL_CMD_CPU_RESET = 0x2,
+ DDL_CMD_CHANNEL_SET = 0x3,
+ DDL_CMD_INIT_CODEC = 0x4,
+ DDL_CMD_HEADER_PARSE = 0x5,
+ DDL_CMD_DECODE_SET_DPB = 0x6,
+ DDL_CMD_DECODE_FRAME = 0x7,
+ DDL_CMD_ENCODE_FRAME = 0x8,
+ DDL_CMD_EOS = 0x9,
+ DDL_CMD_CHANNEL_END = 0xA,
+ DDL_CMD_32BIT = 0x7FFFFFFF
+};
+
+enum ddl_client_state {
+ DDL_CLIENT_INVALID = 0x0,
+ DDL_CLIENT_OPEN = 0x1,
+ DDL_CLIENT_WAIT_FOR_CHDONE = 0x2,
+ DDL_CLIENT_WAIT_FOR_INITCODEC = 0x3,
+ DDL_CLIENT_WAIT_FOR_INITCODECDONE = 0x4,
+ DDL_CLIENT_WAIT_FOR_DPB = 0x5,
+ DDL_CLIENT_WAIT_FOR_DPBDONE = 0x6,
+ DDL_CLIENT_WAIT_FOR_FRAME = 0x7,
+ DDL_CLIENT_WAIT_FOR_FRAME_DONE = 0x8,
+ DDL_CLIENT_WAIT_FOR_EOS_DONE = 0x9,
+ DDL_CLIENT_WAIT_FOR_CHEND = 0xA,
+ DDL_CLIENT_FATAL_ERROR = 0xB,
+ DDL_CLIENT_32BIT = 0x7FFFFFFF
+};
+
+struct ddl_mask {
+ u32 client_mask;
+ u32 hw_mask;
+};
+
+struct ddl_context;
+
+struct ddl_client_context;
+
+struct ddl_codec_data_hdr {
+ u32 decoding;
+};
+
+struct ddl_encoder_data {
+ struct ddl_codec_data_hdr hdr;
+ struct vcd_property_codec codec;
+ struct vcd_property_frame_size frame_size;
+ struct vcd_property_frame_rate frame_rate;
+ struct vcd_property_target_bitrate target_bit_rate;
+ struct vcd_property_profile profile;
+ struct vcd_property_level level;
+ struct vcd_property_rate_control rc;
+ struct vcd_property_multi_slice multi_slice;
+ u32 meta_data_enable_flag;
+ u32 suffix;
+ struct ddl_buf_addr meta_data_input;
+ u32 meta_data_offset;
+ struct vcd_property_short_header short_header;
+ struct vcd_property_vop_timing vop_timing;
+ u32 hdr_ext_control;
+ struct vcd_property_db_config db_control;
+ struct vcd_property_entropy_control entropy_control;
+ struct vcd_property_i_period i_period;
+ struct vcd_property_session_qp session_qp;
+ struct vcd_property_qp_range qp_range;
+ struct vcd_property_rc_level rc_level;
+ u32 r_cframe_skip;
+ u32 vb_vbuffer_size;
+ struct vcd_property_frame_level_rc_params frame_level_rc;
+ struct vcd_property_adaptive_rc_params adaptive_rc;
+ struct vcd_property_intra_refresh_mb_number intra_refresh;
+ struct vcd_property_buffer_format buf_format;
+ struct vcd_property_buffer_format re_con_buf_format;
+ u32 dynamic_prop_change;
+ u32 dynmic_prop_change_req;
+ u32 ext_enc_control_val;
+ struct vidc_720p_enc_frame_info enc_frame_info;
+ struct ddl_buf_addr enc_dpb_addr;
+ struct ddl_buf_addr seq_header;
+ struct vcd_buffer_requirement input_buf_req;
+ struct vcd_buffer_requirement output_buf_req;
+ struct vcd_buffer_requirement client_input_buf_req;
+ struct vcd_buffer_requirement client_output_buf_req;
+};
+
+struct ddl_decoder_data {
+ struct ddl_codec_data_hdr hdr;
+ struct vcd_property_codec codec;
+ struct vcd_property_buffer_format buf_format;
+ struct vcd_property_frame_size frame_size;
+ struct vcd_property_frame_size client_frame_size;
+ struct vcd_property_profile profile;
+ struct vcd_property_level level;
+ u32 progressive_only;
+ u32 output_order;
+ u32 meta_data_enable_flag;
+ u32 suffix;
+ struct ddl_buf_addr meta_data_input;
+ struct ddl_buf_addr ref_buffer;
+ u32 meta_data_offset;
+ struct vcd_property_post_filter post_filter;
+ struct vcd_sequence_hdr decode_config;
+ u32 header_in_start;
+ u32 min_dpb_num;
+ u32 y_cb_cr_size;
+ struct ddl_property_dec_pic_buffers dp_buf;
+ struct ddl_mask dpb_mask;
+ u32 dynamic_prop_change;
+ u32 dynmic_prop_change_req;
+ struct vidc_720p_dec_disp_info dec_disp_info;
+ struct ddl_buf_addr dpb_comv_buffer;
+ struct ddl_buf_addr h264Vsp_temp_buffer;
+ struct vcd_buffer_requirement actual_input_buf_req;
+ struct vcd_buffer_requirement min_input_buf_req;
+ struct vcd_buffer_requirement client_input_buf_req;
+ struct vcd_buffer_requirement actual_output_buf_req;
+ struct vcd_buffer_requirement min_output_buf_req;
+ struct vcd_buffer_requirement client_output_buf_req;
+};
+
+union ddl_codec_data {
+ struct ddl_codec_data_hdr hdr;
+ struct ddl_decoder_data decoder;
+ struct ddl_encoder_data encoder;
+};
+
+struct ddl_context {
+ int memtype;
+ u8 *core_virtual_base_addr;
+ void (*ddl_callback) (u32 event, u32 status, void *payload, size_t sz,
+ u32 *ddl_handle, void *const client_data);
+ void *client_data;
+ void (*interrupt_clr) (void);
+ enum ddl_cmd_state cmd_state;
+ struct ddl_client_context *current_ddl;
+ struct ddl_buf_addr context_buf_addr;
+ struct ddl_buf_addr db_line_buffer;
+ struct ddl_buf_addr data_partition_tempbuf;
+ struct ddl_buf_addr metadata_shared_input;
+ struct ddl_buf_addr dbg_core_dump;
+ u32 enable_dbg_core_dump;
+ struct ddl_client_context *ddl_clients[VCD_MAX_NO_CLIENT];
+ u32 device_state;
+ u32 ddl_busy;
+ u32 intr_status;
+ u32 cmd_err_status;
+ u32 disp_pic_err_status;
+ u32 op_failed;
+};
+
+struct ddl_client_context {
+ struct ddl_context *ddl_context;
+ enum ddl_client_state client_state;
+ u32 decoding;
+ u32 channel_id;
+ struct ddl_frame_data_tag input_frame;
+ struct ddl_frame_data_tag output_frame;
+ union ddl_codec_data codec_data;
+};
+
+DDL_INLINE struct ddl_context *ddl_get_context(void);
+DDL_INLINE void ddl_move_command_state(struct ddl_context *ddl_context,
+ enum ddl_cmd_state command_state);
+DDL_INLINE void ddl_move_client_state(struct ddl_client_context *ddl,
+ enum ddl_client_state client_state);
+void ddl_core_init(struct ddl_context *);
+void ddl_core_start_cpu(struct ddl_context *);
+void ddl_channel_set(struct ddl_client_context *);
+void ddl_channel_end(struct ddl_client_context *);
+void ddl_encode_init_codec(struct ddl_client_context *);
+void ddl_decode_init_codec(struct ddl_client_context *);
+void ddl_encode_frame_run(struct ddl_client_context *);
+void ddl_decode_frame_run(struct ddl_client_context *);
+void ddl_decode_eos_run(struct ddl_client_context *);
+void ddl_release_context_buffers(struct ddl_context *);
+void ddl_release_client_internal_buffers(struct ddl_client_context *ddl);
+u32 ddl_decode_set_buffers(struct ddl_client_context *);
+u32 ddl_decoder_dpb_transact(struct ddl_decoder_data *decoder,
+ struct ddl_frame_data_tag *in_out_frame,
+ u32 operation);
+u32 ddl_client_transact(u32, struct ddl_client_context **);
+void ddl_set_default_decoder_buffer_req
+ (struct ddl_decoder_data *decoder, u32 estimate);
+void ddl_set_default_encoder_buffer_req
+ (struct ddl_encoder_data *encoder);
+void ddl_set_default_dec_property(struct ddl_client_context *);
+u32 ddl_encoder_ready_to_start(struct ddl_client_context *);
+u32 ddl_decoder_ready_to_start(struct ddl_client_context *,
+ struct vcd_sequence_hdr *);
+u32 ddl_get_yuv_buffer_size
+ (struct vcd_property_frame_size *frame_size,
+ struct vcd_property_buffer_format *buf_format, u32 inter_lace,
+ enum vcd_codec codec);
+void ddl_calculate_stride(struct vcd_property_frame_size *frame_size,
+ u32 inter_lace, enum vcd_codec codec);
+void ddl_encode_dynamic_property(struct ddl_client_context *ddl,
+ u32 enable);
+void ddl_decode_dynamic_property(struct ddl_client_context *ddl,
+ u32 enable);
+void ddl_set_initial_default_values(struct ddl_client_context *ddl);
+u32 ddl_handle_core_errors(struct ddl_context *ddl_context);
+void ddl_client_fatal_cb(struct ddl_context *ddl_context);
+void ddl_hw_fatal_cb(struct ddl_context *ddl_context);
+u32 ddl_hal_engine_reset(struct ddl_context *ddl_context);
+#endif
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_api.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_api.h
new file mode 100644
index 0000000..53cc93e
--- /dev/null
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_api.h
@@ -0,0 +1,53 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _VCD_DDL_API_H_
+#define _VCD_DDL_API_H_
+#include "vcd_ddl_internal_property.h"
+
+struct ddl_init_config {
+ int memtype;
+ u8 *core_virtual_base_addr;
+ void (*interrupt_clr) (void);
+ void (*ddl_callback) (u32 event, u32 status, void *payload, size_t sz,
+ u32 *ddl_handle, void *const client_data);
+};
+
+struct ddl_frame_data_tag {
+ struct vcd_frame_data vcd_frm;
+ u32 frm_trans_end;
+ u32 frm_delta;
+};
+
+u32 ddl_device_init(struct ddl_init_config *ddl_init_config,
+ void *client_data);
+u32 ddl_device_release(void *client_data);
+u32 ddl_open(u32 **ddl_handle, u32 decoding);
+u32 ddl_close(u32 **ddl_handle);
+u32 ddl_encode_start(u32 *ddl_handle, void *client_data);
+u32 ddl_encode_frame(u32 *ddl_handle,
+ struct ddl_frame_data_tag *input_frame,
+ struct ddl_frame_data_tag *output_bit, void *client_data);
+u32 ddl_encode_end(u32 *ddl_handle, void *client_data);
+u32 ddl_decode_start(u32 *ddl_handle, struct vcd_sequence_hdr *header,
+ void *client_data);
+u32 ddl_decode_frame(u32 *ddl_handle,
+ struct ddl_frame_data_tag *input_bits, void *client_data);
+u32 ddl_decode_end(u32 *ddl_handle, void *client_data);
+u32 ddl_set_property(u32 *ddl_handle,
+ struct vcd_property_hdr *property_hdr, void *property_value);
+u32 ddl_get_property(u32 *ddl_handle,
+ struct vcd_property_hdr *property_hdr, void *property_value);
+void ddl_read_and_clear_interrupt(void);
+u32 ddl_process_core_response(void);
+u32 ddl_reset_hw(u32 mode);
+#endif
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_core.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_core.h
new file mode 100644
index 0000000..9fdb668
--- /dev/null
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_core.h
@@ -0,0 +1,99 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _VCD_DDL_CORE_H_
+#define _VCD_DDL_CORE_H_
+
+#define DDL_LINEAR_BUF_ALIGN_MASK 0xFFFFFFF8U
+#define DDL_LINEAR_BUF_ALIGN_GUARD_BYTES 0x7
+#define DDL_LINEAR_BUFFER_ALIGN_BYTES 8
+
+#define DDL_TILE_BUF_ALIGN_MASK 0xFFFFE000U
+#define DDL_TILE_BUF_ALIGN_GUARD_BYTES 0x1FFF
+#define DDL_TILE_BUFFER_ALIGN_BYTES 8192
+
+#define DDL_MAX_FRAME_WIDTH (1280)
+#define DDL_MAX_FRAME_HEIGHT (720)
+
+#define DDL_MAX_DP_FRAME_WIDTH 352
+#define DDL_MAX_DP_FRAME_HEIGHT 288
+
+#define DDL_MAX_BIT_RATE (14*1000*1000)
+
+#define DDL_SW_RESET_SLEEP 10
+
+#define VCD_MAX_NO_CLIENT 4
+#define VCD_FRAME_COMMAND_DEPTH 1
+#define VCD_GENERAL_COMMAND_DEPTH 1
+#define VCD_COMMAND_EXCLUSIVE true
+
+#define DDL_HW_TIMEOUT_IN_MS 1000
+
+#define DDL_STREAMBUF_ALIGN_GUARD_BYTES 0x7
+
+#define DDL_CONTEXT_MEMORY (1024 * 15 * (VCD_MAX_NO_CLIENT + 1))
+#define DDL_DB_LINE_BUF_SIZE \
+(((((DDL_MAX_FRAME_WIDTH * 4) - 1) / 256) + 1) * 8 * 1024)
+#define DDL_MPEG4_DATA_PARTITION_BUF_SIZE (64 * 1024)
+#define DDL_DECODE_H264_VSPTEMP_BUFSIZE 0x59c00
+#define DDL_ENC_NUM_DPB_BUFFERS 2
+
+#define DDL_DBG_CORE_DUMP_SIZE (10 * 1024)
+
+#define DDL_BUFEND_PAD 256
+#define DDL_ENC_SEQHEADER_SIZE (256+DDL_BUFEND_PAD)
+#define DDL_MAX_BUFFER_COUNT 32
+
+#define DDL_MPEG_REFBUF_COUNT 2
+
+#define DDL_MPEG_COMV_BUF_NO 2
+#define DDL_H263_COMV_BUF_NO 2
+#define DDL_COMV_BUFLINE_NO 128
+#define DDL_VC1_COMV_BUFLINE_NO 32
+#define DDL_MINIMUM_BYTE_PER_SLICE 1920
+
+#define DDL_MAX_H264_QP 51
+#define DDL_MAX_MPEG4_QP 31
+
+#define DDL_PADDING_HACK(addr) \
+ (addr) = (u32)((((u32)(addr) + DDL_STREAMBUF_ALIGN_GUARD_BYTES) & \
+ ~(DDL_STREAMBUF_ALIGN_GUARD_BYTES)) + DDL_BUFEND_PAD)
+
+#define DDL_QCIF_MBS 99
+#define DDL_CIF_MBS 396
+#define DDL_QVGA_MBS 300
+#define DDL_VGA_MBS 1200
+#define DDL_WVGA_MBS 1500
+#define DDL_720P_MBS 3600
+
+#define DDL_FRAMESIZE_DIV_FACTOR (0xF)
+
+#define DDL_NO_OF_MB(width, height) \
+ (((width + 15) >> 4) * ((height + 15) >> 4))
+
+#define DDL_ALLOW_ENC_FRAMESIZE(width, height) \
+((DDL_NO_OF_MB(width, height) <= DDL_720P_MBS) \
+ && (((width) <= DDL_MAX_FRAME_WIDTH) && \
+ ((height) <= DDL_MAX_FRAME_WIDTH)) \
+ && ((width) >= 32 && (height) >= 32))
+
+#define DDL_VALIDATE_ENC_FRAMESIZE(width, height) \
+ (!((width) & DDL_FRAMESIZE_DIV_FACTOR) && \
+ !((height) & DDL_FRAMESIZE_DIV_FACTOR))
+
+#define DDL_TILE_ALIGN_WIDTH 128
+#define DDL_TILE_ALIGN_HEIGHT 32
+#define DDL_TILE_MULTIPLY_FACTOR 8192
+#define DDL_TILE_ALIGN(val, grid) \
+ (((val) + (grid) - 1) / (grid) * (grid))
+
+#endif
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c
new file mode 100644
index 0000000..1b62553
--- /dev/null
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c
@@ -0,0 +1,595 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "vidc_type.h"
+#include "vcd_ddl_utils.h"
+#include "vcd_ddl.h"
+
+#if DEBUG
+#define DBG(x...) printk(KERN_DEBUG x)
+#else
+#define DBG(x...)
+#endif
+
+#define ERR(x...) printk(KERN_ERR x)
+
+#define INVALID_CHANNEL_NUMBER 1
+#define INVALID_COMMAND_ID 2
+#define CHANNEL_ALREADY_IN_USE 3
+#define CHANNEL_NOT_SET_BEFORE_CHANNEL_CLOSE 4
+#define CHANNEL_SET_ERROR_INIT_CODEC 5
+#define INIT_CODEC_ALREADY_CALLED 6
+#define CHANNEL_SET_ERROR_INIT_BUFFERS 7
+#define INIT_CODEC_ERROR_INIT_BUFFERS 8
+#define INIT_BUFFER_ALREADY_CALLED 9
+#define CHANNEL_SET_ERROR_FRAME_RUN 10
+#define INIT_CODEC_ERROR_FRAME_RUN 11
+#define INIT_BUFFERS_ERROR_FRAME_RUN 12
+#define CODEC_LIMIT_EXCEEDED 13
+#define FIRMWARE_SIZE_ZERO 14
+#define FIRMWARE_ADDRESS_EXT_ZERO 15
+#define CONTEXT_DMA_IN_ERROR 16
+#define CONTEXT_DMA_OUT_ERROR 17
+#define PROGRAM_DMA_ERROR 18
+#define CONTEXT_STORE_EXT_ADD_ZERO 19
+#define MEM_ALLOCATION_FAILED 20
+
+
+#define UNSUPPORTED_FEATURE_IN_PROFILE 27
+#define RESOLUTION_NOT_SUPPORTED 28
+#define HEADER_NOT_FOUND 52
+#define MB_NUM_INVALID 61
+#define FRAME_RATE_NOT_SUPPORTED 62
+#define INVALID_QP_VALUE 63
+#define INVALID_RC_REACTION_COEFFICIENT 64
+#define INVALID_CPB_SIZE_AT_GIVEN_LEVEL 65
+
+#define ALLOC_DPB_SIZE_NOT_SUFFICIENT 71
+#define ALLOC_DB_SIZE_NOT_SUFFICIENT 72
+#define ALLOC_COMV_SIZE_NOT_SUFFICIENT 73
+#define NUM_BUF_OUT_OF_RANGE 74
+#define NULL_CONTEXT_POINTER 75
+#define NULL_COMAMND_CONTROL_COMM_POINTER 76
+#define NULL_METADATA_INPUT_POINTER 77
+#define NULL_DPB_POINTER 78
+#define NULL_DB_POINTER 79
+#define NULL_COMV_POINTER 80
+
+#define DIVIDE_BY_ZERO 81
+#define BIT_STREAM_BUF_EXHAUST 82
+#define DMA_NOT_STOPPED 83
+#define DMA_TX_NOT_COMPLETE 84
+
+#define MB_HEADER_NOT_DONE 85
+#define MB_COEFF_NOT_DONE 86
+#define CODEC_SLICE_NOT_DONE 87
+#define VME_NOT_READY 88
+#define VC1_BITPLANE_DECODE_ERR 89
+
+
+#define VSP_NOT_READY 90
+#define BUFFER_FULL_STATE 91
+
+#define RESOLUTION_MISMATCH 112
+#define NV_QUANT_ERR 113
+#define SYNC_MARKER_ERR 114
+#define FEATURE_NOT_SUPPORTED 115
+#define MEM_CORRUPTION 116
+#define INVALID_REFERENCE_FRAME 117
+#define PICTURE_CODING_TYPE_ERR 118
+#define MV_RANGE_ERR 119
+#define PICTURE_STRUCTURE_ERR 120
+#define SLICE_ADDR_INVALID 121
+#define NON_PAIRED_FIELD_NOT_SUPPORTED 122
+#define NON_FRAME_DATA_RECEIVED 123
+#define INCOMPLETE_FRAME 124
+#define NO_BUFFER_RELEASED_FROM_HOST 125
+#define PICTURE_MANAGEMENT_ERROR 128
+#define INVALID_MMCO 129
+#define INVALID_PIC_REORDERING 130
+#define INVALID_POC_TYPE 131
+#define ACTIVE_SPS_NOT_PRESENT 132
+#define ACTIVE_PPS_NOT_PRESENT 133
+#define INVALID_SPS_ID 134
+#define INVALID_PPS_ID 135
+
+
+#define METADATA_NO_SPACE_QP 151
+#define METADATA_NO_SAPCE_CONCEAL_MB 152
+#define METADATA_NO_SPACE_VC1_PARAM 153
+#define METADATA_NO_SPACE_SEI 154
+#define METADATA_NO_SPACE_VUI 155
+#define METADATA_NO_SPACE_EXTRA 156
+#define METADATA_NO_SPACE_DATA_NONE 157
+#define FRAME_RATE_UNKNOWN 158
+#define ASPECT_RATIO_UNKOWN 159
+#define COLOR_PRIMARIES_UNKNOWN 160
+#define TRANSFER_CHAR_UNKWON 161
+#define MATRIX_COEFF_UNKNOWN 162
+#define NON_SEQ_SLICE_ADDR 163
+#define BROKEN_LINK 164
+#define FRAME_CONCEALED 165
+#define PROFILE_UNKOWN 166
+#define LEVEL_UNKOWN 167
+#define BIT_RATE_NOT_SUPPORTED 168
+#define COLOR_DIFF_FORMAT_NOT_SUPPORTED 169
+#define NULL_EXTRA_METADATA_POINTER 170
+#define SYNC_POINT_NOT_RECEIVED_STARTED_DECODING 171
+#define NULL_FW_DEBUG_INFO_POINTER 172
+#define ALLOC_DEBUG_INFO_SIZE_INSUFFICIENT 173
+#define MAX_STAGE_COUNTER_EXCEEDED 174
+
+#define METADATA_NO_SPACE_MB_INFO 180
+#define METADATA_NO_SPACE_SLICE_SIZE 181
+#define RESOLUTION_WARNING 182
+
+static void ddl_handle_npf_decoding_error(
+ struct ddl_context *ddl_context);
+
+static u32 ddl_handle_seqhdr_fail_error(
+ struct ddl_context *ddl_context);
+
+void ddl_hw_fatal_cb(struct ddl_context *ddl_context)
+{
+ /* Invalidate the command state */
+ ddl_move_command_state(ddl_context, DDL_CMD_INVALID);
+ ddl_context->device_state = DDL_DEVICE_HWFATAL;
+
+ /* callback to the client to indicate hw fatal error */
+ ddl_context->ddl_callback(VCD_EVT_IND_HWERRFATAL,
+ VCD_ERR_HW_FATAL, NULL, 0,
+ (void *)ddl_context->current_ddl,
+ ddl_context->client_data);
+
+ DDL_IDLE(ddl_context);
+}
+
+static u32 ddl_handle_hw_fatal_errors(struct ddl_context
+ *ddl_context)
+{
+ u32 status = false;
+
+ switch (ddl_context->cmd_err_status) {
+
+ case INVALID_CHANNEL_NUMBER:
+ case INVALID_COMMAND_ID:
+ case CHANNEL_ALREADY_IN_USE:
+ case CHANNEL_NOT_SET_BEFORE_CHANNEL_CLOSE:
+ case CHANNEL_SET_ERROR_INIT_CODEC:
+ case INIT_CODEC_ALREADY_CALLED:
+ case CHANNEL_SET_ERROR_INIT_BUFFERS:
+ case INIT_CODEC_ERROR_INIT_BUFFERS:
+ case INIT_BUFFER_ALREADY_CALLED:
+ case CHANNEL_SET_ERROR_FRAME_RUN:
+ case INIT_CODEC_ERROR_FRAME_RUN:
+ case INIT_BUFFERS_ERROR_FRAME_RUN:
+ case CODEC_LIMIT_EXCEEDED:
+ case FIRMWARE_SIZE_ZERO:
+ case FIRMWARE_ADDRESS_EXT_ZERO:
+
+ case CONTEXT_DMA_IN_ERROR:
+ case CONTEXT_DMA_OUT_ERROR:
+ case PROGRAM_DMA_ERROR:
+ case CONTEXT_STORE_EXT_ADD_ZERO:
+ case MEM_ALLOCATION_FAILED:
+
+ case DIVIDE_BY_ZERO:
+ case DMA_NOT_STOPPED:
+ case DMA_TX_NOT_COMPLETE:
+
+ case VSP_NOT_READY:
+ case BUFFER_FULL_STATE:
+ case NULL_DB_POINTER:
+ ERR("HW FATAL ERROR");
+ ddl_hw_fatal_cb(ddl_context);
+ status = true;
+ break;
+ }
+ return status;
+}
+
+void ddl_client_fatal_cb(struct ddl_context *ddl_context)
+{
+ struct ddl_client_context *ddl =
+ ddl_context->current_ddl;
+
+ if (ddl_context->cmd_state == DDL_CMD_DECODE_FRAME)
+ ddl_decode_dynamic_property(ddl, false);
+ else if (ddl_context->cmd_state == DDL_CMD_ENCODE_FRAME)
+ ddl_encode_dynamic_property(ddl, false);
+
+ ddl_move_command_state(ddl_context, DDL_CMD_INVALID);
+
+ ddl_move_client_state(ddl, DDL_CLIENT_FATAL_ERROR);
+
+ ddl_context->ddl_callback
+ (
+ VCD_EVT_IND_HWERRFATAL,
+ VCD_ERR_CLIENT_FATAL,
+ NULL,
+ 0,
+ (void *)ddl,
+ ddl_context->client_data
+ );
+
+ DDL_IDLE(ddl_context);
+}
+
+static u32 ddl_handle_client_fatal_errors(struct ddl_context
+ *ddl_context)
+{
+ u32 status = false;
+
+ switch (ddl_context->cmd_err_status) {
+ case MB_NUM_INVALID:
+ case FRAME_RATE_NOT_SUPPORTED:
+ case INVALID_QP_VALUE:
+ case INVALID_RC_REACTION_COEFFICIENT:
+ case INVALID_CPB_SIZE_AT_GIVEN_LEVEL:
+
+ case ALLOC_DPB_SIZE_NOT_SUFFICIENT:
+ case ALLOC_DB_SIZE_NOT_SUFFICIENT:
+ case ALLOC_COMV_SIZE_NOT_SUFFICIENT:
+ case NUM_BUF_OUT_OF_RANGE:
+ case NULL_CONTEXT_POINTER:
+ case NULL_COMAMND_CONTROL_COMM_POINTER:
+ case NULL_METADATA_INPUT_POINTER:
+ case NULL_DPB_POINTER:
+ case NULL_COMV_POINTER:
+ {
+ status = true;
+ break;
+ }
+ }
+
+ if (!status)
+ ERR("UNKNOWN-OP-FAILED");
+
+ ddl_client_fatal_cb(ddl_context);
+
+ return true;
+}
+
+static void ddl_input_failed_cb(struct ddl_context *ddl_context,
+ u32 vcd_event, u32 vcd_status)
+{
+ struct ddl_client_context *ddl = ddl_context->current_ddl;
+
+ ddl_move_command_state(ddl_context, DDL_CMD_INVALID);
+
+ if (ddl->decoding)
+ ddl_decode_dynamic_property(ddl, false);
+ else
+ ddl_encode_dynamic_property(ddl, false);
+
+ ddl_context->ddl_callback(vcd_event,
+ vcd_status, &ddl->input_frame,
+ sizeof(struct ddl_frame_data_tag),
+ (void *)ddl, ddl_context->client_data);
+
+ ddl_move_client_state(ddl, DDL_CLIENT_WAIT_FOR_FRAME);
+}
+
+static u32 ddl_handle_core_recoverable_errors(struct ddl_context \
+ *ddl_context)
+{
+ struct ddl_client_context *ddl = ddl_context->current_ddl;
+ u32 vcd_status = VCD_S_SUCCESS;
+ u32 vcd_event = VCD_EVT_RESP_INPUT_DONE;
+ u32 eos = false, pending_display = 0, release_mask = 0;
+
+ if (ddl->decoding)
+ if (ddl_handle_seqhdr_fail_error(ddl_context))
+ return true;
+
+ if (ddl_context->cmd_state != DDL_CMD_DECODE_FRAME &&
+ ddl_context->cmd_state != DDL_CMD_ENCODE_FRAME) {
+ return false;
+ }
+ switch (ddl_context->cmd_err_status) {
+ case NON_PAIRED_FIELD_NOT_SUPPORTED:
+ {
+ ddl_handle_npf_decoding_error(ddl_context);
+ return true;
+ }
+ case NO_BUFFER_RELEASED_FROM_HOST:
+ {
+ /* lets check sanity of this error */
+ release_mask =
+ ddl->codec_data.decoder.dpb_mask.hw_mask;
+ while (release_mask > 0) {
+ if ((release_mask & 0x1))
+ pending_display += 1;
+ release_mask >>= 1;
+ }
+
+ if (pending_display >=
+ ddl->codec_data.decoder.min_dpb_num) {
+ DBG("FWISSUE-REQBUF!!");
+ /* callback to client for client fatal error */
+ ddl_client_fatal_cb(ddl_context);
+ return true ;
+ }
+ vcd_event = VCD_EVT_RESP_OUTPUT_REQ;
+ break;
+ }
+ case BIT_STREAM_BUF_EXHAUST:
+ case MB_HEADER_NOT_DONE:
+ case MB_COEFF_NOT_DONE:
+ case CODEC_SLICE_NOT_DONE:
+ case VME_NOT_READY:
+ case VC1_BITPLANE_DECODE_ERR:
+ {
+ u32 reset_core;
+ /* need to reset the internal core hw engine */
+ reset_core = ddl_hal_engine_reset(ddl_context);
+ if (!reset_core)
+ return true;
+ /* fall through to process bitstream error handling */
+ }
+ case RESOLUTION_MISMATCH:
+ case NV_QUANT_ERR:
+ case SYNC_MARKER_ERR:
+ case FEATURE_NOT_SUPPORTED:
+ case MEM_CORRUPTION:
+ case INVALID_REFERENCE_FRAME:
+ case PICTURE_CODING_TYPE_ERR:
+ case MV_RANGE_ERR:
+ case PICTURE_STRUCTURE_ERR:
+ case SLICE_ADDR_INVALID:
+ case NON_FRAME_DATA_RECEIVED:
+ case INCOMPLETE_FRAME:
+ case PICTURE_MANAGEMENT_ERROR:
+ case INVALID_MMCO:
+ case INVALID_PIC_REORDERING:
+ case INVALID_POC_TYPE:
+ case ACTIVE_SPS_NOT_PRESENT:
+ case ACTIVE_PPS_NOT_PRESENT:
+ {
+ vcd_status = VCD_ERR_BITSTREAM_ERR;
+ break;
+ }
+ }
+
+ if (!vcd_status && vcd_event == VCD_EVT_RESP_INPUT_DONE)
+ return false;
+
+ ddl->input_frame.frm_trans_end = true;
+
+ eos = ((vcd_event == VCD_EVT_RESP_INPUT_DONE) &&
+ ((VCD_FRAME_FLAG_EOS & ddl->input_frame.
+ vcd_frm.flags)));
+
+ if ((ddl->decoding && eos) ||
+ (!ddl->decoding))
+ ddl->input_frame.frm_trans_end = false;
+
+ if (vcd_event == VCD_EVT_RESP_INPUT_DONE &&
+ ddl->decoding &&
+ !ddl->codec_data.decoder.header_in_start &&
+ !ddl->codec_data.decoder.dec_disp_info.img_size_x &&
+ !ddl->codec_data.decoder.dec_disp_info.img_size_y
+ ) {
+ /* this is first frame seq. header only case */
+ vcd_status = VCD_S_SUCCESS;
+ ddl->input_frame.vcd_frm.flags |=
+ VCD_FRAME_FLAG_CODECCONFIG;
+ ddl->input_frame.frm_trans_end = !eos;
+ /* put just some non - zero value */
+ ddl->codec_data.decoder.dec_disp_info.img_size_x = 0xff;
+ }
+ /* inform client about input failed */
+ ddl_input_failed_cb(ddl_context, vcd_event, vcd_status);
+
+ /* for Encoder case, we need to send output done also */
+ if (!ddl->decoding) {
+ /* transaction is complete after this callback */
+ ddl->output_frame.frm_trans_end = !eos;
+ /* error case: NO data present */
+ ddl->output_frame.vcd_frm.data_len = 0;
+ /* call back to client for output frame done */
+ ddl_context->ddl_callback(VCD_EVT_RESP_OUTPUT_DONE,
+ VCD_ERR_FAIL, &(ddl->output_frame),
+ sizeof(struct ddl_frame_data_tag),
+ (void *)ddl, ddl_context->client_data);
+
+ if (eos) {
+ DBG("ENC-EOS_DONE");
+ /* send client EOS DONE callback */
+ ddl_context->ddl_callback(VCD_EVT_RESP_EOS_DONE,
+ VCD_S_SUCCESS, NULL, 0, (void *)ddl,
+ ddl_context->client_data);
+ }
+ }
+
+ /* if it is decoder EOS case */
+ if (ddl->decoding && eos)
+ ddl_decode_eos_run(ddl);
+ else
+ DDL_IDLE(ddl_context);
+
+ return true;
+}
+
+static u32 ddl_handle_core_warnings(u32 err_status)
+{
+ u32 status = false;
+
+ switch (err_status) {
+ case FRAME_RATE_UNKNOWN:
+ case ASPECT_RATIO_UNKOWN:
+ case COLOR_PRIMARIES_UNKNOWN:
+ case TRANSFER_CHAR_UNKWON:
+ case MATRIX_COEFF_UNKNOWN:
+ case NON_SEQ_SLICE_ADDR:
+ case BROKEN_LINK:
+ case FRAME_CONCEALED:
+ case PROFILE_UNKOWN:
+ case LEVEL_UNKOWN:
+ case BIT_RATE_NOT_SUPPORTED:
+ case COLOR_DIFF_FORMAT_NOT_SUPPORTED:
+ case NULL_EXTRA_METADATA_POINTER:
+ case SYNC_POINT_NOT_RECEIVED_STARTED_DECODING:
+
+ case NULL_FW_DEBUG_INFO_POINTER:
+ case ALLOC_DEBUG_INFO_SIZE_INSUFFICIENT:
+ case MAX_STAGE_COUNTER_EXCEEDED:
+
+ case METADATA_NO_SPACE_MB_INFO:
+ case METADATA_NO_SPACE_SLICE_SIZE:
+ case RESOLUTION_WARNING:
+
+ /* decoder warnings */
+ case METADATA_NO_SPACE_QP:
+ case METADATA_NO_SAPCE_CONCEAL_MB:
+ case METADATA_NO_SPACE_VC1_PARAM:
+ case METADATA_NO_SPACE_SEI:
+ case METADATA_NO_SPACE_VUI:
+ case METADATA_NO_SPACE_EXTRA:
+ case METADATA_NO_SPACE_DATA_NONE:
+ {
+ status = true;
+ DBG("CMD-WARNING-IGNORED!!");
+ break;
+ }
+ }
+ return status;
+}
+
+u32 ddl_handle_core_errors(struct ddl_context *ddl_context)
+{
+ u32 status = false;
+
+ if (!ddl_context->cmd_err_status &&
+ !ddl_context->disp_pic_err_status &&
+ !ddl_context->op_failed)
+ return false;
+
+ if (ddl_context->cmd_state == DDL_CMD_INVALID) {
+ DBG("SPURIOUS_INTERRUPT_ERROR");
+ return true;
+ }
+
+ if (!ddl_context->op_failed) {
+ u32 disp_status;
+ status = ddl_handle_core_warnings(ddl_context->
+ cmd_err_status);
+ disp_status = ddl_handle_core_warnings(
+ ddl_context->disp_pic_err_status);
+ if (!status && !disp_status)
+ DBG("ddl_warning:Unknown");
+
+ return false;
+ }
+
+ ERR("\n %s(): OPFAILED!!", __func__);
+ ERR("\n CMD_ERROR_STATUS = %u, DISP_ERR_STATUS = %u",
+ ddl_context->cmd_err_status,
+ ddl_context->disp_pic_err_status);
+
+ status = ddl_handle_hw_fatal_errors(ddl_context);
+
+ if (!status)
+ status = ddl_handle_core_recoverable_errors(ddl_context);
+
+ if (!status)
+ status = ddl_handle_client_fatal_errors(ddl_context);
+
+ return status;
+}
+
+void ddl_handle_npf_decoding_error(struct ddl_context *ddl_context)
+{
+ struct ddl_client_context *ddl = ddl_context->current_ddl;
+ struct ddl_decoder_data *decoder = &ddl->codec_data.decoder;
+ if (!ddl->decoding) {
+ ERR("FWISSUE-ENC-NPF!!!");
+ ddl_client_fatal_cb(ddl_context);
+ return;
+ }
+ vidc_720p_decode_display_info(&decoder->dec_disp_info);
+ ddl_decode_dynamic_property(ddl, false);
+ ddl->output_frame.vcd_frm.ip_frm_tag =
+ decoder->dec_disp_info.tag_top;
+ ddl->output_frame.vcd_frm.physical = NULL;
+ ddl->output_frame.frm_trans_end = false;
+ ddl->ddl_context->ddl_callback(
+ VCD_EVT_RESP_OUTPUT_DONE,
+ VCD_ERR_INTRLCD_FIELD_DROP,
+ &ddl->output_frame,
+ sizeof(struct ddl_frame_data_tag),
+ (void *)ddl,
+ ddl->ddl_context->client_data);
+ ddl_decode_frame_run(ddl);
+}
+
+u32 ddl_handle_seqhdr_fail_error(struct ddl_context *ddl_context)
+{
+ struct ddl_client_context *ddl = ddl_context->current_ddl;
+ struct ddl_decoder_data *decoder = &ddl->codec_data.decoder;
+ u32 status = false;
+ if (ddl_context->cmd_state == DDL_CMD_HEADER_PARSE &&
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_INITCODECDONE)) {
+ switch (ddl_context->cmd_err_status) {
+ case UNSUPPORTED_FEATURE_IN_PROFILE:
+ case HEADER_NOT_FOUND:
+ case INVALID_SPS_ID:
+ case INVALID_PPS_ID:
+ case RESOLUTION_NOT_SUPPORTED:
+ ERR("SEQ-HDR-FAILED!!!");
+ if ((ddl_context->cmd_err_status ==
+ RESOLUTION_NOT_SUPPORTED) &&
+ (decoder->codec.codec == VCD_CODEC_H264 ||
+ decoder->codec.codec == VCD_CODEC_H263 ||
+ decoder->codec.codec == VCD_CODEC_MPEG4 ||
+ decoder->codec.codec == VCD_CODEC_VC1_RCV ||
+ decoder->codec.codec == VCD_CODEC_VC1)) {
+ ddl_client_fatal_cb(ddl_context);
+ status = true;
+ break;
+ }
+ if (decoder->header_in_start) {
+ decoder->header_in_start = false;
+ ddl_context->ddl_callback(VCD_EVT_RESP_START,
+ VCD_ERR_SEQHDR_PARSE_FAIL,
+ NULL, 0, (void *)ddl,
+ ddl_context->client_data);
+ } else {
+ if (ddl->input_frame.vcd_frm.flags &
+ VCD_FRAME_FLAG_EOS)
+ ddl->input_frame.frm_trans_end = false;
+ else
+ ddl->input_frame.frm_trans_end = true;
+ ddl_decode_dynamic_property(ddl, false);
+ ddl_context->ddl_callback(
+ VCD_EVT_RESP_INPUT_DONE,
+ VCD_ERR_SEQHDR_PARSE_FAIL,
+ &ddl->input_frame,
+ sizeof(struct ddl_frame_data_tag),
+ (void *)ddl, ddl_context->client_data);
+ if (ddl->input_frame.vcd_frm.flags &
+ VCD_FRAME_FLAG_EOS)
+ ddl_context->ddl_callback(
+ VCD_EVT_RESP_EOS_DONE,
+ VCD_S_SUCCESS, NULL,
+ 0, (void *)ddl,
+ ddl_context->client_data);
+ }
+ ddl_move_client_state(ddl,
+ DDL_CLIENT_WAIT_FOR_INITCODEC);
+ DDL_IDLE(ddl_context);
+ status = true;
+ }
+ }
+ return status;
+}
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.c
new file mode 100644
index 0000000..25aa6bc
--- /dev/null
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.c
@@ -0,0 +1,352 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "vidc_type.h"
+#include "vcd_ddl_firmware.h"
+#include "vcd_ddl_utils.h"
+
+#define VCDFW_TOTALNUM_IMAGE 7
+#define VCDFW_MAX_NO_IMAGE 2
+
+struct vcd_firmware {
+ u32 active_fw_img[VCDFW_TOTALNUM_IMAGE];
+ struct ddl_buf_addr boot_code;
+
+ struct ddl_buf_addr enc_mpeg4;
+ struct ddl_buf_addr encH264;
+
+ struct ddl_buf_addr dec_mpeg4;
+ struct ddl_buf_addr decH264;
+ struct ddl_buf_addr decH263;
+ struct ddl_buf_addr dec_mpeg2;
+ struct ddl_buf_addr dec_vc1;
+};
+
+static struct vcd_firmware vcd_firmware;
+
+
+static void vcd_fw_change_endian(unsigned char *fw, u32 fw_size)
+{
+ u32 i = 0;
+ unsigned char temp;
+ for (i = 0; i < fw_size; i = i + 4) {
+ temp = fw[i];
+ fw[i] = fw[i + 3];
+ fw[i + 3] = temp;
+
+ temp = fw[i + 1];
+ fw[i + 1] = fw[i + 2];
+ fw[i + 2] = temp;
+ }
+ return;
+}
+
+static u32 vcd_fw_prepare(struct ddl_buf_addr *fw_details,
+ const unsigned char fw_array[],
+ const unsigned int fw_array_size, u32 change_endian)
+{
+ u32 *buffer;
+
+ ddl_pmem_alloc(fw_details, fw_array_size,
+ DDL_LINEAR_BUFFER_ALIGN_BYTES);
+ if (!fw_details->virtual_base_addr)
+ return false;
+
+ fw_details->buffer_size = fw_array_size / 4;
+
+ buffer = fw_details->align_virtual_addr;
+
+ memcpy(buffer, fw_array, fw_array_size);
+ if (change_endian)
+ vcd_fw_change_endian((unsigned char *)buffer, fw_array_size);
+ return true;
+}
+
+u32 vcd_fw_init(void)
+{
+ u32 status = false;
+
+ status = vcd_fw_prepare(&vcd_firmware.boot_code,
+ vidc_command_control_fw,
+ vidc_command_control_fw_size, false);
+
+ if (status) {
+ status = vcd_fw_prepare(&vcd_firmware.dec_mpeg4,
+ vidc_mpg4_dec_fw,
+ vidc_mpg4_dec_fw_size, true);
+ }
+
+ if (status) {
+ status = vcd_fw_prepare(&vcd_firmware.decH264,
+ vidc_h264_dec_fw,
+ vidc_h264_dec_fw_size, true);
+ }
+
+ if (status) {
+ status = vcd_fw_prepare(&vcd_firmware.decH263,
+ vidc_h263_dec_fw,
+ vidc_h263_dec_fw_size, true);
+ }
+
+ if (status) {
+ status = vcd_fw_prepare(&vcd_firmware.enc_mpeg4,
+ vidc_mpg4_enc_fw,
+ vidc_mpg4_enc_fw_size, true);
+ }
+
+ if (status) {
+ status = vcd_fw_prepare(&vcd_firmware.encH264,
+ vidc_h264_enc_fw,
+ vidc_h264_enc_fw_size, true);
+ }
+
+ if (status) {
+ status = vcd_fw_prepare(&vcd_firmware.dec_vc1,
+ vidc_vc1_dec_fw,
+ vidc_vc1_dec_fw_size, true);
+ }
+ return status;
+}
+
+
+static u32 get_dec_fw_image(struct vcd_fw_details *fw_details)
+{
+ u32 status = true;
+ switch (fw_details->codec) {
+ case VCD_CODEC_DIVX_4:
+ case VCD_CODEC_DIVX_5:
+ case VCD_CODEC_DIVX_6:
+ case VCD_CODEC_XVID:
+ case VCD_CODEC_MPEG4:
+ {
+ fw_details->fw_buffer_addr =
+ vcd_firmware.dec_mpeg4.align_physical_addr;
+ fw_details->fw_size =
+ vcd_firmware.dec_mpeg4.buffer_size;
+ break;
+ }
+ case VCD_CODEC_H264:
+ {
+ fw_details->fw_buffer_addr =
+ vcd_firmware.decH264.align_physical_addr;
+ fw_details->fw_size =
+ vcd_firmware.decH264.buffer_size;
+ break;
+ }
+ case VCD_CODEC_VC1:
+ case VCD_CODEC_VC1_RCV:
+ {
+ fw_details->fw_buffer_addr =
+ vcd_firmware.dec_vc1.align_physical_addr;
+ fw_details->fw_size =
+ vcd_firmware.dec_vc1.buffer_size;
+ break;
+ }
+ case VCD_CODEC_MPEG2:
+ {
+ fw_details->fw_buffer_addr =
+ vcd_firmware.dec_mpeg2.align_physical_addr;
+ fw_details->fw_size =
+ vcd_firmware.dec_mpeg2.buffer_size;
+ break;
+ }
+ case VCD_CODEC_H263:
+ {
+ fw_details->fw_buffer_addr =
+ vcd_firmware.decH263.align_physical_addr;
+ fw_details->fw_size =
+ vcd_firmware.decH263.buffer_size;
+ break;
+ }
+ default:
+ {
+ status = false;
+ break;
+ }
+ }
+ return status;
+}
+
+static u32 get_enc_fw_image(struct vcd_fw_details *fw_details)
+{
+ u32 status = true;
+ switch (fw_details->codec) {
+ case VCD_CODEC_H263:
+ case VCD_CODEC_MPEG4:
+ {
+ fw_details->fw_buffer_addr =
+ vcd_firmware.enc_mpeg4.align_physical_addr;
+ fw_details->fw_size =
+ vcd_firmware.enc_mpeg4.buffer_size;
+ break;
+ }
+ case VCD_CODEC_H264:
+ {
+ fw_details->fw_buffer_addr =
+ vcd_firmware.encH264.align_physical_addr;
+ fw_details->fw_size =
+ vcd_firmware.encH264.buffer_size;
+ break;
+ }
+ default:
+ {
+ status = false;
+ break;
+ }
+ }
+ return status;
+}
+
+u32 vcd_get_fw_property(u32 prop_id, void *prop_details)
+{
+ u32 status = true;
+ struct vcd_fw_details *fw_details;
+ switch (prop_id) {
+ case VCD_FW_ENDIAN:
+ {
+ *(u32 *) prop_details = VCD_FW_BIG_ENDIAN;
+ break;
+ }
+ case VCD_FW_BOOTCODE:
+ {
+ fw_details =
+ (struct vcd_fw_details *)prop_details;
+ fw_details->fw_buffer_addr =
+ vcd_firmware.boot_code.align_physical_addr;
+ fw_details->fw_size =
+ vcd_firmware.boot_code.buffer_size;
+ break;
+ }
+ case VCD_FW_DECODE:
+ {
+ fw_details =
+ (struct vcd_fw_details *)prop_details;
+ status = get_dec_fw_image(fw_details);
+ break;
+ }
+ case VCD_FW_ENCODE:
+ {
+ fw_details =
+ (struct vcd_fw_details *)prop_details;
+ status = get_enc_fw_image(fw_details);
+ break;
+ }
+ default:
+ {
+ status = false;
+ break;
+ }
+ }
+ return status;
+}
+
+u32 vcd_fw_transact(u32 add, u32 decoding, enum vcd_codec codec)
+{
+ u32 status = true;
+ u32 index = 0, active_fw = 0, loop_count;
+
+ if (decoding) {
+ switch (codec) {
+ case VCD_CODEC_DIVX_4:
+ case VCD_CODEC_DIVX_5:
+ case VCD_CODEC_DIVX_6:
+ case VCD_CODEC_XVID:
+ case VCD_CODEC_MPEG4:
+ {
+ index = 0;
+ break;
+ }
+ case VCD_CODEC_H264:
+ {
+ index = 1;
+ break;
+ }
+ case VCD_CODEC_H263:
+ {
+ index = 2;
+ break;
+ }
+ case VCD_CODEC_MPEG2:
+ {
+ index = 3;
+ break;
+ }
+ case VCD_CODEC_VC1:
+ case VCD_CODEC_VC1_RCV:
+ {
+ index = 4;
+ break;
+ }
+ default:
+ {
+ status = false;
+ break;
+ }
+ }
+ } else {
+ switch (codec) {
+ case VCD_CODEC_H263:
+ case VCD_CODEC_MPEG4:
+ {
+ index = 5;
+ break;
+ }
+ case VCD_CODEC_H264:
+ {
+ index = 6;
+ break;
+ }
+ default:
+ {
+ status = false;
+ break;
+ }
+ }
+ }
+
+ if (!status)
+ return status;
+
+ if (!add &&
+ vcd_firmware.active_fw_img[index]
+ ) {
+ --vcd_firmware.active_fw_img[index];
+ return status;
+ }
+
+ for (loop_count = 0; loop_count < VCDFW_TOTALNUM_IMAGE;
+ ++loop_count) {
+ if (vcd_firmware.active_fw_img[loop_count])
+ ++active_fw;
+ }
+
+ if (active_fw < VCDFW_MAX_NO_IMAGE ||
+ vcd_firmware.active_fw_img[index] > 0) {
+ ++vcd_firmware.active_fw_img[index];
+ } else {
+ status = false;
+ }
+ return status;
+}
+
+void vcd_fw_release(void)
+{
+ ddl_pmem_free(&vcd_firmware.boot_code);
+ ddl_pmem_free(&vcd_firmware.enc_mpeg4);
+ ddl_pmem_free(&vcd_firmware.encH264);
+ ddl_pmem_free(&vcd_firmware.dec_mpeg4);
+ ddl_pmem_free(&vcd_firmware.decH264);
+ ddl_pmem_free(&vcd_firmware.decH263);
+ ddl_pmem_free(&vcd_firmware.dec_mpeg2);
+ ddl_pmem_free(&vcd_firmware.dec_vc1);
+}
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.h
new file mode 100644
index 0000000..7952dfb
--- /dev/null
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.h
@@ -0,0 +1,53 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _VCD_DDL_FIRMWARE_H_
+#define _VCD_DDL_FIRMWARE_H_
+#include "vcd_property.h"
+
+#define VCD_FW_BIG_ENDIAN 0x0
+#define VCD_FW_LITTLE_ENDIAN 0x1
+
+struct vcd_fw_details {
+ enum vcd_codec codec;
+ u32 *fw_buffer_addr;
+ u32 fw_size;
+};
+
+#define VCD_FW_PROP_BASE 0x0
+
+#define VCD_FW_ENDIAN (VCD_FW_PROP_BASE + 0x1)
+#define VCD_FW_BOOTCODE (VCD_FW_PROP_BASE + 0x2)
+#define VCD_FW_DECODE (VCD_FW_PROP_BASE + 0x3)
+#define VCD_FW_ENCODE (VCD_FW_PROP_BASE + 0x4)
+
+extern unsigned char *vidc_command_control_fw;
+extern u32 vidc_command_control_fw_size;
+extern unsigned char *vidc_mpg4_dec_fw;
+extern u32 vidc_mpg4_dec_fw_size;
+extern unsigned char *vidc_h263_dec_fw;
+extern u32 vidc_h263_dec_fw_size;
+extern unsigned char *vidc_h264_dec_fw;
+extern u32 vidc_h264_dec_fw_size;
+extern unsigned char *vidc_mpg4_enc_fw;
+extern u32 vidc_mpg4_enc_fw_size;
+extern unsigned char *vidc_h264_enc_fw;
+extern u32 vidc_h264_enc_fw_size;
+extern unsigned char *vidc_vc1_dec_fw;
+extern u32 vidc_vc1_dec_fw_size;
+
+u32 vcd_fw_init(void);
+u32 vcd_get_fw_property(u32 prop_id, void *prop_details);
+u32 vcd_fw_transact(u32 add, u32 decoding, enum vcd_codec codec);
+void vcd_fw_release(void);
+
+#endif
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c
new file mode 100644
index 0000000..a81dd84
--- /dev/null
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c
@@ -0,0 +1,944 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "vidc_type.h"
+
+#include "vcd_ddl_utils.h"
+#include "vcd_ddl_metadata.h"
+
+#if DEBUG
+#define DBG(x...) printk(KERN_DEBUG x)
+#else
+#define DBG(x...)
+#endif
+
+void ddl_core_init(struct ddl_context *ddl_context)
+{
+ char *psz_version;
+ struct vcd_fw_details fw_details;
+ u32 fw_endianness;
+ enum vidc_720p_endian dma_endian;
+ u32 interrupt_off;
+ enum vidc_720p_interrupt_level_selection interrupt_sel;
+ u32 intr_mask = 0x0;
+
+ vcd_get_fw_property(VCD_FW_BOOTCODE, &fw_details);
+ vcd_get_fw_property(VCD_FW_ENDIAN, &fw_endianness);
+ if (fw_endianness == VCD_FW_BIG_ENDIAN)
+ dma_endian = VIDC_720P_BIG_ENDIAN;
+ else
+ dma_endian = VIDC_720P_LITTLE_ENDIAN;
+
+ interrupt_off = false;
+ interrupt_sel = VIDC_720P_INTERRUPT_LEVEL_SEL;
+
+ intr_mask |= VIDC_720P_INTR_BUFFER_FULL;
+ intr_mask |= VIDC_720P_INTR_FW_DONE;
+ intr_mask |= VIDC_720P_INTR_DMA_DONE;
+ intr_mask |= VIDC_720P_INTR_FRAME_DONE;
+
+ vidc_720p_do_sw_reset();
+
+ vidc_720p_init(&psz_version,
+ fw_details.fw_size,
+ fw_details.fw_buffer_addr,
+ dma_endian,
+ interrupt_off, interrupt_sel, intr_mask);
+ return;
+}
+
+void ddl_core_start_cpu(struct ddl_context *ddl_context)
+{
+ u32 fw_endianness;
+ enum vidc_720p_endian dma_endian;
+ u32 dbg_core_dump_buf_size = 0;
+
+ vcd_get_fw_property(VCD_FW_ENDIAN, &fw_endianness);
+ if (fw_endianness == VCD_FW_BIG_ENDIAN)
+ dma_endian = VIDC_720P_LITTLE_ENDIAN;
+ else
+ dma_endian = VIDC_720P_BIG_ENDIAN;
+
+ ddl_move_command_state(ddl_context, DDL_CMD_CPU_RESET);
+
+ DBG("VSP_BUF_ADDR_SIZE %d",
+ ddl_context->context_buf_addr.buffer_size);
+ if (ddl_context->enable_dbg_core_dump) {
+ dbg_core_dump_buf_size = ddl_context->dbg_core_dump.
+ buffer_size;
+ }
+
+ vidc_720p_start_cpu(dma_endian,
+ ddl_context->context_buf_addr.align_physical_addr,
+ ddl_context->dbg_core_dump.align_physical_addr,
+ dbg_core_dump_buf_size);
+
+ VIDC_DEBUG_REGISTER_LOG;
+}
+
+void ddl_channel_set(struct ddl_client_context *ddl)
+{
+ enum vidc_720p_enc_dec_selection enc_dec_sel;
+ enum vidc_720p_codec codec;
+ enum vcd_codec *vcd_codec;
+ u32 fw_property_id;
+ struct vcd_fw_details fw_details;
+
+ if (ddl->decoding) {
+ if (vidc_msg_timing)
+ ddl_set_core_start_time(__func__, DEC_OP_TIME);
+ enc_dec_sel = VIDC_720P_DECODER;
+ fw_property_id = VCD_FW_DECODE;
+ vcd_codec = &(ddl->codec_data.decoder.codec.codec);
+ } else {
+ enc_dec_sel = VIDC_720P_ENCODER;
+ fw_property_id = VCD_FW_ENCODE;
+ vcd_codec = &(ddl->codec_data.encoder.codec.codec);
+ }
+ switch (*vcd_codec) {
+ default:
+ case VCD_CODEC_MPEG4:
+ {
+ codec = VIDC_720P_MPEG4;
+
+ if (ddl->decoding) {
+ vidc_720p_decode_set_mpeg4_data_partitionbuffer
+ (ddl->ddl_context->data_partition_tempbuf.
+ align_physical_addr);
+ }
+
+ break;
+ }
+ case VCD_CODEC_H264:
+ {
+ codec = VIDC_720P_H264;
+ break;
+ }
+ case VCD_CODEC_DIVX_4:
+ case VCD_CODEC_DIVX_5:
+ case VCD_CODEC_DIVX_6:
+ {
+ codec = VIDC_720P_DIVX;
+ break;
+ }
+ case VCD_CODEC_XVID:
+ {
+ codec = VIDC_720P_XVID;
+ break;
+ }
+ case VCD_CODEC_H263:
+ {
+ codec = VIDC_720P_H263;
+ break;
+ }
+ case VCD_CODEC_MPEG2:
+ {
+ codec = VIDC_720P_MPEG2;
+ break;
+ }
+ case VCD_CODEC_VC1:
+ case VCD_CODEC_VC1_RCV:
+ {
+ codec = VIDC_720P_VC1;
+ break;
+ }
+ }
+
+ fw_details.codec = *vcd_codec;
+ vcd_get_fw_property(fw_property_id, &fw_details);
+ VIDC_DEBUG_REGISTER_LOG;
+
+ ddl_move_command_state(ddl->ddl_context, DDL_CMD_CHANNEL_SET);
+ ddl_move_client_state(ddl, DDL_CLIENT_WAIT_FOR_CHDONE);
+
+ vidc_720p_set_channel(ddl->channel_id,
+ enc_dec_sel,
+ codec,
+ fw_details.fw_buffer_addr,
+ fw_details.fw_size);
+}
+
+void ddl_decode_init_codec(struct ddl_client_context *ddl)
+{
+ u32 seq_h = 0, seq_e = 0, start_byte_num = 0;
+ struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
+ struct vcd_sequence_hdr *seq_hdr = &decoder->decode_config;
+ enum vidc_720p_memory_access_method mem_access_method;
+ if (vidc_msg_timing)
+ ddl_set_core_start_time(__func__, DEC_OP_TIME);
+ ddl_metadata_enable(ddl);
+
+ vidc_720p_decode_set_error_control(true);
+
+ vidc_720p_decode_set_mpeg4Post_filter(decoder->post_filter.
+ post_filter);
+
+ if (decoder->codec.codec == VCD_CODEC_H264) {
+ vidc_720p_decode_setH264VSPBuffer(decoder->
+ h264Vsp_temp_buffer.
+ align_physical_addr);
+ VIDC_LOG1("VSP_BUF_ADDR_SIZE",
+ decoder->h264Vsp_temp_buffer.buffer_size);
+ }
+
+ if (decoder->codec.codec == VCD_CODEC_VC1_RCV ||
+ decoder->codec.codec == VCD_CODEC_VC1) {
+ vidc_720p_set_frame_size(decoder->client_frame_size.width,
+ decoder->client_frame_size.height);
+ } else {
+ vidc_720p_set_frame_size(0x0, 0x0);
+ }
+
+ switch (decoder->buf_format.buffer_format) {
+ default:
+ case VCD_BUFFER_FORMAT_NV12:
+ {
+ mem_access_method = VIDC_720P_TILE_LINEAR;
+ break;
+ }
+ case VCD_BUFFER_FORMAT_TILE_4x2:
+ {
+ mem_access_method = VIDC_720P_TILE_64x32;
+ break;
+ }
+ }
+ VIDC_LOG_STRING("HEADER-PARSE-START");
+ VIDC_DEBUG_REGISTER_LOG;
+ seq_h = (u32) seq_hdr->sequence_header;
+ start_byte_num = 8 - (seq_h & DDL_STREAMBUF_ALIGN_GUARD_BYTES);
+ seq_e = seq_h + seq_hdr->sequence_header_len;
+ seq_h &= ~(DDL_STREAMBUF_ALIGN_GUARD_BYTES);
+ DDL_PADDING_HACK(seq_e);
+
+ ddl_move_client_state(ddl, DDL_CLIENT_WAIT_FOR_INITCODECDONE);
+ ddl_move_command_state(ddl->ddl_context, DDL_CMD_HEADER_PARSE);
+
+ vidc_720p_decode_bitstream_header(ddl->channel_id,
+ seq_hdr->sequence_header_len,
+ start_byte_num,
+ seq_h,
+ seq_e,
+ mem_access_method,
+ decoder->output_order);
+}
+
+void ddl_decode_dynamic_property(struct ddl_client_context *ddl,
+ u32 enable)
+{
+ uint8_t *temp = NULL;
+ u32 extra_datastart = 0;
+ struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
+ struct vcd_frame_data *bit_stream =
+ &(ddl->input_frame.vcd_frm);
+
+ if (!enable) {
+ if (decoder->dynmic_prop_change_req) {
+ decoder->dynmic_prop_change_req = false;
+ vidc_720p_decode_dynamic_req_reset();
+ }
+ return;
+ }
+ if ((decoder->dynamic_prop_change &
+ DDL_DEC_REQ_OUTPUT_FLUSH)) {
+ decoder->dynmic_prop_change_req = true;
+ decoder->dynamic_prop_change &= ~(DDL_DEC_REQ_OUTPUT_FLUSH);
+ decoder->dpb_mask.hw_mask = 0;
+ vidc_720p_decode_dynamic_req_set(VIDC_720P_FLUSH_REQ);
+ }
+ if (((decoder->meta_data_enable_flag & VCD_METADATA_PASSTHROUGH))
+ && ((VCD_FRAME_FLAG_EXTRADATA & bit_stream->flags))
+ ) {
+
+ temp = ((uint8_t *)bit_stream->physical +
+ bit_stream->offset +
+ bit_stream->data_len + 3);
+
+ extra_datastart = (u32) ((u32)temp & ~3);
+ decoder->dynmic_prop_change_req = true;
+
+ vidc_720p_decode_setpassthrough_start(extra_datastart);
+
+ vidc_720p_decode_dynamic_req_set(VIDC_720P_EXTRADATA);
+ }
+}
+
+void ddl_encode_dynamic_property(struct ddl_client_context *ddl,
+ u32 enable)
+{
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ u32 enc_param_change = 0;
+
+ if (!enable) {
+ if (encoder->dynmic_prop_change_req) {
+ encoder->dynmic_prop_change_req = false;
+ encoder->ext_enc_control_val &=
+ ~(VIDC_720P_ENC_IFRAME_REQ);
+ vidc_720p_encode_set_control_param
+ (encoder->ext_enc_control_val);
+ vidc_720p_encoder_set_param_change(enc_param_change);
+ }
+ return;
+ }
+ if ((encoder->dynamic_prop_change & DDL_ENC_REQ_IFRAME)) {
+ encoder->dynamic_prop_change &= ~(DDL_ENC_REQ_IFRAME);
+ encoder->ext_enc_control_val |= VIDC_720P_ENC_IFRAME_REQ;
+ vidc_720p_encode_set_control_param
+ (encoder->ext_enc_control_val);
+ }
+ if ((encoder->dynamic_prop_change & DDL_ENC_CHANGE_BITRATE)) {
+ vidc_720p_encode_set_bit_rate(
+ encoder->target_bit_rate.target_bitrate);
+ enc_param_change |= VIDC_720P_ENC_BITRATE_CHANGE;
+ encoder->dynamic_prop_change &= ~(DDL_ENC_CHANGE_BITRATE);
+ }
+ if ((encoder->dynamic_prop_change & DDL_ENC_CHANGE_CIR)) {
+ vidc_720p_encode_set_intra_refresh_mb_number(
+ encoder->intra_refresh.cir_mb_number);
+ encoder->dynamic_prop_change &= ~(DDL_ENC_CHANGE_CIR);
+ }
+ if ((encoder->dynamic_prop_change & DDL_ENC_CHANGE_IPERIOD)) {
+ vidc_720p_encode_set_i_period
+ (encoder->i_period.p_frames);
+ enc_param_change |= VIDC_720P_ENC_IPERIOD_CHANGE;
+ encoder->dynamic_prop_change &= ~(DDL_ENC_CHANGE_IPERIOD);
+ }
+ if ((encoder->dynamic_prop_change &
+ DDL_ENC_CHANGE_FRAMERATE)) {
+ vidc_720p_encode_set_fps
+ ((encoder->frame_rate.fps_numerator * 1000) /
+ encoder->frame_rate.fps_denominator);
+ enc_param_change |= VIDC_720P_ENC_FRAMERATE_CHANGE;
+ encoder->dynamic_prop_change &= ~(DDL_ENC_CHANGE_FRAMERATE);
+ }
+ if (enc_param_change)
+ vidc_720p_encoder_set_param_change(enc_param_change);
+}
+
+static void ddl_encode_set_profile_level(struct ddl_client_context *ddl)
+{
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ u32 profile;
+ u32 level;
+
+ switch (encoder->profile.profile) {
+ default:
+ case VCD_PROFILE_MPEG4_SP:
+ {
+ profile = VIDC_720P_PROFILE_MPEG4_SP;
+ break;
+ }
+ case VCD_PROFILE_MPEG4_ASP:
+ {
+ profile = VIDC_720P_PROFILE_MPEG4_ASP;
+ break;
+ }
+ case VCD_PROFILE_H264_BASELINE:
+ {
+ profile = VIDC_720P_PROFILE_H264_CPB;
+ break;
+ }
+ case VCD_PROFILE_H264_MAIN:
+ {
+ profile = VIDC_720P_PROFILE_H264_MAIN;
+ break;
+ }
+ case VCD_PROFILE_H264_HIGH:
+ {
+ profile = VIDC_720P_PROFILE_H264_HIGH;
+ break;
+ }
+ case VCD_PROFILE_H263_BASELINE:
+ {
+ profile = VIDC_720P_PROFILE_H263_BASELINE;
+ break;
+ }
+ }
+ switch (encoder->level.level) {
+ default:
+ case VCD_LEVEL_MPEG4_0:
+ {
+ level = VIDC_720P_MPEG4_LEVEL0;
+ break;
+ }
+ case VCD_LEVEL_MPEG4_0b:
+ {
+ level = VIDC_720P_MPEG4_LEVEL0b;
+ break;
+ }
+ case VCD_LEVEL_MPEG4_1:
+ {
+ level = VIDC_720P_MPEG4_LEVEL1;
+ break;
+ }
+ case VCD_LEVEL_MPEG4_2:
+ {
+ level = VIDC_720P_MPEG4_LEVEL2;
+ break;
+ }
+ case VCD_LEVEL_MPEG4_3:
+ {
+ level = VIDC_720P_MPEG4_LEVEL3;
+ break;
+ }
+ case VCD_LEVEL_MPEG4_3b:
+ {
+ level = VIDC_720P_MPEG4_LEVEL3b;
+ break;
+ }
+
+ case VCD_LEVEL_MPEG4_4:
+ case VCD_LEVEL_MPEG4_4a:
+ {
+ level = VIDC_720P_MPEG4_LEVEL4a;
+ break;
+ }
+ case VCD_LEVEL_MPEG4_5:
+ {
+ level = VIDC_720P_MPEG4_LEVEL5;
+ break;
+ }
+ case VCD_LEVEL_MPEG4_6:
+ {
+ level = VIDC_720P_MPEG4_LEVEL6;
+ break;
+ }
+ case VCD_LEVEL_H264_1:
+ {
+ level = VIDC_720P_H264_LEVEL1;
+ break;
+ }
+ case VCD_LEVEL_H264_1b:
+ {
+ level = VIDC_720P_H264_LEVEL1b;
+ break;
+ }
+ case VCD_LEVEL_H264_1p1:
+ {
+ level = VIDC_720P_H264_LEVEL1p1;
+ break;
+ }
+ case VCD_LEVEL_H264_1p2:
+ {
+ level = VIDC_720P_H264_LEVEL1p2;
+ break;
+ }
+ case VCD_LEVEL_H264_1p3:
+ {
+ level = VIDC_720P_H264_LEVEL1p3;
+ break;
+ }
+ case VCD_LEVEL_H264_2:
+ {
+ level = VIDC_720P_H264_LEVEL2;
+ break;
+ }
+ case VCD_LEVEL_H264_2p1:
+ {
+ level = VIDC_720P_H264_LEVEL2p1;
+ break;
+ }
+ case VCD_LEVEL_H264_2p2:
+ {
+ level = VIDC_720P_H264_LEVEL2p2;
+ break;
+ }
+ case VCD_LEVEL_H264_3:
+ {
+ level = VIDC_720P_H264_LEVEL3;
+ break;
+ }
+ case VCD_LEVEL_H264_3p1:
+ {
+ level = VIDC_720P_H264_LEVEL3p1;
+ break;
+ }
+ case VCD_LEVEL_H263_10:
+ {
+ level = VIDC_720P_H263_LEVEL10;
+ break;
+ }
+ case VCD_LEVEL_H263_20:
+ {
+ level = VIDC_720P_H263_LEVEL20;
+ break;
+ }
+ case VCD_LEVEL_H263_30:
+ {
+ level = VIDC_720P_H263_LEVEL30;
+ break;
+ }
+ case VCD_LEVEL_H263_40:
+ {
+ level = VIDC_720P_H263_LEVEL40;
+ break;
+ }
+ case VCD_LEVEL_H263_45:
+ {
+ level = VIDC_720P_H263_LEVEL45;
+ break;
+ }
+ case VCD_LEVEL_H263_50:
+ {
+ level = VIDC_720P_H263_LEVEL50;
+ break;
+ }
+ case VCD_LEVEL_H263_60:
+ {
+ level = VIDC_720P_H263_LEVEL60;
+ break;
+ }
+ case VCD_LEVEL_H263_70:
+ {
+ level = VIDC_720P_H263_LEVEL70;
+ break;
+ }
+ }
+ vidc_720p_encode_set_profile(profile, level);
+}
+
+void ddl_encode_init_codec(struct ddl_client_context *ddl)
+{
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ enum vidc_720p_memory_access_method mem_access_method;
+ enum vidc_720p_DBConfig db_config;
+ enum vidc_720p_MSlice_selection m_slice_sel;
+
+ ddl_encode_set_profile_level(ddl);
+
+ vidc_720p_set_frame_size
+ (encoder->frame_size.width, encoder->frame_size.height);
+ vidc_720p_encode_set_qp_params
+ (encoder->qp_range.max_qp, encoder->qp_range.min_qp);
+ vidc_720p_encode_set_rc_config
+ (encoder->rc_level.frame_level_rc,
+ encoder->rc_level.mb_level_rc,
+ encoder->session_qp.i_frame_qp,
+ encoder->session_qp.p_frame_qp);
+
+ if (encoder->r_cframe_skip) {
+ if (encoder->vb_vbuffer_size) {
+ encoder->ext_enc_control_val = (0x2 << 0x2) |
+ (encoder->vb_vbuffer_size << 0x10);
+ } else
+ encoder->ext_enc_control_val = (0x1 << 2);
+ } else
+ encoder->ext_enc_control_val = 0;
+
+ vidc_720p_encode_set_fps
+ ((encoder->frame_rate.fps_numerator * 1000) /
+ encoder->frame_rate.fps_denominator);
+
+ vidc_720p_encode_set_vop_time(
+ encoder->vop_timing.vop_time_resolution, 0);
+
+ if (encoder->rc_level.frame_level_rc) {
+ vidc_720p_encode_set_bit_rate
+ (encoder->target_bit_rate.target_bitrate);
+
+ vidc_720p_encode_set_frame_level_rc_params
+ (encoder->frame_level_rc.reaction_coeff);
+ }
+ if (encoder->rc_level.mb_level_rc) {
+ vidc_720p_encode_set_mb_level_rc_params
+ (encoder->adaptive_rc.dark_region_as_flag,
+ encoder->adaptive_rc.smooth_region_as_flag,
+ encoder->adaptive_rc.static_region_as_flag,
+ encoder->adaptive_rc.activity_region_flag);
+ }
+ if (encoder->codec.codec == VCD_CODEC_MPEG4) {
+ vidc_720p_encode_set_short_header
+ (encoder->short_header.short_header);
+
+ if (encoder->hdr_ext_control) {
+ vidc_720p_encode_set_hec_period
+ (encoder->hdr_ext_control);
+ encoder->ext_enc_control_val |= (0x1 << 0x1);
+ }
+ }
+ /* set extended encoder control settings */
+ vidc_720p_encode_set_control_param
+ (encoder->ext_enc_control_val);
+
+ if (encoder->codec.codec == VCD_CODEC_H264) {
+ enum vidc_720p_entropy_sel entropy_sel;
+ enum vidc_720p_cabac_model cabac_model_number;
+ switch (encoder->entropy_control.entropy_sel) {
+ default:
+ case VCD_ENTROPY_SEL_CAVLC:
+ {
+ entropy_sel = VIDC_720P_ENTROPY_SEL_CAVLC;
+ break;
+ }
+ case VCD_ENTROPY_SEL_CABAC:
+ {
+ entropy_sel = VIDC_720P_ENTROPY_SEL_CABAC;
+ break;
+ }
+ }
+ switch (encoder->entropy_control.cabac_model) {
+ default:
+ case VCD_CABAC_MODEL_NUMBER_0:
+ {
+ cabac_model_number =
+ VIDC_720P_CABAC_MODEL_NUMBER_0;
+ break;
+ }
+ case VCD_CABAC_MODEL_NUMBER_1:
+ {
+ cabac_model_number =
+ VIDC_720P_CABAC_MODEL_NUMBER_1;
+ break;
+ }
+ case VCD_CABAC_MODEL_NUMBER_2:
+ {
+ cabac_model_number =
+ VIDC_720P_CABAC_MODEL_NUMBER_2;
+ break;
+ }
+ }
+ vidc_720p_encode_set_entropy_control
+ (entropy_sel, cabac_model_number);
+ switch (encoder->db_control.db_config) {
+ default:
+ case VCD_DB_ALL_BLOCKING_BOUNDARY:
+ {
+ db_config =
+ VIDC_720P_DB_ALL_BLOCKING_BOUNDARY;
+ break;
+ }
+ case VCD_DB_DISABLE:
+ {
+ db_config =
+ VIDC_720P_DB_DISABLE;
+ break;
+ }
+ case VCD_DB_SKIP_SLICE_BOUNDARY:
+ {
+ db_config =
+ VIDC_720P_DB_SKIP_SLICE_BOUNDARY;
+ break;
+ }
+ }
+ vidc_720p_encode_set_db_filter_control
+ (db_config,
+ encoder->db_control.slice_alpha_offset,
+ encoder->db_control.slice_beta_offset);
+ }
+
+ vidc_720p_encode_set_intra_refresh_mb_number
+ (encoder->intra_refresh.cir_mb_number);
+
+ switch (encoder->multi_slice.m_slice_sel) {
+ default:
+ case VCD_MSLICE_OFF:
+ m_slice_sel = VIDC_720P_MSLICE_OFF;
+ break;
+ case VCD_MSLICE_BY_MB_COUNT:
+ {
+ m_slice_sel = VIDC_720P_MSLICE_BY_MB_COUNT;
+ break;
+ }
+ case VCD_MSLICE_BY_BYTE_COUNT:
+ {
+ m_slice_sel = VIDC_720P_MSLICE_BY_BYTE_COUNT;
+ break;
+ }
+ case VCD_MSLICE_BY_GOB:
+ {
+ m_slice_sel = VIDC_720P_MSLICE_BY_GOB;
+ break;
+ }
+ }
+ vidc_720p_encode_set_multi_slice_info
+ (m_slice_sel, encoder->multi_slice.m_slice_size);
+
+ vidc_720p_encode_set_dpb_buffer
+ (encoder->enc_dpb_addr.align_physical_addr,
+ encoder->enc_dpb_addr.buffer_size);
+
+ VIDC_LOG1("ENC_DPB_ADDR_SIZE", encoder->enc_dpb_addr.buffer_size);
+
+ vidc_720p_encode_set_i_period(encoder->i_period.p_frames);
+
+ ddl_metadata_enable(ddl);
+
+ if (encoder->seq_header.virtual_base_addr) {
+ u32 ext_buffer_start, ext_buffer_end, start_byte_num;
+ ext_buffer_start =
+ (u32) encoder->seq_header.align_physical_addr;
+ ext_buffer_end =
+ ext_buffer_start + encoder->seq_header.buffer_size;
+ start_byte_num =
+ (ext_buffer_start & DDL_STREAMBUF_ALIGN_GUARD_BYTES);
+ ext_buffer_start &= ~(DDL_STREAMBUF_ALIGN_GUARD_BYTES);
+ ext_buffer_end &= ~(DDL_STREAMBUF_ALIGN_GUARD_BYTES);
+ VIDC_LOG1("ENC_SEQHDR_ALLOC_SIZE",
+ encoder->seq_header.buffer_size);
+ vidc_720p_encode_set_seq_header_buffer(ext_buffer_start,
+ ext_buffer_end,
+ start_byte_num);
+ }
+
+ if (encoder->re_con_buf_format.buffer_format ==
+ VCD_BUFFER_FORMAT_NV12)
+ mem_access_method = VIDC_720P_TILE_LINEAR;
+ else
+ mem_access_method = VIDC_720P_TILE_16x16;
+
+ ddl_move_client_state(ddl, DDL_CLIENT_WAIT_FOR_INITCODECDONE);
+ ddl_move_command_state(ddl->ddl_context, DDL_CMD_INIT_CODEC);
+
+ vidc_720p_encode_init_codec(ddl->channel_id, mem_access_method);
+}
+
+void ddl_channel_end(struct ddl_client_context *ddl)
+{
+ VIDC_DEBUG_REGISTER_LOG;
+
+ ddl_move_client_state(ddl, DDL_CLIENT_WAIT_FOR_CHEND);
+ ddl_move_command_state(ddl->ddl_context, DDL_CMD_CHANNEL_END);
+
+ vidc_720p_submit_command(ddl->channel_id, VIDC_720P_CMD_CHEND);
+}
+
+void ddl_encode_frame_run(struct ddl_client_context *ddl)
+{
+ u32 ext_buffer_start, ext_buffer_end;
+ u32 y_addr, c_addr;
+ u32 start_byte_number = 0;
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ struct vcd_frame_data *stream = &(ddl->output_frame.vcd_frm);
+
+ ext_buffer_start = (u32) stream->physical + stream->offset;
+ ext_buffer_end = ddl_encode_set_metadata_output_buf(ddl);
+ start_byte_number =
+ (ext_buffer_start & DDL_STREAMBUF_ALIGN_GUARD_BYTES);
+ if (start_byte_number) {
+ u32 upper_data, lower_data;
+ u32 *align_virtual_addr;
+ ext_buffer_start &= ~(DDL_STREAMBUF_ALIGN_GUARD_BYTES);
+ align_virtual_addr = (u32 *) (((u32) stream->virtual +
+ stream->offset) -
+ start_byte_number);
+ upper_data = *align_virtual_addr;
+ align_virtual_addr++;
+ lower_data = *align_virtual_addr;
+ vidc_720p_encode_unalign_bitstream(upper_data, lower_data);
+ }
+
+ y_addr = (u32) ddl->input_frame.vcd_frm.physical +
+ ddl->input_frame.vcd_frm.offset;
+ c_addr = (y_addr + (encoder->frame_size.scan_lines *
+ encoder->frame_size.stride));
+ ddl_move_client_state(ddl, DDL_CLIENT_WAIT_FOR_FRAME_DONE);
+ ddl_move_command_state(ddl->ddl_context, DDL_CMD_ENCODE_FRAME);
+
+ if (encoder->dynamic_prop_change) {
+ encoder->dynmic_prop_change_req = true;
+ ddl_encode_dynamic_property(ddl, true);
+ }
+ vidc_720p_encode_set_vop_time(
+ encoder->vop_timing.vop_time_resolution,
+ ddl->input_frame.frm_delta
+ );
+
+ vidc_720p_encode_frame(ddl->channel_id,
+ ext_buffer_start,
+ ext_buffer_end,
+ start_byte_number, y_addr, c_addr);
+}
+
+u32 ddl_decode_set_buffers(struct ddl_client_context *ddl)
+{
+ struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
+ u32 comv_buf_size = DDL_COMV_BUFLINE_NO, comv_buf_no = 0;
+ u32 ref_buf_no = 0;
+
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_DPB)) {
+ VIDC_LOG_STRING("STATE-CRITICAL");
+ return VCD_ERR_FAIL;
+ }
+ if (vidc_msg_timing)
+ ddl_set_core_start_time(__func__, DEC_OP_TIME);
+ switch (decoder->codec.codec) {
+ default:
+ case VCD_CODEC_DIVX_4:
+ case VCD_CODEC_DIVX_5:
+ case VCD_CODEC_DIVX_6:
+ case VCD_CODEC_XVID:
+ case VCD_CODEC_MPEG2:
+ case VCD_CODEC_MPEG4:
+ {
+ comv_buf_no = DDL_MPEG_COMV_BUF_NO;
+ ref_buf_no = DDL_MPEG_REFBUF_COUNT;
+ break;
+ }
+ case VCD_CODEC_H263:
+ {
+ comv_buf_no = DDL_H263_COMV_BUF_NO;
+ break;
+ }
+ case VCD_CODEC_VC1:
+ case VCD_CODEC_VC1_RCV:
+ {
+ comv_buf_no =
+ decoder->client_output_buf_req.actual_count + 1;
+ comv_buf_size = DDL_VC1_COMV_BUFLINE_NO;
+ break;
+ }
+ case VCD_CODEC_H264:
+ {
+ comv_buf_no =
+ decoder->client_output_buf_req.actual_count;
+ break;
+ }
+ }
+
+ if (comv_buf_no) {
+ comv_buf_size *= (comv_buf_no *
+ (decoder->client_frame_size.stride >> 4) *
+ ((decoder->client_frame_size.scan_lines >> 4) + 1));
+ if (decoder->dpb_comv_buffer.virtual_base_addr)
+ ddl_pmem_free(&decoder->dpb_comv_buffer);
+ ddl_pmem_alloc(&decoder->dpb_comv_buffer, comv_buf_size,
+ DDL_LINEAR_BUFFER_ALIGN_BYTES);
+ if (!decoder->dpb_comv_buffer.virtual_base_addr) {
+ VIDC_LOGERR_STRING
+ ("Dec_set_buf:Comv_buf_alloc_failed");
+ return VCD_ERR_ALLOC_FAIL;
+ }
+ vidc_720p_decode_set_comv_buffer(decoder->dpb_comv_buffer.
+ align_physical_addr,
+ decoder->dpb_comv_buffer.
+ buffer_size);
+ }
+ decoder->ref_buffer.align_physical_addr = NULL;
+ if (ref_buf_no) {
+ size_t sz, align_bytes;
+ sz = decoder->dp_buf.dec_pic_buffers[0].vcd_frm.alloc_len;
+ sz *= ref_buf_no;
+ align_bytes = decoder->client_output_buf_req.align;
+ if (decoder->ref_buffer.virtual_base_addr)
+ ddl_pmem_free(&decoder->ref_buffer);
+ ddl_pmem_alloc(&decoder->ref_buffer, sz, align_bytes);
+ if (!decoder->ref_buffer.virtual_base_addr) {
+ ddl_pmem_free(&decoder->dpb_comv_buffer);
+ VIDC_LOGERR_STRING
+ ("Dec_set_buf:mpeg_ref_buf_alloc_failed");
+ return VCD_ERR_ALLOC_FAIL;
+ }
+ }
+ ddl_decode_set_metadata_output(decoder);
+ ddl_decoder_dpb_transact(decoder, NULL, DDL_DPB_OP_INIT);
+ ddl_move_client_state(ddl, DDL_CLIENT_WAIT_FOR_DPBDONE);
+ ddl_move_command_state(ddl->ddl_context, DDL_CMD_DECODE_SET_DPB);
+
+ vidc_720p_submit_command(ddl->channel_id,
+ VIDC_720P_CMD_INITBUFFERS);
+ return VCD_S_SUCCESS;
+}
+
+void ddl_decode_frame_run(struct ddl_client_context *ddl)
+{
+ u32 ext_buffer_start = 0, ext_buffer_end = 0;
+ u32 start_byte_num = 8;
+ struct ddl_decoder_data *decoder = &ddl->codec_data.decoder;
+ struct vcd_frame_data *bit_stream =
+ &(ddl->input_frame.vcd_frm);
+ if (vidc_msg_timing) {
+ ddl_set_core_start_time(__func__, DEC_OP_TIME);
+ ddl_set_core_start_time(__func__, DEC_IP_TIME);
+ }
+ if (!bit_stream->data_len ||
+ !bit_stream->physical) {
+ ddl_decode_eos_run(ddl);
+ return;
+ }
+
+ ddl_move_client_state(ddl, DDL_CLIENT_WAIT_FOR_FRAME_DONE);
+
+ ddl_decode_dynamic_property(ddl, true);
+
+ ddl_decoder_dpb_transact(decoder, NULL, DDL_DPB_OP_SET_MASK);
+
+ ext_buffer_start = (u32)bit_stream->physical +
+ bit_stream->offset;
+ start_byte_num = 8 - (ext_buffer_start &
+ DDL_STREAMBUF_ALIGN_GUARD_BYTES);
+ ext_buffer_end = ext_buffer_start + bit_stream->data_len;
+ ext_buffer_start &= ~(DDL_STREAMBUF_ALIGN_GUARD_BYTES);
+ DDL_PADDING_HACK(ext_buffer_end);
+
+ ddl_move_command_state(ddl->ddl_context, DDL_CMD_DECODE_FRAME);
+
+ vidc_720p_decode_frame(ddl->channel_id,
+ ext_buffer_start,
+ ext_buffer_end,
+ bit_stream->data_len,
+ start_byte_num, bit_stream->ip_frm_tag);
+}
+
+void ddl_decode_eos_run(struct ddl_client_context *ddl)
+{
+ struct ddl_decoder_data *decoder = &ddl->codec_data.decoder;
+
+ ddl_move_client_state(ddl, DDL_CLIENT_WAIT_FOR_EOS_DONE);
+
+ ddl_decode_dynamic_property(ddl, true);
+
+ ddl_decoder_dpb_transact(decoder, NULL, DDL_DPB_OP_SET_MASK);
+
+ decoder->dynmic_prop_change_req = true;
+
+ ddl_move_command_state(ddl->ddl_context, DDL_CMD_EOS);
+
+ vidc_720p_issue_eos(ddl->channel_id);
+}
+
+u32 ddl_hal_engine_reset(struct ddl_context *ddl_context)
+{
+ u32 eng_reset;
+ u32 channel_id = 0;
+ u32 fw_endianness;
+ enum vidc_720p_endian dma_endian;
+ enum vidc_720p_interrupt_level_selection interrupt_sel;
+ u32 intr_mask = 0x0;
+
+ if (ddl_context->current_ddl)
+ channel_id = ddl_context->current_ddl->channel_id;
+
+ interrupt_sel = VIDC_720P_INTERRUPT_LEVEL_SEL;
+ /* Enable all the supported interrupt */
+ intr_mask |= VIDC_720P_INTR_BUFFER_FULL;
+ intr_mask |= VIDC_720P_INTR_FW_DONE;
+ intr_mask |= VIDC_720P_INTR_DMA_DONE;
+ intr_mask |= VIDC_720P_INTR_FRAME_DONE;
+
+ vcd_get_fw_property(VCD_FW_ENDIAN, &fw_endianness);
+ /* Reverse the endianness settings after boot code download */
+ if (fw_endianness == VCD_FW_BIG_ENDIAN)
+ dma_endian = VIDC_720P_LITTLE_ENDIAN;
+ else
+ dma_endian = VIDC_720P_BIG_ENDIAN;
+
+ /* Need to reset MFC silently */
+ eng_reset = vidc_720p_engine_reset(
+ channel_id,
+ dma_endian, interrupt_sel,
+ intr_mask);
+ if (!eng_reset) {
+ /* call the hw fatal callback if engine reset fails */
+ ddl_hw_fatal_cb(ddl_context);
+ }
+ return eng_reset ;
+}
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c
new file mode 100644
index 0000000..2899df6
--- /dev/null
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c
@@ -0,0 +1,286 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "vidc_type.h"
+#include "vcd_ddl_utils.h"
+
+DDL_INLINE struct ddl_context *ddl_get_context(void)
+{
+ static struct ddl_context ddl_context;
+ return &ddl_context;
+}
+
+DDL_INLINE void ddl_move_client_state(struct ddl_client_context *ddl,
+ enum ddl_client_state client_state)
+{
+ ddl->client_state = client_state;
+}
+
+DDL_INLINE void ddl_move_command_state(struct ddl_context *ddl_context,
+ enum ddl_cmd_state command_state)
+{
+ ddl_context->cmd_state = command_state;
+}
+
+u32 ddl_client_transact(u32 operation,
+ struct ddl_client_context **pddl_client)
+{
+ u32 ret_status = VCD_ERR_FAIL;
+ u32 counter;
+ struct ddl_context *ddl_context;
+
+ ddl_context = ddl_get_context();
+ switch (operation) {
+ case DDL_FREE_CLIENT:
+ {
+ if (pddl_client && *pddl_client) {
+ u32 channel_id;
+ channel_id = (*pddl_client)->channel_id;
+ if (channel_id < VCD_MAX_NO_CLIENT) {
+ ddl_context->
+ ddl_clients[channel_id] = NULL;
+ } else {
+ VIDC_LOG_STRING("CHID_CORRUPTION");
+ }
+ DDL_FREE(*pddl_client);
+ ret_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case DDL_GET_CLIENT:
+ {
+ ret_status = VCD_ERR_MAX_CLIENT;
+ for (counter = 0; counter < VCD_MAX_NO_CLIENT &&
+ ret_status == VCD_ERR_MAX_CLIENT; ++counter) {
+ if (!ddl_context->ddl_clients[counter]) {
+ *pddl_client =
+ (struct ddl_client_context *)
+ DDL_MALLOC(sizeof
+ (struct ddl_client_context)
+ );
+ if (!*pddl_client) {
+ ret_status = VCD_ERR_ALLOC_FAIL;
+ } else {
+ DDL_MEMSET(*pddl_client, 0,
+ sizeof(struct
+ ddl_client_context));
+ ddl_context->
+ ddl_clients[counter] =
+ *pddl_client;
+ (*pddl_client)->channel_id =
+ counter;
+ (*pddl_client)->ddl_context =
+ ddl_context;
+ ret_status = VCD_S_SUCCESS;
+ }
+ }
+ }
+ break;
+ }
+ case DDL_INIT_CLIENTS:
+ {
+ for (counter = 0; counter < VCD_MAX_NO_CLIENT;
+ ++counter) {
+ ddl_context->ddl_clients[counter] = NULL;
+ }
+ ret_status = VCD_S_SUCCESS;
+ break;
+ }
+ case DDL_ACTIVE_CLIENT:
+ {
+ for (counter = 0; counter < VCD_MAX_NO_CLIENT;
+ ++counter) {
+ if (ddl_context->ddl_clients[counter]) {
+ ret_status = VCD_S_SUCCESS;
+ break;
+ }
+ }
+ break;
+ }
+ default:
+ {
+ ret_status = VCD_ERR_ILLEGAL_PARM;
+ break;
+ }
+ }
+ return ret_status;
+}
+
+u32 ddl_decoder_dpb_transact(struct ddl_decoder_data *decoder,
+ struct ddl_frame_data_tag *in_out_frame,
+ u32 operation)
+{
+ u32 vcd_status = VCD_S_SUCCESS;
+ u32 loopc;
+ struct ddl_frame_data_tag *found_frame = NULL;
+ struct ddl_mask *dpb_mask = &decoder->dpb_mask;
+
+ switch (operation) {
+ case DDL_DPB_OP_MARK_BUSY:
+ case DDL_DPB_OP_MARK_FREE:
+ {
+ for (loopc = 0; !found_frame &&
+ loopc < decoder->dp_buf.no_of_dec_pic_buf;
+ ++loopc) {
+ if (in_out_frame->vcd_frm.physical ==
+ decoder->dp_buf.
+ dec_pic_buffers[loopc].vcd_frm.
+ physical) {
+ found_frame =
+ &(decoder->dp_buf.
+ dec_pic_buffers[loopc]);
+ break;
+ }
+ }
+
+ if (found_frame) {
+ if (operation == DDL_DPB_OP_MARK_BUSY) {
+ dpb_mask->hw_mask &=
+ (~(0x1 << loopc));
+ *in_out_frame = *found_frame;
+ } else if (operation ==
+ DDL_DPB_OP_MARK_FREE) {
+ dpb_mask->client_mask |=
+ (0x1 << loopc);
+ *found_frame = *in_out_frame;
+ }
+ } else {
+ in_out_frame->vcd_frm.physical = NULL;
+ in_out_frame->vcd_frm.virtual = NULL;
+ vcd_status = VCD_ERR_BAD_POINTER;
+ VIDC_LOG_STRING("BUF_NOT_FOUND");
+ }
+ break;
+ }
+ case DDL_DPB_OP_SET_MASK:
+ {
+ dpb_mask->hw_mask |= dpb_mask->client_mask;
+ dpb_mask->client_mask = 0;
+ vidc_720p_decode_set_dpb_release_buffer_mask
+ (dpb_mask->hw_mask);
+ break;
+ }
+ case DDL_DPB_OP_INIT:
+ {
+ u32 dpb_size;
+ dpb_size = (!decoder->meta_data_offset) ?
+ decoder->dp_buf.dec_pic_buffers[0].vcd_frm.
+ alloc_len : decoder->meta_data_offset;
+ vidc_720p_decode_set_dpb_details(decoder->dp_buf.
+ no_of_dec_pic_buf,
+ dpb_size,
+ decoder->ref_buffer.
+ align_physical_addr);
+ for (loopc = 0;
+ loopc < decoder->dp_buf.no_of_dec_pic_buf;
+ ++loopc) {
+ vidc_720p_decode_set_dpb_buffers(loopc,
+ (u32 *)
+ decoder->
+ dp_buf.
+ dec_pic_buffers
+ [loopc].
+ vcd_frm.
+ physical);
+ VIDC_LOG1("DEC_DPB_BUFn_SIZE",
+ decoder->dp_buf.
+ dec_pic_buffers[loopc].vcd_frm.
+ alloc_len);
+ }
+ break;
+ }
+ case DDL_DPB_OP_RETRIEVE:
+ {
+ u32 position;
+ if (dpb_mask->client_mask) {
+ position = 0x1;
+ for (loopc = 0;
+ loopc <
+ decoder->dp_buf.no_of_dec_pic_buf
+ && !found_frame; ++loopc) {
+ if (dpb_mask->
+ client_mask & position) {
+ found_frame =
+ &decoder->dp_buf.
+ dec_pic_buffers[loopc];
+ dpb_mask->client_mask &=
+ ~(position);
+ }
+ position <<= 1;
+ }
+ } else if (dpb_mask->hw_mask) {
+ position = 0x1;
+ for (loopc = 0;
+ loopc <
+ decoder->dp_buf.no_of_dec_pic_buf
+ && !found_frame; ++loopc) {
+ if (dpb_mask->hw_mask
+ & position) {
+ found_frame =
+ &decoder->dp_buf.
+ dec_pic_buffers[loopc];
+ dpb_mask->hw_mask &=
+ ~(position);
+ }
+ position <<= 1;
+ }
+ }
+ if (found_frame)
+ *in_out_frame = *found_frame;
+ else {
+ in_out_frame->vcd_frm.physical = NULL;
+ in_out_frame->vcd_frm.virtual = NULL;
+ }
+ break;
+ }
+ }
+ return vcd_status;
+}
+
+void ddl_release_context_buffers(struct ddl_context *ddl_context)
+{
+ ddl_pmem_free(&ddl_context->context_buf_addr);
+ ddl_pmem_free(&ddl_context->db_line_buffer);
+ ddl_pmem_free(&ddl_context->data_partition_tempbuf);
+ ddl_pmem_free(&ddl_context->metadata_shared_input);
+ ddl_pmem_free(&ddl_context->dbg_core_dump);
+
+ vcd_fw_release();
+}
+
+void ddl_release_client_internal_buffers(struct ddl_client_context *ddl)
+{
+ if (ddl->decoding) {
+ struct ddl_decoder_data *decoder =
+ &(ddl->codec_data.decoder);
+ ddl_pmem_free(&decoder->h264Vsp_temp_buffer);
+ ddl_pmem_free(&decoder->dpb_comv_buffer);
+ ddl_pmem_free(&decoder->ref_buffer);
+ DDL_FREE(decoder->dp_buf.dec_pic_buffers);
+ ddl_decode_dynamic_property(ddl, false);
+ decoder->decode_config.sequence_header_len = 0;
+ decoder->decode_config.sequence_header = NULL;
+ decoder->dpb_mask.client_mask = 0;
+ decoder->dpb_mask.hw_mask = 0;
+ decoder->dp_buf.no_of_dec_pic_buf = 0;
+ decoder->dynamic_prop_change = 0;
+
+ } else {
+ struct ddl_encoder_data *encoder =
+ &(ddl->codec_data.encoder);
+ ddl_pmem_free(&encoder->enc_dpb_addr);
+ ddl_pmem_free(&encoder->seq_header);
+ ddl_encode_dynamic_property(ddl, false);
+ encoder->dynamic_prop_change = 0;
+ }
+}
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h
new file mode 100644
index 0000000..00c00cd
--- /dev/null
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h
@@ -0,0 +1,75 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _VCD_DDL_INTERNAL_PROPERTY_H_
+#define _VCD_DDL_INTERNAL_PROPERTY_H_
+#include "vcd_api.h"
+
+#define VCD_EVT_RESP_DDL_BASE 0x3000
+#define VCD_EVT_RESP_DEVICE_INIT (VCD_EVT_RESP_DDL_BASE + 0x1)
+#define VCD_EVT_RESP_OUTPUT_REQ (VCD_EVT_RESP_DDL_BASE + 0x2)
+#define VCD_EVT_RESP_EOS_DONE (VCD_EVT_RESP_DDL_BASE + 0x3)
+#define VCD_EVT_RESP_TRANSACTION_PENDING (VCD_EVT_RESP_DDL_BASE + 0x4)
+
+#define VCD_S_DDL_ERR_BASE 0x90000000
+#define VCD_ERR_MAX_NO_CODEC (VCD_S_DDL_ERR_BASE + 0x1)
+#define VCD_ERR_CLIENT_PRESENT (VCD_S_DDL_ERR_BASE + 0x2)
+#define VCD_ERR_CLIENT_FATAL (VCD_S_DDL_ERR_BASE + 0x3)
+
+#define VCD_I_CUSTOM_BASE (VCD_I_RESERVED_BASE)
+#define VCD_I_RC_LEVEL_CONFIG (VCD_I_CUSTOM_BASE + 0x1)
+#define VCD_I_FRAME_LEVEL_RC (VCD_I_CUSTOM_BASE + 0x2)
+#define VCD_I_ADAPTIVE_RC (VCD_I_CUSTOM_BASE + 0x3)
+#define VCD_I_CUSTOM_DDL_BASE (VCD_I_RESERVED_BASE + 0x100)
+#define DDL_I_INPUT_BUF_REQ (VCD_I_CUSTOM_DDL_BASE + 0x1)
+#define DDL_I_OUTPUT_BUF_REQ (VCD_I_CUSTOM_DDL_BASE + 0x2)
+#define DDL_I_DPB (VCD_I_CUSTOM_DDL_BASE + 0x3)
+#define DDL_I_DPB_RELEASE (VCD_I_CUSTOM_DDL_BASE + 0x4)
+#define DDL_I_DPB_RETRIEVE (VCD_I_CUSTOM_DDL_BASE + 0x5)
+#define DDL_I_REQ_OUTPUT_FLUSH (VCD_I_CUSTOM_DDL_BASE + 0x6)
+#define DDL_I_SEQHDR_ALIGN_BYTES (VCD_I_CUSTOM_DDL_BASE + 0x7)
+#define DDL_I_SEQHDR_PRESENT (VCD_I_CUSTOM_DDL_BASE + 0xb)
+#define DDL_I_CAPABILITY (VCD_I_CUSTOM_DDL_BASE + 0x8)
+#define DDL_I_FRAME_PROC_UNITS (VCD_I_CUSTOM_DDL_BASE + 0x9)
+
+struct vcd_property_rc_level {
+ u32 frame_level_rc;
+ u32 mb_level_rc;
+};
+
+struct vcd_property_frame_level_rc_params {
+ u32 reaction_coeff;
+};
+
+struct vcd_property_adaptive_rc_params {
+ u32 dark_region_as_flag;
+ u32 smooth_region_as_flag;
+ u32 static_region_as_flag;
+ u32 activity_region_flag;
+};
+
+struct ddl_frame_data_tag;
+
+struct ddl_property_dec_pic_buffers {
+ struct ddl_frame_data_tag *dec_pic_buffers;
+ u32 no_of_dec_pic_buf;
+};
+
+struct ddl_property_capability {
+ u32 max_num_client;
+ u32 general_command_depth;
+ u32 frame_command_depth;
+ u32 exclusive;
+ u32 ddl_time_out_in_ms;
+};
+
+#endif
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_interrupt_handler.c
new file mode 100644
index 0000000..ef5b717
--- /dev/null
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_interrupt_handler.c
@@ -0,0 +1,1122 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "vidc_type.h"
+#include "vidc.h"
+#include "vcd_ddl_utils.h"
+#include "vcd_ddl_metadata.h"
+
+#if DEBUG
+#define DBG(x...) printk(KERN_DEBUG x)
+#else
+#define DBG(x...)
+#endif
+
+static void ddl_decoder_input_done_callback(
+ struct ddl_client_context *ddl, u32 frame_transact_end);
+static u32 ddl_decoder_output_done_callback(
+ struct ddl_client_context *ddl, u32 frame_transact_end);
+
+static u32 ddl_get_frame
+ (struct vcd_frame_data *frame, u32 frame_type);
+
+static void ddl_getdec_profilelevel
+(struct ddl_decoder_data *decoder, u32 profile, u32 level);
+
+static void ddl_dma_done_callback(struct ddl_context *ddl_context)
+{
+ if (!DDLCOMMAND_STATE_IS(ddl_context, DDL_CMD_DMA_INIT)) {
+ VIDC_LOGERR_STRING("UNKWN_DMADONE");
+ return;
+ }
+ ddl_move_command_state(ddl_context, DDL_CMD_INVALID);
+ VIDC_LOG_STRING("DMA_DONE");
+ ddl_core_start_cpu(ddl_context);
+}
+
+static void ddl_cpu_started_callback(struct ddl_context *ddl_context)
+{
+ ddl_move_command_state(ddl_context, DDL_CMD_INVALID);
+ VIDC_LOG_STRING("CPU-STARTED");
+
+ if (!vidc_720p_cpu_start()) {
+ ddl_hw_fatal_cb(ddl_context);
+ return;
+ }
+
+ vidc_720p_set_deblock_line_buffer(
+ ddl_context->db_line_buffer.align_physical_addr,
+ ddl_context->db_line_buffer.buffer_size);
+ ddl_context->device_state = DDL_DEVICE_INITED;
+ ddl_context->ddl_callback(VCD_EVT_RESP_DEVICE_INIT, VCD_S_SUCCESS,
+ NULL, 0, NULL, ddl_context->client_data);
+ DDL_IDLE(ddl_context);
+}
+
+
+static u32 ddl_eos_done_callback(struct ddl_context *ddl_context)
+{
+ struct ddl_client_context *ddl = ddl_context->current_ddl;
+ u32 displaystatus, resl_change;
+
+ if (!DDLCOMMAND_STATE_IS(ddl_context, DDL_CMD_EOS)) {
+ VIDC_LOGERR_STRING("UNKWN_EOSDONE");
+ ddl_client_fatal_cb(ddl_context);
+ return true;
+ }
+
+ if (!ddl ||
+ !ddl->decoding ||
+ !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_EOS_DONE)
+ ) {
+ VIDC_LOG_STRING("STATE-CRITICAL-EOSDONE");
+ ddl_client_fatal_cb(ddl_context);
+ return true;
+ }
+ ddl_move_command_state(ddl_context, DDL_CMD_INVALID);
+
+ vidc_720p_eos_info(&displaystatus, &resl_change);
+ if ((enum vidc_720p_display_status)displaystatus
+ != VIDC_720P_EMPTY_BUFFER) {
+ VIDC_LOG_STRING("EOSDONE-EMPTYBUF-ISSUE");
+ }
+
+ ddl_decode_dynamic_property(ddl, false);
+ if (resl_change == 0x1) {
+ ddl->codec_data.decoder.header_in_start = false;
+ ddl->codec_data.decoder.decode_config.sequence_header =
+ ddl->input_frame.vcd_frm.physical;
+ ddl->codec_data.decoder.decode_config.sequence_header_len =
+ ddl->input_frame.vcd_frm.data_len;
+ ddl_decode_init_codec(ddl);
+ return false;
+ }
+ ddl_move_client_state(ddl, DDL_CLIENT_WAIT_FOR_FRAME);
+ VIDC_LOG_STRING("EOS_DONE");
+ ddl_context->ddl_callback(VCD_EVT_RESP_EOS_DONE, VCD_S_SUCCESS,
+ NULL, 0, (u32 *) ddl, ddl_context->client_data);
+ DDL_IDLE(ddl_context);
+
+ return true;
+}
+
+static u32 ddl_channel_set_callback(struct ddl_context *ddl_context)
+{
+ struct ddl_client_context *ddl = ddl_context->current_ddl;
+ u32 return_status = false;
+
+ ddl_move_command_state(ddl_context, DDL_CMD_INVALID);
+ VIDC_DEBUG_REGISTER_LOG;
+
+ if (!ddl ||
+ !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_CHDONE)
+ ) {
+ VIDC_LOG_STRING("STATE-CRITICAL-CHSET");
+ DDL_IDLE(ddl_context);
+ return return_status;
+ }
+ VIDC_LOG_STRING("Channel-set");
+ ddl_move_client_state(ddl, DDL_CLIENT_WAIT_FOR_INITCODEC);
+
+ if (ddl->decoding) {
+ if (vidc_msg_timing)
+ ddl_calc_core_proc_time(__func__, DEC_OP_TIME);
+ if (ddl->codec_data.decoder.header_in_start) {
+ ddl_decode_init_codec(ddl);
+ } else {
+ ddl_context->ddl_callback(VCD_EVT_RESP_START,
+ VCD_S_SUCCESS, NULL,
+ 0, (u32 *) ddl,
+ ddl_context->client_data);
+
+ DDL_IDLE(ddl_context);
+ return_status = true;
+ }
+ } else {
+ ddl_encode_init_codec(ddl);
+ }
+ return return_status;
+}
+
+static void ddl_init_codec_done_callback(struct ddl_context *ddl_context)
+{
+ struct ddl_client_context *ddl = ddl_context->current_ddl;
+ struct ddl_encoder_data *encoder;
+
+ if (!ddl ||
+ ddl->decoding ||
+ !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_INITCODECDONE)
+ ) {
+ VIDC_LOG_STRING("STATE-CRITICAL-INITCODEC");
+ ddl_client_fatal_cb(ddl_context);
+ return;
+ }
+ ddl_move_command_state(ddl_context, DDL_CMD_INVALID);
+ ddl_move_client_state(ddl, DDL_CLIENT_WAIT_FOR_FRAME);
+ VIDC_LOG_STRING("INIT_CODEC_DONE");
+
+ encoder = &ddl->codec_data.encoder;
+ if (encoder->seq_header.virtual_base_addr) {
+ vidc_720p_encode_get_header(&encoder->seq_header.
+ buffer_size);
+ }
+
+ ddl_context->ddl_callback(VCD_EVT_RESP_START, VCD_S_SUCCESS, NULL,
+ 0, (u32 *) ddl, ddl_context->client_data);
+
+ DDL_IDLE(ddl_context);
+}
+
+static u32 ddl_header_done_callback(struct ddl_context *ddl_context)
+{
+ struct ddl_client_context *ddl = ddl_context->current_ddl;
+ struct ddl_decoder_data *decoder;
+ struct vidc_720p_seq_hdr_info seq_hdr_info;
+
+ u32 process_further = true;
+ u32 seq_hdr_only_frame = false;
+ u32 need_reconfig = true;
+ struct vcd_frame_data *input_vcd_frm;
+ struct ddl_frame_data_tag *reconfig_payload = NULL;
+ u32 reconfig_payload_size = 0;
+
+ if (!ddl ||
+ !ddl->decoding ||
+ !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_INITCODECDONE)
+ ) {
+ VIDC_LOG_STRING("STATE-CRITICAL-HDDONE");
+ ddl_client_fatal_cb(ddl_context);
+ return true;
+ }
+ if (vidc_msg_timing)
+ ddl_calc_core_proc_time(__func__, DEC_OP_TIME);
+ ddl_move_command_state(ddl_context, DDL_CMD_INVALID);
+ ddl_move_client_state(ddl, DDL_CLIENT_WAIT_FOR_DPB);
+ VIDC_LOG_STRING("HEADER_DONE");
+ VIDC_DEBUG_REGISTER_LOG;
+
+ vidc_720p_decode_get_seq_hdr_info(&seq_hdr_info);
+
+ decoder = &(ddl->codec_data.decoder);
+ decoder->frame_size.width = seq_hdr_info.img_size_x;
+ decoder->frame_size.height = seq_hdr_info.img_size_y;
+ decoder->min_dpb_num = seq_hdr_info.min_num_dpb;
+ decoder->y_cb_cr_size = seq_hdr_info.min_dpb_size;
+ decoder->progressive_only = 1 - seq_hdr_info.progressive;
+ if (!seq_hdr_info.img_size_x || !seq_hdr_info.img_size_y) {
+ VIDC_LOGERR_STRING("FATAL: ZeroImageSize");
+ ddl_client_fatal_cb(ddl_context);
+ return process_further;
+ }
+ if (seq_hdr_info.data_partitioned == 0x1 &&
+ decoder->codec.codec == VCD_CODEC_MPEG4 &&
+ seq_hdr_info.img_size_x > DDL_MAX_DP_FRAME_WIDTH &&
+ seq_hdr_info.img_size_y > DDL_MAX_DP_FRAME_HEIGHT) {
+ ddl_client_fatal_cb(ddl_context);
+ return process_further;
+ }
+ ddl_getdec_profilelevel(decoder, seq_hdr_info.profile,
+ seq_hdr_info.level);
+ ddl_calculate_stride(&decoder->frame_size,
+ !decoder->progressive_only,
+ decoder->codec.codec);
+ if (decoder->buf_format.buffer_format == VCD_BUFFER_FORMAT_TILE_4x2) {
+ decoder->frame_size.stride =
+ DDL_TILE_ALIGN(decoder->frame_size.width,
+ DDL_TILE_ALIGN_WIDTH);
+ decoder->frame_size.scan_lines =
+ DDL_TILE_ALIGN(decoder->frame_size.height,
+ DDL_TILE_ALIGN_HEIGHT);
+ }
+ if (seq_hdr_info.crop_exists) {
+ decoder->frame_size.width -=
+ (seq_hdr_info.crop_right_offset
+ + seq_hdr_info.crop_left_offset);
+ decoder->frame_size.height -=
+ (seq_hdr_info.crop_top_offset +
+ seq_hdr_info.crop_bottom_offset);
+ }
+ ddl_set_default_decoder_buffer_req(decoder, false);
+
+ if (decoder->header_in_start) {
+ decoder->client_frame_size = decoder->frame_size;
+ decoder->client_output_buf_req =
+ decoder->actual_output_buf_req;
+ decoder->client_input_buf_req =
+ decoder->actual_input_buf_req;
+ ddl_context->ddl_callback(VCD_EVT_RESP_START, VCD_S_SUCCESS,
+ NULL, 0, (u32 *) ddl, ddl_context->client_data);
+ DDL_IDLE(ddl_context);
+ } else {
+ DBG("%s(): Client data: WxH(%u x %u) SxSL(%u x %u) Sz(%u)\n",
+ __func__, decoder->client_frame_size.width,
+ decoder->client_frame_size.height,
+ decoder->client_frame_size.stride,
+ decoder->client_frame_size.scan_lines,
+ decoder->client_output_buf_req.sz);
+ DBG("%s(): DDL data: WxH(%u x %u) SxSL(%u x %u) Sz(%u)\n",
+ __func__, decoder->frame_size.width,
+ decoder->frame_size.height,
+ decoder->frame_size.stride,
+ decoder->frame_size.scan_lines,
+ decoder->actual_output_buf_req.sz);
+ DBG("%s(): min_dpb_num = %d actual_count = %d\n", __func__,
+ decoder->min_dpb_num,
+ decoder->client_output_buf_req.actual_count);
+
+ input_vcd_frm = &(ddl->input_frame.vcd_frm);
+
+ if (decoder->frame_size.width ==
+ decoder->client_frame_size.width
+ && decoder->frame_size.height ==
+ decoder->client_frame_size.height
+ && decoder->frame_size.stride ==
+ decoder->client_frame_size.stride
+ && decoder->frame_size.scan_lines ==
+ decoder->client_frame_size.scan_lines
+ && decoder->actual_output_buf_req.sz <=
+ decoder->client_output_buf_req.sz
+ && decoder->actual_output_buf_req.actual_count <=
+ decoder->client_output_buf_req.actual_count
+ && decoder->progressive_only)
+ need_reconfig = false;
+ if ((input_vcd_frm->data_len <= seq_hdr_info.dec_frm_size ||
+ (input_vcd_frm->flags & VCD_FRAME_FLAG_CODECCONFIG)) &&
+ (!need_reconfig ||
+ !(input_vcd_frm->flags & VCD_FRAME_FLAG_EOS))) {
+ input_vcd_frm->flags |=
+ VCD_FRAME_FLAG_CODECCONFIG;
+ seq_hdr_only_frame = true;
+ input_vcd_frm->data_len = 0;
+ ddl->input_frame.frm_trans_end = !need_reconfig;
+ ddl_context->ddl_callback(
+ VCD_EVT_RESP_INPUT_DONE,
+ VCD_S_SUCCESS, &ddl->input_frame,
+ sizeof(struct ddl_frame_data_tag),
+ (u32 *) ddl,
+ ddl->ddl_context->client_data);
+ } else if (decoder->codec.codec != VCD_CODEC_H263) {
+ input_vcd_frm->offset += seq_hdr_info.dec_frm_size;
+ input_vcd_frm->data_len -= seq_hdr_info.dec_frm_size;
+ }
+ if (need_reconfig) {
+ decoder->client_frame_size = decoder->frame_size;
+ decoder->client_output_buf_req =
+ decoder->actual_output_buf_req;
+ decoder->client_input_buf_req =
+ decoder->actual_input_buf_req;
+ if (!seq_hdr_only_frame) {
+ reconfig_payload = &ddl->input_frame;
+ reconfig_payload_size =
+ sizeof(struct ddl_frame_data_tag);
+ }
+ ddl_context->ddl_callback(VCD_EVT_IND_OUTPUT_RECONFIG,
+ VCD_S_SUCCESS, reconfig_payload,
+ reconfig_payload_size,
+ (u32 *) ddl,
+ ddl_context->client_data);
+ }
+ if (!need_reconfig && !seq_hdr_only_frame) {
+ if (ddl_decode_set_buffers(ddl) == VCD_S_SUCCESS)
+ process_further = false;
+ else
+ ddl_client_fatal_cb(ddl_context);
+ } else
+ DDL_IDLE(ddl_context);
+ }
+ return process_further;
+}
+
+static u32 ddl_dpb_buffers_set_done_callback(struct ddl_context
+ *ddl_context)
+{
+ struct ddl_client_context *ddl = ddl_context->current_ddl;
+
+ ddl_move_command_state(ddl_context, DDL_CMD_INVALID);
+ if (!ddl ||
+ !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_DPBDONE)
+ ) {
+ VIDC_LOG_STRING("STATE-CRITICAL-DPBDONE");
+ ddl_client_fatal_cb(ddl_context);
+ return true;
+ }
+ if (vidc_msg_timing) {
+ ddl_calc_core_proc_time(__func__, DEC_OP_TIME);
+ ddl_reset_core_time_variables(DEC_OP_TIME);
+ }
+ VIDC_LOG_STRING("INTR_DPBDONE");
+ ddl_move_client_state(ddl, DDL_CLIENT_WAIT_FOR_FRAME);
+ ddl->codec_data.decoder.dec_disp_info.img_size_x = 0;
+ ddl->codec_data.decoder.dec_disp_info.img_size_y = 0;
+ ddl_decode_frame_run(ddl);
+ return false;
+}
+
+static void ddl_encoder_frame_run_callback(struct ddl_context
+ *ddl_context)
+{
+ struct ddl_client_context *ddl = ddl_context->current_ddl;
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ u32 eos_present = false;
+
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME_DONE)
+ ) {
+ VIDC_LOG_STRING("STATE-CRITICAL-ENCFRMRUN");
+ ddl_client_fatal_cb(ddl_context);
+ return;
+ }
+
+ VIDC_LOG_STRING("ENC_FRM_RUN_DONE");
+
+ ddl_move_command_state(ddl_context, DDL_CMD_INVALID);
+ vidc_720p_enc_frame_info(&encoder->enc_frame_info);
+
+ ddl->output_frame.vcd_frm.ip_frm_tag =
+ ddl->input_frame.vcd_frm.ip_frm_tag;
+ ddl->output_frame.vcd_frm.data_len =
+ encoder->enc_frame_info.enc_size;
+ ddl->output_frame.vcd_frm.flags |= VCD_FRAME_FLAG_ENDOFFRAME;
+ ddl_get_frame
+ (&(ddl->output_frame.vcd_frm),
+ encoder->enc_frame_info.frame);
+ ddl_process_encoder_metadata(ddl);
+
+ ddl_encode_dynamic_property(ddl, false);
+
+ ddl->input_frame.frm_trans_end = false;
+ ddl_context->ddl_callback(VCD_EVT_RESP_INPUT_DONE, VCD_S_SUCCESS,
+ &(ddl->input_frame), sizeof(struct ddl_frame_data_tag),
+ (u32 *) ddl, ddl_context->client_data);
+
+ if (vidc_msg_timing)
+ ddl_calc_core_proc_time(__func__, ENC_OP_TIME);
+
+ /* check the presence of EOS */
+ eos_present =
+ ((VCD_FRAME_FLAG_EOS & ddl->input_frame.vcd_frm.flags));
+
+ ddl->output_frame.frm_trans_end = !eos_present;
+ ddl_context->ddl_callback(VCD_EVT_RESP_OUTPUT_DONE, VCD_S_SUCCESS,
+ &(ddl->output_frame), sizeof(struct ddl_frame_data_tag),
+ (u32 *) ddl, ddl_context->client_data);
+
+ if (eos_present) {
+ VIDC_LOG_STRING("ENC-EOS_DONE");
+ ddl_context->ddl_callback(VCD_EVT_RESP_EOS_DONE,
+ VCD_S_SUCCESS, NULL, 0, (u32 *)ddl,
+ ddl_context->client_data);
+ }
+
+ ddl_move_client_state(ddl, DDL_CLIENT_WAIT_FOR_FRAME);
+ DDL_IDLE(ddl_context);
+}
+
+static u32 ddl_decoder_frame_run_callback(struct ddl_context
+ *ddl_context)
+{
+ struct ddl_client_context *ddl = ddl_context->current_ddl;
+ struct vidc_720p_dec_disp_info *dec_disp_info =
+ &(ddl->codec_data.decoder.dec_disp_info);
+ u32 callback_end = false;
+ u32 status = true, eos_present = false;;
+
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME_DONE)) {
+ VIDC_LOG_STRING("STATE-CRITICAL-DECFRMRUN");
+ ddl_client_fatal_cb(ddl_context);
+ return true;
+ }
+
+ VIDC_LOG_STRING("DEC_FRM_RUN_DONE");
+
+ ddl_move_command_state(ddl_context, DDL_CMD_INVALID);
+
+ vidc_720p_decode_display_info(dec_disp_info);
+
+ ddl_decode_dynamic_property(ddl, false);
+
+ if (dec_disp_info->resl_change) {
+ VIDC_LOG_STRING
+ ("DEC_FRM_RUN_DONE: RECONFIG");
+ ddl_move_client_state(ddl, DDL_CLIENT_WAIT_FOR_EOS_DONE);
+ ddl_move_command_state(ddl_context, DDL_CMD_EOS);
+ vidc_720p_submit_command(ddl->channel_id,
+ VIDC_720P_CMD_FRAMERUN_REALLOCATE);
+ return false;
+ }
+
+ if ((VCD_FRAME_FLAG_EOS & ddl->input_frame.vcd_frm.flags)) {
+ callback_end = false;
+ eos_present = true;
+ }
+
+
+ if (dec_disp_info->disp_status == VIDC_720P_DECODE_ONLY ||
+ dec_disp_info->disp_status
+ == VIDC_720P_DECODE_AND_DISPLAY) {
+ if (!eos_present)
+ callback_end = (dec_disp_info->disp_status
+ == VIDC_720P_DECODE_ONLY);
+
+ ddl_decoder_input_done_callback(ddl, callback_end);
+ }
+
+ if (dec_disp_info->disp_status == VIDC_720P_DECODE_AND_DISPLAY
+ || dec_disp_info->disp_status == VIDC_720P_DISPLAY_ONLY) {
+ if (!eos_present)
+ callback_end =
+ (dec_disp_info->disp_status
+ == VIDC_720P_DECODE_AND_DISPLAY);
+
+ if (ddl_decoder_output_done_callback(ddl, callback_end)
+ != VCD_S_SUCCESS)
+ return true;
+ }
+
+ if (dec_disp_info->disp_status == VIDC_720P_DISPLAY_ONLY ||
+ dec_disp_info->disp_status == VIDC_720P_EMPTY_BUFFER) {
+ /* send the same input once again for decoding */
+ ddl_decode_frame_run(ddl);
+ /* client need to ignore the interrupt */
+ status = false;
+ } else if (eos_present) {
+ /* send EOS command to HW */
+ ddl_decode_eos_run(ddl);
+ /* client need to ignore the interrupt */
+ status = false;
+ } else {
+ ddl_move_client_state(ddl, DDL_CLIENT_WAIT_FOR_FRAME);
+ /* move to Idle */
+ DDL_IDLE(ddl_context);
+ }
+ return status;
+}
+
+static u32 ddl_eos_frame_done_callback(struct ddl_context *ddl_context)
+{
+ struct ddl_client_context *ddl = ddl_context->current_ddl;
+ struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
+ struct vidc_720p_dec_disp_info *dec_disp_info =
+ &(decoder->dec_disp_info);
+
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_EOS_DONE)) {
+ VIDC_LOGERR_STRING("STATE-CRITICAL-EOSFRMRUN");
+ ddl_client_fatal_cb(ddl_context);
+ return true;
+ }
+ VIDC_LOG_STRING("EOS_FRM_RUN_DONE");
+
+ ddl_move_command_state(ddl_context, DDL_CMD_INVALID);
+
+ vidc_720p_decode_display_info(dec_disp_info);
+
+ ddl_decode_dynamic_property(ddl, false);
+
+ if (dec_disp_info->disp_status == VIDC_720P_DISPLAY_ONLY) {
+ if (ddl_decoder_output_done_callback(ddl, false)
+ != VCD_S_SUCCESS)
+ return true;
+ } else
+ VIDC_LOG_STRING("STATE-CRITICAL-WRONG-DISP-STATUS");
+
+ ddl_decoder_dpb_transact(decoder, NULL, DDL_DPB_OP_SET_MASK);
+ ddl_move_command_state(ddl_context, DDL_CMD_EOS);
+ vidc_720p_submit_command(ddl->channel_id,
+ VIDC_720P_CMD_FRAMERUN);
+ return false;
+}
+
+static void ddl_channel_end_callback(struct ddl_context *ddl_context)
+{
+ struct ddl_client_context *ddl;
+
+ ddl_move_command_state(ddl_context, DDL_CMD_INVALID);
+ VIDC_LOG_STRING("CH_END_DONE");
+
+ ddl = ddl_context->current_ddl;
+ if (!ddl ||
+ !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_CHEND)
+ ) {
+ VIDC_LOG_STRING("STATE-CRITICAL-CHEND");
+ DDL_IDLE(ddl_context);
+ return;
+ }
+
+ ddl_release_client_internal_buffers(ddl);
+ ddl_context->ddl_callback(VCD_EVT_RESP_STOP, VCD_S_SUCCESS,
+ NULL, 0, (u32 *) ddl, ddl_context->client_data);
+ ddl_move_client_state(ddl, DDL_CLIENT_OPEN);
+ DDL_IDLE(ddl_context);
+}
+
+static u32 ddl_operation_done_callback(struct ddl_context *ddl_context)
+{
+ u32 return_status = true;
+
+ switch (ddl_context->cmd_state) {
+ case DDL_CMD_DECODE_FRAME:
+ {
+ return_status = ddl_decoder_frame_run_callback(
+ ddl_context);
+ break;
+ }
+ case DDL_CMD_ENCODE_FRAME:
+ {
+ ddl_encoder_frame_run_callback(ddl_context);
+ break;
+ }
+ case DDL_CMD_CHANNEL_SET:
+ {
+ return_status = ddl_channel_set_callback(
+ ddl_context);
+ break;
+ }
+ case DDL_CMD_INIT_CODEC:
+ {
+ ddl_init_codec_done_callback(ddl_context);
+ break;
+ }
+ case DDL_CMD_HEADER_PARSE:
+ {
+ return_status = ddl_header_done_callback(
+ ddl_context);
+ break;
+ }
+ case DDL_CMD_DECODE_SET_DPB:
+ {
+ return_status = ddl_dpb_buffers_set_done_callback(
+ ddl_context);
+ break;
+ }
+ case DDL_CMD_CHANNEL_END:
+ {
+ ddl_channel_end_callback(ddl_context);
+ break;
+ }
+ case DDL_CMD_EOS:
+ {
+ return_status = ddl_eos_frame_done_callback(
+ ddl_context);
+ break;
+ }
+ case DDL_CMD_CPU_RESET:
+ {
+ ddl_cpu_started_callback(ddl_context);
+ break;
+ }
+ default:
+ {
+ VIDC_LOG_STRING("UNKWN_OPDONE");
+ return_status = false;
+ break;
+ }
+ }
+ return return_status;
+}
+
+static u32 ddl_process_intr_status(struct ddl_context *ddl_context,
+ u32 int_status)
+{
+ u32 status = true;
+ switch (int_status) {
+ case VIDC_720P_INTR_FRAME_DONE:
+ {
+ status = ddl_operation_done_callback(ddl_context);
+ break;
+ }
+ case VIDC_720P_INTR_DMA_DONE:
+ {
+ ddl_dma_done_callback(ddl_context);
+ status = false;
+ break;
+ }
+ case VIDC_720P_INTR_FW_DONE:
+ {
+ status = ddl_eos_done_callback(ddl_context);
+ break;
+ }
+ case VIDC_720P_INTR_BUFFER_FULL:
+ {
+ VIDC_LOGERR_STRING("BUF_FULL_INTR");
+ ddl_hw_fatal_cb(ddl_context);
+ break;
+ }
+ default:
+ {
+ VIDC_LOGERR_STRING("UNKWN_INTR");
+ break;
+ }
+ }
+ return status;
+}
+
+void ddl_read_and_clear_interrupt(void)
+{
+ struct ddl_context *ddl_context;
+
+ ddl_context = ddl_get_context();
+ if (!ddl_context->core_virtual_base_addr) {
+ VIDC_LOGERR_STRING("SPURIOUS_INTERRUPT");
+ return;
+ }
+ vidc_720p_get_interrupt_status(&ddl_context->intr_status,
+ &ddl_context->cmd_err_status,
+ &ddl_context->disp_pic_err_status,
+ &ddl_context->op_failed
+ );
+
+ vidc_720p_interrupt_done_clear();
+
+}
+
+u32 ddl_process_core_response(void)
+{
+ struct ddl_context *ddl_context;
+ u32 return_status = true;
+
+ ddl_context = ddl_get_context();
+ if (!ddl_context->core_virtual_base_addr) {
+ VIDC_LOGERR_STRING("UNKWN_INTR");
+ return false;
+ }
+
+ if (!ddl_handle_core_errors(ddl_context)) {
+ return_status = ddl_process_intr_status(ddl_context,
+ ddl_context->intr_status);
+ }
+
+ if (ddl_context->interrupt_clr)
+ (*ddl_context->interrupt_clr)();
+
+ return return_status;
+}
+
+static void ddl_decoder_input_done_callback(
+ struct ddl_client_context *ddl, u32 frame_transact_end)
+{
+ struct vidc_720p_dec_disp_info *dec_disp_info =
+ &(ddl->codec_data.decoder.dec_disp_info);
+ struct vcd_frame_data *input_vcd_frm =
+ &(ddl->input_frame.vcd_frm);
+ ddl_get_frame(input_vcd_frm, dec_disp_info->
+ input_frame);
+
+ input_vcd_frm->interlaced = (dec_disp_info->
+ input_is_interlace);
+
+ input_vcd_frm->offset += dec_disp_info->input_bytes_consumed;
+ input_vcd_frm->data_len -= dec_disp_info->input_bytes_consumed;
+
+ ddl->input_frame.frm_trans_end = frame_transact_end;
+ if (vidc_msg_timing)
+ ddl_calc_core_proc_time(__func__, DEC_IP_TIME);
+ ddl->ddl_context->ddl_callback(
+ VCD_EVT_RESP_INPUT_DONE,
+ VCD_S_SUCCESS,
+ &ddl->input_frame,
+ sizeof(struct ddl_frame_data_tag),
+ (void *)ddl,
+ ddl->ddl_context->client_data);
+}
+
+static u32 ddl_decoder_output_done_callback(
+ struct ddl_client_context *ddl,
+ u32 frame_transact_end)
+{
+ struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
+ struct vidc_720p_dec_disp_info *dec_disp_info =
+ &(decoder->dec_disp_info);
+ struct ddl_frame_data_tag *output_frame =
+ &ddl->output_frame;
+ struct vcd_frame_data *output_vcd_frm =
+ &(output_frame->vcd_frm);
+ u32 vcd_status;
+ u32 free_luma_dpb = 0;
+
+ output_vcd_frm->physical = (u8 *)dec_disp_info->y_addr;
+
+ if (decoder->codec.codec == VCD_CODEC_MPEG4 ||
+ decoder->codec.codec == VCD_CODEC_VC1 ||
+ decoder->codec.codec == VCD_CODEC_VC1_RCV ||
+ (decoder->codec.codec >= VCD_CODEC_DIVX_3 &&
+ decoder->codec.codec <= VCD_CODEC_XVID)){
+ vidc_720p_decode_skip_frm_details(&free_luma_dpb);
+ if (free_luma_dpb)
+ output_vcd_frm->physical = (u8 *) free_luma_dpb;
+ }
+
+
+ vcd_status = ddl_decoder_dpb_transact(
+ decoder,
+ output_frame,
+ DDL_DPB_OP_MARK_BUSY);
+
+ if (vcd_status != VCD_S_SUCCESS) {
+ VIDC_LOGERR_STRING("CorruptedOutputBufferAddress");
+ ddl_hw_fatal_cb(ddl->ddl_context);
+ return vcd_status;
+ }
+
+ output_vcd_frm->ip_frm_tag = dec_disp_info->tag_top;
+ if (dec_disp_info->crop_exists == 0x1) {
+ output_vcd_frm->dec_op_prop.disp_frm.left =
+ dec_disp_info->crop_left_offset;
+ output_vcd_frm->dec_op_prop.disp_frm.top =
+ dec_disp_info->crop_top_offset;
+ output_vcd_frm->dec_op_prop.disp_frm.right =
+ dec_disp_info->img_size_x -
+ dec_disp_info->crop_right_offset;
+ output_vcd_frm->dec_op_prop.disp_frm.bottom =
+ dec_disp_info->img_size_y -
+ dec_disp_info->crop_bottom_offset;
+ } else {
+ output_vcd_frm->dec_op_prop.disp_frm.left = 0;
+ output_vcd_frm->dec_op_prop.disp_frm.top = 0;
+ output_vcd_frm->dec_op_prop.disp_frm.right =
+ dec_disp_info->img_size_x;
+ output_vcd_frm->dec_op_prop.disp_frm.bottom =
+ dec_disp_info->img_size_y;
+ }
+ if (!dec_disp_info->disp_is_interlace) {
+ output_vcd_frm->interlaced = false;
+ output_vcd_frm->intrlcd_ip_frm_tag = VCD_FRAMETAG_INVALID;
+ } else {
+ output_vcd_frm->interlaced = true;
+ output_vcd_frm->intrlcd_ip_frm_tag =
+ dec_disp_info->tag_bottom;
+ }
+
+ output_vcd_frm->offset = 0;
+ output_vcd_frm->data_len = decoder->y_cb_cr_size;
+ if (free_luma_dpb) {
+ output_vcd_frm->data_len = 0;
+ output_vcd_frm->flags |= VCD_FRAME_FLAG_DECODEONLY;
+ }
+ output_vcd_frm->flags |= VCD_FRAME_FLAG_ENDOFFRAME;
+ ddl_process_decoder_metadata(ddl);
+ output_frame->frm_trans_end = frame_transact_end;
+
+ if (vidc_msg_timing)
+ ddl_calc_core_proc_time(__func__, DEC_OP_TIME);
+
+ ddl->ddl_context->ddl_callback(
+ VCD_EVT_RESP_OUTPUT_DONE,
+ vcd_status,
+ output_frame,
+ sizeof(struct ddl_frame_data_tag),
+ (void *)ddl,
+ ddl->ddl_context->client_data);
+ return vcd_status;
+}
+
+static u32 ddl_get_frame
+ (struct vcd_frame_data *frame, u32 frametype) {
+ enum vidc_720p_frame vidc_frame =
+ (enum vidc_720p_frame)frametype;
+ u32 status = true;
+
+ switch (vidc_frame) {
+ case VIDC_720P_IFRAME:
+ {
+ frame->flags |= VCD_FRAME_FLAG_SYNCFRAME;
+ frame->frame = VCD_FRAME_I;
+ break;
+ }
+ case VIDC_720P_PFRAME:
+ {
+ frame->frame = VCD_FRAME_P;
+ break;
+ }
+ case VIDC_720P_BFRAME:
+ {
+ frame->frame = VCD_FRAME_B;
+ break;
+ }
+ case VIDC_720P_NOTCODED:
+ {
+ frame->frame = VCD_FRAME_NOTCODED;
+ frame->data_len = 0;
+ break;
+ }
+ default:
+ {
+ VIDC_LOG_STRING("CRITICAL-FRAMETYPE");
+ status = false;
+ break;
+ }
+ }
+ return status;
+}
+
+static void ddl_getmpeg4_declevel(enum vcd_codec_level *codec_level,
+ u32 level)
+{
+ switch (level) {
+ case VIDC_720P_MPEG4_LEVEL0:
+ {
+ *codec_level = VCD_LEVEL_MPEG4_0;
+ break;
+ }
+ case VIDC_720P_MPEG4_LEVEL0b:
+ {
+ *codec_level = VCD_LEVEL_MPEG4_0b;
+ break;
+ }
+ case VIDC_720P_MPEG4_LEVEL1:
+ {
+ *codec_level = VCD_LEVEL_MPEG4_1;
+ break;
+ }
+ case VIDC_720P_MPEG4_LEVEL2:
+ {
+ *codec_level = VCD_LEVEL_MPEG4_2;
+ break;
+ }
+ case VIDC_720P_MPEG4_LEVEL3:
+ {
+ *codec_level = VCD_LEVEL_MPEG4_3;
+ break;
+ }
+ case VIDC_720P_MPEG4_LEVEL3b:
+ {
+ *codec_level = VCD_LEVEL_MPEG4_3b;
+ break;
+ }
+ case VIDC_720P_MPEG4_LEVEL4a:
+ {
+ *codec_level = VCD_LEVEL_MPEG4_4a;
+ break;
+ }
+ case VIDC_720P_MPEG4_LEVEL5:
+ {
+ *codec_level = VCD_LEVEL_MPEG4_5;
+ break;
+ }
+ case VIDC_720P_MPEG4_LEVEL6:
+ {
+ *codec_level = VCD_LEVEL_MPEG4_6;
+ break;
+ }
+ }
+}
+
+static void ddl_geth264_declevel(enum vcd_codec_level *codec_level,
+ u32 level)
+{
+ switch (level) {
+ case VIDC_720P_H264_LEVEL1:
+ {
+ *codec_level = VCD_LEVEL_H264_1;
+ break;
+ }
+ case VIDC_720P_H264_LEVEL1b:
+ {
+ *codec_level = VCD_LEVEL_H264_1b;
+ break;
+ }
+ case VIDC_720P_H264_LEVEL1p1:
+ {
+ *codec_level = VCD_LEVEL_H264_1p1;
+ break;
+ }
+ case VIDC_720P_H264_LEVEL1p2:
+ {
+ *codec_level = VCD_LEVEL_H264_1p2;
+ break;
+ }
+ case VIDC_720P_H264_LEVEL1p3:
+ {
+ *codec_level = VCD_LEVEL_H264_1p3;
+ break;
+ }
+ case VIDC_720P_H264_LEVEL2:
+ {
+ *codec_level = VCD_LEVEL_H264_2;
+ break;
+ }
+ case VIDC_720P_H264_LEVEL2p1:
+ {
+ *codec_level = VCD_LEVEL_H264_2p1;
+ break;
+ }
+ case VIDC_720P_H264_LEVEL2p2:
+ {
+ *codec_level = VCD_LEVEL_H264_2p2;
+ break;
+ }
+ case VIDC_720P_H264_LEVEL3:
+ {
+ *codec_level = VCD_LEVEL_H264_3;
+ break;
+ }
+ case VIDC_720P_H264_LEVEL3p1:
+ {
+ *codec_level = VCD_LEVEL_H264_3p1;
+ break;
+ }
+ case VIDC_720P_H264_LEVEL3p2:
+ {
+ *codec_level = VCD_LEVEL_H264_3p2;
+ break;
+ }
+
+ }
+}
+
+static void ddl_get_vc1_dec_level(
+ enum vcd_codec_level *codec_level, u32 level,
+ enum vcd_codec_profile vc1_profile)
+{
+ if (vc1_profile == VCD_PROFILE_VC1_ADVANCE) {
+ switch (level) {
+ case VIDC_720P_VC1_LEVEL0:
+ {
+ *codec_level = VCD_LEVEL_VC1_A_0;
+ break;
+ }
+ case VIDC_720P_VC1_LEVEL1:
+ {
+ *codec_level = VCD_LEVEL_VC1_A_1;
+ break;
+ }
+ case VIDC_720P_VC1_LEVEL2:
+ {
+ *codec_level = VCD_LEVEL_VC1_A_2;
+ break;
+ }
+ case VIDC_720P_VC1_LEVEL3:
+ {
+ *codec_level = VCD_LEVEL_VC1_A_3;
+ break;
+ }
+ case VIDC_720P_VC1_LEVEL4:
+ {
+ *codec_level = VCD_LEVEL_VC1_A_4;
+ break;
+ }
+ }
+ return;
+ } else if (vc1_profile == VCD_PROFILE_VC1_MAIN) {
+ switch (level) {
+ case VIDC_720P_VC1_LEVEL_LOW:
+ {
+ *codec_level = VCD_LEVEL_VC1_M_LOW;
+ break;
+ }
+ case VIDC_720P_VC1_LEVEL_MED:
+ {
+ *codec_level = VCD_LEVEL_VC1_M_MEDIUM;
+ break;
+ }
+ case VIDC_720P_VC1_LEVEL_HIGH:
+ {
+ *codec_level = VCD_LEVEL_VC1_M_HIGH;
+ break;
+ }
+ }
+ } else if (vc1_profile == VCD_PROFILE_VC1_SIMPLE) {
+ switch (level) {
+ case VIDC_720P_VC1_LEVEL_LOW:
+ {
+ *codec_level = VCD_LEVEL_VC1_S_LOW;
+ break;
+ }
+ case VIDC_720P_VC1_LEVEL_MED:
+ {
+ *codec_level = VCD_LEVEL_VC1_S_MEDIUM;
+ break;
+ }
+ }
+ }
+}
+
+static void ddl_get_mpeg2_dec_level(enum vcd_codec_level *codec_level,
+ u32 level)
+{
+ switch (level) {
+ case VIDCL_720P_MPEG2_LEVEL_LOW:
+ {
+ *codec_level = VCD_LEVEL_MPEG2_LOW;
+ break;
+ }
+ case VIDCL_720P_MPEG2_LEVEL_MAIN:
+ {
+ *codec_level = VCD_LEVEL_MPEG2_MAIN;
+ break;
+ }
+ case VIDCL_720P_MPEG2_LEVEL_HIGH14:
+ {
+ *codec_level = VCD_LEVEL_MPEG2_HIGH_14;
+ break;
+ }
+ }
+}
+
+static void ddl_getdec_profilelevel(struct ddl_decoder_data *decoder,
+ u32 profile, u32 level)
+{
+ enum vcd_codec_profile codec_profile = VCD_PROFILE_UNKNOWN;
+ enum vcd_codec_level codec_level = VCD_LEVEL_UNKNOWN;
+
+ switch (decoder->codec.codec) {
+ case VCD_CODEC_MPEG4:
+ {
+ if (profile == VIDC_720P_PROFILE_MPEG4_SP)
+ codec_profile = VCD_PROFILE_MPEG4_SP;
+ else if (profile == VIDC_720P_PROFILE_MPEG4_ASP)
+ codec_profile = VCD_PROFILE_MPEG4_ASP;
+
+ ddl_getmpeg4_declevel(&codec_level, level);
+ break;
+ }
+ case VCD_CODEC_H264:
+ {
+ if (profile == VIDC_720P_PROFILE_H264_BASELINE)
+ codec_profile = VCD_PROFILE_H264_BASELINE;
+ else if (profile == VIDC_720P_PROFILE_H264_MAIN)
+ codec_profile = VCD_PROFILE_H264_MAIN;
+ else if (profile == VIDC_720P_PROFILE_H264_HIGH)
+ codec_profile = VCD_PROFILE_H264_HIGH;
+ ddl_geth264_declevel(&codec_level, level);
+ break;
+ }
+ default:
+ case VCD_CODEC_H263:
+ {
+ break;
+ }
+ case VCD_CODEC_VC1:
+ case VCD_CODEC_VC1_RCV:
+ {
+ if (profile == VIDC_720P_PROFILE_VC1_SP)
+ codec_profile = VCD_PROFILE_VC1_SIMPLE;
+ else if (profile == VIDC_720P_PROFILE_VC1_MAIN)
+ codec_profile = VCD_PROFILE_VC1_MAIN;
+ else if (profile == VIDC_720P_PROFILE_VC1_ADV)
+ codec_profile = VCD_PROFILE_VC1_ADVANCE;
+ ddl_get_vc1_dec_level(&codec_level, level, profile);
+ break;
+ }
+ case VCD_CODEC_MPEG2:
+ {
+ if (profile == VIDC_720P_PROFILE_MPEG2_MAIN)
+ codec_profile = VCD_PROFILE_MPEG2_MAIN;
+ else if (profile == VIDC_720P_PROFILE_MPEG2_SP)
+ codec_profile = VCD_PROFILE_MPEG2_SIMPLE;
+ ddl_get_mpeg2_dec_level(&codec_level, level);
+ break;
+ }
+ }
+
+ decoder->profile.profile = codec_profile;
+ decoder->level.level = codec_level;
+}
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.c
new file mode 100644
index 0000000..376ea6d
--- /dev/null
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.c
@@ -0,0 +1,580 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "vidc_type.h"
+#include "vcd_ddl_utils.h"
+#include "vcd_ddl_metadata.h"
+
+static u32 *ddl_metadata_hdr_entry(struct ddl_client_context *ddl,
+ u32 meta_data)
+{
+ u32 skip_words = 0;
+ u32 *buffer;
+
+ if (ddl->decoding) {
+ buffer = (u32 *)
+ ddl->codec_data.decoder.meta_data_input.
+ align_virtual_addr;
+ skip_words = 32 + 1;
+ buffer += skip_words;
+
+ switch (meta_data) {
+ default:
+ case VCD_METADATA_DATANONE:
+ {
+ skip_words = 0;
+ break;
+ }
+ case VCD_METADATA_QPARRAY:
+ {
+ skip_words = 3;
+ break;
+ }
+ case VCD_METADATA_CONCEALMB:
+ {
+ skip_words = 6;
+ break;
+ }
+ case VCD_METADATA_VC1:
+ {
+ skip_words = 9;
+ break;
+ }
+ case VCD_METADATA_SEI:
+ {
+ skip_words = 12;
+ break;
+ }
+ case VCD_METADATA_VUI:
+ {
+ skip_words = 15;
+ break;
+ }
+ case VCD_METADATA_PASSTHROUGH:
+ {
+ skip_words = 18;
+ break;
+ }
+ case VCD_METADATA_QCOMFILLER:
+ {
+ skip_words = 21;
+ break;
+ }
+ }
+ } else {
+ buffer = (u32 *)
+ ddl->codec_data.encoder.meta_data_input.
+ align_virtual_addr;
+ skip_words = 2;
+ buffer += skip_words;
+
+ switch (meta_data) {
+ default:
+ case VCD_METADATA_DATANONE:
+ {
+ skip_words = 0;
+ break;
+ }
+ case VCD_METADATA_ENC_SLICE:
+ {
+ skip_words = 3;
+ break;
+ }
+ case VCD_METADATA_QCOMFILLER:
+ {
+ skip_words = 6;
+ break;
+ }
+ }
+
+ }
+
+ buffer += skip_words;
+ return buffer;
+}
+
+void ddl_set_default_meta_data_hdr(struct ddl_client_context *ddl)
+{
+ struct ddl_buf_addr *main_buffer =
+ &ddl->ddl_context->metadata_shared_input;
+ struct ddl_buf_addr *client_buffer;
+ u32 *hdr_entry;
+
+ if (ddl->decoding)
+ client_buffer = &(ddl->codec_data.decoder.meta_data_input);
+ else
+ client_buffer = &(ddl->codec_data.encoder.meta_data_input);
+
+ DDL_METADATA_CLIENT_INPUTBUF(main_buffer, client_buffer,
+ ddl->channel_id);
+
+ hdr_entry = ddl_metadata_hdr_entry(ddl, VCD_METADATA_QCOMFILLER);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] = VCD_METADATA_QCOMFILLER;
+
+ hdr_entry = ddl_metadata_hdr_entry(ddl, VCD_METADATA_DATANONE);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] = VCD_METADATA_DATANONE;
+
+ if (ddl->decoding) {
+ hdr_entry =
+ ddl_metadata_hdr_entry(ddl, VCD_METADATA_QPARRAY);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] = VCD_METADATA_QPARRAY;
+
+ hdr_entry =
+ ddl_metadata_hdr_entry(ddl, VCD_METADATA_CONCEALMB);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] = VCD_METADATA_CONCEALMB;
+
+ hdr_entry = ddl_metadata_hdr_entry(ddl, VCD_METADATA_SEI);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] = VCD_METADATA_SEI;
+
+ hdr_entry = ddl_metadata_hdr_entry(ddl, VCD_METADATA_VUI);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] = VCD_METADATA_VUI;
+
+ hdr_entry = ddl_metadata_hdr_entry(ddl, VCD_METADATA_VC1);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] = VCD_METADATA_VC1;
+
+ hdr_entry =
+ ddl_metadata_hdr_entry(ddl, VCD_METADATA_PASSTHROUGH);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] =
+ VCD_METADATA_PASSTHROUGH;
+
+ } else {
+ hdr_entry =
+ ddl_metadata_hdr_entry(ddl, VCD_METADATA_ENC_SLICE);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] =
+ VCD_METADATA_ENC_SLICE;
+ }
+}
+
+static u32 ddl_supported_metadata_flag(struct ddl_client_context *ddl)
+{
+ u32 flag = 0;
+
+ if (ddl->decoding) {
+ enum vcd_codec codec =
+ ddl->codec_data.decoder.codec.codec;
+
+ flag |= (VCD_METADATA_CONCEALMB |
+ VCD_METADATA_PASSTHROUGH | VCD_METADATA_QPARRAY);
+ if (codec == VCD_CODEC_H264) {
+ flag |= (VCD_METADATA_SEI | VCD_METADATA_VUI);
+ } else if (codec == VCD_CODEC_VC1 ||
+ codec == VCD_CODEC_VC1_RCV) {
+ flag |= VCD_METADATA_VC1;
+ }
+ } else {
+ flag |= VCD_METADATA_ENC_SLICE;
+ }
+
+ return flag;
+}
+
+void ddl_set_default_metadata_flag(struct ddl_client_context *ddl)
+{
+ if (ddl->decoding)
+ ddl->codec_data.decoder.meta_data_enable_flag = 0;
+ else
+ ddl->codec_data.encoder.meta_data_enable_flag = 0;
+}
+
+void ddl_set_default_decoder_metadata_buffer_size(
+ struct ddl_decoder_data *decoder,
+ struct vcd_property_frame_size *frame_size,
+ struct vcd_buffer_requirement *output_buf_req)
+{
+ u32 flag = decoder->meta_data_enable_flag;
+ u32 suffix = 0;
+ size_t sz = 0;
+
+ if (!flag) {
+ decoder->suffix = 0;
+ return;
+ }
+
+ if (flag & VCD_METADATA_QPARRAY) {
+ u32 num_of_mb =
+ ((frame_size->width * frame_size->height) >> 8);
+ sz = DDL_METADATA_HDR_SIZE;
+ sz += num_of_mb;
+ DDL_METADATA_ALIGNSIZE(sz);
+ suffix += sz;
+ }
+ if (flag & VCD_METADATA_CONCEALMB) {
+ u32 num_of_mb =
+ ((frame_size->width * frame_size->height) >> 8);
+ sz = DDL_METADATA_HDR_SIZE + (num_of_mb >> 3);
+ DDL_METADATA_ALIGNSIZE(sz);
+ suffix += sz;
+ }
+ if (flag & VCD_METADATA_VC1) {
+ sz = DDL_METADATA_HDR_SIZE;
+ sz += DDL_METADATA_VC1_PAYLOAD_SIZE;
+ DDL_METADATA_ALIGNSIZE(sz);
+ suffix += sz;
+ }
+ if (flag & VCD_METADATA_SEI) {
+ sz = DDL_METADATA_HDR_SIZE;
+ sz += DDL_METADATA_SEI_PAYLOAD_SIZE;
+ DDL_METADATA_ALIGNSIZE(sz);
+ suffix += (sz * DDL_METADATA_SEI_MAX);
+ }
+ if (flag & VCD_METADATA_VUI) {
+ sz = DDL_METADATA_HDR_SIZE;
+ sz += DDL_METADATA_VUI_PAYLOAD_SIZE;
+ DDL_METADATA_ALIGNSIZE(sz);
+ suffix += (sz);
+ }
+ if (flag & VCD_METADATA_PASSTHROUGH) {
+ sz = DDL_METADATA_HDR_SIZE;
+ sz += DDL_METADATA_PASSTHROUGH_PAYLOAD_SIZE;
+ DDL_METADATA_ALIGNSIZE(sz);
+ suffix += (sz);
+ }
+ sz = DDL_METADATA_EXTRADATANONE_SIZE;
+ DDL_METADATA_ALIGNSIZE(sz);
+ suffix += (sz);
+
+ suffix += DDL_METADATA_EXTRAPAD_SIZE;
+ DDL_METADATA_ALIGNSIZE(suffix);
+
+ decoder->suffix = suffix;
+ output_buf_req->sz += suffix;
+ return;
+}
+
+void ddl_set_default_encoder_metadata_buffer_size(struct ddl_encoder_data
+ *encoder)
+{
+ u32 flag = encoder->meta_data_enable_flag;
+ u32 suffix = 0;
+ size_t sz = 0;
+
+ if (!flag) {
+ encoder->suffix = 0;
+ return;
+ }
+
+ if (flag & VCD_METADATA_ENC_SLICE) {
+ u32 num_of_mb = (encoder->frame_size.width *
+ encoder->frame_size.height / 16 / 16);
+ sz = DDL_METADATA_HDR_SIZE;
+
+ sz += 4;
+
+ sz += (8 * num_of_mb);
+ DDL_METADATA_ALIGNSIZE(sz);
+ suffix += sz;
+ }
+
+ sz = DDL_METADATA_EXTRADATANONE_SIZE;
+ DDL_METADATA_ALIGNSIZE(sz);
+ suffix += (sz);
+
+ suffix += DDL_METADATA_EXTRAPAD_SIZE;
+ DDL_METADATA_ALIGNSIZE(suffix);
+
+ encoder->suffix = suffix;
+ encoder->output_buf_req.sz += suffix;
+}
+
+u32 ddl_set_metadata_params(struct ddl_client_context *ddl,
+ struct vcd_property_hdr *property_hdr,
+ void *property_value)
+{
+ u32 vcd_status = VCD_ERR_ILLEGAL_PARM;
+ if (property_hdr->prop_id == VCD_I_METADATA_ENABLE) {
+ struct vcd_property_meta_data_enable *meta_data_enable =
+ (struct vcd_property_meta_data_enable *)
+ property_value;
+ u32 *meta_data_enable_flag;
+ enum vcd_codec codec;
+ if (ddl->decoding) {
+ meta_data_enable_flag =
+ &(ddl->codec_data.decoder.
+ meta_data_enable_flag);
+ codec = ddl->codec_data.decoder.codec.codec;
+ } else {
+ meta_data_enable_flag =
+ &(ddl->codec_data.encoder.
+ meta_data_enable_flag);
+ codec = ddl->codec_data.encoder.codec.codec;
+ }
+ if (sizeof(struct vcd_property_meta_data_enable) ==
+ property_hdr->sz &&
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN) &&
+ codec) {
+ u32 flag = ddl_supported_metadata_flag(ddl);
+ flag &= (meta_data_enable->meta_data_enable_flag);
+ if (flag)
+ flag |= DDL_METADATA_MANDATORY;
+ if (flag != *meta_data_enable_flag) {
+ *meta_data_enable_flag = flag;
+ if (ddl->decoding) {
+ ddl_set_default_decoder_buffer_req
+ (&ddl->codec_data.decoder,
+ true);
+ } else {
+ ddl_set_default_encoder_buffer_req
+ (&ddl->codec_data.encoder);
+ }
+ }
+ vcd_status = VCD_S_SUCCESS;
+ }
+ } else if (property_hdr->prop_id == VCD_I_METADATA_HEADER) {
+ struct vcd_property_metadata_hdr *hdr =
+ (struct vcd_property_metadata_hdr *)property_value;
+ if (sizeof(struct vcd_property_metadata_hdr) ==
+ property_hdr->sz) {
+ u32 flag = ddl_supported_metadata_flag(ddl);
+ flag |= DDL_METADATA_MANDATORY;
+ flag &= hdr->meta_data_id;
+ if (!(flag & (flag - 1))) {
+ u32 *hdr_entry =
+ ddl_metadata_hdr_entry(ddl, flag);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] =
+ hdr->version;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] =
+ hdr->port_index;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] =
+ hdr->type;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ }
+ return vcd_status;
+}
+
+u32 ddl_get_metadata_params(struct ddl_client_context *ddl,
+ struct vcd_property_hdr *property_hdr,
+ void *property_value)
+{
+ u32 vcd_status = VCD_ERR_ILLEGAL_PARM ;
+ if (property_hdr->prop_id == VCD_I_METADATA_ENABLE &&
+ sizeof(struct vcd_property_meta_data_enable)
+ == property_hdr->sz) {
+ struct vcd_property_meta_data_enable *meta_data_enable =
+ (struct vcd_property_meta_data_enable *)
+ property_value;
+ meta_data_enable->meta_data_enable_flag =
+ ((ddl->decoding) ?
+ (ddl->codec_data.decoder.meta_data_enable_flag)
+ : (ddl->codec_data.encoder.meta_data_enable_flag));
+ vcd_status = VCD_S_SUCCESS;
+ } else if (property_hdr->prop_id == VCD_I_METADATA_HEADER &&
+ sizeof(struct vcd_property_metadata_hdr) ==
+ property_hdr->sz) {
+ struct vcd_property_metadata_hdr *hdr =
+ (struct vcd_property_metadata_hdr *)
+ property_value;
+ u32 flag = ddl_supported_metadata_flag(ddl);
+ flag |= DDL_METADATA_MANDATORY;
+ flag &= hdr->meta_data_id;
+ if (!(flag & (flag - 1))) {
+ u32 *hdr_entry = ddl_metadata_hdr_entry(ddl,
+ flag);
+ hdr->version =
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX];
+ hdr->port_index =
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX];
+ hdr->type =
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX];
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ return vcd_status;
+}
+
+void ddl_metadata_enable(struct ddl_client_context *ddl)
+{
+ u32 flag, hal_flag = 0;
+ u32 *metadata_input;
+ if (ddl->decoding) {
+ flag = ddl->codec_data.decoder.meta_data_enable_flag;
+ metadata_input =
+ ddl->codec_data.decoder.meta_data_input.
+ align_physical_addr;
+ } else {
+ flag = ddl->codec_data.encoder.meta_data_enable_flag;
+ metadata_input =
+ ddl->codec_data.encoder.meta_data_input.
+ align_physical_addr;
+ }
+ if (flag) {
+ if (flag & VCD_METADATA_QPARRAY)
+ hal_flag |= VIDC_720P_METADATA_ENABLE_QP;
+ if (flag & VCD_METADATA_CONCEALMB)
+ hal_flag |= VIDC_720P_METADATA_ENABLE_CONCEALMB;
+ if (flag & VCD_METADATA_VC1)
+ hal_flag |= VIDC_720P_METADATA_ENABLE_VC1;
+ if (flag & VCD_METADATA_SEI)
+ hal_flag |= VIDC_720P_METADATA_ENABLE_SEI;
+ if (flag & VCD_METADATA_VUI)
+ hal_flag |= VIDC_720P_METADATA_ENABLE_VUI;
+ if (flag & VCD_METADATA_ENC_SLICE)
+ hal_flag |= VIDC_720P_METADATA_ENABLE_ENCSLICE;
+ if (flag & VCD_METADATA_PASSTHROUGH)
+ hal_flag |= VIDC_720P_METADATA_ENABLE_PASSTHROUGH;
+ } else {
+ metadata_input = 0;
+ }
+ vidc_720p_metadata_enable(hal_flag, metadata_input);
+}
+
+u32 ddl_encode_set_metadata_output_buf(struct ddl_client_context *ddl)
+{
+ struct ddl_encoder_data *encoder = &ddl->codec_data.encoder;
+ u32 *buffer;
+ struct vcd_frame_data *stream = &(ddl->output_frame.vcd_frm);
+ u32 ext_buffer_end, hw_metadata_start;
+
+ ext_buffer_end = (u32) stream->physical + stream->alloc_len;
+ if (!encoder->meta_data_enable_flag) {
+ ext_buffer_end &= ~(DDL_STREAMBUF_ALIGN_GUARD_BYTES);
+ return ext_buffer_end;
+ }
+ hw_metadata_start = (ext_buffer_end - encoder->suffix) &
+ ~(DDL_STREAMBUF_ALIGN_GUARD_BYTES);
+
+ ext_buffer_end = (hw_metadata_start - 1) &
+ ~(DDL_STREAMBUF_ALIGN_GUARD_BYTES);
+
+ buffer = encoder->meta_data_input.align_virtual_addr;
+
+ *buffer++ = encoder->suffix;
+
+ *buffer = hw_metadata_start;
+
+ encoder->meta_data_offset =
+ hw_metadata_start - (u32) stream->physical;
+
+ return ext_buffer_end;
+}
+
+void ddl_decode_set_metadata_output(struct ddl_decoder_data *decoder)
+{
+ u32 *buffer;
+ u32 loopc;
+
+ if (!decoder->meta_data_enable_flag) {
+ decoder->meta_data_offset = 0;
+ return;
+ }
+
+ decoder->meta_data_offset = ddl_get_yuv_buffer_size(
+ &decoder->client_frame_size, &decoder->buf_format,
+ (!decoder->progressive_only), decoder->codec.codec);
+
+ buffer = decoder->meta_data_input.align_virtual_addr;
+
+ *buffer++ = decoder->suffix;
+
+ for (loopc = 0; loopc < decoder->dp_buf.no_of_dec_pic_buf;
+ ++loopc) {
+ *buffer++ = (u32) (decoder->meta_data_offset + (u8 *)
+ decoder->dp_buf.
+ dec_pic_buffers[loopc].vcd_frm.
+ physical);
+ }
+}
+
+void ddl_process_encoder_metadata(struct ddl_client_context *ddl)
+{
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ struct vcd_frame_data *out_frame =
+ &(ddl->output_frame.vcd_frm);
+ u32 *qfiller_hdr, *qfiller, start_addr;
+ u32 qfiller_size;
+
+ if (!encoder->meta_data_enable_flag) {
+ out_frame->flags &= ~(VCD_FRAME_FLAG_EXTRADATA);
+ return;
+ }
+
+ if (!encoder->enc_frame_info.metadata_exists) {
+ out_frame->flags &= ~(VCD_FRAME_FLAG_EXTRADATA);
+ return;
+ }
+ out_frame->flags |= VCD_FRAME_FLAG_EXTRADATA;
+
+ start_addr = (u32) ((u8 *) out_frame->virtual +
+ out_frame->offset);
+ qfiller = (u32 *) ((out_frame->data_len + start_addr + 3) & ~3);
+
+ qfiller_size = (u32) ((encoder->meta_data_offset +
+ (u8 *) out_frame->virtual) -
+ (u8 *) qfiller);
+
+ qfiller_hdr = ddl_metadata_hdr_entry(ddl, VCD_METADATA_QCOMFILLER);
+
+ *qfiller++ = qfiller_size;
+ *qfiller++ = qfiller_hdr[DDL_METADATA_HDR_VERSION_INDEX];
+ *qfiller++ = qfiller_hdr[DDL_METADATA_HDR_PORT_INDEX];
+ *qfiller++ = qfiller_hdr[DDL_METADATA_HDR_TYPE_INDEX];
+ *qfiller = (u32) (qfiller_size - DDL_METADATA_HDR_SIZE);
+}
+
+void ddl_process_decoder_metadata(struct ddl_client_context *ddl)
+{
+ struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
+ struct vcd_frame_data *output_frame =
+ &(ddl->output_frame.vcd_frm);
+ u32 *qfiller_hdr, *qfiller;
+ u32 qfiller_size;
+
+ if (!decoder->meta_data_enable_flag) {
+ output_frame->flags &= ~(VCD_FRAME_FLAG_EXTRADATA);
+ return;
+ }
+
+ if (!decoder->dec_disp_info.metadata_exists) {
+ output_frame->flags &= ~(VCD_FRAME_FLAG_EXTRADATA);
+ return;
+ }
+ output_frame->flags |= VCD_FRAME_FLAG_EXTRADATA;
+
+ if (output_frame->data_len != decoder->meta_data_offset) {
+ qfiller = (u32 *) ((u32) ((output_frame->data_len +
+ output_frame->offset +
+ (u8 *) output_frame->virtual) +
+ 3) & ~3);
+
+ qfiller_size = (u32) ((decoder->meta_data_offset +
+ (u8 *) output_frame->virtual) -
+ (u8 *) qfiller);
+
+ qfiller_hdr =
+ ddl_metadata_hdr_entry(ddl, VCD_METADATA_QCOMFILLER);
+ *qfiller++ = qfiller_size;
+ *qfiller++ = qfiller_hdr[DDL_METADATA_HDR_VERSION_INDEX];
+ *qfiller++ = qfiller_hdr[DDL_METADATA_HDR_PORT_INDEX];
+ *qfiller++ = qfiller_hdr[DDL_METADATA_HDR_TYPE_INDEX];
+ *qfiller = (u32) (qfiller_size - DDL_METADATA_HDR_SIZE);
+ }
+}
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.h
new file mode 100644
index 0000000..ed43861
--- /dev/null
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.h
@@ -0,0 +1,79 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _VCD_DDL_METADATA_H_
+#define _VCD_DDL_METADATA_H_
+
+#define DDL_MAX_DEC_METADATATYPE (8)
+#define DDL_MAX_ENC_METADATATYPE (3)
+
+#define DDL_METADATA_EXTRAPAD_SIZE (256)
+#define DDL_METADATA_HDR_SIZE (20)
+
+#define DDL_METADATA_EXTRADATANONE_SIZE (24)
+
+#define DDL_METADATA_ALIGNSIZE(x) ((x) = (((x) + 0x7) & ~0x7))
+
+#define DDL_METADATA_MANDATORY (VCD_METADATA_DATANONE | \
+ VCD_METADATA_QCOMFILLER)
+
+#define DDL_METADATA_VC1_PAYLOAD_SIZE (38*4)
+
+#define DDL_METADATA_SEI_PAYLOAD_SIZE (100)
+#define DDL_METADATA_SEI_MAX (5)
+
+#define DDL_METADATA_VUI_PAYLOAD_SIZE (256)
+
+#define DDL_METADATA_PASSTHROUGH_PAYLOAD_SIZE (68)
+
+#define DDL_METADATA_CLIENT_INPUTBUFSIZE (256)
+#define DDL_METADATA_TOTAL_INPUTBUFSIZE \
+ (DDL_METADATA_CLIENT_INPUTBUFSIZE * VCD_MAX_NO_CLIENT)
+
+#define DDL_METADATA_CLIENT_INPUTBUF(main_buffer, client_buffer, \
+ channel_id) \
+{ \
+ (client_buffer)->align_physical_addr = (u32 *)\
+ ((u8 *)(main_buffer)->align_physical_addr + \
+ (DDL_METADATA_CLIENT_INPUTBUFSIZE * (channel_id)) \
+ ); \
+ (client_buffer)->align_virtual_addr = (u32 *)\
+ ((u8 *)(main_buffer)->align_virtual_addr + \
+ (DDL_METADATA_CLIENT_INPUTBUFSIZE * (channel_id)) \
+ ); \
+ (client_buffer)->virtual_base_addr = 0; \
+}
+
+#define DDL_METADATA_HDR_VERSION_INDEX 0
+#define DDL_METADATA_HDR_PORT_INDEX 1
+#define DDL_METADATA_HDR_TYPE_INDEX 2
+
+
+void ddl_set_default_meta_data_hdr(struct ddl_client_context *ddl);
+u32 ddl_get_metadata_params(struct ddl_client_context *ddl,
+ struct vcd_property_hdr *property_hdr, void *property_value);
+u32 ddl_set_metadata_params(struct ddl_client_context *ddl,
+ struct vcd_property_hdr *property_hdr,
+ void *property_value);
+void ddl_set_default_metadata_flag(struct ddl_client_context *ddl);
+void ddl_set_default_decoder_metadata_buffer_size
+ (struct ddl_decoder_data *decoder,
+ struct vcd_property_frame_size *frame_size,
+ struct vcd_buffer_requirement *output_buf_req);
+void ddl_set_default_encoder_metadata_buffer_size(struct ddl_encoder_data
+ *encoder);
+void ddl_metadata_enable(struct ddl_client_context *ddl);
+u32 ddl_encode_set_metadata_output_buf(struct ddl_client_context *ddl);
+void ddl_decode_set_metadata_output(struct ddl_decoder_data *decoder);
+void ddl_process_encoder_metadata(struct ddl_client_context *ddl);
+void ddl_process_decoder_metadata(struct ddl_client_context *ddl);
+#endif
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c
new file mode 100644
index 0000000..73dba03
--- /dev/null
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c
@@ -0,0 +1,1919 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "vidc_type.h"
+#include "vcd_ddl_utils.h"
+#include "vcd_ddl_metadata.h"
+
+static u32 ddl_set_dec_property(struct ddl_client_context *pddl,
+ struct vcd_property_hdr *property_hdr,
+ void *property_value);
+static u32 ddl_set_enc_property(struct ddl_client_context *pddl,
+ struct vcd_property_hdr *property_hdr,
+ void *property_value);
+static u32 ddl_get_dec_property(struct ddl_client_context *pddl,
+ struct vcd_property_hdr *property_hdr,
+ void *property_value);
+static u32 ddl_get_enc_property(struct ddl_client_context *pddl,
+ struct vcd_property_hdr *property_hdr,
+ void *property_value);
+static u32 ddl_set_enc_dynamic_property(struct ddl_client_context *ddl,
+ struct vcd_property_hdr *property_hdr,
+ void *property_value);
+static void ddl_set_default_enc_property(struct ddl_client_context *ddl);
+static void ddl_set_default_enc_profile(struct ddl_encoder_data
+ *encoder);
+static void ddl_set_default_enc_level(struct ddl_encoder_data *encoder);
+static void ddl_set_default_enc_vop_timing(struct ddl_encoder_data
+ *encoder);
+static void ddl_set_default_enc_intra_period(struct ddl_encoder_data
+ *encoder);
+static void ddl_set_default_enc_rc_params(struct ddl_encoder_data
+ *encoder);
+static u32 ddl_valid_buffer_requirement(struct vcd_buffer_requirement
+ *original_buf_req,
+ struct vcd_buffer_requirement
+ *req_buf_req);
+static u32 ddl_decoder_min_num_dpb(struct ddl_decoder_data *decoder);
+static u32 ddl_set_dec_buffers
+ (struct ddl_decoder_data *decoder,
+ struct ddl_property_dec_pic_buffers *dpb);
+
+u32 ddl_set_property(u32 *ddl_handle,
+ struct vcd_property_hdr *property_hdr, void *property_value)
+{
+ u32 vcd_status;
+ struct ddl_context *ddl_context;
+ struct ddl_client_context *ddl =
+ (struct ddl_client_context *)ddl_handle;
+
+ if (!property_hdr || !property_value) {
+ VIDC_LOGERR_STRING("ddl_set_prop:Bad_argument");
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+ ddl_context = ddl_get_context();
+
+ if (!DDL_IS_INITIALIZED(ddl_context)) {
+ VIDC_LOGERR_STRING("ddl_set_prop:Not_inited");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+
+ if (!ddl) {
+ VIDC_LOGERR_STRING("ddl_set_prop:Bad_handle");
+ return VCD_ERR_BAD_HANDLE;
+ }
+ if (ddl->decoding) {
+ vcd_status =
+ ddl_set_dec_property(ddl, property_hdr,
+ property_value);
+ } else {
+ vcd_status =
+ ddl_set_enc_property(ddl, property_hdr,
+ property_value);
+ }
+ if (vcd_status)
+ VIDC_LOGERR_STRING("ddl_set_prop:FAILED");
+
+ return vcd_status;
+}
+
+u32 ddl_get_property(u32 *ddl_handle,
+ struct vcd_property_hdr *property_hdr, void *property_value)
+{
+
+ u32 vcd_status = VCD_ERR_ILLEGAL_PARM;
+ struct ddl_context *ddl_context;
+ struct ddl_client_context *ddl =
+ (struct ddl_client_context *)ddl_handle;
+
+ if (!property_hdr || !property_value)
+ return VCD_ERR_ILLEGAL_PARM;
+
+ if (property_hdr->prop_id == DDL_I_CAPABILITY) {
+ if (sizeof(struct ddl_property_capability) ==
+ property_hdr->sz) {
+ struct ddl_property_capability *ddl_capability =
+ (struct ddl_property_capability *)
+ property_value;
+ ddl_capability->max_num_client = VCD_MAX_NO_CLIENT;
+ ddl_capability->exclusive =
+ VCD_COMMAND_EXCLUSIVE;
+ ddl_capability->frame_command_depth =
+ VCD_FRAME_COMMAND_DEPTH;
+ ddl_capability->general_command_depth =
+ VCD_GENERAL_COMMAND_DEPTH;
+ ddl_capability->ddl_time_out_in_ms =
+ DDL_HW_TIMEOUT_IN_MS;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ return vcd_status;
+ }
+ ddl_context = ddl_get_context();
+ if (!DDL_IS_INITIALIZED(ddl_context))
+ return VCD_ERR_ILLEGAL_OP;
+
+ if (!ddl)
+ return VCD_ERR_BAD_HANDLE;
+
+ if (ddl->decoding) {
+ vcd_status =
+ ddl_get_dec_property(ddl, property_hdr,
+ property_value);
+ } else {
+ vcd_status =
+ ddl_get_enc_property(ddl, property_hdr,
+ property_value);
+ }
+ if (vcd_status)
+ VIDC_LOGERR_STRING("ddl_get_prop:FAILED");
+
+ return vcd_status;
+}
+
+u32 ddl_decoder_ready_to_start(struct ddl_client_context *ddl,
+ struct vcd_sequence_hdr *header)
+{
+ struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
+ if (!decoder->codec.codec) {
+ VIDC_LOGERR_STRING("ddl_dec_start_check:Codec_not_set");
+ return false;
+ }
+ if ((!header) &&
+ (!decoder->client_frame_size.height ||
+ !decoder->client_frame_size.width)
+ ) {
+ VIDC_LOGERR_STRING
+ ("ddl_dec_start_check:Client_height_width_default");
+ return false;
+ }
+ return true;
+}
+
+u32 ddl_encoder_ready_to_start(struct ddl_client_context *ddl)
+{
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+
+ if (!encoder->codec.codec ||
+ !encoder->frame_size.height ||
+ !encoder->frame_size.width ||
+ !encoder->frame_rate.fps_denominator ||
+ !encoder->frame_rate.fps_numerator ||
+ !encoder->target_bit_rate.target_bitrate) {
+ return false;
+ }
+ return true;
+}
+
+static u32 ddl_set_dec_property
+ (struct ddl_client_context *ddl,
+ struct vcd_property_hdr *property_hdr, void *property_value) {
+ u32 vcd_status = VCD_ERR_ILLEGAL_PARM;
+ struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
+ switch (property_hdr->prop_id) {
+ case DDL_I_DPB_RELEASE:
+ {
+ if (sizeof(struct ddl_frame_data_tag) ==
+ property_hdr->sz
+ && decoder->dp_buf.no_of_dec_pic_buf) {
+ vcd_status =
+ ddl_decoder_dpb_transact(decoder,
+ (struct ddl_frame_data_tag *)
+ property_value,
+ DDL_DPB_OP_MARK_FREE);
+ }
+ break;
+ }
+ case DDL_I_DPB:
+ {
+ struct ddl_property_dec_pic_buffers *dpb =
+ (struct ddl_property_dec_pic_buffers *)
+ property_value;
+
+ if (sizeof(struct ddl_property_dec_pic_buffers) ==
+ property_hdr->sz &&
+ (DDLCLIENT_STATE_IS
+ (ddl, DDL_CLIENT_WAIT_FOR_INITCODEC)
+ || DDLCLIENT_STATE_IS(ddl,
+ DDL_CLIENT_WAIT_FOR_DPB)
+ ) &&
+ dpb->no_of_dec_pic_buf >=
+ decoder->client_output_buf_req.actual_count) {
+ vcd_status =
+ ddl_set_dec_buffers(decoder, dpb);
+ }
+ break;
+ }
+ case DDL_I_REQ_OUTPUT_FLUSH:
+ {
+ if (sizeof(u32) == property_hdr->sz) {
+ decoder->dynamic_prop_change |=
+ DDL_DEC_REQ_OUTPUT_FLUSH;
+ decoder->dpb_mask.client_mask = 0;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case DDL_I_INPUT_BUF_REQ:
+ {
+ struct vcd_buffer_requirement *buffer_req =
+ (struct vcd_buffer_requirement *)
+ property_value;
+ if (sizeof(struct vcd_buffer_requirement) ==
+ property_hdr->sz &&
+ (ddl_valid_buffer_requirement(
+ &decoder->min_input_buf_req,
+ buffer_req))) {
+ decoder->client_input_buf_req = *buffer_req;
+ decoder->client_input_buf_req.min_count =
+ decoder->min_input_buf_req.min_count;
+ decoder->client_input_buf_req.max_count =
+ decoder->min_input_buf_req.max_count;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case DDL_I_OUTPUT_BUF_REQ:
+ {
+ struct vcd_buffer_requirement *buffer_req =
+ (struct vcd_buffer_requirement *)
+ property_value;
+ if (sizeof(struct vcd_buffer_requirement) ==
+ property_hdr->sz &&
+ (ddl_valid_buffer_requirement(
+ &decoder->min_output_buf_req,
+ buffer_req))) {
+ decoder->client_output_buf_req =
+ *buffer_req;
+ decoder->client_output_buf_req.min_count =
+ decoder->min_output_buf_req.min_count;
+ decoder->client_output_buf_req.max_count =
+ decoder->min_output_buf_req.max_count;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+
+ case VCD_I_CODEC:
+ {
+ struct vcd_property_codec *codec =
+ (struct vcd_property_codec *)property_value;
+ if (sizeof(struct vcd_property_codec) ==
+ property_hdr->sz
+ && DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)
+ ) {
+ u32 status;
+ vcd_fw_transact(false, true,
+ decoder->codec.codec);
+ status = vcd_fw_transact(true, true,
+ codec->codec);
+ if (status) {
+ decoder->codec = *codec;
+ ddl_set_default_dec_property(ddl);
+ vcd_status = VCD_S_SUCCESS;
+ } else {
+ status = vcd_fw_transact(true, true,
+ decoder->codec.codec);
+ vcd_status = VCD_ERR_NOT_SUPPORTED;
+ }
+ }
+ break;
+ }
+ case VCD_I_POST_FILTER:
+ {
+ if (sizeof(struct vcd_property_post_filter) ==
+ property_hdr->sz
+ && DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN) &&
+ (decoder->codec.codec == VCD_CODEC_MPEG4 ||
+ decoder->codec.codec == VCD_CODEC_MPEG2)
+ ) {
+ decoder->post_filter =
+ *(struct vcd_property_post_filter *)
+ property_value;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_FRAME_SIZE:
+ {
+ struct vcd_property_frame_size *frame_size =
+ (struct vcd_property_frame_size *)
+ property_value;
+
+ if ((sizeof(struct vcd_property_frame_size) ==
+ property_hdr->sz) &&
+ (DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN))) {
+ if (decoder->client_frame_size.height !=
+ frame_size->height
+ || decoder->client_frame_size.width !=
+ frame_size->width) {
+ decoder->client_frame_size =
+ *frame_size;
+ ddl_set_default_decoder_buffer_req
+ (decoder, true);
+ }
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_BUFFER_FORMAT:
+ {
+ struct vcd_property_buffer_format *tile =
+ (struct vcd_property_buffer_format *)
+ property_value;
+ if (sizeof(struct vcd_property_buffer_format) ==
+ property_hdr->sz &&
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN) &&
+ (tile->buffer_format == VCD_BUFFER_FORMAT_NV12
+ || tile->buffer_format ==
+ VCD_BUFFER_FORMAT_TILE_4x2)
+ ) {
+ if (tile->buffer_format !=
+ decoder->buf_format.buffer_format) {
+ decoder->buf_format = *tile;
+ ddl_set_default_decoder_buffer_req
+ (decoder, true);
+ }
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_METADATA_ENABLE:
+ case VCD_I_METADATA_HEADER:
+ {
+ vcd_status = ddl_set_metadata_params(ddl,
+ property_hdr,
+ property_value);
+ break;
+ }
+ case VCD_I_OUTPUT_ORDER:
+ {
+ if (sizeof(u32) == property_hdr->sz &&
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)) {
+ decoder->output_order =
+ *(u32 *)property_value;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_FRAME_RATE:
+ {
+ vcd_status = VCD_S_SUCCESS;
+ break;
+ }
+ default:
+ {
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ break;
+ }
+ }
+ return vcd_status;
+}
+
+static u32 ddl_set_enc_property(struct ddl_client_context *ddl,
+ struct vcd_property_hdr *property_hdr, void *property_value)
+{
+ u32 vcd_status = VCD_ERR_ILLEGAL_PARM;
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+
+ if (DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME) ||
+ (DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME_DONE) ||
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)))
+ vcd_status = ddl_set_enc_dynamic_property(ddl,
+ property_hdr, property_value);
+ if (vcd_status == VCD_S_SUCCESS)
+ return vcd_status;
+
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN) ||
+ vcd_status != VCD_ERR_ILLEGAL_OP) {
+ VIDC_LOGERR_STRING
+ ("ddl_set_enc_property:Fails_as_not_in_open_state");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+
+ switch (property_hdr->prop_id) {
+ case VCD_I_FRAME_SIZE:
+ {
+ struct vcd_property_frame_size *framesize =
+ (struct vcd_property_frame_size *)
+ property_value;
+
+ if (sizeof(struct vcd_property_frame_size)
+ == property_hdr->sz &&
+ DDL_ALLOW_ENC_FRAMESIZE(framesize->width,
+ framesize->height) &&
+ (encoder->codec.codec == VCD_CODEC_H264 ||
+ DDL_VALIDATE_ENC_FRAMESIZE(framesize->width,
+ framesize->height))
+ ) {
+ encoder->frame_size = *framesize;
+ ddl_calculate_stride(&encoder->frame_size,
+ false, encoder->codec.codec);
+ ddl_set_default_encoder_buffer_req(encoder);
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_CODEC:
+ {
+ struct vcd_property_codec *codec =
+ (struct vcd_property_codec *)
+ property_value;
+ if (sizeof(struct vcd_property_codec) ==
+ property_hdr->sz) {
+ u32 status;
+
+ vcd_fw_transact(false, false,
+ encoder->codec.codec);
+
+ status = vcd_fw_transact(true, false,
+ codec->codec);
+ if (status) {
+ encoder->codec = *codec;
+ ddl_set_default_enc_property(ddl);
+ vcd_status = VCD_S_SUCCESS;
+ } else {
+ status = vcd_fw_transact(true, false,
+ encoder->codec.codec);
+ vcd_status = VCD_ERR_NOT_SUPPORTED;
+ }
+ }
+ break;
+ }
+ case VCD_I_PROFILE:
+ {
+ struct vcd_property_profile *profile =
+ (struct vcd_property_profile *)
+ property_value;
+ if ((sizeof(struct vcd_property_profile) ==
+ property_hdr->sz) &&
+ ((encoder->codec.codec ==
+ VCD_CODEC_MPEG4 &&
+ (profile->profile ==
+ VCD_PROFILE_MPEG4_SP ||
+ profile->profile ==
+ VCD_PROFILE_MPEG4_ASP)) ||
+ (encoder->codec.codec ==
+ VCD_CODEC_H264 &&
+ (profile->profile >=
+ VCD_PROFILE_H264_BASELINE ||
+ profile->profile <=
+ VCD_PROFILE_H264_HIGH)) ||
+ (encoder->codec.codec ==
+ VCD_CODEC_H263 &&
+ profile->profile ==
+ VCD_PROFILE_H263_BASELINE))
+ ) {
+ encoder->profile = *profile;
+ vcd_status = VCD_S_SUCCESS;
+
+ if (profile->profile ==
+ VCD_PROFILE_H264_BASELINE)
+ encoder->entropy_control.entropy_sel
+ = VCD_ENTROPY_SEL_CAVLC;
+ else
+ encoder->entropy_control.entropy_sel
+ = VCD_ENTROPY_SEL_CABAC;
+ }
+ break;
+ }
+ case VCD_I_LEVEL:
+ {
+ struct vcd_property_level *level =
+ (struct vcd_property_level *)
+ property_value;
+ if (
+ (sizeof(struct vcd_property_level) ==
+ property_hdr->sz
+ ) &&
+ (
+ (
+ (encoder->codec.
+ codec == VCD_CODEC_MPEG4) &&
+ (level->level >= VCD_LEVEL_MPEG4_0) &&
+ (level->level <= VCD_LEVEL_MPEG4_6)
+ ) ||
+ (
+ (encoder->codec.
+ codec == VCD_CODEC_H264) &&
+ (level->level >= VCD_LEVEL_H264_1) &&
+ (level->level <= VCD_LEVEL_H264_3p1)
+ ) ||
+ (
+ (encoder->codec.
+ codec == VCD_CODEC_H263) &&
+ (level->level >= VCD_LEVEL_H263_10) &&
+ (level->level <= VCD_LEVEL_H263_70)
+ )
+ )
+ ) {
+ encoder->level = *level;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_MULTI_SLICE:
+ {
+ struct vcd_property_multi_slice *multislice =
+ (struct vcd_property_multi_slice *)
+ property_value;
+ switch (multislice->m_slice_sel) {
+ case VCD_MSLICE_OFF:
+ {
+ vcd_status = VCD_S_SUCCESS;
+ break;
+ }
+ case VCD_MSLICE_BY_GOB:
+ {
+ if (encoder->codec.codec ==
+ VCD_CODEC_H263)
+ vcd_status = VCD_S_SUCCESS;
+ break;
+ }
+ case VCD_MSLICE_BY_MB_COUNT:
+ {
+ if (multislice->m_slice_size
+ >= 1 && (multislice->
+ m_slice_size <=
+ (encoder->frame_size.height
+ * encoder->frame_size.width
+ / 16 / 16))
+ ) {
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_MSLICE_BY_BYTE_COUNT:
+ {
+ if (multislice->m_slice_size > 0)
+ vcd_status = VCD_S_SUCCESS;
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ if (sizeof(struct vcd_property_multi_slice) ==
+ property_hdr->sz &&
+ !vcd_status) {
+ encoder->multi_slice = *multislice;
+ if (multislice->m_slice_sel ==
+ VCD_MSLICE_OFF)
+ encoder->multi_slice.m_slice_size = 0;
+ }
+ break;
+ }
+ case VCD_I_RATE_CONTROL:
+ {
+ struct vcd_property_rate_control
+ *ratecontrol =
+ (struct vcd_property_rate_control *)
+ property_value;
+ if (sizeof(struct vcd_property_rate_control) ==
+ property_hdr->sz &&
+ ratecontrol->
+ rate_control >= VCD_RATE_CONTROL_OFF &&
+ ratecontrol->
+ rate_control <= VCD_RATE_CONTROL_CBR_CFR
+ ) {
+ encoder->rc = *ratecontrol;
+ ddl_set_default_enc_rc_params(encoder);
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_SHORT_HEADER:
+ {
+
+ if (sizeof(struct vcd_property_short_header) ==
+ property_hdr->sz &&
+ encoder->codec.codec == VCD_CODEC_MPEG4) {
+ encoder->short_header =
+ *(struct vcd_property_short_header *)
+ property_value;
+ vcd_status = VCD_S_SUCCESS;
+ }
+
+ break;
+ }
+ case VCD_I_VOP_TIMING:
+ {
+ struct vcd_property_vop_timing *voptime =
+ (struct vcd_property_vop_timing *)
+ property_value;
+ if (
+ (sizeof(struct vcd_property_vop_timing) ==
+ property_hdr->sz
+ ) &&
+ (encoder->frame_rate.fps_numerator <=
+ voptime->vop_time_resolution)
+ ) {
+ encoder->vop_timing = *voptime;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_HEADER_EXTENSION:
+ {
+ if (sizeof(u32) == property_hdr->sz &&
+ encoder->codec.codec == VCD_CODEC_MPEG4
+ ) {
+ encoder->hdr_ext_control = *(u32 *)
+ property_value;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_ENTROPY_CTRL:
+ {
+ struct vcd_property_entropy_control
+ *entropy_control =
+ (struct vcd_property_entropy_control *)
+ property_value;
+ if (sizeof(struct vcd_property_entropy_control) ==
+ property_hdr->sz &&
+ encoder->codec.codec == VCD_CODEC_H264
+ && entropy_control->
+ entropy_sel >= VCD_ENTROPY_SEL_CAVLC &&
+ entropy_control->entropy_sel <=
+ VCD_ENTROPY_SEL_CABAC) {
+ encoder->entropy_control = *entropy_control;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_DEBLOCKING:
+ {
+ struct vcd_property_db_config *dbconfig =
+ (struct vcd_property_db_config *)
+ property_value;
+ if (sizeof(struct vcd_property_db_config) ==
+ property_hdr->sz &&
+ encoder->codec.codec == VCD_CODEC_H264
+ && dbconfig->db_config >=
+ VCD_DB_ALL_BLOCKING_BOUNDARY
+ && dbconfig->db_config <=
+ VCD_DB_SKIP_SLICE_BOUNDARY
+ ) {
+ encoder->db_control = *dbconfig;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_QP_RANGE:
+ {
+ struct vcd_property_qp_range *qp =
+ (struct vcd_property_qp_range *)
+ property_value;
+ if ((sizeof(struct vcd_property_qp_range) ==
+ property_hdr->sz) &&
+ (qp->min_qp <= qp->max_qp) &&
+ (
+ (encoder->codec.codec == VCD_CODEC_H264
+ && qp->max_qp <= DDL_MAX_H264_QP) ||
+ (qp->max_qp <= DDL_MAX_MPEG4_QP)
+ )
+ ) {
+ encoder->qp_range = *qp;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_SESSION_QP:
+ {
+ struct vcd_property_session_qp *qp =
+ (struct vcd_property_session_qp *)
+ property_value;
+
+ if ((sizeof(struct vcd_property_session_qp) ==
+ property_hdr->sz) &&
+ (qp->i_frame_qp >= encoder->qp_range.min_qp) &&
+ (qp->i_frame_qp <= encoder->qp_range.max_qp) &&
+ (qp->p_frame_qp >= encoder->qp_range.min_qp) &&
+ (qp->p_frame_qp <= encoder->qp_range.max_qp)
+ ) {
+ encoder->session_qp = *qp;
+ vcd_status = VCD_S_SUCCESS;
+ }
+
+ break;
+ }
+ case VCD_I_RC_LEVEL_CONFIG:
+ {
+ struct vcd_property_rc_level *rc_level =
+ (struct vcd_property_rc_level *)
+ property_value;
+ if (sizeof(struct vcd_property_rc_level) ==
+ property_hdr->sz &&
+ (
+ encoder->rc.
+ rate_control >= VCD_RATE_CONTROL_VBR_VFR ||
+ encoder->rc.
+ rate_control <= VCD_RATE_CONTROL_CBR_VFR
+ ) &&
+ (!rc_level->mb_level_rc ||
+ encoder->codec.codec == VCD_CODEC_H264
+ )
+ ) {
+ encoder->rc_level = *rc_level;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_FRAME_LEVEL_RC:
+ {
+
+ struct vcd_property_frame_level_rc_params
+ *frame_levelrc =
+ (struct vcd_property_frame_level_rc_params *)
+ property_value;
+
+ if ((sizeof(struct
+ vcd_property_frame_level_rc_params)
+ == property_hdr->sz) &&
+ (frame_levelrc->reaction_coeff) &&
+ (encoder->rc_level.frame_level_rc)
+ ) {
+ encoder->frame_level_rc = *frame_levelrc;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_ADAPTIVE_RC:
+ {
+
+ if ((sizeof(struct
+ vcd_property_adaptive_rc_params)
+ == property_hdr->sz) &&
+ (encoder->codec.
+ codec == VCD_CODEC_H264) &&
+ (encoder->rc_level.mb_level_rc)) {
+
+ encoder->adaptive_rc =
+ *(struct vcd_property_adaptive_rc_params *)
+ property_value;
+
+ vcd_status = VCD_S_SUCCESS;
+ }
+
+ break;
+ }
+ case VCD_I_BUFFER_FORMAT:
+ {
+ struct vcd_property_buffer_format *tile =
+ (struct vcd_property_buffer_format *)
+ property_value;
+ if (sizeof(struct vcd_property_buffer_format) ==
+ property_hdr->sz &&
+ tile->buffer_format ==
+ VCD_BUFFER_FORMAT_NV12) {
+ encoder->buf_format = *tile;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case DDL_I_INPUT_BUF_REQ:
+ {
+ struct vcd_buffer_requirement *buffer_req =
+ (struct vcd_buffer_requirement *)
+ property_value;
+ if (sizeof(struct vcd_buffer_requirement) ==
+ property_hdr->sz &&
+ (ddl_valid_buffer_requirement(
+ &encoder->input_buf_req, buffer_req))
+ ) {
+ encoder->client_input_buf_req = *buffer_req;
+ encoder->client_input_buf_req.min_count =
+ encoder->input_buf_req.min_count;
+ encoder->client_input_buf_req.max_count =
+ encoder->input_buf_req.max_count;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case DDL_I_OUTPUT_BUF_REQ:
+ {
+ struct vcd_buffer_requirement *buffer_req =
+ (struct vcd_buffer_requirement *)
+ property_value;
+ if (sizeof(struct vcd_buffer_requirement) ==
+ property_hdr->sz &&
+ (ddl_valid_buffer_requirement(
+ &encoder->output_buf_req, buffer_req))
+ ) {
+ encoder->client_output_buf_req =
+ *buffer_req;
+ encoder->client_output_buf_req.min_count =
+ encoder->output_buf_req.min_count;
+ encoder->client_output_buf_req.max_count =
+ encoder->output_buf_req.max_count;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_METADATA_ENABLE:
+ case VCD_I_METADATA_HEADER:
+ {
+ vcd_status = ddl_set_metadata_params(
+ ddl, property_hdr, property_value);
+ break;
+ }
+ default:
+ {
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ break;
+ }
+ }
+ return vcd_status;
+}
+
+static u32 ddl_get_dec_property
+ (struct ddl_client_context *ddl,
+ struct vcd_property_hdr *property_hdr, void *property_value) {
+ u32 vcd_status = VCD_ERR_ILLEGAL_PARM;
+ struct ddl_decoder_data *decoder = &ddl->codec_data.decoder;
+
+ switch (property_hdr->prop_id) {
+ case VCD_I_FRAME_SIZE:
+ {
+ struct vcd_property_frame_size *fz_size;
+ if (sizeof(struct vcd_property_frame_size) ==
+ property_hdr->sz) {
+ ddl_calculate_stride(
+ &decoder->client_frame_size,
+ !decoder->progressive_only,
+ decoder->codec.codec);
+ if (decoder->buf_format.buffer_format
+ == VCD_BUFFER_FORMAT_TILE_4x2) {
+ fz_size =
+ &decoder->client_frame_size;
+ fz_size->stride =
+ DDL_TILE_ALIGN(fz_size->width,
+ DDL_TILE_ALIGN_WIDTH);
+ fz_size->scan_lines =
+ DDL_TILE_ALIGN(fz_size->height,
+ DDL_TILE_ALIGN_HEIGHT);
+ }
+ *(struct vcd_property_frame_size *)
+ property_value =
+ decoder->client_frame_size;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_PROFILE:
+ {
+ if (sizeof(struct vcd_property_profile) ==
+ property_hdr->sz) {
+ *(struct vcd_property_profile *)
+ property_value = decoder->profile;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_LEVEL:
+ {
+ if (sizeof(struct vcd_property_level) ==
+ property_hdr->sz) {
+ *(struct vcd_property_level *)
+ property_value = decoder->level;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_PROGRESSIVE_ONLY:
+ {
+ if (sizeof(u32) == property_hdr->sz) {
+ *(u32 *) property_value =
+ decoder->progressive_only;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case DDL_I_INPUT_BUF_REQ:
+ {
+ if (sizeof(struct vcd_buffer_requirement) ==
+ property_hdr->sz) {
+ *(struct vcd_buffer_requirement *)
+ property_value =
+ decoder->client_input_buf_req;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case DDL_I_OUTPUT_BUF_REQ:
+ {
+ if (sizeof(struct vcd_buffer_requirement) ==
+ property_hdr->sz) {
+ *(struct vcd_buffer_requirement *)
+ property_value =
+ decoder->client_output_buf_req;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_CODEC:
+ {
+ if (sizeof(struct vcd_property_codec) ==
+ property_hdr->sz) {
+ *(struct vcd_property_codec *)
+ property_value = decoder->codec;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_BUFFER_FORMAT:
+ {
+ if (sizeof(struct vcd_property_buffer_format) ==
+ property_hdr->sz) {
+ *(struct vcd_property_buffer_format *)
+ property_value = decoder->buf_format;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_POST_FILTER:
+ {
+ if (sizeof(struct vcd_property_post_filter) ==
+ property_hdr->sz) {
+ *(struct vcd_property_post_filter *)
+ property_value = decoder->post_filter;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case DDL_I_SEQHDR_ALIGN_BYTES:
+ {
+ if (sizeof(u32) == property_hdr->sz) {
+ *(u32 *) property_value =
+ DDL_LINEAR_BUFFER_ALIGN_BYTES;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case DDL_I_FRAME_PROC_UNITS:
+ {
+ if (sizeof(u32) == property_hdr->sz) {
+ struct vcd_property_frame_size frame_sz =
+ decoder->client_frame_size;
+ ddl_calculate_stride(&frame_sz,
+ !decoder->progressive_only,
+ decoder->codec.codec);
+ *(u32 *) property_value =
+ ((frame_sz.stride >> 4) *
+ (frame_sz.scan_lines >> 4));
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case DDL_I_DPB_RETRIEVE:
+ {
+ if (sizeof(struct ddl_frame_data_tag) ==
+ property_hdr->sz) {
+ vcd_status =
+ ddl_decoder_dpb_transact(decoder,
+ (struct ddl_frame_data_tag *)
+ property_value,
+ DDL_DPB_OP_RETRIEVE);
+ }
+ break;
+ }
+ case VCD_I_OUTPUT_ORDER:
+ {
+ if (sizeof(u32) == property_hdr->sz) {
+ *(u32 *)property_value = decoder->output_order;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_METADATA_ENABLE:
+ case VCD_I_METADATA_HEADER:
+ {
+ vcd_status = ddl_get_metadata_params(
+ ddl,
+ property_hdr,
+ property_value);
+ break;
+ }
+ default:
+ {
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ break;
+ }
+ }
+ return vcd_status;
+}
+
+static u32 ddl_get_enc_property
+ (struct ddl_client_context *ddl,
+ struct vcd_property_hdr *property_hdr, void *property_value) {
+ u32 vcd_status = VCD_ERR_ILLEGAL_PARM;
+ struct ddl_encoder_data *encoder = &ddl->codec_data.encoder;
+
+ struct vcd_property_entropy_control *entropy_control;
+ struct vcd_property_intra_refresh_mb_number *intra_refresh;
+
+ switch (property_hdr->prop_id) {
+ case VCD_I_CODEC:
+ {
+ if (sizeof(struct vcd_property_codec) ==
+ property_hdr->sz) {
+ *(struct vcd_property_codec *)
+ property_value =
+ encoder->codec;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_FRAME_SIZE:
+ {
+ if (sizeof(struct vcd_property_frame_size) ==
+ property_hdr->sz) {
+ *(struct vcd_property_frame_size *)
+ property_value =
+ encoder->frame_size;
+
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_FRAME_RATE:
+ {
+ if (sizeof(struct vcd_property_frame_rate) ==
+ property_hdr->sz) {
+
+ *(struct vcd_property_frame_rate *)
+ property_value =
+ encoder->frame_rate;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_TARGET_BITRATE:
+ {
+
+ if (sizeof(struct vcd_property_target_bitrate) ==
+ property_hdr->sz) {
+ *(struct vcd_property_target_bitrate *)
+ property_value =
+ encoder->target_bit_rate;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_RATE_CONTROL:
+ {
+ if (sizeof(struct vcd_property_rate_control) ==
+ property_hdr->sz) {
+ *(struct vcd_property_rate_control *)
+ property_value = encoder->rc;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_PROFILE:
+ {
+ if (sizeof(struct vcd_property_profile) ==
+ property_hdr->sz) {
+ *(struct vcd_property_profile *)
+ property_value = encoder->profile;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_LEVEL:
+ {
+ if (sizeof(struct vcd_property_level) ==
+ property_hdr->sz) {
+ *(struct vcd_property_level *)
+ property_value = encoder->level;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_MULTI_SLICE:
+ {
+ if (sizeof(struct vcd_property_multi_slice) ==
+ property_hdr->sz) {
+ *(struct vcd_property_multi_slice *)
+ property_value = encoder->multi_slice;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_SEQ_HEADER:
+ {
+ struct vcd_sequence_hdr *seq_hdr =
+ (struct vcd_sequence_hdr *)property_value;
+ if (encoder->seq_header.buffer_size &&
+ sizeof(struct vcd_sequence_hdr) ==
+ property_hdr->sz
+ && encoder->seq_header.buffer_size <=
+ seq_hdr->sequence_header_len) {
+ DDL_MEMCPY(seq_hdr->sequence_header,
+ encoder->seq_header.
+ align_virtual_addr,
+ encoder->seq_header.buffer_size);
+ seq_hdr->sequence_header_len =
+ encoder->seq_header.buffer_size;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case DDL_I_SEQHDR_PRESENT:
+ {
+ if (sizeof(u32) == property_hdr->sz) {
+ if ((encoder->codec.
+ codec == VCD_CODEC_MPEG4 &&
+ !encoder->short_header.short_header)
+ || encoder->codec.codec ==
+ VCD_CODEC_H264) {
+ *(u32 *)property_value = 0x1;
+ } else {
+ *(u32 *)property_value = 0x0;
+ }
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_VOP_TIMING:
+ {
+ if (sizeof(struct vcd_property_vop_timing) ==
+ property_hdr->sz) {
+ *(struct vcd_property_vop_timing *)
+ property_value = encoder->vop_timing;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_SHORT_HEADER:
+ {
+ if (sizeof(struct vcd_property_short_header) ==
+ property_hdr->sz) {
+ if (encoder->codec.codec ==
+ VCD_CODEC_MPEG4) {
+ *(struct vcd_property_short_header
+ *)property_value =
+ encoder->short_header;
+ vcd_status = VCD_S_SUCCESS;
+ } else {
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ }
+ }
+ break;
+ }
+ case VCD_I_ENTROPY_CTRL:
+ {
+ entropy_control = property_value;
+ if (sizeof(struct vcd_property_entropy_control) ==
+ property_hdr->sz) {
+ if (encoder->codec.codec ==
+ VCD_CODEC_H264) {
+ *entropy_control =
+ encoder->entropy_control;
+ vcd_status = VCD_S_SUCCESS;
+ } else {
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ }
+ }
+ break;
+ }
+ case VCD_I_DEBLOCKING:
+ {
+ if (sizeof(struct vcd_property_db_config) ==
+ property_hdr->sz) {
+ if (encoder->codec.codec ==
+ VCD_CODEC_H264) {
+ *(struct vcd_property_db_config *)
+ property_value =
+ encoder->db_control;
+ vcd_status = VCD_S_SUCCESS;
+ } else {
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ }
+ }
+ break;
+ }
+ case VCD_I_INTRA_PERIOD:
+ {
+ if (sizeof(struct vcd_property_i_period) ==
+ property_hdr->sz) {
+ *(struct vcd_property_i_period *)
+ property_value = encoder->i_period;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_QP_RANGE:
+ {
+ if (sizeof(struct vcd_property_qp_range) ==
+ property_hdr->sz) {
+ *(struct vcd_property_qp_range *)
+ property_value = encoder->qp_range;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_SESSION_QP:
+ {
+ if (sizeof(struct vcd_property_session_qp) ==
+ property_hdr->sz) {
+ *(struct vcd_property_session_qp *)
+ property_value = encoder->session_qp;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_RC_LEVEL_CONFIG:
+ {
+ if (sizeof(struct vcd_property_rc_level) ==
+ property_hdr->sz) {
+ *(struct vcd_property_rc_level *)
+ property_value = encoder->rc_level;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_FRAME_LEVEL_RC:
+ {
+ if (sizeof
+ (struct vcd_property_frame_level_rc_params) ==
+ property_hdr->sz) {
+ *(struct vcd_property_frame_level_rc_params
+ *)property_value =
+ encoder->frame_level_rc;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_ADAPTIVE_RC:
+ {
+ if (sizeof(struct vcd_property_adaptive_rc_params)
+ == property_hdr->sz) {
+ *(struct vcd_property_adaptive_rc_params *)
+ property_value = encoder->adaptive_rc;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_INTRA_REFRESH:
+ {
+ intra_refresh = property_value;
+ if (sizeof
+ (struct vcd_property_intra_refresh_mb_number)
+ == property_hdr->sz) {
+ *intra_refresh = encoder->intra_refresh;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case DDL_I_INPUT_BUF_REQ:
+ {
+ if (sizeof(struct vcd_buffer_requirement) ==
+ property_hdr->sz) {
+ *(struct vcd_buffer_requirement *)
+ property_value =
+ encoder->client_input_buf_req;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case DDL_I_OUTPUT_BUF_REQ:
+ {
+ if (sizeof(struct vcd_buffer_requirement) ==
+ property_hdr->sz) {
+ *(struct vcd_buffer_requirement *)
+ property_value =
+ encoder->client_output_buf_req;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_BUFFER_FORMAT:
+ {
+ if (sizeof(struct vcd_property_buffer_format) ==
+ property_hdr->sz) {
+ *(struct vcd_property_buffer_format *)
+ property_value = encoder->buf_format;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case DDL_I_FRAME_PROC_UNITS:
+ {
+ if (sizeof(u32) == property_hdr->sz) {
+ *(u32 *) property_value =
+ ((encoder->frame_size.width >> 4) *
+ (encoder->frame_size.height >> 4)
+ );
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_HEADER_EXTENSION:
+ {
+ if (sizeof(u32) == property_hdr->sz &&
+ encoder->codec.codec == VCD_CODEC_MPEG4) {
+ *(u32 *) property_value =
+ encoder->hdr_ext_control;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_METADATA_ENABLE:
+ case VCD_I_METADATA_HEADER:
+ {
+ vcd_status = ddl_get_metadata_params(
+ ddl,
+ property_hdr,
+ property_value);
+ break;
+ }
+ default:
+ {
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ break;
+ }
+ }
+ return vcd_status;
+}
+
+static u32 ddl_set_enc_dynamic_property
+ (struct ddl_client_context *ddl,
+ struct vcd_property_hdr *property_hdr, void *property_value) {
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ u32 vcd_status = VCD_ERR_ILLEGAL_PARM, dynamic_prop_change = 0x0;
+ switch (property_hdr->prop_id) {
+ case VCD_I_REQ_IFRAME:
+ {
+ if (sizeof(struct vcd_property_req_i_frame) ==
+ property_hdr->sz) {
+ dynamic_prop_change = DDL_ENC_REQ_IFRAME;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_TARGET_BITRATE:
+ {
+ struct vcd_property_target_bitrate *bitrate =
+ (struct vcd_property_target_bitrate *)
+ property_value;
+ if (sizeof(struct vcd_property_target_bitrate) ==
+ property_hdr->sz && bitrate->target_bitrate > 0
+ && bitrate->target_bitrate <= DDL_MAX_BIT_RATE) {
+ encoder->target_bit_rate = *bitrate;
+ dynamic_prop_change = DDL_ENC_CHANGE_BITRATE;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_INTRA_PERIOD:
+ {
+ struct vcd_property_i_period *iperiod =
+ (struct vcd_property_i_period *)
+ property_value;
+ if (sizeof(struct vcd_property_i_period) ==
+ property_hdr->sz &&
+ !iperiod->b_frames) {
+ encoder->i_period = *iperiod;
+ dynamic_prop_change = DDL_ENC_CHANGE_IPERIOD;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_FRAME_RATE:
+ {
+ struct vcd_property_frame_rate *frame_rate =
+ (struct vcd_property_frame_rate *)
+ property_value;
+ if (sizeof(struct vcd_property_frame_rate)
+ == property_hdr->sz &&
+ frame_rate->fps_denominator &&
+ frame_rate->fps_numerator &&
+ frame_rate->fps_denominator <=
+ frame_rate->fps_numerator) {
+ encoder->frame_rate = *frame_rate;
+ dynamic_prop_change = DDL_ENC_CHANGE_FRAMERATE;
+ if (DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN) &&
+ (encoder->codec.codec != VCD_CODEC_MPEG4
+ || encoder->short_header.short_header))
+ ddl_set_default_enc_vop_timing(encoder);
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_INTRA_REFRESH:
+ {
+ struct vcd_property_intra_refresh_mb_number
+ *intra_refresh_mbnum = (
+ struct vcd_property_intra_refresh_mb_number *)
+ property_value;
+ u32 frame_mbnum =
+ (encoder->frame_size.width >> 4) *
+ (encoder->frame_size.height >> 4);
+ if (sizeof(struct
+ vcd_property_intra_refresh_mb_number)
+ == property_hdr->sz &&
+ intra_refresh_mbnum->cir_mb_number <=
+ frame_mbnum) {
+ encoder->intra_refresh =
+ *intra_refresh_mbnum;
+ dynamic_prop_change = DDL_ENC_CHANGE_CIR;
+ vcd_status = VCD_S_SUCCESS;
+ }
+
+ break;
+ }
+ default:
+ {
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ break;
+ }
+ }
+ if (vcd_status == VCD_S_SUCCESS &&
+ (DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME) ||
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME_DONE)))
+ encoder->dynamic_prop_change |= dynamic_prop_change;
+ return vcd_status;
+}
+
+void ddl_set_default_dec_property(struct ddl_client_context *ddl)
+{
+ struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
+
+ if (decoder->codec.codec == VCD_CODEC_MPEG4 ||
+ decoder->codec.codec == VCD_CODEC_MPEG2)
+ decoder->post_filter.post_filter = true;
+ else
+ decoder->post_filter.post_filter = false;
+ decoder->buf_format.buffer_format = VCD_BUFFER_FORMAT_NV12;
+ decoder->client_frame_size.height = 144;
+ decoder->client_frame_size.width = 176;
+ decoder->client_frame_size.stride = 176;
+ decoder->client_frame_size.scan_lines = 144;
+ decoder->progressive_only = 1;
+ decoder->profile.profile = VCD_PROFILE_UNKNOWN;
+ decoder->level.level = VCD_LEVEL_UNKNOWN;
+ decoder->output_order = VCD_DEC_ORDER_DISPLAY;
+ ddl_set_default_metadata_flag(ddl);
+ ddl_set_default_decoder_buffer_req(decoder, true);
+}
+
+static void ddl_set_default_enc_property(struct ddl_client_context *ddl)
+{
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+
+ ddl_set_default_enc_profile(encoder);
+ ddl_set_default_enc_level(encoder);
+
+ encoder->rc.rate_control = VCD_RATE_CONTROL_VBR_VFR;
+ ddl_set_default_enc_rc_params(encoder);
+
+ ddl_set_default_enc_intra_period(encoder);
+
+ encoder->intra_refresh.cir_mb_number = 0;
+ ddl_set_default_enc_vop_timing(encoder);
+
+ encoder->multi_slice.m_slice_sel = VCD_MSLICE_OFF;
+ encoder->multi_slice.m_slice_size = 0;
+ encoder->short_header.short_header = false;
+
+ encoder->entropy_control.entropy_sel = VCD_ENTROPY_SEL_CAVLC;
+ encoder->entropy_control.cabac_model = VCD_CABAC_MODEL_NUMBER_0;
+ encoder->db_control.db_config = VCD_DB_ALL_BLOCKING_BOUNDARY;
+ encoder->db_control.slice_alpha_offset = 0;
+ encoder->db_control.slice_beta_offset = 0;
+
+ encoder->re_con_buf_format.buffer_format =
+ VCD_BUFFER_FORMAT_TILE_4x2;
+
+ encoder->buf_format.buffer_format = VCD_BUFFER_FORMAT_NV12;
+
+ encoder->hdr_ext_control = 0;
+
+ ddl_set_default_metadata_flag(ddl);
+
+ ddl_set_default_encoder_buffer_req(encoder);
+}
+
+static void ddl_set_default_enc_profile(struct ddl_encoder_data *encoder)
+{
+ enum vcd_codec codec = encoder->codec.codec;
+ if (codec == VCD_CODEC_MPEG4)
+ encoder->profile.profile = VCD_PROFILE_MPEG4_SP;
+ else if (codec == VCD_CODEC_H264)
+ encoder->profile.profile = VCD_PROFILE_H264_BASELINE;
+ else
+ encoder->profile.profile = VCD_PROFILE_H263_BASELINE;
+}
+
+static void ddl_set_default_enc_level(struct ddl_encoder_data *encoder)
+{
+ enum vcd_codec codec = encoder->codec.codec;
+ if (codec == VCD_CODEC_MPEG4)
+ encoder->level.level = VCD_LEVEL_MPEG4_1;
+ else if (codec == VCD_CODEC_H264)
+ encoder->level.level = VCD_LEVEL_H264_1;
+ else
+ encoder->level.level = VCD_LEVEL_H263_10;
+}
+
+static void ddl_set_default_enc_vop_timing
+ (struct ddl_encoder_data *encoder)
+{
+ if (encoder->codec.codec == VCD_CODEC_MPEG4)
+ encoder->vop_timing.vop_time_resolution =
+ (2 * encoder->frame_rate.fps_numerator) /
+ encoder->frame_rate.fps_denominator;
+ else
+ encoder->vop_timing.vop_time_resolution = 0x7530;
+}
+
+static void ddl_set_default_enc_intra_period(
+ struct ddl_encoder_data *encoder)
+{
+ switch (encoder->rc.rate_control) {
+ default:
+ case VCD_RATE_CONTROL_VBR_VFR:
+ case VCD_RATE_CONTROL_VBR_CFR:
+ case VCD_RATE_CONTROL_CBR_VFR:
+ case VCD_RATE_CONTROL_OFF:
+ {
+ encoder->i_period.p_frames =
+ ((encoder->frame_rate.fps_numerator << 1) /
+ encoder->frame_rate.fps_denominator) - 1;
+ break;
+ }
+ case VCD_RATE_CONTROL_CBR_CFR:
+ {
+ encoder->i_period.p_frames =
+ ((encoder->frame_rate.fps_numerator >> 1) /
+ encoder->frame_rate.fps_denominator) - 1;
+ break;
+ }
+ }
+ encoder->i_period.b_frames = 0;
+}
+
+static void ddl_set_default_enc_rc_params(
+ struct ddl_encoder_data *encoder)
+{
+ enum vcd_codec codec = encoder->codec.codec;
+
+ encoder->rc_level.frame_level_rc = true;
+ encoder->qp_range.min_qp = 0x1;
+
+ if (codec == VCD_CODEC_H264) {
+ encoder->qp_range.max_qp = 0x33;
+ encoder->session_qp.i_frame_qp = 0x14;
+ encoder->session_qp.p_frame_qp = 0x14;
+
+ encoder->rc_level.mb_level_rc = true;
+ encoder->adaptive_rc.activity_region_flag = true;
+ encoder->adaptive_rc.dark_region_as_flag = true;
+ encoder->adaptive_rc.smooth_region_as_flag = true;
+ encoder->adaptive_rc.static_region_as_flag = true;
+ } else {
+ encoder->qp_range.max_qp = 0x1f;
+ encoder->session_qp.i_frame_qp = 0xd;
+ encoder->session_qp.p_frame_qp = 0xd;
+ encoder->rc_level.mb_level_rc = false;
+ }
+
+ switch (encoder->rc.rate_control) {
+ default:
+ case VCD_RATE_CONTROL_VBR_VFR:
+ {
+ encoder->r_cframe_skip = 1;
+ encoder->frame_level_rc.reaction_coeff = 0x1f4;
+ break;
+ }
+ case VCD_RATE_CONTROL_VBR_CFR:
+ {
+ encoder->r_cframe_skip = 0;
+ encoder->frame_level_rc.reaction_coeff = 0x1f4;
+ break;
+ }
+ case VCD_RATE_CONTROL_CBR_VFR:
+ {
+ encoder->r_cframe_skip = 1;
+ if (codec != VCD_CODEC_H264) {
+ encoder->session_qp.i_frame_qp = 0xf;
+ encoder->session_qp.p_frame_qp = 0xf;
+ }
+
+ encoder->frame_level_rc.reaction_coeff = 0x14;
+ break;
+ }
+ case VCD_RATE_CONTROL_CBR_CFR:
+ {
+ encoder->r_cframe_skip = 0;
+ encoder->frame_level_rc.reaction_coeff = 0x6;
+ break;
+ }
+ case VCD_RATE_CONTROL_OFF:
+ {
+ encoder->r_cframe_skip = 0;
+ encoder->rc_level.frame_level_rc = false;
+ encoder->rc_level.mb_level_rc = false;
+ break;
+ }
+ }
+}
+
+void ddl_set_default_encoder_buffer_req(struct ddl_encoder_data *encoder)
+{
+ u32 y_cb_cr_size;
+
+ y_cb_cr_size = ddl_get_yuv_buffer_size(&encoder->frame_size,
+ &encoder->buf_format, false, encoder->codec.codec);
+
+ memset(&encoder->input_buf_req, 0,
+ sizeof(struct vcd_buffer_requirement));
+
+ encoder->input_buf_req.min_count = 1;
+ encoder->input_buf_req.actual_count =
+ encoder->input_buf_req.min_count + 8;
+ encoder->input_buf_req.max_count = DDL_MAX_BUFFER_COUNT;
+ encoder->input_buf_req.sz = y_cb_cr_size;
+ encoder->input_buf_req.align = DDL_LINEAR_BUFFER_ALIGN_BYTES;
+
+ encoder->client_input_buf_req = encoder->input_buf_req;
+
+ memset(&encoder->output_buf_req, 0,
+ sizeof(struct vcd_buffer_requirement));
+
+ encoder->output_buf_req.min_count = 2;
+ encoder->output_buf_req.actual_count =
+ encoder->output_buf_req.min_count + 3;
+ encoder->output_buf_req.max_count = DDL_MAX_BUFFER_COUNT;
+ encoder->output_buf_req.align = DDL_LINEAR_BUFFER_ALIGN_BYTES;
+ encoder->output_buf_req.sz = y_cb_cr_size;
+ ddl_set_default_encoder_metadata_buffer_size(encoder);
+ encoder->client_output_buf_req = encoder->output_buf_req;
+}
+
+void ddl_set_default_decoder_buffer_req(struct ddl_decoder_data *decoder,
+ u32 estimate)
+{
+ u32 y_cb_cr_size, min_dpb, num_mb;
+ struct vcd_property_frame_size *frame_size;
+ struct vcd_buffer_requirement *output_buf_req, *input_buf_req;
+
+ if (!decoder->codec.codec)
+ return;
+
+ if (estimate) {
+ frame_size = &decoder->client_frame_size;
+ output_buf_req = &decoder->client_output_buf_req;
+ input_buf_req = &decoder->client_input_buf_req;
+ min_dpb = ddl_decoder_min_num_dpb(decoder);
+ y_cb_cr_size = ddl_get_yuv_buffer_size(frame_size,
+ &decoder->buf_format, (!decoder->progressive_only),
+ decoder->codec.codec);
+ } else {
+ frame_size = &decoder->frame_size;
+ output_buf_req = &decoder->actual_output_buf_req;
+ input_buf_req = &decoder->actual_input_buf_req;
+ y_cb_cr_size = decoder->y_cb_cr_size;
+ min_dpb = decoder->min_dpb_num;
+ }
+
+ memset(output_buf_req, 0, sizeof(struct vcd_buffer_requirement));
+
+ output_buf_req->min_count = min_dpb;
+
+ num_mb = DDL_NO_OF_MB(frame_size->width, frame_size->height);
+ if (num_mb >= DDL_WVGA_MBS) {
+ output_buf_req->actual_count = min_dpb + 2;
+ if (output_buf_req->actual_count < 10)
+ output_buf_req->actual_count = 10;
+ } else
+ output_buf_req->actual_count = min_dpb + 5;
+
+ output_buf_req->max_count = DDL_MAX_BUFFER_COUNT;
+ output_buf_req->sz = y_cb_cr_size;
+ if (decoder->buf_format.buffer_format != VCD_BUFFER_FORMAT_NV12)
+ output_buf_req->align = DDL_TILE_BUFFER_ALIGN_BYTES;
+ else
+ output_buf_req->align = DDL_LINEAR_BUFFER_ALIGN_BYTES;
+
+ ddl_set_default_decoder_metadata_buffer_size(decoder,
+ frame_size, output_buf_req);
+
+ decoder->min_output_buf_req = *output_buf_req;
+
+ memset(input_buf_req, 0, sizeof(struct vcd_buffer_requirement));
+
+ input_buf_req->min_count = 1;
+ input_buf_req->actual_count = input_buf_req->min_count + 3;
+ input_buf_req->max_count = DDL_MAX_BUFFER_COUNT;
+ input_buf_req->sz = (1280*720*3*3) >> 3;
+ input_buf_req->align = DDL_LINEAR_BUFFER_ALIGN_BYTES;
+
+ decoder->min_input_buf_req = *input_buf_req;
+
+}
+
+u32 ddl_get_yuv_buffer_size(struct vcd_property_frame_size *frame_size,
+ struct vcd_property_buffer_format *buf_format, u32 inter_lace,
+ enum vcd_codec codec)
+{
+ struct vcd_property_frame_size frame_sz = *frame_size;
+ u32 total_memory_size;
+ ddl_calculate_stride(&frame_sz, inter_lace, codec);
+
+ if (buf_format->buffer_format != VCD_BUFFER_FORMAT_NV12) {
+ u32 component_mem_size;
+ u32 width_round_up;
+ u32 height_round_up;
+ u32 height_chroma = (frame_sz.scan_lines >> 1);
+
+ width_round_up =
+ DDL_TILE_ALIGN(frame_sz.stride, DDL_TILE_ALIGN_WIDTH);
+ height_round_up =
+ DDL_TILE_ALIGN(frame_sz.scan_lines, DDL_TILE_ALIGN_HEIGHT);
+
+ component_mem_size = width_round_up * height_round_up;
+ component_mem_size = DDL_TILE_ALIGN(component_mem_size,
+ DDL_TILE_MULTIPLY_FACTOR);
+
+ total_memory_size = ((component_mem_size +
+ DDL_TILE_BUF_ALIGN_GUARD_BYTES) &
+ DDL_TILE_BUF_ALIGN_MASK);
+
+ height_round_up =
+ DDL_TILE_ALIGN(height_chroma, DDL_TILE_ALIGN_HEIGHT);
+ component_mem_size = width_round_up * height_round_up;
+ component_mem_size = DDL_TILE_ALIGN(component_mem_size,
+ DDL_TILE_MULTIPLY_FACTOR);
+ total_memory_size += component_mem_size;
+ } else {
+ total_memory_size = frame_sz.scan_lines * frame_sz.stride;
+ total_memory_size += (total_memory_size >> 1);
+ }
+ return total_memory_size;
+}
+
+void ddl_calculate_stride(struct vcd_property_frame_size *frame_size,
+ u32 interlace, enum vcd_codec codec)
+{
+ frame_size->stride = ((frame_size->width + 15) >> 4) << 4;
+ if (!interlace || codec == VCD_CODEC_MPEG4 ||
+ codec == VCD_CODEC_DIVX_4 ||
+ codec == VCD_CODEC_DIVX_5 ||
+ codec == VCD_CODEC_DIVX_6 ||
+ codec == VCD_CODEC_XVID) {
+ frame_size->scan_lines =
+ ((frame_size->height + 15) >> 4) << 4;
+ } else {
+ frame_size->scan_lines =
+ ((frame_size->height + 31) >> 5) << 5;
+ }
+
+}
+
+static u32 ddl_valid_buffer_requirement
+ (struct vcd_buffer_requirement *original_buf_req,
+ struct vcd_buffer_requirement *req_buf_req)
+{
+ u32 status = false;
+ if (original_buf_req->max_count >= req_buf_req->actual_count &&
+ original_buf_req->min_count <= req_buf_req->actual_count &&
+ original_buf_req->align <= req_buf_req->align &&
+ original_buf_req->sz <= req_buf_req->sz) {
+ status = true;
+ } else {
+ VIDC_LOGERR_STRING("ddl_valid_buf_req:Failed");
+ }
+ return status;
+}
+
+static u32 ddl_decoder_min_num_dpb(struct ddl_decoder_data *decoder)
+{
+ u32 min_dpb = 0, yuv_size = 0;
+ struct vcd_property_frame_size frame_sz = decoder->client_frame_size;
+ switch (decoder->codec.codec) {
+ default:
+ case VCD_CODEC_MPEG4:
+ case VCD_CODEC_MPEG2:
+ case VCD_CODEC_DIVX_4:
+ case VCD_CODEC_DIVX_5:
+ case VCD_CODEC_DIVX_6:
+ case VCD_CODEC_XVID:
+ {
+ min_dpb = 3;
+ break;
+ }
+ case VCD_CODEC_H263:
+ {
+ min_dpb = 2;
+ break;
+ }
+ case VCD_CODEC_VC1:
+ case VCD_CODEC_VC1_RCV:
+ {
+ min_dpb = 4;
+ break;
+ }
+ case VCD_CODEC_H264:
+ {
+ ddl_calculate_stride(&frame_sz,
+ !decoder->progressive_only,
+ decoder->codec.codec);
+ yuv_size =
+ ((frame_sz.scan_lines *
+ frame_sz.stride * 3) >> 1);
+ min_dpb = 6912000 / yuv_size;
+ if (min_dpb > 16)
+ min_dpb = 16;
+
+ min_dpb += 2;
+ break;
+ }
+ }
+ return min_dpb;
+}
+
+static u32 ddl_set_dec_buffers
+ (struct ddl_decoder_data *decoder,
+ struct ddl_property_dec_pic_buffers *dpb) {
+ u32 vcd_status = VCD_S_SUCCESS;
+ u32 loopc;
+ for (loopc = 0; !vcd_status &&
+ loopc < dpb->no_of_dec_pic_buf; ++loopc) {
+ if ((!DDL_ADDR_IS_ALIGNED
+ (dpb->dec_pic_buffers[loopc].vcd_frm.physical,
+ decoder->client_output_buf_req.align)
+ )
+ || (dpb->dec_pic_buffers[loopc].vcd_frm.alloc_len <
+ decoder->client_output_buf_req.sz)
+ ) {
+ vcd_status = VCD_ERR_ILLEGAL_PARM;
+ }
+ }
+ if (vcd_status) {
+ VIDC_LOGERR_STRING
+ ("ddl_set_prop:Dpb_align_fail_or_alloc_size_small");
+ return vcd_status;
+ }
+ if (decoder->dp_buf.no_of_dec_pic_buf) {
+ DDL_FREE(decoder->dp_buf.dec_pic_buffers);
+ decoder->dp_buf.no_of_dec_pic_buf = 0;
+ }
+ decoder->dp_buf.dec_pic_buffers =
+ DDL_MALLOC(dpb->no_of_dec_pic_buf *
+ sizeof(struct ddl_frame_data_tag));
+
+ if (!decoder->dp_buf.dec_pic_buffers) {
+ VIDC_LOGERR_STRING
+ ("ddl_dec_set_prop:Dpb_container_alloc_failed");
+ return VCD_ERR_ALLOC_FAIL;
+ }
+ decoder->dp_buf.no_of_dec_pic_buf = dpb->no_of_dec_pic_buf;
+ for (loopc = 0; loopc < dpb->no_of_dec_pic_buf; ++loopc) {
+ decoder->dp_buf.dec_pic_buffers[loopc] =
+ dpb->dec_pic_buffers[loopc];
+ }
+ decoder->dpb_mask.client_mask = 0;
+ decoder->dpb_mask.hw_mask = 0;
+ decoder->dynamic_prop_change = 0;
+ return VCD_S_SUCCESS;
+}
+
+void ddl_set_initial_default_values(struct ddl_client_context *ddl)
+{
+ if (ddl->decoding) {
+ ddl->codec_data.decoder.codec.codec = VCD_CODEC_MPEG4;
+ vcd_fw_transact(true, true,
+ ddl->codec_data.decoder.codec.codec);
+ ddl_set_default_dec_property(ddl);
+ } else {
+ struct ddl_encoder_data *encoder =
+ &(ddl->codec_data.encoder);
+ encoder->codec.codec = VCD_CODEC_MPEG4;
+ vcd_fw_transact(true, false,
+ encoder->codec.codec);
+
+ encoder->target_bit_rate.target_bitrate = 64000;
+ encoder->frame_size.width = 176;
+ encoder->frame_size.height = 144;
+ encoder->frame_size.stride = 176;
+ encoder->frame_size.scan_lines = 144;
+ encoder->frame_rate.fps_numerator = 30;
+ encoder->frame_rate.fps_denominator = 1;
+ ddl_set_default_enc_property(ddl);
+ }
+
+ return;
+}
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
new file mode 100644
index 0000000..3b4528f
--- /dev/null
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
@@ -0,0 +1,223 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/memory_alloc.h>
+#include "vidc_type.h"
+#include "vcd_ddl_utils.h"
+
+#if DEBUG
+#define DBG(x...) printk(KERN_DEBUG x)
+#else
+#define DBG(x...)
+#endif
+
+#define DBG_TIME(x...) printk(KERN_DEBUG x)
+#define ERR(x...) printk(KERN_ERR x)
+
+struct time_data {
+ unsigned int ddl_t1;
+ unsigned int ddl_ttotal;
+ unsigned int ddl_count;
+};
+
+static struct time_data proc_time[MAX_TIME_DATA];
+
+#ifdef NO_IN_KERNEL_PMEM
+
+void ddl_pmem_alloc(struct ddl_buf_addr *buff_addr, size_t sz, u32 align)
+{
+ u32 guard_bytes, align_mask;
+ u32 physical_addr, align_offset;
+ dma_addr_t phy_addr;
+
+ if (align == DDL_LINEAR_BUFFER_ALIGN_BYTES) {
+
+ guard_bytes = 31;
+ align_mask = 0xFFFFFFE0U;
+
+ } else {
+
+ guard_bytes = DDL_TILE_BUF_ALIGN_GUARD_BYTES;
+ align_mask = DDL_TILE_BUF_ALIGN_MASK;
+ }
+
+ buff_addr->virtual_base_addr =
+ kmalloc((sz + guard_bytes), GFP_KERNEL);
+
+ if (!buff_addr->virtual_base_addr) {
+ ERR("\n ERROR %s:%u kamlloc fails to allocate"
+ " sz + guard_bytes = %u\n", __func__, __LINE__,
+ (sz + guard_bytes));
+ return;
+ }
+
+ phy_addr = dma_map_single(NULL, buff_addr->virtual_base_addr,
+ sz + guard_bytes, DMA_TO_DEVICE);
+
+ buff_addr->buffer_size = sz;
+ physical_addr = (u32) phy_addr;
+ buff_addr->align_physical_addr =
+ (u32 *) ((physical_addr + guard_bytes) & align_mask);
+ align_offset =
+ (u32) (buff_addr->align_physical_addr) - physical_addr;
+ buff_addr->align_virtual_addr =
+ (u32 *) ((u32) (buff_addr->virtual_base_addr)
+ + align_offset);
+}
+
+void ddl_pmem_free(struct ddl_buf_addr *buff_addr)
+{
+ kfree(buff_addr->virtual_base_addr);
+ buff_addr->buffer_size = 0;
+ buff_addr->virtual_base_addr = NULL;
+}
+
+#else
+
+void ddl_pmem_alloc(struct ddl_buf_addr *buff_addr, size_t sz, u32 align)
+{
+ u32 guard_bytes, align_mask;
+ u32 physical_addr;
+ u32 align_offset;
+ u32 alloc_size;
+ struct ddl_context *ddl_context;
+
+ if (!buff_addr) {
+ ERR("\n%s() Invalid Parameters", __func__);
+ return;
+ }
+
+ DBG_PMEM("\n%s() IN: Requested alloc size(%u)", __func__, (u32)sz);
+
+ if (align == DDL_LINEAR_BUFFER_ALIGN_BYTES) {
+
+ guard_bytes = 31;
+ align_mask = 0xFFFFFFE0U;
+
+ } else {
+
+ guard_bytes = DDL_TILE_BUF_ALIGN_GUARD_BYTES;
+ align_mask = DDL_TILE_BUF_ALIGN_MASK;
+ }
+ ddl_context = ddl_get_context();
+ alloc_size = sz + guard_bytes;
+
+ physical_addr = (u32)
+ allocate_contiguous_memory_nomap(alloc_size,
+ ddl_context->memtype, SZ_4K);
+
+ if (!physical_addr) {
+ pr_err("%s(): could not allocate kernel pmem buffers\n",
+ __func__);
+ goto bailout;
+ }
+ buff_addr->physical_base_addr = (u32 *) physical_addr;
+
+ buff_addr->virtual_base_addr =
+ (u32 *) ioremap((unsigned long)physical_addr,
+ sz + guard_bytes);
+ if (!buff_addr->virtual_base_addr) {
+
+ pr_err("%s: could not ioremap in kernel pmem buffers\n",
+ __func__);
+ free_contiguous_memory_by_paddr(
+ (unsigned long) physical_addr);
+ goto bailout;
+ }
+ memset(buff_addr->virtual_base_addr, 0 , sz + guard_bytes);
+ buff_addr->buffer_size = sz;
+
+ buff_addr->align_physical_addr =
+ (u32 *) ((physical_addr + guard_bytes) & align_mask);
+
+ align_offset =
+ (u32) (buff_addr->align_physical_addr) - physical_addr;
+
+ buff_addr->align_virtual_addr =
+ (u32 *) ((u32) (buff_addr->virtual_base_addr)
+ + align_offset);
+
+ DBG_PMEM("\n%s() OUT: phy_addr(%p) ker_addr(%p) size(%u)", __func__,
+ buff_addr->physical_base_addr, buff_addr->virtual_base_addr,
+ buff_addr->buffer_size);
+
+ return;
+bailout:
+ buff_addr->physical_base_addr = NULL;
+ buff_addr->virtual_base_addr = NULL;
+ buff_addr->buffer_size = 0;
+}
+
+void ddl_pmem_free(struct ddl_buf_addr *buff_addr)
+{
+ if (!buff_addr) {
+ ERR("\n %s() invalid arguments %p", __func__, buff_addr);
+ return;
+ }
+ DBG_PMEM("\n%s() IN: phy_addr(%p) ker_addr(%p) size(%u)", __func__,
+ buff_addr->physical_base_addr, buff_addr->virtual_base_addr,
+ buff_addr->buffer_size);
+
+ if (buff_addr->virtual_base_addr)
+ iounmap((void *)buff_addr->virtual_base_addr);
+ if (buff_addr->physical_base_addr)
+ free_contiguous_memory_by_paddr(
+ (unsigned long) buff_addr->physical_base_addr);
+ DBG_PMEM("\n%s() OUT: phy_addr(%p) ker_addr(%p) size(%u)", __func__,
+ buff_addr->physical_base_addr, buff_addr->virtual_base_addr,
+ buff_addr->buffer_size);
+ buff_addr->buffer_size = 0;
+ buff_addr->physical_base_addr = NULL;
+ buff_addr->virtual_base_addr = NULL;
+}
+#endif
+
+void ddl_set_core_start_time(const char *func_name, u32 index)
+{
+ u32 act_time;
+ struct timeval ddl_tv;
+ struct time_data *time_data = &proc_time[index];
+ do_gettimeofday(&ddl_tv);
+ act_time = (ddl_tv.tv_sec * 1000) + (ddl_tv.tv_usec / 1000);
+ if (!time_data->ddl_t1) {
+ time_data->ddl_t1 = act_time;
+ DBG("\n%s(): Start Time (%u)", func_name, act_time);
+ } else {
+ DBG_TIME("\n%s(): Timer already started! St(%u) Act(%u)",
+ func_name, time_data->ddl_t1, act_time);
+ }
+}
+
+void ddl_calc_core_proc_time(const char *func_name, u32 index)
+{
+ struct time_data *time_data = &proc_time[index];
+ if (time_data->ddl_t1) {
+ int ddl_t2;
+ struct timeval ddl_tv;
+ do_gettimeofday(&ddl_tv);
+ ddl_t2 = (ddl_tv.tv_sec * 1000) + (ddl_tv.tv_usec / 1000);
+ time_data->ddl_ttotal += (ddl_t2 - time_data->ddl_t1);
+ time_data->ddl_count++;
+ DBG_TIME("\n%s(): cnt(%u) Diff(%u) Avg(%u)",
+ func_name, time_data->ddl_count,
+ ddl_t2 - time_data->ddl_t1,
+ time_data->ddl_ttotal/time_data->ddl_count);
+ time_data->ddl_t1 = 0;
+ }
+}
+
+void ddl_reset_core_time_variables(u32 index)
+{
+ proc_time[index].ddl_t1 = 0;
+ proc_time[index].ddl_ttotal = 0;
+ proc_time[index].ddl_count = 0;
+}
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.h
new file mode 100644
index 0000000..4d39ef0
--- /dev/null
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.h
@@ -0,0 +1,60 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _VCD_DDL_UTILS_H_
+#define _VCD_DDL_UTILS_H_
+
+#include "vcd_ddl_core.h"
+#include "vcd_ddl.h"
+
+extern u32 vidc_msg_pmem;
+extern u32 vidc_msg_timing;
+
+enum timing_data {
+ DEC_OP_TIME,
+ DEC_IP_TIME,
+ ENC_OP_TIME,
+ MAX_TIME_DATA
+};
+
+#define DDL_INLINE
+
+#define DDL_ALIGN_SIZE(sz, guard_bytes, align_mask) \
+ (((u32)(sz) + guard_bytes) & align_mask)
+
+#define DDL_MALLOC(x) kmalloc(x, GFP_KERNEL)
+#define DDL_FREE(x) { if ((x)) kfree((x)); (x) = NULL; }
+
+#define DBG_PMEM(x...) \
+do { \
+ if (vidc_msg_pmem) \
+ printk(KERN_DEBUG x); \
+} while (0)
+
+void ddl_pmem_alloc(struct ddl_buf_addr *, u32, u32);
+
+void ddl_pmem_free(struct ddl_buf_addr *);
+
+void ddl_set_core_start_time(const char *func_name, u32 index);
+
+void ddl_calc_core_proc_time(const char *func_name, u32 index);
+
+void ddl_reset_core_time_variables(u32 index);
+
+#define DDL_ASSERT(x)
+#define DDL_MEMSET(src, value, len) memset((src), (value), (len))
+#define DDL_MEMCPY(dest, src, len) memcpy((dest), (src), (len))
+
+#define DDL_ADDR_IS_ALIGNED(addr, align_bytes) \
+(!((u32)(addr) & ((align_bytes) - 1)))
+
+#endif
diff --git a/drivers/video/msm/vidc/720p/ddl/vidc.c b/drivers/video/msm/vidc/720p/ddl/vidc.c
new file mode 100644
index 0000000..8e7abc4
--- /dev/null
+++ b/drivers/video/msm/vidc/720p/ddl/vidc.c
@@ -0,0 +1,801 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/unistd.h>
+#include "vidc.h"
+#include "vidc_type.h"
+
+#if DEBUG
+#define DBG(x...) printk(KERN_DEBUG x)
+#else
+#define DBG(x...)
+#endif
+
+#define VIDC_720P_VERSION_STRING "VIDC_V1.0"
+u8 *vidc_base_addr;
+
+#ifdef VIDC_REGISTER_LOG_INTO_BUFFER
+char vidclog[VIDC_REGLOG_BUFSIZE];
+unsigned int vidclog_index;
+#endif
+
+void vidc_720p_set_device_virtual_base(u8 *core_virtual_base_addr)
+{
+ vidc_base_addr = core_virtual_base_addr;
+}
+
+void vidc_720p_init(char **ppsz_version, u32 i_firmware_size,
+ u32 *pi_firmware_address,
+ enum vidc_720p_endian dma_endian,
+ u32 interrupt_off,
+ enum vidc_720p_interrupt_level_selection
+ interrupt_sel, u32 interrupt_mask)
+{
+ if (ppsz_version)
+ *ppsz_version = VIDC_720P_VERSION_STRING;
+
+ if (interrupt_sel == VIDC_720P_INTERRUPT_LEVEL_SEL)
+ VIDC_IO_OUT(REG_491082, 0);
+ else
+ VIDC_IO_OUT(REG_491082, 1);
+
+ if (interrupt_off)
+ VIDC_IO_OUT(REG_609676, 1);
+ else
+ VIDC_IO_OUT(REG_609676, 0);
+
+ VIDC_IO_OUT(REG_614776, 1);
+
+ VIDC_IO_OUT(REG_418173, 0);
+
+ VIDC_IO_OUT(REG_418173, interrupt_mask);
+
+ VIDC_IO_OUT(REG_736316, dma_endian);
+
+ VIDC_IO_OUT(REG_215724, 0);
+
+ VIDC_IO_OUT(REG_361582, 1);
+
+ VIDC_IO_OUT(REG_591577, i_firmware_size);
+
+ VIDC_IO_OUT(REG_203921, pi_firmware_address);
+
+ VIDC_IO_OUT(REG_531515_ADDR, 0);
+
+ VIDC_IO_OUT(REG_614413, 1);
+}
+
+u32 vidc_720p_do_sw_reset(void)
+{
+
+ u32 fw_start = 0;
+ VIDC_BUSY_WAIT(5);
+ VIDC_IO_OUT(REG_224135, 0);
+ VIDC_BUSY_WAIT(5);
+ VIDC_IO_OUT(REG_193553, 0);
+ VIDC_BUSY_WAIT(5);
+ VIDC_IO_OUT(REG_141269, 1);
+ VIDC_BUSY_WAIT(15);
+ VIDC_IO_OUT(REG_141269, 0);
+ VIDC_BUSY_WAIT(5);
+ VIDC_IO_IN(REG_193553, &fw_start);
+
+ if (!fw_start) {
+ DBG("\n VIDC-SW-RESET-FAILS!");
+ return false;
+ }
+ return true;
+}
+
+u32 vidc_720p_reset_is_success()
+{
+ u32 stagecounter = 0;
+ VIDC_IO_IN(REG_352831, &stagecounter);
+ stagecounter &= 0xff;
+ if (stagecounter != 0xe5) {
+ DBG("\n VIDC-CPU_RESET-FAILS!");
+ VIDC_IO_OUT(REG_224135, 0);
+ msleep(10);
+ return false;
+ }
+ return true;
+}
+
+void vidc_720p_start_cpu(enum vidc_720p_endian dma_endian,
+ u32 *icontext_bufferstart,
+ u32 *debug_core_dump_addr,
+ u32 debug_buffer_size)
+{
+ u32 dbg_info_input0_reg = 0x1;
+ VIDC_IO_OUT(REG_361582, 0);
+ VIDC_IO_OUT(REG_958768, icontext_bufferstart);
+ VIDC_IO_OUT(REG_736316, dma_endian);
+ if (debug_buffer_size) {
+ dbg_info_input0_reg = (debug_buffer_size << 0x10)
+ | (0x2 << 1) | 0x1;
+ VIDC_IO_OUT(REG_166247, debug_core_dump_addr);
+ }
+ VIDC_IO_OUT(REG_699747, dbg_info_input0_reg);
+ VIDC_IO_OUT(REG_224135, 1);
+}
+
+u32 vidc_720p_cpu_start()
+{
+ u32 fw_status = 0x0;
+ VIDC_IO_IN(REG_381535, &fw_status);
+ if (fw_status != 0x02)
+ return false;
+ return true;
+}
+
+
+void vidc_720p_stop_fw(void)
+{
+ VIDC_IO_OUT(REG_193553, 0);
+ VIDC_IO_OUT(REG_224135, 0);
+}
+
+void vidc_720p_get_interrupt_status(u32 *interrupt_status,
+ u32 *cmd_err_status, u32 *disp_pic_err_status, u32 *op_failed)
+{
+ u32 err_status;
+ VIDC_IO_IN(REG_512143, interrupt_status);
+ VIDC_IO_IN(REG_300310, &err_status);
+ *cmd_err_status = err_status & 0xffff;
+ *disp_pic_err_status = (err_status & 0xffff0000) >> 16;
+ VIDC_IO_INF(REG_724381, OPERATION_FAILED, \
+ op_failed);
+}
+
+void vidc_720p_interrupt_done_clear(void)
+{
+ VIDC_IO_OUT(REG_614776, 1);
+ VIDC_IO_OUT(REG_97293, 4);
+}
+
+void vidc_720p_submit_command(u32 ch_id, u32 cmd_id)
+{
+ u32 fw_status;
+ VIDC_IO_OUT(REG_97293, ch_id);
+ VIDC_IO_OUT(REG_62325, cmd_id);
+ VIDC_DEBUG_REGISTER_LOG;
+ VIDC_IO_IN(REG_381535, &fw_status);
+ VIDC_IO_OUT(REG_926519, fw_status);
+}
+
+u32 vidc_720p_engine_reset(u32 ch_id,
+ enum vidc_720p_endian dma_endian,
+ enum vidc_720p_interrupt_level_selection interrupt_sel,
+ u32 interrupt_mask
+)
+{
+ u32 op_done = 0;
+ u32 counter = 0;
+
+ VIDC_LOGERR_STRING("ENG-RESET!!");
+ /* issue the engine reset command */
+ vidc_720p_submit_command(ch_id, VIDC_720P_CMD_MFC_ENGINE_RESET);
+
+ do {
+ VIDC_BUSY_WAIT(20);
+ VIDC_IO_IN(REG_982553, &op_done);
+ counter++;
+ } while (!op_done && counter < 10);
+
+ if (!op_done) {
+ /* Reset fails */
+ return false ;
+ }
+
+ /* write invalid channel id */
+ VIDC_IO_OUT(REG_97293, 4);
+
+ /* Set INT_PULSE_SEL */
+ if (interrupt_sel == VIDC_720P_INTERRUPT_LEVEL_SEL)
+ VIDC_IO_OUT(REG_491082, 0);
+ else
+ VIDC_IO_OUT(REG_491082, 1);
+
+ if (!interrupt_mask) {
+ /* Disable interrupt */
+ VIDC_IO_OUT(REG_609676, 1);
+ } else {
+ /* Enable interrupt */
+ VIDC_IO_OUT(REG_609676, 0);
+ }
+
+ /* Clear any pending interrupt */
+ VIDC_IO_OUT(REG_614776, 1);
+
+ /* Set INT_ENABLE_REG */
+ VIDC_IO_OUT(REG_418173, interrupt_mask);
+
+ /*Sets the DMA endianness */
+ VIDC_IO_OUT(REG_736316, dma_endian);
+
+ /*Restore ARM endianness */
+ VIDC_IO_OUT(REG_215724, 0);
+
+ /* retun engine reset success */
+ return true ;
+}
+
+void vidc_720p_set_channel(u32 i_ch_id,
+ enum vidc_720p_enc_dec_selection
+ enc_dec_sel, enum vidc_720p_codec codec,
+ u32 *pi_fw, u32 i_firmware_size)
+{
+ u32 std_sel = 0;
+ VIDC_IO_OUT(REG_661565, 0);
+
+ if (enc_dec_sel)
+ std_sel = VIDC_REG_713080_ENC_ON_BMSK;
+
+ std_sel |= (u32) codec;
+
+ VIDC_IO_OUT(REG_713080, std_sel);
+
+ switch (codec) {
+ default:
+ case VIDC_720P_DIVX:
+ case VIDC_720P_XVID:
+ case VIDC_720P_MPEG4:
+ {
+ if (enc_dec_sel == VIDC_720P_ENCODER)
+ VIDC_IO_OUT(REG_765787, pi_fw);
+ else
+ VIDC_IO_OUT(REG_225040, pi_fw);
+ break;
+ }
+ case VIDC_720P_H264:
+ {
+ if (enc_dec_sel == VIDC_720P_ENCODER)
+ VIDC_IO_OUT(REG_942456, pi_fw);
+ else
+ VIDC_IO_OUT(REG_942170_ADDR_3, pi_fw);
+ break;
+ }
+ case VIDC_720P_H263:
+ {
+ if (enc_dec_sel == VIDC_720P_ENCODER)
+ VIDC_IO_OUT(REG_765787, pi_fw);
+ else
+ VIDC_IO_OUT(REG_942170_ADDR_6, pi_fw);
+ break;
+ }
+ case VIDC_720P_VC1:
+ {
+ VIDC_IO_OUT(REG_880188, pi_fw);
+ break;
+ }
+ case VIDC_720P_MPEG2:
+ {
+ VIDC_IO_OUT(REG_40293, pi_fw);
+ break;
+ }
+ }
+ VIDC_IO_OUT(REG_591577, i_firmware_size);
+
+ vidc_720p_submit_command(i_ch_id, VIDC_720P_CMD_CHSET);
+}
+
+void vidc_720p_encode_set_profile(u32 i_profile, u32 i_level)
+{
+ u32 profile_level = i_profile|(i_level << 0x8);
+ VIDC_IO_OUT(REG_839021, profile_level);
+}
+
+void vidc_720p_set_frame_size(u32 i_size_x, u32 i_size_y)
+{
+ VIDC_IO_OUT(REG_999267, i_size_x);
+
+ VIDC_IO_OUT(REG_345712, i_size_y);
+}
+
+void vidc_720p_encode_set_fps(u32 i_rc_frame_rate)
+{
+ VIDC_IO_OUT(REG_625444, i_rc_frame_rate);
+}
+
+void vidc_720p_encode_set_short_header(u32 i_short_header)
+{
+ VIDC_IO_OUT(REG_314290, i_short_header);
+}
+
+void vidc_720p_encode_set_vop_time(u32 vop_time_resolution,
+ u32 vop_time_increment)
+{
+ u32 enable_vop, vop_timing_reg;
+ if (!vop_time_resolution)
+ VIDC_IO_OUT(REG_64895, 0x0);
+ else {
+ enable_vop = 0x1;
+ vop_timing_reg = (enable_vop << 0x1f) |
+ (vop_time_resolution << 0x10) | vop_time_increment;
+ VIDC_IO_OUT(REG_64895, vop_timing_reg);
+ }
+}
+
+void vidc_720p_encode_set_hec_period(u32 hec_period)
+{
+ VIDC_IO_OUT(REG_407718, hec_period);
+}
+
+void vidc_720p_encode_set_qp_params(u32 i_max_qp, u32 i_min_qp)
+{
+ u32 qp = i_min_qp | (i_max_qp << 0x8);
+ VIDC_IO_OUT(REG_734318, qp);
+}
+
+void vidc_720p_encode_set_rc_config(u32 enable_frame_level_rc,
+ u32 enable_mb_level_rc_flag,
+ u32 i_frame_qp, u32 pframe_qp)
+{
+ u32 rc_config = i_frame_qp;
+
+ if (enable_frame_level_rc)
+ rc_config |= (0x1 << 0x9);
+
+ if (enable_mb_level_rc_flag)
+ rc_config |= (0x1 << 0x8);
+
+ VIDC_IO_OUT(REG_58211, rc_config);
+ VIDC_IO_OUT(REG_548359, pframe_qp);
+}
+
+void vidc_720p_encode_set_bit_rate(u32 i_target_bitrate)
+{
+ VIDC_IO_OUT(REG_174150, i_target_bitrate);
+}
+
+void vidc_720p_encoder_set_param_change(u32 enc_param_change)
+{
+ VIDC_IO_OUT(REG_804959, enc_param_change);
+}
+
+void vidc_720p_encode_set_control_param(u32 param_val)
+{
+ VIDC_IO_OUT(REG_128234, param_val);
+}
+
+void vidc_720p_encode_set_frame_level_rc_params(u32 i_reaction_coeff)
+{
+ VIDC_IO_OUT(REG_677784, i_reaction_coeff);
+}
+
+void vidc_720p_encode_set_mb_level_rc_params(u32 dark_region_as_flag,
+ u32 smooth_region_as_flag,
+ u32 static_region_as_flag,
+ u32 activity_region_flag)
+{
+ u32 mb_level_rc = 0x0;
+ if (activity_region_flag)
+ mb_level_rc |= 0x1;
+ if (static_region_as_flag)
+ mb_level_rc |= (0x1 << 0x1);
+ if (smooth_region_as_flag)
+ mb_level_rc |= (0x1 << 0x2);
+ if (dark_region_as_flag)
+ mb_level_rc |= (0x1 << 0x3);
+ /* Write MB level rate control */
+ VIDC_IO_OUT(REG_995041, mb_level_rc);
+}
+
+void vidc_720p_encode_set_entropy_control(enum vidc_720p_entropy_sel
+ entropy_sel,
+ enum vidc_720p_cabac_model
+ cabac_model_number)
+{
+ u32 num;
+ u32 entropy_params = (u32)entropy_sel;
+ /* Set Model Number */
+ if (entropy_sel == VIDC_720P_ENTROPY_SEL_CABAC) {
+ num = (u32)cabac_model_number;
+ entropy_params |= (num << 0x2);
+ }
+ /* Set Entropy parameters */
+ VIDC_IO_OUT(REG_504878, entropy_params);
+}
+
+void vidc_720p_encode_set_db_filter_control(enum vidc_720p_DBConfig
+ db_config,
+ u32 i_slice_alpha_offset,
+ u32 i_slice_beta_offset)
+{
+ u32 deblock_params;
+ deblock_params = (u32)db_config;
+ deblock_params |=
+ ((i_slice_beta_offset << 0x2) | (i_slice_alpha_offset << 0x7));
+
+ /* Write deblocking control settings */
+ VIDC_IO_OUT(REG_458130, deblock_params);
+}
+
+void vidc_720p_encode_set_intra_refresh_mb_number(u32 i_cir_mb_number)
+{
+ VIDC_IO_OUT(REG_857491, i_cir_mb_number);
+}
+
+void vidc_720p_encode_set_multi_slice_info(enum
+ vidc_720p_MSlice_selection
+ m_slice_sel,
+ u32 multi_slice_size)
+{
+ switch (m_slice_sel) {
+ case VIDC_720P_MSLICE_BY_MB_COUNT:
+ {
+ VIDC_IO_OUT(REG_588301, 0x1);
+ VIDC_IO_OUT(REG_1517, m_slice_sel);
+ VIDC_IO_OUT(REG_105335, multi_slice_size);
+ break;
+ }
+ case VIDC_720P_MSLICE_BY_BYTE_COUNT:
+ {
+ VIDC_IO_OUT(REG_588301, 0x1);
+ VIDC_IO_OUT(REG_1517, m_slice_sel);
+ VIDC_IO_OUT(REG_561679, multi_slice_size);
+ break;
+ }
+ case VIDC_720P_MSLICE_BY_GOB:
+ {
+ VIDC_IO_OUT(REG_588301, 0x1);
+ break;
+ }
+ default:
+ case VIDC_720P_MSLICE_OFF:
+ {
+ VIDC_IO_OUT(REG_588301, 0x0);
+ break;
+ }
+ }
+}
+
+void vidc_720p_encode_set_dpb_buffer(u32 *pi_enc_dpb_addr, u32 alloc_len)
+{
+ VIDC_IO_OUT(REG_341928_ADDR, pi_enc_dpb_addr);
+ VIDC_IO_OUT(REG_319934, alloc_len);
+}
+
+void vidc_720p_encode_set_i_period(u32 i_i_period)
+{
+ VIDC_IO_OUT(REG_950374, i_i_period);
+}
+
+void vidc_720p_encode_init_codec(u32 i_ch_id,
+ enum vidc_720p_memory_access_method
+ memory_access_model)
+{
+
+ VIDC_IO_OUT(REG_841539, memory_access_model);
+ vidc_720p_submit_command(i_ch_id, VIDC_720P_CMD_INITCODEC);
+}
+
+void vidc_720p_encode_unalign_bitstream(u32 upper_unalign_word,
+ u32 lower_unalign_word)
+{
+ VIDC_IO_OUT(REG_792026, upper_unalign_word);
+ VIDC_IO_OUT(REG_844152, lower_unalign_word);
+}
+
+void vidc_720p_encode_set_seq_header_buffer(u32 ext_buffer_start,
+ u32 ext_buffer_end,
+ u32 start_byte_num)
+{
+ VIDC_IO_OUT(REG_275113_ADDR, ext_buffer_start);
+
+ VIDC_IO_OUT(REG_87912, ext_buffer_start);
+
+ VIDC_IO_OUT(REG_988007_ADDR, ext_buffer_end);
+
+ VIDC_IO_OUT(REG_66693, start_byte_num);
+}
+
+void vidc_720p_encode_frame(u32 ch_id,
+ u32 ext_buffer_start,
+ u32 ext_buffer_end,
+ u32 start_byte_number, u32 y_addr,
+ u32 c_addr)
+{
+ VIDC_IO_OUT(REG_275113_ADDR, ext_buffer_start);
+
+ VIDC_IO_OUT(REG_988007_ADDR, ext_buffer_end);
+
+ VIDC_IO_OUT(REG_87912, ext_buffer_start);
+
+ VIDC_IO_OUT(REG_66693, start_byte_number);
+
+ VIDC_IO_OUT(REG_99105, y_addr);
+
+ VIDC_IO_OUT(REG_777113_ADDR, c_addr);
+
+ vidc_720p_submit_command(ch_id, VIDC_720P_CMD_FRAMERUN);
+}
+
+void vidc_720p_encode_get_header(u32 *pi_enc_header_size)
+{
+ VIDC_IO_IN(REG_114286, pi_enc_header_size);
+}
+
+void vidc_720p_enc_frame_info(struct vidc_720p_enc_frame_info
+ *enc_frame_info)
+{
+ VIDC_IO_IN(REG_782249, &enc_frame_info->enc_size);
+
+ VIDC_IO_IN(REG_441270, &enc_frame_info->frame);
+
+ enc_frame_info->frame &= 0x03;
+
+ VIDC_IO_IN(REG_613254,
+ &enc_frame_info->metadata_exists);
+}
+
+void vidc_720p_decode_bitstream_header(u32 ch_id,
+ u32 dec_unit_size,
+ u32 start_byte_num,
+ u32 ext_buffer_start,
+ u32 ext_buffer_end,
+ enum
+ vidc_720p_memory_access_method
+ memory_access_model,
+ u32 decode_order)
+{
+ VIDC_IO_OUT(REG_965480, decode_order);
+
+ VIDC_IO_OUT(REG_639999, 0x8080);
+
+ VIDC_IO_OUT(REG_275113_ADDR, ext_buffer_start);
+
+ VIDC_IO_OUT(REG_988007_ADDR, ext_buffer_end);
+
+ VIDC_IO_OUT(REG_87912, ext_buffer_end);
+
+ VIDC_IO_OUT(REG_761892, dec_unit_size);
+
+ VIDC_IO_OUT(REG_66693, start_byte_num);
+
+ VIDC_IO_OUT(REG_841539, memory_access_model);
+
+ vidc_720p_submit_command(ch_id, VIDC_720P_CMD_INITCODEC);
+}
+
+void vidc_720p_decode_get_seq_hdr_info(struct vidc_720p_seq_hdr_info
+ *seq_hdr_info)
+{
+ u32 display_status;
+ VIDC_IO_IN(REG_999267, &seq_hdr_info->img_size_x);
+
+ VIDC_IO_IN(REG_345712, &seq_hdr_info->img_size_y);
+
+ VIDC_IO_IN(REG_257463, &seq_hdr_info->min_num_dpb);
+
+ VIDC_IO_IN(REG_854281, &seq_hdr_info->min_dpb_size);
+
+ VIDC_IO_IN(REG_580603, &seq_hdr_info->dec_frm_size);
+
+ VIDC_IO_INF(REG_606447, DISP_PIC_PROFILE,
+ &seq_hdr_info->profile);
+
+ VIDC_IO_INF(REG_606447, DIS_PIC_LEVEL,
+ &seq_hdr_info->level);
+
+ VIDC_IO_INF(REG_612715, DISPLAY_STATUS,
+ &display_status);
+ seq_hdr_info->progressive =
+ ((display_status & 0x4) >> 2);
+ /* bit 3 is for crop existence */
+ seq_hdr_info->crop_exists = ((display_status & 0x8) >> 3);
+
+ if (seq_hdr_info->crop_exists) {
+ /* read the cropping information */
+ VIDC_IO_INF(REG_881638, CROP_RIGHT_OFFSET, \
+ &seq_hdr_info->crop_right_offset);
+ VIDC_IO_INF(REG_881638, CROP_LEFT_OFFSET, \
+ &seq_hdr_info->crop_left_offset);
+ VIDC_IO_INF(REG_161486, CROP_BOTTOM_OFFSET, \
+ &seq_hdr_info->crop_bottom_offset);
+ VIDC_IO_INF(REG_161486, CROP_TOP_OFFSET, \
+ &seq_hdr_info->crop_top_offset);
+ }
+ /* Read the MPEG4 data partitioning indication */
+ VIDC_IO_INF(REG_441270, DATA_PARTITIONED, \
+ &seq_hdr_info->data_partitioned);
+
+}
+
+void vidc_720p_decode_set_dpb_release_buffer_mask(u32
+ i_dpb_release_buffer_mask)
+{
+ VIDC_IO_OUT(REG_603032, i_dpb_release_buffer_mask);
+}
+
+void vidc_720p_decode_set_dpb_buffers(u32 i_buf_index, u32 *pi_dpb_buffer)
+{
+ VIDC_IO_OUTI(REG_615716, i_buf_index, pi_dpb_buffer);
+}
+
+void vidc_720p_decode_set_comv_buffer(u32 *pi_dpb_comv_buffer,
+ u32 alloc_len)
+{
+ VIDC_IO_OUT(REG_456376_ADDR, pi_dpb_comv_buffer);
+
+ VIDC_IO_OUT(REG_490443, alloc_len);
+}
+
+void vidc_720p_decode_set_dpb_details(u32 num_dpb, u32 alloc_len,
+ u32 *ref_buffer)
+{
+ VIDC_IO_OUT(REG_518133, ref_buffer);
+
+ VIDC_IO_OUT(REG_267567, 0);
+
+ VIDC_IO_OUT(REG_883500, num_dpb);
+
+ VIDC_IO_OUT(REG_319934, alloc_len);
+}
+
+void vidc_720p_decode_set_mpeg4Post_filter(u32 enable_post_filter)
+{
+ if (enable_post_filter)
+ VIDC_IO_OUT(REG_443811, 0x1);
+ else
+ VIDC_IO_OUT(REG_443811, 0x0);
+}
+
+void vidc_720p_decode_set_error_control(u32 enable_error_control)
+{
+ if (enable_error_control)
+ VIDC_IO_OUT(REG_846346, 0);
+ else
+ VIDC_IO_OUT(REG_846346, 1);
+}
+
+void vidc_720p_set_deblock_line_buffer(u32 *pi_deblock_line_buffer_start,
+ u32 alloc_len)
+{
+ VIDC_IO_OUT(REG_979942, pi_deblock_line_buffer_start);
+
+ VIDC_IO_OUT(REG_101184, alloc_len);
+}
+
+void vidc_720p_decode_set_mpeg4_data_partitionbuffer(u32 *vsp_buf_start)
+{
+ VIDC_IO_OUT(REG_958768, vsp_buf_start);
+}
+
+void vidc_720p_decode_setH264VSPBuffer(u32 *pi_vsp_temp_buffer_start)
+{
+ VIDC_IO_OUT(REG_958768, pi_vsp_temp_buffer_start);
+}
+
+void vidc_720p_decode_frame(u32 ch_id, u32 ext_buffer_start,
+ u32 ext_buffer_end, u32 dec_unit_size,
+ u32 start_byte_num, u32 input_frame_tag)
+{
+ VIDC_IO_OUT(REG_275113_ADDR, ext_buffer_start);
+
+ VIDC_IO_OUT(REG_988007_ADDR, ext_buffer_end);
+
+ VIDC_IO_OUT(REG_87912, ext_buffer_end);
+
+ VIDC_IO_OUT(REG_66693, start_byte_num);
+
+ VIDC_IO_OUT(REG_94750, input_frame_tag);
+
+ VIDC_IO_OUT(REG_761892, dec_unit_size);
+
+ vidc_720p_submit_command(ch_id, VIDC_720P_CMD_FRAMERUN);
+}
+
+void vidc_720p_issue_eos(u32 i_ch_id)
+{
+ VIDC_IO_OUT(REG_896825, 0x1);
+
+ VIDC_IO_OUT(REG_761892, 0);
+
+ vidc_720p_submit_command(i_ch_id, VIDC_720P_CMD_FRAMERUN);
+}
+
+void vidc_720p_eos_info(u32 *disp_status, u32 *resl_change)
+{
+ VIDC_IO_INF(REG_612715, DISPLAY_STATUS, disp_status);
+ (*disp_status) = (*disp_status) & 0x3;
+ VIDC_IO_INF(REG_724381, RESOLUTION_CHANGE, resl_change);
+}
+
+void vidc_720p_decode_display_info(struct vidc_720p_dec_disp_info
+ *disp_info)
+{
+ u32 display_status = 0;
+ VIDC_IO_INF(REG_612715, DISPLAY_STATUS, &display_status);
+
+ disp_info->disp_status =
+ (enum vidc_720p_display_status)((display_status & 0x3));
+
+ disp_info->disp_is_interlace = ((display_status & 0x4) >> 2);
+ disp_info->crop_exists = ((display_status & 0x8) >> 3);
+
+ disp_info->resl_change = ((display_status & 0x30) >> 4);
+
+ VIDC_IO_INF(REG_724381, RESOLUTION_CHANGE,
+ &disp_info->reconfig_flush_done);
+
+ VIDC_IO_IN(REG_999267, &disp_info->img_size_x);
+
+ VIDC_IO_IN(REG_345712, &disp_info->img_size_y);
+ VIDC_IO_IN(REG_151345, &disp_info->y_addr);
+ VIDC_IO_IN(REG_293983, &disp_info->c_addr);
+ VIDC_IO_IN(REG_370409, &disp_info->tag_top);
+ VIDC_IO_IN(REG_438677, &disp_info->tag_bottom);
+ VIDC_IO_IN(REG_679165, &disp_info->pic_time_top);
+ VIDC_IO_IN(REG_374150, &disp_info->pic_time_bottom);
+
+ if (disp_info->crop_exists) {
+ VIDC_IO_INF(REG_881638, CROP_RIGHT_OFFSET,
+ &disp_info->crop_right_offset);
+ VIDC_IO_INF(REG_881638, CROP_LEFT_OFFSET,
+ &disp_info->crop_left_offset);
+ VIDC_IO_INF(REG_161486, CROP_BOTTOM_OFFSET,
+ &disp_info->crop_bottom_offset);
+ VIDC_IO_INF(REG_161486, CROP_TOP_OFFSET,
+ &disp_info->crop_top_offset);
+ }
+ VIDC_IO_IN(REG_613254, &disp_info->metadata_exists);
+
+ VIDC_IO_IN(REG_580603,
+ &disp_info->input_bytes_consumed);
+
+ VIDC_IO_IN(REG_757835, &disp_info->input_frame_num);
+
+ VIDC_IO_INF(REG_441270, FRAME_TYPE,
+ &disp_info->input_frame);
+
+ disp_info->input_is_interlace =
+ ((disp_info->input_frame & 0x4) >> 2);
+
+ disp_info->input_frame &= 0x3;
+}
+
+void vidc_720p_decode_skip_frm_details(u32 *free_luma_dpb)
+{
+ u32 disp_frm;
+ VIDC_IO_IN(REG_697961, &disp_frm);
+
+ if (disp_frm == VIDC_720P_NOTCODED)
+ VIDC_IO_IN(REG_347105, free_luma_dpb);
+}
+
+void vidc_720p_metadata_enable(u32 flag, u32 *input_buffer)
+{
+ VIDC_IO_OUT(REG_854681, flag);
+ VIDC_IO_OUT(REG_988552, input_buffer);
+}
+
+void vidc_720p_decode_dynamic_req_reset(void)
+{
+ VIDC_IO_OUT(REG_76706, 0x0);
+ VIDC_IO_OUT(REG_147682, 0x0);
+ VIDC_IO_OUT(REG_896825, 0x0);
+}
+
+void vidc_720p_decode_dynamic_req_set(u32 property)
+{
+ if (property == VIDC_720P_FLUSH_REQ)
+ VIDC_IO_OUT(REG_76706, 0x1);
+ else if (property == VIDC_720P_EXTRADATA)
+ VIDC_IO_OUT(REG_147682, 0x1);
+}
+
+void vidc_720p_decode_setpassthrough_start(u32 pass_startaddr)
+{
+ VIDC_IO_OUT(REG_486169, pass_startaddr);
+}
diff --git a/drivers/video/msm/vidc/720p/ddl/vidc.h b/drivers/video/msm/vidc/720p/ddl/vidc.h
new file mode 100644
index 0000000..685b7cc
--- /dev/null
+++ b/drivers/video/msm/vidc/720p/ddl/vidc.h
@@ -0,0 +1,2704 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef VIDC_H
+#define VIDC_H
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <asm/system.h>
+
+#define VIDC_720P_IN(reg) VIDC_##reg##_IN
+#define VIDC_720P_INM(reg, mask) VIDC_##reg##_INM(mask)
+#define VIDC_720P_OUT(reg, val) VIDC_##reg##_OUT(val)
+#define VIDC_720P_OUTI(reg, index, val) VIDC_##reg##_OUTI(index, val)
+#define VIDC_720P_OUTM(reg, mask, val) VIDC_##reg##_OUTM(mask, val)
+#define VIDC_720P_SHFT(reg, field) VIDC_##reg##_##field##_SHFT
+#define VIDC_720P_FMSK(reg, field) VIDC_##reg##_##field##_BMSK
+
+#define VIDC_720P_INF(io, field) (VIDC_720P_INM(io, VIDC_720P_FMSK(io, field)) \
+ >> VIDC_720P_SHFT(io, field))
+#define VIDC_720P_OUTF(io, field, val) \
+ VIDC_720P_OUTM(io, VIDC_720P_FMSK(io, field), \
+ val << VIDC_720P_SHFT(io, field))
+
+#define __inpdw(port) ioread32(port)
+#define __outpdw(port, val) iowrite32(val, port)
+
+#define in_dword_masked(addr, mask) (__inpdw(addr) & (mask))
+
+#define out_dword(addr, val) __outpdw(addr, val)
+
+#define out_dword_masked(io, mask, val, shadow) \
+do { \
+ shadow = (shadow & (u32)(~(mask))) | ((u32)((val) & (mask))); \
+ (void) out_dword(io, shadow); \
+} while (0)
+
+#define out_dword_masked_ns(io, mask, val, current_reg_content) \
+ (void) out_dword(io, ((current_reg_content & (u32)(~(mask))) | \
+ ((u32)((val) & (mask)))))
+
+extern u8 *vidc_base_addr;
+
+#define VIDC720P_BASE vidc_base_addr
+#define VIDC_720P_WRAPPER_REG_BASE (VIDC720P_BASE + \
+ 0x00000000)
+#define VIDC_720P_WRAPPER_REG_BASE_PHYS VIDC_720P_BASE_PHYS
+
+#define VIDC_REG_614413_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 00000000)
+#define VIDC_REG_614413_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 00000000)
+#define VIDC_REG_614413_RMSK 0x1
+#define VIDC_REG_614413_SHFT 0
+#define VIDC_REG_614413_IN \
+ in_dword_masked(VIDC_REG_614413_ADDR, \
+ VIDC_REG_614413_RMSK)
+#define VIDC_REG_614413_INM(m) \
+ in_dword_masked(VIDC_REG_614413_ADDR, m)
+#define VIDC_REG_614413_OUT(v) \
+ out_dword(VIDC_REG_614413_ADDR, v)
+#define VIDC_REG_614413_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_614413_ADDR, m, v, \
+ VIDC_REG_614413_IN); \
+} while (0)
+#define VIDC_REG_614413_DMA_START_BMSK 0x1
+#define VIDC_REG_614413_DMA_START_SHFT 0
+
+#define VIDC_REG_591577_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x0000000c)
+#define VIDC_REG_591577_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x0000000c)
+#define VIDC_REG_591577_RMSK 0xffffffff
+#define VIDC_REG_591577_SHFT 0
+#define VIDC_REG_591577_IN \
+ in_dword_masked(VIDC_REG_591577_ADDR, \
+ VIDC_REG_591577_RMSK)
+#define VIDC_REG_591577_INM(m) \
+ in_dword_masked(VIDC_REG_591577_ADDR, m)
+#define VIDC_REG_591577_OUT(v) \
+ out_dword(VIDC_REG_591577_ADDR, v)
+#define VIDC_REG_591577_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_591577_ADDR, m, v, \
+ VIDC_REG_591577_IN); \
+} while (0)
+#define VIDC_REG_591577_BOOTCODE_SIZE_BMSK 0xffffffff
+#define VIDC_REG_591577_BOOTCODE_SIZE_SHFT 0
+
+#define VIDC_REG_203921_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000014)
+#define VIDC_REG_203921_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000014)
+#define VIDC_REG_203921_RMSK 0xffffffff
+#define VIDC_REG_203921_SHFT 0
+#define VIDC_REG_203921_IN \
+ in_dword_masked(VIDC_REG_203921_ADDR, \
+ VIDC_REG_203921_RMSK)
+#define VIDC_REG_203921_INM(m) \
+ in_dword_masked(VIDC_REG_203921_ADDR, m)
+#define VIDC_REG_203921_OUT(v) \
+ out_dword(VIDC_REG_203921_ADDR, v)
+#define VIDC_REG_203921_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_203921_ADDR, m, v, \
+ VIDC_REG_203921_IN); \
+} while (0)
+#define VIDC_REG_203921_DMA_EXTADDR_BMSK 0xffffffff
+#define VIDC_REG_203921_DMA_EXTADDR_SHFT 0
+
+#define VIDC_REG_275113_ADDR_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000018)
+#define VIDC_REG_275113_ADDR_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000018)
+#define VIDC_REG_275113_ADDR_RMSK 0xffffffff
+#define VIDC_REG_275113_ADDR_SHFT 0
+#define VIDC_REG_275113_ADDR_IN \
+ in_dword_masked(VIDC_REG_275113_ADDR_ADDR, \
+ VIDC_REG_275113_ADDR_RMSK)
+#define VIDC_REG_275113_ADDR_INM(m) \
+ in_dword_masked(VIDC_REG_275113_ADDR_ADDR, m)
+#define VIDC_REG_275113_ADDR_OUT(v) \
+ out_dword(VIDC_REG_275113_ADDR_ADDR, v)
+#define VIDC_REG_275113_ADDR_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_275113_ADDR_ADDR, m, v, \
+ VIDC_REG_275113_ADDR_IN); \
+} while (0)
+#define VIDC_REG_742076_ADDR_BMSK 0xffffffff
+#define VIDC_REG_742076_ADDR_SHFT 0
+
+#define VIDC_REG_988007_ADDR_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x0000001c)
+#define VIDC_REG_988007_ADDR_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x0000001c)
+#define VIDC_REG_988007_ADDR_RMSK 0xffffffff
+#define VIDC_REG_988007_ADDR_SHFT 0
+#define VIDC_REG_988007_ADDR_IN \
+ in_dword_masked(VIDC_REG_988007_ADDR_ADDR, \
+ VIDC_REG_988007_ADDR_RMSK)
+#define VIDC_REG_988007_ADDR_INM(m) \
+ in_dword_masked(VIDC_REG_988007_ADDR_ADDR, m)
+#define VIDC_REG_988007_ADDR_OUT(v) \
+ out_dword(VIDC_REG_988007_ADDR_ADDR, v)
+#define VIDC_REG_988007_ADDR_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_988007_ADDR_ADDR, m, v, \
+ VIDC_REG_988007_ADDR_IN); \
+} while (0)
+#define VIDC_REG_988007_ADDR_EXT_BUF_END_ADDR_BMSK 0xffffffff
+#define VIDC_REG_988007_ADDR_EXT_BUF_END_ADDR_SHFT 0
+
+#define VIDC_REG_531515_ADDR_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000020)
+#define VIDC_REG_531515_ADDR_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000020)
+#define VIDC_REG_531515_ADDR_RMSK 0xffffffff
+#define VIDC_REG_531515_ADDR_SHFT 0
+#define VIDC_REG_531515_ADDR_IN \
+ in_dword_masked(VIDC_REG_531515_ADDR_ADDR, \
+ VIDC_REG_531515_ADDR_RMSK)
+#define VIDC_REG_531515_ADDR_INM(m) \
+ in_dword_masked(VIDC_REG_531515_ADDR_ADDR, m)
+#define VIDC_REG_531515_ADDR_OUT(v) \
+ out_dword(VIDC_REG_531515_ADDR_ADDR, v)
+#define VIDC_REG_531515_ADDR_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_531515_ADDR_ADDR, m, v, \
+ VIDC_REG_531515_ADDR_IN); \
+} while (0)
+#define VIDC_REG_531515_ADDR_DMA_INT_ADDR_BMSK 0xffffffff
+#define VIDC_REG_531515_ADDR_DMA_INT_ADDR_SHFT 0
+
+#define VIDC_REG_87912_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000024)
+#define VIDC_REG_87912_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000024)
+#define VIDC_REG_87912_RMSK 0xffffffff
+#define VIDC_REG_87912_SHFT 0
+#define VIDC_REG_87912_IN \
+ in_dword_masked(VIDC_REG_87912_ADDR, \
+ VIDC_REG_87912_RMSK)
+#define VIDC_REG_87912_INM(m) \
+ in_dword_masked(VIDC_REG_87912_ADDR, m)
+#define VIDC_REG_87912_OUT(v) \
+ out_dword(VIDC_REG_87912_ADDR, v)
+#define VIDC_REG_87912_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_87912_ADDR, m, v, \
+ VIDC_REG_87912_IN); \
+} while (0)
+#define VIDC_REG_87912_HOST_PTR_ADDR_BMSK 0xffffffff
+#define VIDC_REG_87912_HOST_PTR_ADDR_SHFT 0
+
+#define VIDC_REG_896825_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000028)
+#define VIDC_REG_896825_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000028)
+#define VIDC_REG_896825_RMSK 0x1
+#define VIDC_REG_896825_SHFT 0
+#define VIDC_REG_896825_IN \
+ in_dword_masked(VIDC_REG_896825_ADDR, \
+ VIDC_REG_896825_RMSK)
+#define VIDC_REG_896825_INM(m) \
+ in_dword_masked(VIDC_REG_896825_ADDR, m)
+#define VIDC_REG_896825_OUT(v) \
+ out_dword(VIDC_REG_896825_ADDR, v)
+#define VIDC_REG_896825_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_896825_ADDR, m, v, \
+ VIDC_REG_896825_IN); \
+} while (0)
+#define VIDC_REG_896825_LAST_DEC_BMSK 0x1
+#define VIDC_REG_896825_LAST_DEC_SHFT 0
+
+#define VIDC_REG_174526_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x0000002c)
+#define VIDC_REG_174526_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x0000002c)
+#define VIDC_REG_174526_RMSK 0x1
+#define VIDC_REG_174526_SHFT 0
+#define VIDC_REG_174526_IN \
+ in_dword_masked(VIDC_REG_174526_ADDR, VIDC_REG_174526_RMSK)
+#define VIDC_REG_174526_INM(m) \
+ in_dword_masked(VIDC_REG_174526_ADDR, m)
+#define VIDC_REG_174526_DONE_M_BMSK 0x1
+#define VIDC_REG_174526_DONE_M_SHFT 0
+
+#define VIDC_REG_736316_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000044)
+#define VIDC_REG_736316_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000044)
+#define VIDC_REG_736316_RMSK 0x1
+#define VIDC_REG_736316_SHFT 0
+#define VIDC_REG_736316_IN \
+ in_dword_masked(VIDC_REG_736316_ADDR, \
+ VIDC_REG_736316_RMSK)
+#define VIDC_REG_736316_INM(m) \
+ in_dword_masked(VIDC_REG_736316_ADDR, m)
+#define VIDC_REG_736316_OUT(v) \
+ out_dword(VIDC_REG_736316_ADDR, v)
+#define VIDC_REG_736316_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_736316_ADDR, m, v, \
+ VIDC_REG_736316_IN); \
+} while (0)
+#define VIDC_REG_736316_BITS_ENDIAN_BMSK 0x1
+#define VIDC_REG_736316_BITS_ENDIAN_SHFT 0
+
+#define VIDC_REG_761892_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000054)
+#define VIDC_REG_761892_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000054)
+#define VIDC_REG_761892_RMSK 0xffffffff
+#define VIDC_REG_761892_SHFT 0
+#define VIDC_REG_761892_IN \
+ in_dword_masked(VIDC_REG_761892_ADDR, \
+ VIDC_REG_761892_RMSK)
+#define VIDC_REG_761892_INM(m) \
+ in_dword_masked(VIDC_REG_761892_ADDR, m)
+#define VIDC_REG_761892_OUT(v) \
+ out_dword(VIDC_REG_761892_ADDR, v)
+#define VIDC_REG_761892_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_761892_ADDR, m, v, \
+ VIDC_REG_761892_IN); \
+} while (0)
+#define VIDC_REG_761892_DEC_UNIT_SIZE_BMSK 0xffffffff
+#define VIDC_REG_761892_DEC_UNIT_SIZE_SHFT 0
+
+#define VIDC_REG_782249_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000058)
+#define VIDC_REG_782249_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000058)
+#define VIDC_REG_782249_RMSK 0xffffffff
+#define VIDC_REG_782249_SHFT 0
+#define VIDC_REG_782249_IN \
+ in_dword_masked(VIDC_REG_782249_ADDR, \
+ VIDC_REG_782249_RMSK)
+#define VIDC_REG_782249_INM(m) \
+ in_dword_masked(VIDC_REG_782249_ADDR, m)
+#define VIDC_REG_782249_ENC_UNIT_SIZE_BMSK 0xffffffff
+#define VIDC_REG_782249_ENC_UNIT_SIZE_SHFT 0
+
+#define VIDC_REG_66693_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x0000005c)
+#define VIDC_REG_66693_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x0000005c)
+#define VIDC_REG_66693_RMSK 0xf
+#define VIDC_REG_66693_SHFT 0
+#define VIDC_REG_66693_IN \
+ in_dword_masked(VIDC_REG_66693_ADDR, \
+ VIDC_REG_66693_RMSK)
+#define VIDC_REG_66693_INM(m) \
+ in_dword_masked(VIDC_REG_66693_ADDR, m)
+#define VIDC_REG_66693_OUT(v) \
+ out_dword(VIDC_REG_66693_ADDR, v)
+#define VIDC_REG_66693_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_66693_ADDR, m, v, \
+ VIDC_REG_66693_IN); \
+} while (0)
+#define VIDC_REG_66693_START_BYTE_NUM_BMSK 0xf
+#define VIDC_REG_66693_START_BYTE_NUM_SHFT 0
+
+#define VIDC_REG_114286_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000060)
+#define VIDC_REG_114286_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000060)
+#define VIDC_REG_114286_RMSK 0xffffffff
+#define VIDC_REG_114286_SHFT 0
+#define VIDC_REG_114286_IN \
+ in_dword_masked(VIDC_REG_114286_ADDR, \
+ VIDC_REG_114286_RMSK)
+#define VIDC_REG_114286_INM(m) \
+ in_dword_masked(VIDC_REG_114286_ADDR, m)
+#define VIDC_REG_114286_ENC_HEADER_SIZE_BMSK 0xffffffff
+#define VIDC_REG_114286_ENC_HEADER_SIZE_SHFT 0
+
+#define VIDC_REG_713080_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000100)
+#define VIDC_REG_713080_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000100)
+#define VIDC_REG_713080_RMSK 0x1f
+#define VIDC_REG_713080_SHFT 0
+#define VIDC_REG_713080_IN \
+ in_dword_masked(VIDC_REG_713080_ADDR, \
+ VIDC_REG_713080_RMSK)
+#define VIDC_REG_713080_INM(m) \
+ in_dword_masked(VIDC_REG_713080_ADDR, m)
+#define VIDC_REG_713080_OUT(v) \
+ out_dword(VIDC_REG_713080_ADDR, v)
+#define VIDC_REG_713080_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_713080_ADDR, m, v, \
+ VIDC_REG_713080_IN); \
+} while (0)
+#define VIDC_REG_713080_ENC_ON_BMSK 0x10
+#define VIDC_REG_713080_ENC_ON_SHFT 0x4
+#define VIDC_REG_713080_STANDARD_SEL_BMSK 0xf
+#define VIDC_REG_713080_STANDARD_SEL_SHFT 0
+
+#define VIDC_REG_97293_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000104)
+#define VIDC_REG_97293_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000104)
+#define VIDC_REG_97293_RMSK 0x1f
+#define VIDC_REG_97293_SHFT 0
+#define VIDC_REG_97293_IN \
+ in_dword_masked(VIDC_REG_97293_ADDR, VIDC_REG_97293_RMSK)
+#define VIDC_REG_97293_INM(m) \
+ in_dword_masked(VIDC_REG_97293_ADDR, m)
+#define VIDC_REG_97293_OUT(v) \
+ out_dword(VIDC_REG_97293_ADDR, v)
+#define VIDC_REG_97293_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_97293_ADDR, m, v, \
+ VIDC_REG_97293_IN); \
+} while (0)
+#define VIDC_REG_97293_CH_ID_BMSK 0x1f
+#define VIDC_REG_97293_CH_ID_SHFT 0
+
+#define VIDC_REG_224135_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000108)
+#define VIDC_REG_224135_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000108)
+#define VIDC_REG_224135_RMSK 0x1
+#define VIDC_REG_224135_SHFT 0
+#define VIDC_REG_224135_IN \
+ in_dword_masked(VIDC_REG_224135_ADDR, \
+ VIDC_REG_224135_RMSK)
+#define VIDC_REG_224135_INM(m) \
+ in_dword_masked(VIDC_REG_224135_ADDR, m)
+#define VIDC_REG_224135_OUT(v) \
+ out_dword(VIDC_REG_224135_ADDR, v)
+#define VIDC_REG_224135_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_224135_ADDR, m, v, \
+ VIDC_REG_224135_IN); \
+} while (0)
+#define VIDC_REG_224135_CPU_RESET_BMSK 0x1
+#define VIDC_REG_224135_CPU_RESET_SHFT 0
+
+#define VIDC_REG_832522_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x0000010c)
+#define VIDC_REG_832522_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x0000010c)
+#define VIDC_REG_832522_RMSK 0x1
+#define VIDC_REG_832522_SHFT 0
+#define VIDC_REG_832522_IN \
+ in_dword_masked(VIDC_REG_832522_ADDR, VIDC_REG_832522_RMSK)
+#define VIDC_REG_832522_INM(m) \
+ in_dword_masked(VIDC_REG_832522_ADDR, m)
+#define VIDC_REG_832522_OUT(v) \
+ out_dword(VIDC_REG_832522_ADDR, v)
+#define VIDC_REG_832522_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_832522_ADDR, m, v, \
+ VIDC_REG_832522_IN); \
+} while (0)
+#define VIDC_REG_832522_FW_END_BMSK 0x1
+#define VIDC_REG_832522_FW_END_SHFT 0
+
+#define VIDC_REG_361582_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000110)
+#define VIDC_REG_361582_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000110)
+#define VIDC_REG_361582_RMSK 0x1
+#define VIDC_REG_361582_SHFT 0
+#define VIDC_REG_361582_IN \
+ in_dword_masked(VIDC_REG_361582_ADDR, \
+ VIDC_REG_361582_RMSK)
+#define VIDC_REG_361582_INM(m) \
+ in_dword_masked(VIDC_REG_361582_ADDR, m)
+#define VIDC_REG_361582_OUT(v) \
+ out_dword(VIDC_REG_361582_ADDR, v)
+#define VIDC_REG_361582_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_361582_ADDR, m, v, \
+ VIDC_REG_361582_IN); \
+} while (0)
+#define VIDC_REG_361582_BUS_MASTER_BMSK 0x1
+#define VIDC_REG_361582_BUS_MASTER_SHFT 0
+
+#define VIDC_REG_314435_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000114)
+#define VIDC_REG_314435_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000114)
+#define VIDC_REG_314435_RMSK 0x1
+#define VIDC_REG_314435_SHFT 0
+#define VIDC_REG_314435_IN \
+ in_dword_masked(VIDC_REG_314435_ADDR, \
+ VIDC_REG_314435_RMSK)
+#define VIDC_REG_314435_INM(m) \
+ in_dword_masked(VIDC_REG_314435_ADDR, m)
+#define VIDC_REG_314435_OUT(v) \
+ out_dword(VIDC_REG_314435_ADDR, v)
+#define VIDC_REG_314435_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_314435_ADDR, m, v, \
+ VIDC_REG_314435_IN); \
+} while (0)
+#define VIDC_REG_314435_FRAME_START_BMSK 0x1
+#define VIDC_REG_314435_FRAME_START_SHFT 0
+
+#define VIDC_REG_999267_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000118)
+#define VIDC_REG_999267_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000118)
+#define VIDC_REG_999267_RMSK 0xffff
+#define VIDC_REG_999267_SHFT 0
+#define VIDC_REG_999267_IN \
+ in_dword_masked(VIDC_REG_999267_ADDR, \
+ VIDC_REG_999267_RMSK)
+#define VIDC_REG_999267_INM(m) \
+ in_dword_masked(VIDC_REG_999267_ADDR, m)
+#define VIDC_REG_999267_OUT(v) \
+ out_dword(VIDC_REG_999267_ADDR, v)
+#define VIDC_REG_999267_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_999267_ADDR, m, v, \
+ VIDC_REG_999267_IN); \
+} while (0)
+#define VIDC_REG_999267_IMG_SIZE_X_BMSK 0xffff
+#define VIDC_REG_999267_IMG_SIZE_X_SHFT 0
+
+#define VIDC_REG_345712_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x0000011c)
+#define VIDC_REG_345712_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x0000011c)
+#define VIDC_REG_345712_RMSK 0xffff
+#define VIDC_REG_345712_SHFT 0
+#define VIDC_REG_345712_IN \
+ in_dword_masked(VIDC_REG_345712_ADDR, \
+ VIDC_REG_345712_RMSK)
+#define VIDC_REG_345712_INM(m) \
+ in_dword_masked(VIDC_REG_345712_ADDR, m)
+#define VIDC_REG_345712_OUT(v) \
+ out_dword(VIDC_REG_345712_ADDR, v)
+#define VIDC_REG_345712_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_345712_ADDR, m, v, \
+ VIDC_REG_345712_IN); \
+} while (0)
+#define VIDC_REG_345712_IMG_SIZE_Y_BMSK 0xffff
+#define VIDC_REG_345712_IMG_SIZE_Y_SHFT 0
+
+#define VIDC_REG_443811_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000124)
+#define VIDC_REG_443811_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000124)
+#define VIDC_REG_443811_RMSK 0x1
+#define VIDC_REG_443811_SHFT 0
+#define VIDC_REG_443811_IN \
+ in_dword_masked(VIDC_REG_443811_ADDR, VIDC_REG_443811_RMSK)
+#define VIDC_REG_443811_INM(m) \
+ in_dword_masked(VIDC_REG_443811_ADDR, m)
+#define VIDC_REG_443811_OUT(v) \
+ out_dword(VIDC_REG_443811_ADDR, v)
+#define VIDC_REG_443811_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_443811_ADDR, m, v, \
+ VIDC_REG_443811_IN); \
+} while (0)
+#define VIDC_REG_443811_POST_ON_BMSK 0x1
+#define VIDC_REG_443811_POST_ON_SHFT 0
+
+#define VIDC_REG_538267_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000128)
+#define VIDC_REG_538267_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000128)
+#define VIDC_REG_538267_RMSK 0xffffffff
+#define VIDC_REG_538267_SHFT 0
+#define VIDC_REG_538267_IN \
+ in_dword_masked(VIDC_REG_538267_ADDR, \
+ VIDC_REG_538267_RMSK)
+#define VIDC_REG_538267_INM(m) \
+ in_dword_masked(VIDC_REG_538267_ADDR, m)
+#define VIDC_REG_538267_OUT(v) \
+ out_dword(VIDC_REG_538267_ADDR, v)
+#define VIDC_REG_538267_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_538267_ADDR, m, v, \
+ VIDC_REG_538267_IN); \
+} while (0)
+#define VIDC_REG_538267_QUOTIENT_VAL_BMSK 0xffff0000
+#define VIDC_REG_538267_QUOTIENT_VAL_SHFT 0x10
+#define VIDC_REG_538267_REMAINDER_VAL_BMSK 0xffff
+#define VIDC_REG_538267_REMAINDER_VAL_SHFT 0
+
+#define VIDC_REG_661565_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x0000012c)
+#define VIDC_REG_661565_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x0000012c)
+#define VIDC_REG_661565_RMSK 0x1
+#define VIDC_REG_661565_SHFT 0
+#define VIDC_REG_661565_IN \
+ in_dword_masked(VIDC_REG_661565_ADDR, \
+ VIDC_REG_661565_RMSK)
+#define VIDC_REG_661565_INM(m) \
+ in_dword_masked(VIDC_REG_661565_ADDR, m)
+#define VIDC_REG_661565_OUT(v) \
+ out_dword(VIDC_REG_661565_ADDR, v)
+#define VIDC_REG_661565_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_661565_ADDR, m, v, \
+ VIDC_REG_661565_IN); \
+} while (0)
+#define VIDC_REG_661565_SEQUENCE_START_BMSK 0x1
+#define VIDC_REG_661565_SEQUENCE_START_SHFT 0
+
+#define VIDC_REG_141269_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000130)
+#define VIDC_REG_141269_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000130)
+#define VIDC_REG_141269_RMSK 0x1
+#define VIDC_REG_141269_SHFT 0
+#define VIDC_REG_141269_IN \
+ in_dword_masked(VIDC_REG_141269_ADDR, \
+ VIDC_REG_141269_RMSK)
+#define VIDC_REG_141269_INM(m) \
+ in_dword_masked(VIDC_REG_141269_ADDR, m)
+#define VIDC_REG_141269_OUT(v) \
+ out_dword(VIDC_REG_141269_ADDR, v)
+#define VIDC_REG_141269_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_141269_ADDR, m, v, \
+ VIDC_REG_141269_IN); \
+} while (0)
+#define VIDC_REG_141269_SW_RESET_BMSK 0x1
+#define VIDC_REG_141269_SW_RESET_SHFT 0
+
+#define VIDC_REG_193553_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000134)
+#define VIDC_REG_193553_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000134)
+#define VIDC_REG_193553_RMSK 0x1
+#define VIDC_REG_193553_SHFT 0
+#define VIDC_REG_193553_IN \
+ in_dword_masked(VIDC_REG_193553_ADDR, \
+ VIDC_REG_193553_RMSK)
+#define VIDC_REG_193553_INM(m) \
+ in_dword_masked(VIDC_REG_193553_ADDR, m)
+#define VIDC_REG_193553_OUT(v) \
+ out_dword(VIDC_REG_193553_ADDR, v)
+#define VIDC_REG_193553_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_193553_ADDR, m, v, \
+ VIDC_REG_193553_IN); \
+} while (0)
+#define VIDC_REG_193553_FW_START_BMSK 0x1
+#define VIDC_REG_193553_FW_START_SHFT 0
+
+#define VIDC_REG_215724_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000138)
+#define VIDC_REG_215724_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000138)
+#define VIDC_REG_215724_RMSK 0x1
+#define VIDC_REG_215724_SHFT 0
+#define VIDC_REG_215724_IN \
+ in_dword_masked(VIDC_REG_215724_ADDR, \
+ VIDC_REG_215724_RMSK)
+#define VIDC_REG_215724_INM(m) \
+ in_dword_masked(VIDC_REG_215724_ADDR, m)
+#define VIDC_REG_215724_OUT(v) \
+ out_dword(VIDC_REG_215724_ADDR, v)
+#define VIDC_REG_215724_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_215724_ADDR, m, v, \
+ VIDC_REG_215724_IN); \
+} while (0)
+#define VIDC_REG_215724_ARM_ENDIAN_BMSK 0x1
+#define VIDC_REG_215724_ARM_ENDIAN_SHFT 0
+
+#define VIDC_REG_846346_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x0000013c)
+#define VIDC_REG_846346_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x0000013c)
+#define VIDC_REG_846346_RMSK 0x1
+#define VIDC_REG_846346_SHFT 0
+#define VIDC_REG_846346_IN \
+ in_dword_masked(VIDC_REG_846346_ADDR, \
+ VIDC_REG_846346_RMSK)
+#define VIDC_REG_846346_INM(m) \
+ in_dword_masked(VIDC_REG_846346_ADDR, m)
+#define VIDC_REG_846346_OUT(v) \
+ out_dword(VIDC_REG_846346_ADDR, v)
+#define VIDC_REG_846346_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_846346_ADDR, m, v, \
+ VIDC_REG_846346_IN); \
+} while (0)
+#define VIDC_REG_846346_ERR_CTRL_BMSK 0x1
+#define VIDC_REG_846346_ERR_CTRL_SHFT 0
+
+#define VIDC_REG_765787_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000200)
+#define VIDC_REG_765787_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000200)
+#define VIDC_REG_765787_RMSK 0xffffffff
+#define VIDC_REG_765787_SHFT 0
+#define VIDC_REG_765787_IN \
+ in_dword_masked(VIDC_REG_765787_ADDR, \
+ VIDC_REG_765787_RMSK)
+#define VIDC_REG_765787_INM(m) \
+ in_dword_masked(VIDC_REG_765787_ADDR, m)
+#define VIDC_REG_765787_OUT(v) \
+ out_dword(VIDC_REG_765787_ADDR, v)
+#define VIDC_REG_765787_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_765787_ADDR, m, v, \
+ VIDC_REG_765787_IN); \
+} while (0)
+#define VIDC_REG_765787_FW_STT_ADDR_0_BMSK 0xffffffff
+#define VIDC_REG_765787_FW_STT_ADDR_0_SHFT 0
+
+#define VIDC_REG_225040_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000204)
+#define VIDC_REG_225040_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000204)
+#define VIDC_REG_225040_RMSK 0xffffffff
+#define VIDC_REG_225040_SHFT 0
+#define VIDC_REG_225040_IN \
+ in_dword_masked(VIDC_REG_225040_ADDR, \
+ VIDC_REG_225040_RMSK)
+#define VIDC_REG_225040_INM(m) \
+ in_dword_masked(VIDC_REG_225040_ADDR, m)
+#define VIDC_REG_225040_OUT(v) \
+ out_dword(VIDC_REG_225040_ADDR, v)
+#define VIDC_REG_225040_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_225040_ADDR, m, v, \
+ VIDC_REG_225040_IN); \
+} while (0)
+#define VIDC_REG_225040_FW_STT_ADDR_1_BMSK 0xffffffff
+#define VIDC_REG_225040_FW_STT_ADDR_1_SHFT 0
+
+#define VIDC_REG_942456_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000208)
+#define VIDC_REG_942456_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000208)
+#define VIDC_REG_942456_RMSK 0xffffffff
+#define VIDC_REG_942456_SHFT 0
+#define VIDC_REG_942456_IN \
+ in_dword_masked(VIDC_REG_942456_ADDR, \
+ VIDC_REG_942456_RMSK)
+#define VIDC_REG_942456_INM(m) \
+ in_dword_masked(VIDC_REG_942456_ADDR, m)
+#define VIDC_REG_942456_OUT(v) \
+ out_dword(VIDC_REG_942456_ADDR, v)
+#define VIDC_REG_942456_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_942456_ADDR, m, v, \
+ VIDC_REG_942456_IN); \
+} while (0)
+#define VIDC_REG_942456_FW_STT_ADDR_2_BMSK 0xffffffff
+#define VIDC_REG_942456_FW_STT_ADDR_2_SHFT 0
+
+#define VIDC_REG_942170_ADDR_3_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x0000020c)
+#define VIDC_REG_942170_ADDR_3_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x0000020c)
+#define VIDC_REG_942170_ADDR_3_RMSK 0xffffffff
+#define VIDC_REG_942170_ADDR_3_SHFT 0
+#define VIDC_REG_942170_ADDR_3_IN \
+ in_dword_masked(VIDC_REG_942170_ADDR_3_ADDR, \
+ VIDC_REG_942170_ADDR_3_RMSK)
+#define VIDC_REG_942170_ADDR_3_INM(m) \
+ in_dword_masked(VIDC_REG_942170_ADDR_3_ADDR, m)
+#define VIDC_REG_942170_ADDR_3_OUT(v) \
+ out_dword(VIDC_REG_942170_ADDR_3_ADDR, v)
+#define VIDC_REG_942170_ADDR_3_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_942170_ADDR_3_ADDR, m, v, \
+ VIDC_REG_942170_ADDR_3_IN); \
+} while (0)
+#define VIDC_REG_942170_ADDR_3_FW_STT_ADDR_3_BMSK 0xffffffff
+#define VIDC_REG_942170_ADDR_3_FW_STT_ADDR_3_SHFT 0
+
+#define VIDC_REG_880188_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000210)
+#define VIDC_REG_880188_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000210)
+#define VIDC_REG_880188_RMSK 0xffffffff
+#define VIDC_REG_880188_SHFT 0
+#define VIDC_REG_880188_IN \
+ in_dword_masked(VIDC_REG_880188_ADDR, \
+ VIDC_REG_880188_RMSK)
+#define VIDC_REG_880188_INM(m) \
+ in_dword_masked(VIDC_REG_880188_ADDR, m)
+#define VIDC_REG_880188_OUT(v) \
+ out_dword(VIDC_REG_880188_ADDR, v)
+#define VIDC_REG_880188_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_880188_ADDR, m, v, \
+ VIDC_REG_880188_IN); \
+} while (0)
+#define VIDC_REG_880188_FW_STT_ADDR_4_BMSK 0xffffffff
+#define VIDC_REG_880188_FW_STT_ADDR_4_SHFT 0
+
+#define VIDC_REG_40293_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000214)
+#define VIDC_REG_40293_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000214)
+#define VIDC_REG_40293_RMSK 0xffffffff
+#define VIDC_REG_40293_SHFT 0
+#define VIDC_REG_40293_IN \
+ in_dword_masked(VIDC_REG_40293_ADDR, \
+ VIDC_REG_40293_RMSK)
+#define VIDC_REG_40293_INM(m) \
+ in_dword_masked(VIDC_REG_40293_ADDR, m)
+#define VIDC_REG_40293_OUT(v) \
+ out_dword(VIDC_REG_40293_ADDR, v)
+#define VIDC_REG_40293_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_40293_ADDR, m, v, \
+ VIDC_REG_40293_IN); \
+} while (0)
+#define VIDC_REG_40293_FW_STT_ADDR_5_BMSK 0xffffffff
+#define VIDC_REG_40293_FW_STT_ADDR_5_SHFT 0
+
+#define VIDC_REG_942170_ADDR_6_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000218)
+#define VIDC_REG_942170_ADDR_6_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000218)
+#define VIDC_REG_942170_ADDR_6_RMSK 0xffffffff
+#define VIDC_REG_942170_ADDR_6_SHFT 0
+#define VIDC_REG_942170_ADDR_6_IN \
+ in_dword_masked(VIDC_REG_942170_ADDR_6_ADDR, \
+ VIDC_REG_942170_ADDR_6_RMSK)
+#define VIDC_REG_942170_ADDR_6_INM(m) \
+ in_dword_masked(VIDC_REG_942170_ADDR_6_ADDR, m)
+#define VIDC_REG_942170_ADDR_6_OUT(v) \
+ out_dword(VIDC_REG_942170_ADDR_6_ADDR, v)
+#define VIDC_REG_942170_ADDR_6_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_942170_ADDR_6_ADDR, m, v, \
+ VIDC_REG_942170_ADDR_6_IN); \
+} while (0)
+#define VIDC_REG_942170_ADDR_6_FW_STT_ADDR_6_BMSK 0xffffffff
+#define VIDC_REG_942170_ADDR_6_FW_STT_ADDR_6_SHFT 0
+
+#define VIDC_REG_958768_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000230)
+#define VIDC_REG_958768_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000230)
+#define VIDC_REG_958768_RMSK 0xffffffff
+#define VIDC_REG_958768_SHFT 0
+#define VIDC_REG_958768_IN \
+ in_dword_masked(VIDC_REG_958768_ADDR, \
+ VIDC_REG_958768_RMSK)
+#define VIDC_REG_958768_INM(m) \
+ in_dword_masked(VIDC_REG_958768_ADDR, m)
+#define VIDC_REG_958768_OUT(v) \
+ out_dword(VIDC_REG_958768_ADDR, v)
+#define VIDC_REG_958768_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_958768_ADDR, m, v, \
+ VIDC_REG_958768_IN); \
+} while (0)
+#define VIDC_REG_699384_ADDR_BMSK 0xffffffff
+#define VIDC_REG_699384_ADDR_SHFT 0
+
+#define VIDC_REG_979942_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000234)
+#define VIDC_REG_979942_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000234)
+#define VIDC_REG_979942_RMSK 0xffffffff
+#define VIDC_REG_979942_SHFT 0
+#define VIDC_REG_979942_IN \
+ in_dword_masked(VIDC_REG_979942_ADDR, \
+ VIDC_REG_979942_RMSK)
+#define VIDC_REG_979942_INM(m) \
+ in_dword_masked(VIDC_REG_979942_ADDR, m)
+#define VIDC_REG_979942_OUT(v) \
+ out_dword(VIDC_REG_979942_ADDR, v)
+#define VIDC_REG_979942_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_979942_ADDR, m, v, \
+ VIDC_REG_979942_IN); \
+} while (0)
+#define VIDC_REG_979942_DB_STT_ADDR_BMSK 0xffffffff
+#define VIDC_REG_979942_DB_STT_ADDR_SHFT 0
+
+#define VIDC_REG_839021_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000300)
+#define VIDC_REG_839021_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000300)
+#define VIDC_REG_839021_RMSK 0xff1f
+#define VIDC_REG_839021_SHFT 0
+#define VIDC_REG_839021_IN \
+ in_dword_masked(VIDC_REG_839021_ADDR, VIDC_REG_839021_RMSK)
+#define VIDC_REG_839021_INM(m) \
+ in_dword_masked(VIDC_REG_839021_ADDR, m)
+#define VIDC_REG_839021_OUT(v) \
+ out_dword(VIDC_REG_839021_ADDR, v)
+#define VIDC_REG_839021_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_839021_ADDR, m, v, \
+ VIDC_REG_839021_IN); \
+} while (0)
+#define VIDC_REG_839021_LEVEL_BMSK 0xff00
+#define VIDC_REG_839021_LEVEL_SHFT 0x8
+#define VIDC_REG_839021_PROFILE_BMSK 0x1f
+#define VIDC_REG_839021_PROFILE_SHFT 0
+
+#define VIDC_REG_950374_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000308)
+#define VIDC_REG_950374_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000308)
+#define VIDC_REG_950374_RMSK 0xffff
+#define VIDC_REG_950374_SHFT 0
+#define VIDC_REG_950374_IN \
+ in_dword_masked(VIDC_REG_950374_ADDR, \
+ VIDC_REG_950374_RMSK)
+#define VIDC_REG_950374_INM(m) \
+ in_dword_masked(VIDC_REG_950374_ADDR, m)
+#define VIDC_REG_950374_OUT(v) \
+ out_dword(VIDC_REG_950374_ADDR, v)
+#define VIDC_REG_950374_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_950374_ADDR, m, v, \
+ VIDC_REG_950374_IN); \
+} while (0)
+#define VIDC_REG_950374_I_PERIOD_BMSK 0xffff
+#define VIDC_REG_950374_I_PERIOD_SHFT 0
+
+#define VIDC_REG_504878_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000310)
+#define VIDC_REG_504878_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000310)
+#define VIDC_REG_504878_RMSK 0xd
+#define VIDC_REG_504878_SHFT 0
+#define VIDC_REG_504878_IN \
+ in_dword_masked(VIDC_REG_504878_ADDR, \
+ VIDC_REG_504878_RMSK)
+#define VIDC_REG_504878_INM(m) \
+ in_dword_masked(VIDC_REG_504878_ADDR, m)
+#define VIDC_REG_504878_OUT(v) \
+ out_dword(VIDC_REG_504878_ADDR, v)
+#define VIDC_REG_504878_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_504878_ADDR, m, v, \
+ VIDC_REG_504878_IN); \
+} while (0)
+#define VIDC_REG_504878_FIXED_NUMBER_BMSK 0xc
+#define VIDC_REG_504878_FIXED_NUMBER_SHFT 0x2
+#define VIDC_REG_504878_ENTROPY_SEL_BMSK 0x1
+#define VIDC_REG_504878_ENTROPY_SEL_SHFT 0
+
+#define VIDC_REG_458130_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000314)
+#define VIDC_REG_458130_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000314)
+#define VIDC_REG_458130_RMSK 0xfff
+#define VIDC_REG_458130_SHFT 0
+#define VIDC_REG_458130_IN \
+ in_dword_masked(VIDC_REG_458130_ADDR, \
+ VIDC_REG_458130_RMSK)
+#define VIDC_REG_458130_INM(m) \
+ in_dword_masked(VIDC_REG_458130_ADDR, m)
+#define VIDC_REG_458130_OUT(v) \
+ out_dword(VIDC_REG_458130_ADDR, v)
+#define VIDC_REG_458130_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_458130_ADDR, m, v, \
+ VIDC_REG_458130_IN); \
+} while (0)
+#define VIDC_REG_458130_SLICE_ALPHA_C0_OFFSET_DIV2_BMSK \
+ 0xf80
+#define VIDC_REG_458130_SLICE_ALPHA_C0_OFFSET_DIV2_SHFT \
+ 0x7
+#define VIDC_REG_458130_SLICE_BETA_OFFSET_DIV2_BMSK 0x7c
+#define VIDC_REG_458130_SLICE_BETA_OFFSET_DIV2_SHFT 0x2
+#define \
+ \
+VIDC_REG_458130_DISABLE_DEBLOCKING_FILTER_IDC_BMSK 0x3
+#define \
+ \
+VIDC_REG_458130_DISABLE_DEBLOCKING_FILTER_IDC_SHFT 0
+
+#define VIDC_REG_314290_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000318)
+#define VIDC_REG_314290_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000318)
+#define VIDC_REG_314290_RMSK 0x1
+#define VIDC_REG_314290_SHFT 0
+#define VIDC_REG_314290_IN \
+ in_dword_masked(VIDC_REG_314290_ADDR, \
+ VIDC_REG_314290_RMSK)
+#define VIDC_REG_314290_INM(m) \
+ in_dword_masked(VIDC_REG_314290_ADDR, m)
+#define VIDC_REG_314290_OUT(v) \
+ out_dword(VIDC_REG_314290_ADDR, v)
+#define VIDC_REG_314290_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_314290_ADDR, m, v, \
+ VIDC_REG_314290_IN); \
+} while (0)
+#define VIDC_REG_314290_SHORT_HD_ON_BMSK 0x1
+#define VIDC_REG_314290_SHORT_HD_ON_SHFT 0
+
+#define VIDC_REG_588301_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x0000031c)
+#define VIDC_REG_588301_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x0000031c)
+#define VIDC_REG_588301_RMSK 0x1
+#define VIDC_REG_588301_SHFT 0
+#define VIDC_REG_588301_IN \
+ in_dword_masked(VIDC_REG_588301_ADDR, \
+ VIDC_REG_588301_RMSK)
+#define VIDC_REG_588301_INM(m) \
+ in_dword_masked(VIDC_REG_588301_ADDR, m)
+#define VIDC_REG_588301_OUT(v) \
+ out_dword(VIDC_REG_588301_ADDR, v)
+#define VIDC_REG_588301_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_588301_ADDR, m, v, \
+ VIDC_REG_588301_IN); \
+} while (0)
+#define VIDC_REG_588301_MSLICE_ENA_BMSK 0x1
+#define VIDC_REG_588301_MSLICE_ENA_SHFT 0
+
+#define VIDC_REG_1517_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000320)
+#define VIDC_REG_1517_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000320)
+#define VIDC_REG_1517_RMSK 0x3
+#define VIDC_REG_1517_SHFT 0
+#define VIDC_REG_1517_IN \
+ in_dword_masked(VIDC_REG_1517_ADDR, \
+ VIDC_REG_1517_RMSK)
+#define VIDC_REG_1517_INM(m) \
+ in_dword_masked(VIDC_REG_1517_ADDR, m)
+#define VIDC_REG_1517_OUT(v) \
+ out_dword(VIDC_REG_1517_ADDR, v)
+#define VIDC_REG_1517_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_1517_ADDR, m, v, \
+ VIDC_REG_1517_IN); \
+} while (0)
+#define VIDC_REG_1517_MSLICE_SEL_BMSK 0x3
+#define VIDC_REG_1517_MSLICE_SEL_SHFT 0
+
+#define VIDC_REG_105335_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000324)
+#define VIDC_REG_105335_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000324)
+#define VIDC_REG_105335_RMSK 0xffffffff
+#define VIDC_REG_105335_SHFT 0
+#define VIDC_REG_105335_IN \
+ in_dword_masked(VIDC_REG_105335_ADDR, \
+ VIDC_REG_105335_RMSK)
+#define VIDC_REG_105335_INM(m) \
+ in_dword_masked(VIDC_REG_105335_ADDR, m)
+#define VIDC_REG_105335_OUT(v) \
+ out_dword(VIDC_REG_105335_ADDR, v)
+#define VIDC_REG_105335_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_105335_ADDR, m, v, \
+ VIDC_REG_105335_IN); \
+} while (0)
+#define VIDC_REG_105335_MSLICE_MB_BMSK 0xffffffff
+#define VIDC_REG_105335_MSLICE_MB_SHFT 0
+
+#define VIDC_REG_561679_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000328)
+#define VIDC_REG_561679_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000328)
+#define VIDC_REG_561679_RMSK 0xffffffff
+#define VIDC_REG_561679_SHFT 0
+#define VIDC_REG_561679_IN \
+ in_dword_masked(VIDC_REG_561679_ADDR, \
+ VIDC_REG_561679_RMSK)
+#define VIDC_REG_561679_INM(m) \
+ in_dword_masked(VIDC_REG_561679_ADDR, m)
+#define VIDC_REG_561679_OUT(v) \
+ out_dword(VIDC_REG_561679_ADDR, v)
+#define VIDC_REG_561679_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_561679_ADDR, m, v, \
+ VIDC_REG_561679_IN); \
+} while (0)
+#define VIDC_REG_561679_MSLICE_BYTE_BMSK 0xffffffff
+#define VIDC_REG_561679_MSLICE_BYTE_SHFT 0
+
+#define VIDC_REG_151345_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000400)
+#define VIDC_REG_151345_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000400)
+#define VIDC_REG_151345_RMSK 0xffffffff
+#define VIDC_REG_151345_SHFT 0
+#define VIDC_REG_151345_IN \
+ in_dword_masked(VIDC_REG_151345_ADDR, \
+ VIDC_REG_151345_RMSK)
+#define VIDC_REG_151345_INM(m) \
+ in_dword_masked(VIDC_REG_151345_ADDR, m)
+#define VIDC_REG_151345_DISPLAY_Y_ADR_BMSK 0xffffffff
+#define VIDC_REG_151345_DISPLAY_Y_ADR_SHFT 0
+
+#define VIDC_REG_293983_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000404)
+#define VIDC_REG_293983_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000404)
+#define VIDC_REG_293983_RMSK 0xffffffff
+#define VIDC_REG_293983_SHFT 0
+#define VIDC_REG_293983_IN \
+ in_dword_masked(VIDC_REG_293983_ADDR, \
+ VIDC_REG_293983_RMSK)
+#define VIDC_REG_293983_INM(m) \
+ in_dword_masked(VIDC_REG_293983_ADDR, m)
+#define VIDC_REG_293983_DISPLAY_C_ADR_BMSK 0xffffffff
+#define VIDC_REG_293983_DISPLAY_C_ADR_SHFT 0
+
+#define VIDC_REG_612715_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000408)
+#define VIDC_REG_612715_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000408)
+#define VIDC_REG_612715_RMSK 0x3f
+#define VIDC_REG_612715_SHFT 0
+#define VIDC_REG_612715_IN \
+ in_dword_masked(VIDC_REG_612715_ADDR, \
+ VIDC_REG_612715_RMSK)
+#define VIDC_REG_612715_INM(m) \
+ in_dword_masked(VIDC_REG_612715_ADDR, m)
+#define VIDC_REG_612715_DISPLAY_STATUS_BMSK 0x3f
+#define VIDC_REG_612715_DISPLAY_STATUS_SHFT 0
+
+#define VIDC_REG_209364_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x0000040c)
+#define VIDC_REG_209364_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x0000040c)
+#define VIDC_REG_209364_RMSK 0x1
+#define VIDC_REG_209364_SHFT 0
+#define VIDC_REG_209364_IN \
+ in_dword_masked(VIDC_REG_209364_ADDR, \
+ VIDC_REG_209364_RMSK)
+#define VIDC_REG_209364_INM(m) \
+ in_dword_masked(VIDC_REG_209364_ADDR, m)
+#define VIDC_REG_209364_HEADER_DONE_BMSK 0x1
+#define VIDC_REG_209364_HEADER_DONE_SHFT 0
+
+#define VIDC_REG_757835_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000410)
+#define VIDC_REG_757835_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000410)
+#define VIDC_REG_757835_RMSK 0xffffffff
+#define VIDC_REG_757835_SHFT 0
+#define VIDC_REG_757835_IN \
+ in_dword_masked(VIDC_REG_757835_ADDR, \
+ VIDC_REG_757835_RMSK)
+#define VIDC_REG_757835_INM(m) \
+ in_dword_masked(VIDC_REG_757835_ADDR, m)
+#define VIDC_REG_757835_FRAME_NUM_BMSK 0xffffffff
+#define VIDC_REG_757835_FRAME_NUM_SHFT 0
+
+#define VIDC_REG_352831_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000414)
+#define VIDC_REG_352831_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000414)
+#define VIDC_REG_352831_RMSK 0xffffffff
+#define VIDC_REG_352831_SHFT 0
+#define VIDC_REG_352831_IN \
+ in_dword_masked(VIDC_REG_352831_ADDR, \
+ VIDC_REG_352831_RMSK)
+#define VIDC_REG_352831_INM(m) \
+ in_dword_masked(VIDC_REG_352831_ADDR, m)
+#define VIDC_REG_352831_DBG_INFO_OUTPUT0_BMSK 0xffffffff
+#define VIDC_REG_352831_DBG_INFO_OUTPUT0_SHFT 0
+
+#define VIDC_REG_668634_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000418)
+#define VIDC_REG_668634_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000418)
+#define VIDC_REG_668634_RMSK 0xffffffff
+#define VIDC_REG_668634_SHFT 0
+#define VIDC_REG_668634_IN \
+ in_dword_masked(VIDC_REG_668634_ADDR, \
+ VIDC_REG_668634_RMSK)
+#define VIDC_REG_668634_INM(m) \
+ in_dword_masked(VIDC_REG_668634_ADDR, m)
+#define VIDC_REG_668634_DBG_INFO_OUTPUT1_BMSK 0xffffffff
+#define VIDC_REG_668634_DBG_INFO_OUTPUT1_SHFT 0
+
+#define VIDC_REG_609676_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000500)
+#define VIDC_REG_609676_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000500)
+#define VIDC_REG_609676_RMSK 0x1
+#define VIDC_REG_609676_SHFT 0
+#define VIDC_REG_609676_IN \
+ in_dword_masked(VIDC_REG_609676_ADDR, VIDC_REG_609676_RMSK)
+#define VIDC_REG_609676_INM(m) \
+ in_dword_masked(VIDC_REG_609676_ADDR, m)
+#define VIDC_REG_609676_OUT(v) \
+ out_dword(VIDC_REG_609676_ADDR, v)
+#define VIDC_REG_609676_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_609676_ADDR, m, v, \
+ VIDC_REG_609676_IN); \
+} while (0)
+#define VIDC_REG_609676_INT_OFF_BMSK 0x1
+#define VIDC_REG_609676_INT_OFF_SHFT 0
+
+#define VIDC_REG_491082_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000504)
+#define VIDC_REG_491082_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000504)
+#define VIDC_REG_491082_RMSK 0x1
+#define VIDC_REG_491082_SHFT 0
+#define VIDC_REG_491082_IN \
+ in_dword_masked(VIDC_REG_491082_ADDR, \
+ VIDC_REG_491082_RMSK)
+#define VIDC_REG_491082_INM(m) \
+ in_dword_masked(VIDC_REG_491082_ADDR, m)
+#define VIDC_REG_491082_OUT(v) \
+ out_dword(VIDC_REG_491082_ADDR, v)
+#define VIDC_REG_491082_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_491082_ADDR, m, v, \
+ VIDC_REG_491082_IN); \
+} while (0)
+#define VIDC_REG_491082_INT_PULSE_SEL_BMSK 0x1
+#define VIDC_REG_491082_INT_PULSE_SEL_SHFT 0
+
+#define VIDC_REG_614776_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000508)
+#define VIDC_REG_614776_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000508)
+#define VIDC_REG_614776_RMSK 0x1
+#define VIDC_REG_614776_SHFT 0
+#define VIDC_REG_614776_IN \
+ in_dword_masked(VIDC_REG_614776_ADDR, \
+ VIDC_REG_614776_RMSK)
+#define VIDC_REG_614776_INM(m) \
+ in_dword_masked(VIDC_REG_614776_ADDR, m)
+#define VIDC_REG_614776_OUT(v) \
+ out_dword(VIDC_REG_614776_ADDR, v)
+#define VIDC_REG_614776_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_614776_ADDR, m, v, \
+ VIDC_REG_614776_IN); \
+} while (0)
+#define VIDC_REG_614776_INT_DONE_CLEAR_BMSK 0x1
+#define VIDC_REG_614776_INT_DONE_CLEAR_SHFT 0
+
+#define VIDC_REG_982553_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x0000050c)
+#define VIDC_REG_982553_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x0000050c)
+#define VIDC_REG_982553_RMSK 0x1
+#define VIDC_REG_982553_SHFT 0
+#define VIDC_REG_982553_IN \
+ in_dword_masked(VIDC_REG_982553_ADDR, \
+ VIDC_REG_982553_RMSK)
+#define VIDC_REG_982553_INM(m) \
+ in_dword_masked(VIDC_REG_982553_ADDR, m)
+#define VIDC_REG_982553_OPERATION_DONE_BMSK 0x1
+#define VIDC_REG_982553_OPERATION_DONE_SHFT 0
+
+#define VIDC_REG_259967_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000510)
+#define VIDC_REG_259967_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000510)
+#define VIDC_REG_259967_RMSK 0x1
+#define VIDC_REG_259967_SHFT 0
+#define VIDC_REG_259967_IN \
+ in_dword_masked(VIDC_REG_259967_ADDR, VIDC_REG_259967_RMSK)
+#define VIDC_REG_259967_INM(m) \
+ in_dword_masked(VIDC_REG_259967_ADDR, m)
+#define VIDC_REG_259967_FW_DONE_BMSK 0x1
+#define VIDC_REG_259967_FW_DONE_SHFT 0
+
+#define VIDC_REG_512143_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000514)
+#define VIDC_REG_512143_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000514)
+#define VIDC_REG_512143_RMSK 0x1f8
+#define VIDC_REG_512143_SHFT 0
+#define VIDC_REG_512143_IN \
+ in_dword_masked(VIDC_REG_512143_ADDR, \
+ VIDC_REG_512143_RMSK)
+#define VIDC_REG_512143_INM(m) \
+ in_dword_masked(VIDC_REG_512143_ADDR, m)
+#define VIDC_REG_512143_FRAME_DONE_STAT_BMSK 0x100
+#define VIDC_REG_512143_FRAME_DONE_STAT_SHFT 0x8
+#define VIDC_REG_512143_DMA_DONE_STAT_BMSK 0x80
+#define VIDC_REG_512143_DMA_DONE_STAT_SHFT 0x7
+#define VIDC_REG_512143_HEADER_DONE_STAT_BMSK 0x40
+#define VIDC_REG_512143_HEADER_DONE_STAT_SHFT 0x6
+#define VIDC_REG_512143_FW_DONE_STAT_BMSK 0x20
+#define VIDC_REG_512143_FW_DONE_STAT_SHFT 0x5
+#define VIDC_REG_512143_OPERATION_FAILED_BMSK 0x10
+#define VIDC_REG_512143_OPERATION_FAILED_SHFT 0x4
+#define VIDC_REG_512143_STREAM_HDR_CHANGED_BMSK 0x8
+#define VIDC_REG_512143_STREAM_HDR_CHANGED_SHFT 0x3
+
+#define VIDC_REG_418173_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000518)
+#define VIDC_REG_418173_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000518)
+#define VIDC_REG_418173_RMSK 0x1fa
+#define VIDC_REG_418173_SHFT 0
+#define VIDC_REG_418173_IN \
+ in_dword_masked(VIDC_REG_418173_ADDR, \
+ VIDC_REG_418173_RMSK)
+#define VIDC_REG_418173_INM(m) \
+ in_dword_masked(VIDC_REG_418173_ADDR, m)
+#define VIDC_REG_418173_OUT(v) \
+ out_dword(VIDC_REG_418173_ADDR, v)
+#define VIDC_REG_418173_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_418173_ADDR, m, v, \
+ VIDC_REG_418173_IN); \
+} while (0)
+#define VIDC_REG_418173_FRAME_DONE_ENABLE_BMSK 0x100
+#define VIDC_REG_418173_FRAME_DONE_ENABLE_SHFT 0x8
+#define VIDC_REG_418173_DMA_DONE_ENABLE_BMSK 0x80
+#define VIDC_REG_418173_DMA_DONE_ENABLE_SHFT 0x7
+#define VIDC_REG_418173_HEADER_DONE_ENABLE_BMSK 0x40
+#define VIDC_REG_418173_HEADER_DONE_ENABLE_SHFT 0x6
+#define VIDC_REG_418173_FW_DONE_ENABLE_BMSK 0x20
+#define VIDC_REG_418173_FW_DONE_ENABLE_SHFT 0x5
+#define VIDC_REG_418173_OPERATION_FAILED_ENABLE_BMSK 0x10
+#define VIDC_REG_418173_OPERATION_FAILED_ENABLE_SHFT 0x4
+#define VIDC_REG_418173_STREAM_HDR_CHANGED_ENABLE_BMSK 0x8
+#define VIDC_REG_418173_STREAM_HDR_CHANGED_ENABLE_SHFT 0x3
+#define VIDC_REG_418173_BUFFER_FULL_ENABLE_BMSK 0x2
+#define VIDC_REG_418173_BUFFER_FULL_ENABLE_SHFT 0x1
+
+#define VIDC_REG_841539_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000600)
+#define VIDC_REG_841539_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000600)
+#define VIDC_REG_841539_RMSK 0x3
+#define VIDC_REG_841539_SHFT 0
+#define VIDC_REG_841539_IN \
+ in_dword_masked(VIDC_REG_841539_ADDR, \
+ VIDC_REG_841539_RMSK)
+#define VIDC_REG_841539_INM(m) \
+ in_dword_masked(VIDC_REG_841539_ADDR, m)
+#define VIDC_REG_841539_OUT(v) \
+ out_dword(VIDC_REG_841539_ADDR, v)
+#define VIDC_REG_841539_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_841539_ADDR, m, v, \
+ VIDC_REG_841539_IN); \
+} while (0)
+#define VIDC_REG_841539_TILE_MODE_BMSK 0x3
+#define VIDC_REG_841539_TILE_MODE_SHFT 0
+
+#define VIDC_REG_99105_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000800)
+#define VIDC_REG_99105_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000800)
+#define VIDC_REG_99105_RMSK 0xffffffff
+#define VIDC_REG_99105_SHFT 0
+#define VIDC_REG_99105_IN \
+ in_dword_masked(VIDC_REG_99105_ADDR, \
+ VIDC_REG_99105_RMSK)
+#define VIDC_REG_99105_INM(m) \
+ in_dword_masked(VIDC_REG_99105_ADDR, m)
+#define VIDC_REG_99105_OUT(v) \
+ out_dword(VIDC_REG_99105_ADDR, v)
+#define VIDC_REG_99105_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_99105_ADDR, m, v, \
+ VIDC_REG_99105_IN); \
+} while (0)
+#define VIDC_REG_99105_ENC_CUR_Y_ADDR_BMSK 0xffffffff
+#define VIDC_REG_99105_ENC_CUR_Y_ADDR_SHFT 0
+
+#define VIDC_REG_777113_ADDR_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000804)
+#define VIDC_REG_777113_ADDR_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000804)
+#define VIDC_REG_777113_ADDR_RMSK 0xffffffff
+#define VIDC_REG_777113_ADDR_SHFT 0
+#define VIDC_REG_777113_ADDR_IN \
+ in_dword_masked(VIDC_REG_777113_ADDR_ADDR, \
+ VIDC_REG_777113_ADDR_RMSK)
+#define VIDC_REG_777113_ADDR_INM(m) \
+ in_dword_masked(VIDC_REG_777113_ADDR_ADDR, m)
+#define VIDC_REG_777113_ADDR_OUT(v) \
+ out_dword(VIDC_REG_777113_ADDR_ADDR, v)
+#define VIDC_REG_777113_ADDR_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_777113_ADDR_ADDR, m, v, \
+ VIDC_REG_777113_ADDR_IN); \
+} while (0)
+#define VIDC_REG_777113_ADDR_ENC_CUR_C_ADDR_BMSK 0xffffffff
+#define VIDC_REG_777113_ADDR_ENC_CUR_C_ADDR_SHFT 0
+
+#define VIDC_REG_341928_ADDR_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x0000080c)
+#define VIDC_REG_341928_ADDR_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x0000080c)
+#define VIDC_REG_341928_ADDR_RMSK 0xffffffff
+#define VIDC_REG_341928_ADDR_SHFT 0
+#define VIDC_REG_341928_ADDR_IN \
+ in_dword_masked(VIDC_REG_341928_ADDR_ADDR, \
+ VIDC_REG_341928_ADDR_RMSK)
+#define VIDC_REG_341928_ADDR_INM(m) \
+ in_dword_masked(VIDC_REG_341928_ADDR_ADDR, m)
+#define VIDC_REG_341928_ADDR_OUT(v) \
+ out_dword(VIDC_REG_341928_ADDR_ADDR, v)
+#define VIDC_REG_341928_ADDR_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_341928_ADDR_ADDR, m, v, \
+ VIDC_REG_341928_ADDR_IN); \
+} while (0)
+#define VIDC_REG_341928_ADDR_ENC_DPB_ADR_BMSK 0xffffffff
+#define VIDC_REG_341928_ADDR_ENC_DPB_ADR_SHFT 0
+
+#define VIDC_REG_857491_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000810)
+#define VIDC_REG_857491_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000810)
+#define VIDC_REG_857491_RMSK 0xfff
+#define VIDC_REG_857491_SHFT 0
+#define VIDC_REG_857491_IN \
+ in_dword_masked(VIDC_REG_857491_ADDR, \
+ VIDC_REG_857491_RMSK)
+#define VIDC_REG_857491_INM(m) \
+ in_dword_masked(VIDC_REG_857491_ADDR, m)
+#define VIDC_REG_857491_OUT(v) \
+ out_dword(VIDC_REG_857491_ADDR, v)
+#define VIDC_REG_857491_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_857491_ADDR, m, v, \
+ VIDC_REG_857491_IN); \
+} while (0)
+#define VIDC_REG_857491_CIR_MB_NUM_BMSK 0xfff
+#define VIDC_REG_857491_CIR_MB_NUM_SHFT 0
+
+#define VIDC_REG_518133_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000900)
+#define VIDC_REG_518133_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000900)
+#define VIDC_REG_518133_RMSK 0xffffffff
+#define VIDC_REG_518133_SHFT 0
+#define VIDC_REG_518133_IN \
+ in_dword_masked(VIDC_REG_518133_ADDR, \
+ VIDC_REG_518133_RMSK)
+#define VIDC_REG_518133_INM(m) \
+ in_dword_masked(VIDC_REG_518133_ADDR, m)
+#define VIDC_REG_518133_OUT(v) \
+ out_dword(VIDC_REG_518133_ADDR, v)
+#define VIDC_REG_518133_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_518133_ADDR, m, v, \
+ VIDC_REG_518133_IN); \
+} while (0)
+#define VIDC_REG_518133_DEC_DPB_ADDR_BMSK 0xffffffff
+#define VIDC_REG_518133_DEC_DPB_ADDR_SHFT 0
+
+#define VIDC_REG_456376_ADDR_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000904)
+#define VIDC_REG_456376_ADDR_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000904)
+#define VIDC_REG_456376_ADDR_RMSK 0xffffffff
+#define VIDC_REG_456376_ADDR_SHFT 0
+#define VIDC_REG_456376_ADDR_IN \
+ in_dword_masked(VIDC_REG_456376_ADDR_ADDR, \
+ VIDC_REG_456376_ADDR_RMSK)
+#define VIDC_REG_456376_ADDR_INM(m) \
+ in_dword_masked(VIDC_REG_456376_ADDR_ADDR, m)
+#define VIDC_REG_456376_ADDR_OUT(v) \
+ out_dword(VIDC_REG_456376_ADDR_ADDR, v)
+#define VIDC_REG_456376_ADDR_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_456376_ADDR_ADDR, m, v, \
+ VIDC_REG_456376_ADDR_IN); \
+} while (0)
+#define VIDC_REG_456376_ADDR_DPB_COMV_ADDR_BMSK 0xffffffff
+#define VIDC_REG_456376_ADDR_DPB_COMV_ADDR_SHFT 0
+
+#define VIDC_REG_267567_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000908)
+#define VIDC_REG_267567_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000908)
+#define VIDC_REG_267567_RMSK 0xffffffff
+#define VIDC_REG_267567_SHFT 0
+#define VIDC_REG_267567_IN \
+ in_dword_masked(VIDC_REG_267567_ADDR, \
+ VIDC_REG_267567_RMSK)
+#define VIDC_REG_267567_INM(m) \
+ in_dword_masked(VIDC_REG_267567_ADDR, m)
+#define VIDC_REG_267567_OUT(v) \
+ out_dword(VIDC_REG_267567_ADDR, v)
+#define VIDC_REG_267567_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_267567_ADDR, m, v, \
+ VIDC_REG_267567_IN); \
+} while (0)
+#define VIDC_REG_798486_ADDR_BMSK 0xffffffff
+#define VIDC_REG_798486_ADDR_SHFT 0
+
+#define VIDC_REG_105770_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x0000090c)
+#define VIDC_REG_105770_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x0000090c)
+#define VIDC_REG_105770_RMSK 0xff
+#define VIDC_REG_105770_SHFT 0
+#define VIDC_REG_105770_IN \
+ in_dword_masked(VIDC_REG_105770_ADDR, \
+ VIDC_REG_105770_RMSK)
+#define VIDC_REG_105770_INM(m) \
+ in_dword_masked(VIDC_REG_105770_ADDR, m)
+#define VIDC_REG_105770_DPB_SIZE_BMSK 0xff
+#define VIDC_REG_105770_DPB_SIZE_SHFT 0
+
+#define VIDC_REG_58211_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000a00)
+#define VIDC_REG_58211_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000a00)
+#define VIDC_REG_58211_RMSK 0x33f
+#define VIDC_REG_58211_SHFT 0
+#define VIDC_REG_58211_IN \
+ in_dword_masked(VIDC_REG_58211_ADDR, \
+ VIDC_REG_58211_RMSK)
+#define VIDC_REG_58211_INM(m) \
+ in_dword_masked(VIDC_REG_58211_ADDR, m)
+#define VIDC_REG_58211_OUT(v) \
+ out_dword(VIDC_REG_58211_ADDR, v)
+#define VIDC_REG_58211_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_58211_ADDR, m, v, \
+ VIDC_REG_58211_IN); \
+} while (0)
+#define VIDC_REG_58211_FR_RC_EN_BMSK 0x200
+#define VIDC_REG_58211_FR_RC_EN_SHFT 0x9
+#define VIDC_REG_58211_MB_RC_EN_BMSK 0x100
+#define VIDC_REG_58211_MB_RC_EN_SHFT 0x8
+#define VIDC_REG_58211_FRAME_QP_BMSK 0x3f
+#define VIDC_REG_58211_FRAME_QP_SHFT 0
+
+#define VIDC_REG_548359_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000a04)
+#define VIDC_REG_548359_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000a04)
+#define VIDC_REG_548359_RMSK 0x3f
+#define VIDC_REG_548359_SHFT 0
+#define VIDC_REG_548359_IN \
+ in_dword_masked(VIDC_REG_548359_ADDR, \
+ VIDC_REG_548359_RMSK)
+#define VIDC_REG_548359_INM(m) \
+ in_dword_masked(VIDC_REG_548359_ADDR, m)
+#define VIDC_REG_548359_OUT(v) \
+ out_dword(VIDC_REG_548359_ADDR, v)
+#define VIDC_REG_548359_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_548359_ADDR, m, v, \
+ VIDC_REG_548359_IN); \
+} while (0)
+#define VIDC_REG_548359_P_FRAME_QP_BMSK 0x3f
+#define VIDC_REG_548359_P_FRAME_QP_SHFT 0
+
+#define VIDC_REG_174150_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000a08)
+#define VIDC_REG_174150_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000a08)
+#define VIDC_REG_174150_RMSK 0xffffffff
+#define VIDC_REG_174150_SHFT 0
+#define VIDC_REG_174150_IN \
+ in_dword_masked(VIDC_REG_174150_ADDR, \
+ VIDC_REG_174150_RMSK)
+#define VIDC_REG_174150_INM(m) \
+ in_dword_masked(VIDC_REG_174150_ADDR, m)
+#define VIDC_REG_174150_OUT(v) \
+ out_dword(VIDC_REG_174150_ADDR, v)
+#define VIDC_REG_174150_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_174150_ADDR, m, v, \
+ VIDC_REG_174150_IN); \
+} while (0)
+#define VIDC_REG_174150_BIT_RATE_BMSK 0xffffffff
+#define VIDC_REG_174150_BIT_RATE_SHFT 0
+
+#define VIDC_REG_734318_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000a0c)
+#define VIDC_REG_734318_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000a0c)
+#define VIDC_REG_734318_RMSK 0x3f3f
+#define VIDC_REG_734318_SHFT 0
+#define VIDC_REG_734318_IN \
+ in_dword_masked(VIDC_REG_734318_ADDR, \
+ VIDC_REG_734318_RMSK)
+#define VIDC_REG_734318_INM(m) \
+ in_dword_masked(VIDC_REG_734318_ADDR, m)
+#define VIDC_REG_734318_OUT(v) \
+ out_dword(VIDC_REG_734318_ADDR, v)
+#define VIDC_REG_734318_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_734318_ADDR, m, v, \
+ VIDC_REG_734318_IN); \
+} while (0)
+#define VIDC_REG_734318_MAX_QP_BMSK 0x3f00
+#define VIDC_REG_734318_MAX_QP_SHFT 0x8
+#define VIDC_REG_734318_MIN_QP_BMSK 0x3f
+#define VIDC_REG_734318_MIN_QP_SHFT 0
+
+#define VIDC_REG_677784_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000a10)
+#define VIDC_REG_677784_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000a10)
+#define VIDC_REG_677784_RMSK 0xffff
+#define VIDC_REG_677784_SHFT 0
+#define VIDC_REG_677784_IN \
+ in_dword_masked(VIDC_REG_677784_ADDR, \
+ VIDC_REG_677784_RMSK)
+#define VIDC_REG_677784_INM(m) \
+ in_dword_masked(VIDC_REG_677784_ADDR, m)
+#define VIDC_REG_677784_OUT(v) \
+ out_dword(VIDC_REG_677784_ADDR, v)
+#define VIDC_REG_677784_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_677784_ADDR, m, v, \
+ VIDC_REG_677784_IN); \
+} while (0)
+#define VIDC_REG_677784_REACT_PARA_BMSK 0xffff
+#define VIDC_REG_677784_REACT_PARA_SHFT 0
+
+#define VIDC_REG_995041_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000a14)
+#define VIDC_REG_995041_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000a14)
+#define VIDC_REG_995041_RMSK 0xf
+#define VIDC_REG_995041_SHFT 0
+#define VIDC_REG_995041_IN \
+ in_dword_masked(VIDC_REG_995041_ADDR, \
+ VIDC_REG_995041_RMSK)
+#define VIDC_REG_995041_INM(m) \
+ in_dword_masked(VIDC_REG_995041_ADDR, m)
+#define VIDC_REG_995041_OUT(v) \
+ out_dword(VIDC_REG_995041_ADDR, v)
+#define VIDC_REG_995041_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_995041_ADDR, m, v, \
+ VIDC_REG_995041_IN); \
+} while (0)
+#define VIDC_REG_995041_DARK_DISABLE_BMSK 0x8
+#define VIDC_REG_995041_DARK_DISABLE_SHFT 0x3
+#define VIDC_REG_995041_SMOOTH_DISABLE_BMSK 0x4
+#define VIDC_REG_995041_SMOOTH_DISABLE_SHFT 0x2
+#define VIDC_REG_995041_STATIC_DISABLE_BMSK 0x2
+#define VIDC_REG_995041_STATIC_DISABLE_SHFT 0x1
+#define VIDC_REG_995041_ACT_DISABLE_BMSK 0x1
+#define VIDC_REG_995041_ACT_DISABLE_SHFT 0
+
+#define VIDC_REG_273649_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000a18)
+#define VIDC_REG_273649_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000a18)
+#define VIDC_REG_273649_RMSK 0x3f
+#define VIDC_REG_273649_SHFT 0
+#define VIDC_REG_273649_IN \
+ in_dword_masked(VIDC_REG_273649_ADDR, VIDC_REG_273649_RMSK)
+#define VIDC_REG_273649_INM(m) \
+ in_dword_masked(VIDC_REG_273649_ADDR, m)
+#define VIDC_REG_273649_QP_OUT_BMSK 0x3f
+#define VIDC_REG_273649_QP_OUT_SHFT 0
+
+#define VIDC_REG_548823_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000b00)
+#define VIDC_REG_548823_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000b00)
+#define VIDC_REG_548823_RMSK 0xffffffff
+#define VIDC_REG_548823_SHFT 0
+#define VIDC_REG_548823_IN \
+ in_dword_masked(VIDC_REG_548823_ADDR, \
+ VIDC_REG_548823_RMSK)
+#define VIDC_REG_548823_INM(m) \
+ in_dword_masked(VIDC_REG_548823_ADDR, m)
+#define VIDC_REG_548823_720P_VERSION_BMSK 0xffffffff
+#define VIDC_REG_548823_720P_VERSION_SHFT 0
+
+#define VIDC_REG_881638_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000c00)
+#define VIDC_REG_881638_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000c00)
+#define VIDC_REG_881638_RMSK 0xffffffff
+#define VIDC_REG_881638_SHFT 0
+#define VIDC_REG_881638_IN \
+ in_dword_masked(VIDC_REG_881638_ADDR, \
+ VIDC_REG_881638_RMSK)
+#define VIDC_REG_881638_INM(m) \
+ in_dword_masked(VIDC_REG_881638_ADDR, m)
+#define VIDC_REG_881638_CROP_RIGHT_OFFSET_BMSK 0xffff0000
+#define VIDC_REG_881638_CROP_RIGHT_OFFSET_SHFT 0x10
+#define VIDC_REG_881638_CROP_LEFT_OFFSET_BMSK 0xffff
+#define VIDC_REG_881638_CROP_LEFT_OFFSET_SHFT 0
+
+#define VIDC_REG_161486_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000c04)
+#define VIDC_REG_161486_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000c04)
+#define VIDC_REG_161486_RMSK 0xffffffff
+#define VIDC_REG_161486_SHFT 0
+#define VIDC_REG_161486_IN \
+ in_dword_masked(VIDC_REG_161486_ADDR, \
+ VIDC_REG_161486_RMSK)
+#define VIDC_REG_161486_INM(m) \
+ in_dword_masked(VIDC_REG_161486_ADDR, m)
+#define VIDC_REG_161486_CROP_BOTTOM_OFFSET_BMSK 0xffff0000
+#define VIDC_REG_161486_CROP_BOTTOM_OFFSET_SHFT 0x10
+#define VIDC_REG_161486_CROP_TOP_OFFSET_BMSK 0xffff
+#define VIDC_REG_161486_CROP_TOP_OFFSET_SHFT 0
+
+#define VIDC_REG_580603_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000c08)
+#define VIDC_REG_580603_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000c08)
+#define VIDC_REG_580603_RMSK 0xffffffff
+#define VIDC_REG_580603_SHFT 0
+#define VIDC_REG_580603_IN \
+ in_dword_masked(VIDC_REG_580603_ADDR, \
+ VIDC_REG_580603_RMSK)
+#define VIDC_REG_580603_INM(m) \
+ in_dword_masked(VIDC_REG_580603_ADDR, m)
+#define VIDC_REG_580603_720P_DEC_FRM_SIZE_BMSK 0xffffffff
+#define VIDC_REG_580603_720P_DEC_FRM_SIZE_SHFT 0
+
+
+#define VIDC_REG_606447_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000c0c)
+#define VIDC_REG_606447_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000c0c)
+#define VIDC_REG_606447_RMSK 0xff1f
+#define VIDC_REG_606447_SHFT 0
+#define VIDC_REG_606447_IN \
+ in_dword_masked(VIDC_REG_606447_ADDR, \
+ VIDC_REG_606447_RMSK)
+#define VIDC_REG_606447_INM(m) \
+ in_dword_masked(VIDC_REG_606447_ADDR, m)
+#define VIDC_REG_606447_OUT(v) \
+ out_dword(VIDC_REG_606447_ADDR, v)
+#define VIDC_REG_606447_OUTM(m, v) \
+ out_dword_masked_ns(VIDC_REG_606447_ADDR, \
+ m, v, VIDC_REG_606447_IN); \
+
+#define VIDC_REG_606447_DIS_PIC_LEVEL_BMSK 0xff00
+#define VIDC_REG_606447_DIS_PIC_LEVEL_SHFT 0x8
+#define VIDC_REG_606447_DISP_PIC_PROFILE_BMSK 0x1f
+#define VIDC_REG_606447_DISP_PIC_PROFILE_SHFT 0
+
+#define VIDC_REG_854281_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000c10)
+#define VIDC_REG_854281_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000c10)
+#define VIDC_REG_854281_RMSK 0xffffffff
+#define VIDC_REG_854281_SHFT 0
+#define VIDC_REG_854281_IN \
+ in_dword_masked(VIDC_REG_854281_ADDR, \
+ VIDC_REG_854281_RMSK)
+#define VIDC_REG_854281_INM(m) \
+ in_dword_masked(VIDC_REG_854281_ADDR, m)
+#define VIDC_REG_854281_MIN_DPB_SIZE_BMSK 0xffffffff
+#define VIDC_REG_854281_MIN_DPB_SIZE_SHFT 0
+
+
+#define VIDC_REG_381535_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000c14)
+#define VIDC_REG_381535_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000c14)
+#define VIDC_REG_381535_RMSK 0xffffffff
+#define VIDC_REG_381535_SHFT 0
+#define VIDC_REG_381535_IN \
+ in_dword_masked(VIDC_REG_381535_ADDR, \
+ VIDC_REG_381535_RMSK)
+#define VIDC_REG_381535_INM(m) \
+ in_dword_masked(VIDC_REG_381535_ADDR, m)
+#define VIDC_REG_381535_720P_FW_STATUS_BMSK 0xffffffff
+#define VIDC_REG_381535_720P_FW_STATUS_SHFT 0
+
+
+#define VIDC_REG_347105_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000c18)
+#define VIDC_REG_347105_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000c18)
+#define VIDC_REG_347105_RMSK 0xffffffff
+#define VIDC_REG_347105_SHFT 0
+#define VIDC_REG_347105_IN \
+ in_dword_masked(VIDC_REG_347105_ADDR, \
+ VIDC_REG_347105_RMSK)
+#define VIDC_REG_347105_INM(m) \
+ in_dword_masked(VIDC_REG_347105_ADDR, m)
+#define VIDC_REG_347105_FREE_LUMA_DPB_BMSK 0xffffffff
+#define VIDC_REG_347105_FREE_LUMA_DPB_SHFT 0
+
+
+#define VIDC_REG_62325_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000d00)
+#define VIDC_REG_62325_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000d00)
+#define VIDC_REG_62325_RMSK 0xf
+#define VIDC_REG_62325_SHFT 0
+#define VIDC_REG_62325_IN \
+ in_dword_masked(VIDC_REG_62325_ADDR, \
+ VIDC_REG_62325_RMSK)
+#define VIDC_REG_62325_INM(m) \
+ in_dword_masked(VIDC_REG_62325_ADDR, m)
+#define VIDC_REG_62325_OUT(v) \
+ out_dword(VIDC_REG_62325_ADDR, v)
+#define VIDC_REG_62325_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_62325_ADDR, m, v, \
+ VIDC_REG_62325_IN); \
+} while (0)
+#define VIDC_REG_62325_COMMAND_TYPE_BMSK 0xf
+#define VIDC_REG_62325_COMMAND_TYPE_SHFT 0
+
+#define VIDC_REG_101184_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000d04)
+#define VIDC_REG_101184_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000d04)
+#define VIDC_REG_101184_RMSK 0xffffffff
+#define VIDC_REG_101184_SHFT 0
+#define VIDC_REG_101184_OUT(v) \
+ out_dword(VIDC_REG_101184_ADDR, v)
+
+#define VIDC_REG_490443_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000d08)
+#define VIDC_REG_490443_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000d08)
+#define VIDC_REG_490443_RMSK \
+ 0xffffffff
+#define \
+ \
+VIDC_REG_490443_SHFT 0
+#define VIDC_REG_490443_OUT(v) \
+ out_dword(VIDC_REG_490443_ADDR, v)
+
+#define VIDC_REG_625444_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000d14)
+#define VIDC_REG_625444_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000d14)
+#define VIDC_REG_625444_RMSK 0xffffffff
+#define VIDC_REG_625444_SHFT 0
+#define VIDC_REG_625444_IN \
+ in_dword_masked(VIDC_REG_625444_ADDR, \
+ VIDC_REG_625444_RMSK)
+#define VIDC_REG_625444_INM(m) \
+ in_dword_masked(VIDC_REG_625444_ADDR, m)
+#define VIDC_REG_625444_OUT(v) \
+ out_dword(VIDC_REG_625444_ADDR, v)
+#define VIDC_REG_625444_OUTM(m, v) \
+do { \
+ out_dword_masked_ns(VIDC_REG_625444_ADDR, m, v, \
+ VIDC_REG_625444_IN); \
+} while (0)
+#define VIDC_REG_625444_FRAME_RATE_BMSK 0xffffffff
+#define VIDC_REG_625444_FRAME_RATE_SHFT 0
+
+#define VIDC_REG_639999_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000d20)
+#define VIDC_REG_639999_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000d20)
+#define VIDC_REG_639999_RMSK 0xffff
+#define VIDC_REG_639999_SHFT 0
+#define VIDC_REG_639999_OUT(v) \
+ out_dword(VIDC_REG_639999_ADDR, v)
+
+#define VIDC_REG_64895_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000e00)
+#define VIDC_REG_64895_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000e00)
+#define VIDC_REG_64895_RMSK 0xffffffff
+#define VIDC_REG_64895_SHFT 0
+#define VIDC_REG_64895_OUT(v) \
+ out_dword(VIDC_REG_64895_ADDR, v)
+
+#define VIDC_REG_965480_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000e04)
+#define VIDC_REG_965480_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000e04)
+#define VIDC_REG_965480_RMSK 0x1
+#define VIDC_REG_965480_SHFT 0
+#define VIDC_REG_965480_OUT(v) \
+ out_dword(VIDC_REG_965480_ADDR, v)
+
+#define VIDC_REG_804959_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000e08)
+#define VIDC_REG_804959_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000e08)
+#define VIDC_REG_804959_RMSK 0x7
+#define VIDC_REG_804959_SHFT 0
+#define VIDC_REG_804959_OUT(v) \
+ out_dword(VIDC_REG_804959_ADDR, v)
+
+#define VIDC_REG_257463_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000e10)
+#define VIDC_REG_257463_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000e10)
+#define VIDC_REG_257463_RMSK 0xffffffff
+#define VIDC_REG_257463_SHFT 0
+#define VIDC_REG_257463_IN \
+ in_dword_masked(VIDC_REG_257463_ADDR, \
+ VIDC_REG_257463_RMSK)
+#define VIDC_REG_257463_INM(m) \
+ in_dword_masked(VIDC_REG_257463_ADDR, m)
+#define VIDC_REG_257463_MIN_NUM_DPB_BMSK 0xffffffff
+#define VIDC_REG_257463_MIN_NUM_DPB_SHFT 0
+
+#define VIDC_REG_883500_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000e14)
+#define VIDC_REG_883500_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000e14)
+#define VIDC_REG_883500_RMSK 0xffffffff
+#define VIDC_REG_883500_SHFT 0
+#define VIDC_REG_883500_OUT(v) \
+ out_dword(VIDC_REG_883500_ADDR, v)
+
+#define VIDC_REG_615716_ADDR(n) \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000e18 + 4 * (n))
+#define VIDC_REG_615716_PHYS(n) \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000e18 + 4 * (n))
+#define VIDC_REG_615716_RMSK 0xffffffff
+#define VIDC_REG_615716_SHFT 0
+#define VIDC_REG_615716_OUTI(n, v) \
+ out_dword(VIDC_REG_615716_ADDR(n), v)
+
+#define VIDC_REG_603032_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000e98)
+#define VIDC_REG_603032_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000e98)
+#define VIDC_REG_603032_RMSK 0xffffffff
+#define VIDC_REG_603032_SHFT 0
+#define VIDC_REG_603032_OUT(v) \
+ out_dword(VIDC_REG_603032_ADDR, v)
+
+#define VIDC_REG_300310_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000e9c)
+#define VIDC_REG_300310_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000e9c)
+#define VIDC_REG_300310_RMSK 0xffffffff
+#define VIDC_REG_300310_SHFT 0
+#define VIDC_REG_300310_IN \
+ in_dword_masked(VIDC_REG_300310_ADDR, \
+ VIDC_REG_300310_RMSK)
+#define VIDC_REG_300310_INM(m) \
+ in_dword_masked(VIDC_REG_300310_ADDR, m)
+#define VIDC_REG_300310_ERROR_STATUS_BMSK 0xffffffff
+#define VIDC_REG_300310_ERROR_STATUS_SHFT 0
+
+#define VIDC_REG_792026_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000ea0)
+#define VIDC_REG_792026_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000ea0)
+#define VIDC_REG_792026_RMSK 0xffffffff
+#define VIDC_REG_792026_SHFT 0
+#define VIDC_REG_792026_OUT(v) \
+ out_dword(VIDC_REG_792026_ADDR, v)
+
+#define VIDC_REG_844152_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000ea4)
+#define VIDC_REG_844152_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000ea4)
+#define VIDC_REG_844152_RMSK 0xffffffff
+#define VIDC_REG_844152_SHFT 0
+#define VIDC_REG_844152_OUT(v) \
+ out_dword(VIDC_REG_844152_ADDR, v)
+
+#define VIDC_REG_370409_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000ea8)
+#define VIDC_REG_370409_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000ea8)
+#define VIDC_REG_370409_RMSK 0xffffffff
+#define VIDC_REG_370409_SHFT 0
+#define VIDC_REG_370409_IN \
+ in_dword_masked(VIDC_REG_370409_ADDR, \
+ VIDC_REG_370409_RMSK)
+#define VIDC_REG_370409_INM(m) \
+ in_dword_masked(VIDC_REG_370409_ADDR, m)
+#define VIDC_REG_370409_GET_FRAME_TAG_TOP_BMSK 0xffffffff
+#define VIDC_REG_370409_GET_FRAME_TAG_TOP_SHFT 0
+
+#define VIDC_REG_147682_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000eac)
+#define VIDC_REG_147682_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000eac)
+#define VIDC_REG_147682_RMSK 0x1
+#define VIDC_REG_147682_SHFT 0
+#define VIDC_REG_147682_OUT(v) \
+ out_dword(VIDC_REG_147682_ADDR, v)
+
+#define VIDC_REG_407718_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000eb0)
+#define VIDC_REG_407718_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000eb0)
+#define VIDC_REG_407718_RMSK 0xffffffff
+#define VIDC_REG_407718_SHFT 0
+#define VIDC_REG_407718_OUT(v) \
+ out_dword(VIDC_REG_407718_ADDR, v)
+
+#define VIDC_REG_697961_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000eb4)
+#define VIDC_REG_697961_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000eb4)
+#define VIDC_REG_697961_RMSK 0x3
+#define VIDC_REG_697961_SHFT 0
+#define VIDC_REG_697961_IN \
+ in_dword_masked(VIDC_REG_697961_ADDR, \
+ VIDC_REG_697961_RMSK)
+#define VIDC_REG_697961_INM(m) \
+ in_dword_masked(VIDC_REG_697961_ADDR, m)
+#define VIDC_REG_697961_FRAME_TYPE_BMSK 0x3
+#define VIDC_REG_697961_FRAME_TYPE_SHFT 0
+
+
+#define VIDC_REG_613254_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000eb8)
+#define VIDC_REG_613254_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000eb8)
+#define VIDC_REG_613254_RMSK 0x1
+#define VIDC_REG_613254_SHFT 0
+#define VIDC_REG_613254_IN \
+ in_dword_masked(VIDC_REG_613254_ADDR, \
+ VIDC_REG_613254_RMSK)
+#define VIDC_REG_613254_INM(m) \
+ in_dword_masked(VIDC_REG_613254_ADDR, m)
+#define VIDC_REG_613254_METADATA_STATUS_BMSK 0x1
+#define VIDC_REG_613254_METADATA_STATUS_SHFT 0
+#define VIDC_REG_441270_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000ebc)
+#define VIDC_REG_441270_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000ebc)
+#define VIDC_REG_441270_RMSK 0xf
+#define VIDC_REG_441270_SHFT 0
+#define VIDC_REG_441270_IN \
+ in_dword_masked(VIDC_REG_441270_ADDR, \
+ VIDC_REG_441270_RMSK)
+#define VIDC_REG_441270_INM(m) \
+ in_dword_masked(VIDC_REG_441270_ADDR, m)
+#define VIDC_REG_441270_DATA_PARTITIONED_BMSK 0x8
+#define VIDC_REG_441270_DATA_PARTITIONED_SHFT 0x3
+
+#define VIDC_REG_441270_FRAME_TYPE_BMSK 0x7
+#define VIDC_REG_441270_FRAME_TYPE_SHFT 0
+
+#define VIDC_REG_724381_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000ec0)
+#define VIDC_REG_724381_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000ec0)
+#define VIDC_REG_724381_RMSK 0x3
+#define VIDC_REG_724381_SHFT 0
+#define VIDC_REG_724381_IN \
+ in_dword_masked(VIDC_REG_724381_ADDR, \
+ VIDC_REG_724381_RMSK)
+#define VIDC_REG_724381_INM(m) \
+ in_dword_masked(VIDC_REG_724381_ADDR, m)
+#define VIDC_REG_724381_MORE_FIELD_NEEDED_BMSK 0x4
+#define VIDC_REG_724381_MORE_FIELD_NEEDED_SHFT 0x2
+#define VIDC_REG_724381_OPERATION_FAILED_BMSK 0x2
+#define VIDC_REG_724381_OPERATION_FAILED_SHFT 0x1
+#define VIDC_REG_724381_RESOLUTION_CHANGE_BMSK 0x1
+#define VIDC_REG_724381_RESOLUTION_CHANGE_SHFT 0
+
+#define VIDC_REG_854681_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000ec4)
+#define VIDC_REG_854681_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000ec4)
+#define VIDC_REG_854681_RMSK 0x7f
+#define VIDC_REG_854681_SHFT 0
+#define VIDC_REG_854681_OUT(v) \
+ out_dword(VIDC_REG_854681_ADDR, v)
+
+#define VIDC_REG_128234_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000ec8)
+#define VIDC_REG_128234_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000ec8)
+#define VIDC_REG_128234_RMSK 0xffff000f
+#define VIDC_REG_128234_SHFT 0
+#define VIDC_REG_128234_OUT(v) \
+ out_dword(VIDC_REG_128234_ADDR, v)
+
+#define VIDC_REG_1137_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000ecc)
+#define VIDC_REG_1137_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000ecc)
+#define VIDC_REG_1137_RMSK 0xffffffff
+#define VIDC_REG_1137_SHFT 0
+#define VIDC_REG_1137_IN \
+ in_dword_masked(VIDC_REG_1137_ADDR, \
+ VIDC_REG_1137_RMSK)
+#define VIDC_REG_1137_INM(m) \
+ in_dword_masked(VIDC_REG_1137_ADDR, m)
+#define VIDC_REG_1137_METADATA_DISPLAY_INDEX_BMSK \
+ 0xffffffff
+#define \
+ \
+VIDC_REG_1137_METADATA_DISPLAY_INDEX_SHFT 0
+
+#define VIDC_REG_988552_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000ed0)
+#define VIDC_REG_988552_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000ed0)
+#define VIDC_REG_988552_RMSK 0xffffffff
+#define VIDC_REG_988552_SHFT 0
+#define VIDC_REG_988552_OUT(v) \
+ out_dword(VIDC_REG_988552_ADDR, v)
+
+#define VIDC_REG_319934_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000ed4)
+#define VIDC_REG_319934_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000ed4)
+#define VIDC_REG_319934_RMSK 0xffffffff
+#define VIDC_REG_319934_SHFT 0
+#define VIDC_REG_319934_OUT(v) \
+ out_dword(VIDC_REG_319934_ADDR, v)
+
+#define VIDC_REG_679165_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000ed8)
+#define VIDC_REG_679165_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000ed8)
+#define VIDC_REG_679165_RMSK 0xffffffff
+#define VIDC_REG_679165_SHFT 0
+#define VIDC_REG_679165_IN \
+ in_dword_masked(VIDC_REG_679165_ADDR, \
+ VIDC_REG_679165_RMSK)
+#define VIDC_REG_679165_INM(m) \
+ in_dword_masked(VIDC_REG_679165_ADDR, m)
+#define VIDC_REG_679165_PIC_TIME_TOP_BMSK 0xffffffff
+#define VIDC_REG_679165_PIC_TIME_TOP_SHFT 0
+
+#define VIDC_REG_374150_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000edc)
+#define VIDC_REG_374150_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000edc)
+#define VIDC_REG_374150_RMSK 0xffffffff
+#define VIDC_REG_374150_SHFT 0
+#define VIDC_REG_374150_IN \
+ in_dword_masked(VIDC_REG_374150_ADDR, \
+ VIDC_REG_374150_RMSK)
+#define VIDC_REG_374150_INM(m) \
+ in_dword_masked(VIDC_REG_374150_ADDR, m)
+#define VIDC_REG_374150_PIC_TIME_BOTTOM_BMSK 0xffffffff
+#define VIDC_REG_374150_PIC_TIME_BOTTOM_SHFT 0
+
+#define VIDC_REG_94750_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000ee0)
+#define VIDC_REG_94750_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000ee0)
+#define VIDC_REG_94750_RMSK 0xffffffff
+#define VIDC_REG_94750_SHFT 0
+#define VIDC_REG_94750_OUT(v) \
+ out_dword(VIDC_REG_94750_ADDR, v)
+
+#define VIDC_REG_438677_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000ee4)
+#define VIDC_REG_438677_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000ee4)
+#define VIDC_REG_438677_RMSK 0xffffffff
+#define VIDC_REG_438677_SHFT 0
+#define VIDC_REG_438677_IN \
+ in_dword_masked(VIDC_REG_438677_ADDR, \
+ VIDC_REG_438677_RMSK)
+#define VIDC_REG_438677_INM(m) \
+ in_dword_masked(VIDC_REG_438677_ADDR, m)
+#define VIDC_REG_438677_GET_FRAME_TAG_BOTTOM_BMSK 0xffffffff
+#define VIDC_REG_438677_GET_FRAME_TAG_BOTTOM_SHFT 0
+
+#define VIDC_REG_76706_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000ee8)
+#define VIDC_REG_76706_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000ee8)
+#define VIDC_REG_76706_RMSK 0x1
+#define VIDC_REG_76706_SHFT 0
+#define VIDC_REG_76706_OUT(v) \
+ out_dword(VIDC_REG_76706_ADDR, v)
+
+#define VIDC_REG_809984_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00001000)
+#define VIDC_REG_809984_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00001000)
+#define VIDC_REG_809984_RMSK 0xffff0007
+#define VIDC_REG_809984_SHFT 0
+#define VIDC_REG_809984_IN \
+ in_dword_masked(VIDC_REG_809984_ADDR, VIDC_REG_809984_RMSK)
+#define VIDC_REG_809984_INM(m) \
+ in_dword_masked(VIDC_REG_809984_ADDR, m)
+#define VIDC_REG_809984_720PV_720P_WRAPPER_VERSION_BMSK 0xffff0000
+#define VIDC_REG_809984_720PV_720P_WRAPPER_VERSION_SHFT 0x10
+#define VIDC_REG_809984_TEST_MUX_SEL_BMSK 0x7
+#define VIDC_REG_809984_TEST_MUX_SEL_SHFT 0
+
+
+#define VIDC_REG_699747_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000d0c)
+#define VIDC_REG_699747_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000d0c)
+#define VIDC_REG_699747_RMSK 0xffffffff
+#define VIDC_REG_699747_SHFT 0
+#define VIDC_REG_699747_OUT(v) \
+ out_dword(VIDC_REG_699747_ADDR, v)
+
+#define VIDC_REG_166247_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000d10)
+#define VIDC_REG_166247_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000d10)
+#define VIDC_REG_166247_RMSK 0xffffffff
+#define VIDC_REG_166247_SHFT 0
+#define VIDC_REG_166247_OUT(v) \
+ out_dword(VIDC_REG_166247_ADDR, v)
+
+#define VIDC_REG_486169_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000d18)
+#define VIDC_REG_486169_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000d18)
+#define VIDC_REG_486169_RMSK 0xffffffff
+#define VIDC_REG_486169_SHFT 0
+#define VIDC_REG_486169_OUT(v) \
+ out_dword(VIDC_REG_486169_ADDR, v)
+
+#define VIDC_REG_926519_ADDR \
+ (VIDC_720P_WRAPPER_REG_BASE + 0x00000d1c)
+#define VIDC_REG_926519_PHYS \
+ (VIDC_720P_WRAPPER_REG_BASE_PHYS + 0x00000d1c)
+#define VIDC_REG_926519_RMSK 0xffffffff
+#define VIDC_REG_926519_SHFT 0
+#define VIDC_REG_926519_OUT(v) \
+ out_dword(VIDC_REG_926519_ADDR, v)
+
+/** List all the levels and their register valus */
+
+#define VIDC_720P_PROFILE_MPEG4_SP 0
+#define VIDC_720P_PROFILE_MPEG4_ASP 1
+#define VIDC_720P_PROFILE_H264_BASELINE 0
+#define VIDC_720P_PROFILE_H264_MAIN 1
+#define VIDC_720P_PROFILE_H264_HIGH 2
+#define VIDC_720P_PROFILE_H264_CPB 3
+#define VIDC_720P_PROFILE_H263_BASELINE 0
+
+#define VIDC_720P_PROFILE_VC1_SP 0
+#define VIDC_720P_PROFILE_VC1_MAIN 1
+#define VIDC_720P_PROFILE_VC1_ADV 2
+#define VIDC_720P_PROFILE_MPEG2_MAIN 4
+#define VIDC_720P_PROFILE_MPEG2_SP 5
+
+#define VIDC_720P_MPEG4_LEVEL0 0
+#define VIDC_720P_MPEG4_LEVEL0b 9
+#define VIDC_720P_MPEG4_LEVEL1 1
+#define VIDC_720P_MPEG4_LEVEL2 2
+#define VIDC_720P_MPEG4_LEVEL3 3
+#define VIDC_720P_MPEG4_LEVEL3b 7
+#define VIDC_720P_MPEG4_LEVEL4a 4
+#define VIDC_720P_MPEG4_LEVEL5 5
+#define VIDC_720P_MPEG4_LEVEL6 6
+
+#define VIDC_720P_H264_LEVEL1 10
+#define VIDC_720P_H264_LEVEL1b 9
+#define VIDC_720P_H264_LEVEL1p1 11
+#define VIDC_720P_H264_LEVEL1p2 12
+#define VIDC_720P_H264_LEVEL1p3 13
+#define VIDC_720P_H264_LEVEL2 20
+#define VIDC_720P_H264_LEVEL2p1 21
+#define VIDC_720P_H264_LEVEL2p2 22
+#define VIDC_720P_H264_LEVEL3 30
+#define VIDC_720P_H264_LEVEL3p1 31
+#define VIDC_720P_H264_LEVEL3p2 32
+
+#define VIDC_720P_H263_LEVEL10 10
+#define VIDC_720P_H263_LEVEL20 20
+#define VIDC_720P_H263_LEVEL30 30
+#define VIDC_720P_H263_LEVEL40 40
+#define VIDC_720P_H263_LEVEL45 45
+#define VIDC_720P_H263_LEVEL50 50
+#define VIDC_720P_H263_LEVEL60 60
+#define VIDC_720P_H263_LEVEL70 70
+
+#define VIDC_720P_VC1_LEVEL_LOW 0
+#define VIDC_720P_VC1_LEVEL_MED 2
+#define VIDC_720P_VC1_LEVEL_HIGH 4
+#define VIDC_720P_VC1_LEVEL0 0
+#define VIDC_720P_VC1_LEVEL1 1
+#define VIDC_720P_VC1_LEVEL2 2
+#define VIDC_720P_VC1_LEVEL3 3
+#define VIDC_720P_VC1_LEVEL4 4
+
+#define VIDCL_720P_MPEG2_LEVEL_LOW 10
+#define VIDCL_720P_MPEG2_LEVEL_MAIN 8
+#define VIDCL_720P_MPEG2_LEVEL_HIGH14 6
+
+#define VIDC_720P_CMD_CHSET 0x0
+#define VIDC_720P_CMD_CHEND 0x2
+#define VIDC_720P_CMD_INITCODEC 0x3
+#define VIDC_720P_CMD_FRAMERUN 0x4
+#define VIDC_720P_CMD_INITBUFFERS 0x5
+#define VIDC_720P_CMD_FRAMERUN_REALLOCATE 0x6
+#define VIDC_720P_CMD_MFC_ENGINE_RESET 0x7
+
+enum vidc_720p_endian {
+ VIDC_720P_BIG_ENDIAN = 0x0,
+ VIDC_720P_LITTLE_ENDIAN = 0x1
+};
+
+enum vidc_720p_memory_access_method {
+ VIDC_720P_TILE_LINEAR = 0,
+ VIDC_720P_TILE_16x16 = 2,
+ VIDC_720P_TILE_64x32 = 3
+};
+
+enum vidc_720p_interrupt_control_mode {
+ VIDC_720P_INTERRUPT_MODE = 0,
+ VIDC_720P_POLL_MODE = 1
+};
+
+enum vidc_720p_interrupt_level_selection {
+ VIDC_720P_INTERRUPT_LEVEL_SEL = 0,
+ VIDC_720P_INTERRUPT_PULSE_SEL = 1
+};
+
+#define VIDC_720P_INTR_BUFFER_FULL 0x002
+#define VIDC_720P_INTR_FW_DONE 0x020
+#define VIDC_720P_INTR_HEADER_DONE 0x040
+#define VIDC_720P_INTR_DMA_DONE 0x080
+#define VIDC_720P_INTR_FRAME_DONE 0x100
+
+enum vidc_720p_enc_dec_selection {
+ VIDC_720P_DECODER = 0,
+ VIDC_720P_ENCODER = 1
+};
+
+enum vidc_720p_codec {
+ VIDC_720P_MPEG4 = 0,
+ VIDC_720P_H264 = 1,
+ VIDC_720P_DIVX = 2,
+ VIDC_720P_XVID = 3,
+ VIDC_720P_H263 = 4,
+ VIDC_720P_MPEG2 = 5,
+ VIDC_720P_VC1 = 6
+};
+
+enum vidc_720p_frame {
+ VIDC_720P_NOTCODED = 0,
+ VIDC_720P_IFRAME = 1,
+ VIDC_720P_PFRAME = 2,
+ VIDC_720P_BFRAME = 3
+};
+
+enum vidc_720p_entropy_sel {
+ VIDC_720P_ENTROPY_SEL_CAVLC = 0,
+ VIDC_720P_ENTROPY_SEL_CABAC = 1
+};
+
+enum vidc_720p_cabac_model {
+ VIDC_720P_CABAC_MODEL_NUMBER_0 = 0,
+ VIDC_720P_CABAC_MODEL_NUMBER_1 = 1,
+ VIDC_720P_CABAC_MODEL_NUMBER_2 = 2
+};
+
+enum vidc_720p_DBConfig {
+ VIDC_720P_DB_ALL_BLOCKING_BOUNDARY = 0,
+ VIDC_720P_DB_DISABLE = 1,
+ VIDC_720P_DB_SKIP_SLICE_BOUNDARY = 2
+};
+
+enum vidc_720p_MSlice_selection {
+ VIDC_720P_MSLICE_BY_MB_COUNT = 0,
+ VIDC_720P_MSLICE_BY_BYTE_COUNT = 1,
+ VIDC_720P_MSLICE_BY_GOB = 2,
+ VIDC_720P_MSLICE_OFF = 3
+};
+
+enum vidc_720p_display_status {
+ VIDC_720P_DECODE_ONLY = 0,
+ VIDC_720P_DECODE_AND_DISPLAY = 1,
+ VIDC_720P_DISPLAY_ONLY = 2,
+ VIDC_720P_EMPTY_BUFFER = 3
+};
+
+#define VIDC_720P_ENC_IFRAME_REQ 0x1
+#define VIDC_720P_ENC_IPERIOD_CHANGE 0x1
+#define VIDC_720P_ENC_FRAMERATE_CHANGE 0x2
+#define VIDC_720P_ENC_BITRATE_CHANGE 0x4
+
+#define VIDC_720P_FLUSH_REQ 0x1
+#define VIDC_720P_EXTRADATA 0x2
+
+#define VIDC_720P_METADATA_ENABLE_QP 0x01
+#define VIDC_720P_METADATA_ENABLE_CONCEALMB 0x02
+#define VIDC_720P_METADATA_ENABLE_VC1 0x04
+#define VIDC_720P_METADATA_ENABLE_SEI 0x08
+#define VIDC_720P_METADATA_ENABLE_VUI 0x10
+#define VIDC_720P_METADATA_ENABLE_ENCSLICE 0x20
+#define VIDC_720P_METADATA_ENABLE_PASSTHROUGH 0x40
+
+struct vidc_720p_dec_disp_info {
+ enum vidc_720p_display_status disp_status;
+ u32 resl_change;
+ u32 reconfig_flush_done;
+ u32 img_size_x;
+ u32 img_size_y;
+ u32 y_addr;
+ u32 c_addr;
+ u32 tag_top;
+ u32 pic_time_top;
+ u32 disp_is_interlace;
+ u32 tag_bottom;
+ u32 pic_time_bottom;
+ u32 metadata_exists;
+ u32 crop_exists;
+ u32 crop_right_offset;
+ u32 crop_left_offset;
+ u32 crop_bottom_offset;
+ u32 crop_top_offset;
+ u32 input_frame;
+ u32 input_bytes_consumed;
+ u32 input_is_interlace;
+ u32 input_frame_num;
+};
+
+struct vidc_720p_seq_hdr_info {
+ u32 img_size_x;
+ u32 img_size_y;
+ u32 dec_frm_size;
+ u32 min_num_dpb;
+ u32 min_dpb_size;
+ u32 profile;
+ u32 level;
+ u32 progressive;
+ u32 data_partitioned;
+ u32 crop_exists;
+ u32 crop_right_offset;
+ u32 crop_left_offset;
+ u32 crop_bottom_offset;
+ u32 crop_top_offset;
+};
+
+struct vidc_720p_enc_frame_info {
+ u32 enc_size;
+ u32 frame;
+ u32 metadata_exists;
+};
+
+void vidc_720p_set_device_virtual_base(u8 *core_virtual_base_addr);
+
+void vidc_720p_init(char **ppsz_version, u32 i_firmware_size,
+ u32 *pi_firmware_address, enum vidc_720p_endian dma_endian,
+ u32 interrupt_off,
+ enum vidc_720p_interrupt_level_selection interrupt_sel,
+ u32 interrupt_mask);
+
+u32 vidc_720p_do_sw_reset(void);
+
+u32 vidc_720p_reset_is_success(void);
+
+void vidc_720p_start_cpu(enum vidc_720p_endian dma_endian,
+ u32 *icontext_bufferstart, u32 *debug_core_dump_addr,
+ u32 debug_buffer_size);
+
+u32 vidc_720p_cpu_start(void);
+
+void vidc_720p_stop_fw(void);
+
+void vidc_720p_get_interrupt_status(u32 *interrupt_status,
+ u32 *cmd_err_status, u32 *disp_pic_err_status,
+ u32 *op_failed);
+
+void vidc_720p_interrupt_done_clear(void);
+
+void vidc_720p_submit_command(u32 ch_id, u32 cmd_id);
+
+
+void vidc_720p_set_channel(u32 i_ch_id,
+ enum vidc_720p_enc_dec_selection enc_dec_sel,
+ enum vidc_720p_codec codec, u32 *pi_fw, u32 i_firmware_size);
+
+u32 vidc_720p_engine_reset(u32 ch_id,
+ enum vidc_720p_endian dma_endian,
+ enum vidc_720p_interrupt_level_selection interrupt_sel,
+ u32 interrupt_mask
+);
+
+void vidc_720p_encode_set_profile(u32 i_profile, u32 i_level);
+
+void vidc_720p_set_frame_size(u32 i_size_x, u32 i_size_y);
+
+void vidc_720p_encode_set_fps(u32 i_rc_frame_rate);
+
+void vidc_720p_encode_set_vop_time(u32 vop_time_resolution,
+ u32 vop_time_increment);
+
+void vidc_720p_encode_set_hec_period(u32 hec_period);
+
+void vidc_720p_encode_set_short_header(u32 i_short_header);
+
+void vidc_720p_encode_set_qp_params(u32 i_max_qp, u32 i_min_qp);
+
+void vidc_720p_encode_set_rc_config(u32 enable_frame_level_rc,
+ u32 enable_mb_level_rc_flag, u32 i_frame_qp, u32 pframe_qp);
+
+void vidc_720p_encode_set_bit_rate(u32 i_target_bitrate);
+
+void vidc_720p_encoder_set_param_change(u32 enc_param_change);
+
+void vidc_720p_encode_set_control_param(u32 param_val);
+
+void vidc_720p_encode_set_frame_level_rc_params(u32 i_reaction_coeff);
+
+void vidc_720p_encode_set_mb_level_rc_params(u32 dark_region_as_flag,
+ u32 smooth_region_as_flag, u32 static_region_as_flag,
+ u32 activity_region_flag);
+
+void vidc_720p_encode_set_entropy_control(enum vidc_720p_entropy_sel \
+ entropy_sel,
+ enum vidc_720p_cabac_model cabac_model_number);
+
+void vidc_720p_encode_set_db_filter_control(enum vidc_720p_DBConfig
+ db_config, u32 i_slice_alpha_offset, u32 i_slice_beta_offset);
+
+void vidc_720p_encode_set_intra_refresh_mb_number(u32 i_cir_mb_number);
+
+void vidc_720p_encode_set_multi_slice_info(
+ enum vidc_720p_MSlice_selection m_slice_sel,
+ u32 multi_slice_size);
+
+void vidc_720p_encode_set_dpb_buffer(u32 *pi_enc_dpb_addr, u32 alloc_len);
+
+void vidc_720p_set_deblock_line_buffer(u32 *pi_deblock_line_buffer_start,
+ u32 alloc_len);
+
+void vidc_720p_encode_set_i_period(u32 i_i_period);
+
+void vidc_720p_encode_init_codec(u32 i_ch_id,
+ enum vidc_720p_memory_access_method memory_access_model);
+
+void vidc_720p_encode_unalign_bitstream(u32 upper_unalign_word,
+ u32 lower_unalign_word);
+
+void vidc_720p_encode_set_seq_header_buffer(u32 ext_buffer_start,
+ u32 ext_buffer_end, u32 start_byte_num);
+
+void vidc_720p_encode_frame(u32 ch_id, u32 ext_buffer_start,
+ u32 ext_buffer_end, u32 start_byte_number,
+ u32 y_addr, u32 c_addr);
+
+void vidc_720p_encode_get_header(u32 *pi_enc_header_size);
+
+void vidc_720p_enc_frame_info
+ (struct vidc_720p_enc_frame_info *enc_frame_info);
+
+void vidc_720p_decode_bitstream_header(u32 ch_id, u32 dec_unit_size,
+ u32 start_byte_num, u32 ext_buffer_start, u32 ext_buffer_end,
+ enum vidc_720p_memory_access_method memory_access_model,
+ u32 decode_order);
+
+void vidc_720p_decode_get_seq_hdr_info
+ (struct vidc_720p_seq_hdr_info *seq_hdr_info);
+
+void vidc_720p_decode_set_dpb_release_buffer_mask
+ (u32 i_dpb_release_buffer_mask);
+
+void vidc_720p_decode_set_dpb_buffers(u32 i_buf_index, u32 *pi_dpb_buffer);
+
+void vidc_720p_decode_set_comv_buffer
+ (u32 *pi_dpb_comv_buffer, u32 alloc_len);
+
+void vidc_720p_decode_set_dpb_details
+ (u32 num_dpb, u32 alloc_len, u32 *ref_buffer);
+
+void vidc_720p_decode_set_mpeg4Post_filter(u32 enable_post_filter);
+
+void vidc_720p_decode_set_error_control(u32 enable_error_control);
+
+void vidc_720p_decode_set_mpeg4_data_partitionbuffer(u32 *vsp_buf_start);
+
+void vidc_720p_decode_setH264VSPBuffer(u32 *pi_vsp_temp_buffer_start);
+
+void vidc_720p_decode_frame(u32 ch_id, u32 ext_buffer_start,
+ u32 ext_buffer_end, u32 dec_unit_size,
+ u32 start_byte_num, u32 input_frame_tag);
+
+void vidc_720p_issue_eos(u32 i_ch_id);
+void vidc_720p_eos_info(u32 *disp_status, u32 *resl_change);
+
+void vidc_720p_decode_display_info
+ (struct vidc_720p_dec_disp_info *disp_info);
+
+void vidc_720p_decode_skip_frm_details(u32 *free_luma_dpb);
+
+void vidc_720p_metadata_enable(u32 flag, u32 *input_buffer);
+
+void vidc_720p_decode_dynamic_req_reset(void);
+
+void vidc_720p_decode_dynamic_req_set(u32 property);
+
+void vidc_720p_decode_setpassthrough_start(u32 pass_startaddr);
+
+
+
+#define DDL_720P_REG_BASE VIDC_720P_WRAPPER_REG_BASE
+#define VIDC_BUSY_WAIT(n) udelay(n)
+
+#undef VIDC_REGISTER_LOG_MSG
+#undef VIDC_REGISTER_LOG_INTO_BUFFER
+
+#ifdef VIDC_REGISTER_LOG_MSG
+#define VIDC_MSG1(msg_format, a) printk(KERN_INFO msg_format, a)
+#define VIDC_MSG2(msg_format, a, b) printk(KERN_INFO msg_format, a, b)
+#define VIDC_MSG3(msg_format, a, b, c) printk(KERN_INFO msg_format, a, b, c)
+#else
+#define VIDC_MSG1(msg_format, a)
+#define VIDC_MSG2(msg_format, a, b)
+#define VIDC_MSG3(msg_format, a, b, c)
+#endif
+
+#ifdef VIDC_REGISTER_LOG_INTO_BUFFER
+
+#define VIDC_REGLOG_BUFSIZE 200000
+#define VIDC_REGLOG_MAX_PRINT_SIZE 100
+extern char vidclog[VIDC_REGLOG_BUFSIZE];
+extern unsigned int vidclog_index;
+
+#define VIDC_LOG_BUFFER_INIT \
+{if (vidclog_index) \
+ memset(vidclog, 0, vidclog_index+1); \
+ vidclog_index = 0; }
+
+#define VIDC_REGLOG_CHECK_BUFINDEX(req_size) \
+ vidclog_index = \
+ (vidclog_index+(req_size) < VIDC_REGLOG_BUFSIZE) ? vidclog_index : 0;
+
+#define VIDC_LOG_WRITE(reg, val) \
+{unsigned int len; \
+ VIDC_REGLOG_CHECK_BUFINDEX(VIDC_REGLOG_MAX_PRINT_SIZE); \
+ len = snprintf(&vidclog[vidclog_index], VIDC_REGLOG_MAX_PRINT_SIZE, \
+ "(0x%x:"#reg"=0x%x)" , VIDC_##reg##_ADDR - DDL_720P_REG_BASE, val);\
+ vidclog_index += len; }
+
+#define VIDC_LOG_WRITEI(reg, index, val) \
+{unsigned int len; \
+ VIDC_REGLOG_CHECK_BUFINDEX(VIDC_REGLOG_MAX_PRINT_SIZE); \
+ len = snprintf(&vidclog[vidclog_index], VIDC_REGLOG_MAX_PRINT_SIZE, \
+ "(0x%x:"#reg"=0x%x)" , VIDC_##reg##_ADDR(index)-DDL_720P_REG_BASE, \
+ val); vidclog_index += len; }
+
+#define VIDC_LOG_WRITEF(reg, field, val) \
+{unsigned int len; \
+ VIDC_REGLOG_CHECK_BUFINDEX(VIDC_REGLOG_MAX_PRINT_SIZE); \
+ len = snprintf(&vidclog[vidclog_index], VIDC_REGLOG_MAX_PRINT_SIZE, \
+ "(0x%x:"#reg":0x%x:=0x%x)" , VIDC_##reg##_ADDR - DDL_720P_REG_BASE, \
+ VIDC_##reg##_##field##_BMSK, val);\
+ vidclog_index += len; }
+
+#define VIDC_LOG_READ(reg, pval) \
+{ unsigned int len; \
+ VIDC_REGLOG_CHECK_BUFINDEX(VIDC_REGLOG_MAX_PRINT_SIZE); \
+ len = snprintf(&vidclog[vidclog_index], VIDC_REGLOG_MAX_PRINT_SIZE, \
+ "(0x%x:"#reg"==0x%x)" , VIDC_##reg##_ADDR - DDL_720P_REG_BASE, \
+ (u32)*pval); \
+ vidclog_index += len; }
+
+#define VIDC_STR_LOGBUFFER(str) \
+{ unsigned int len; \
+ VIDC_REGLOG_CHECK_BUFINDEX(VIDC_REGLOG_MAX_PRINT_SIZE); \
+ len = snprintf(&vidclog[vidclog_index], VIDC_REGLOG_MAX_PRINT_SIZE, \
+ "<%s>" , str); vidclog_index += len; }
+
+#define VIDC_LONG_LOGBUFFER(str, arg1) \
+{ unsigned int len; \
+ VIDC_REGLOG_CHECK_BUFINDEX(VIDC_REGLOG_MAX_PRINT_SIZE); \
+ len = snprintf(&vidclog[vidclog_index], VIDC_REGLOG_MAX_PRINT_SIZE, \
+ "<%s=0x%x>" , str, arg1); vidclog_index += len; }
+
+#define VIDC_DEBUG_REGISTER_LOG \
+{ u32 val; unsigned int len; \
+ val = VIDC_720P_IN(REG_881638); \
+ VIDC_REGLOG_CHECK_BUFINDEX(VIDC_REGLOG_MAX_PRINT_SIZE); \
+ len = snprintf(&vidclog[vidclog_index], 50, "[dbg1=%x]" , val); \
+ vidclog_index += len; \
+ val = VIDC_720P_IN(REG_161486); \
+ VIDC_REGLOG_CHECK_BUFINDEX(VIDC_REGLOG_MAX_PRINT_SIZE); \
+ len = snprintf(&vidclog[vidclog_index], 50, "[dbg2=%x]" , val); \
+ vidclog_index += len; }
+
+#else
+#define VIDC_LOG_WRITE(reg, val)
+#define VIDC_LOG_WRITEI(reg, index, val)
+#define VIDC_LOG_WRITEF(reg, field, val)
+#define VIDC_LOG_READ(reg, pval)
+#define VIDC_LOG_BUFFER_INIT
+#define VIDC_STR_LOGBUFFER(str)
+#define VIDC_LONG_LOGBUFFER(str, arg1)
+#define VIDC_DEBUG_REGISTER_LOG
+#endif
+
+void vidcputlog(char *str);
+void vidcput_debug_reglog(void);
+
+#define VIDC_LOGERR_STRING(str) \
+do { \
+ VIDC_STR_LOGBUFFER(str); \
+ VIDC_MSG1("\n<%s>", str); \
+} while (0)
+
+#define VIDC_LOG_STRING(str) \
+do { \
+ VIDC_STR_LOGBUFFER(str); \
+ VIDC_MSG1("\n<%s>", str); \
+} while (0)
+
+#define VIDC_LOG1(str, arg1) \
+do { \
+ VIDC_LONG_LOGBUFFER(str, arg1); \
+ VIDC_MSG2("\n<%s=0x%08x>", str, arg1); \
+} while (0)
+
+#define VIDC_IO_OUT(reg, val) \
+do { \
+ VIDC_LOG_WRITE(reg, (u32)val); \
+ VIDC_MSG2("\n(0x%08x:"#reg"=0x%08x)", \
+ (u32)(VIDC_##reg##_ADDR - DDL_720P_REG_BASE), (u32)val); \
+ mb(); \
+ VIDC_720P_OUT(reg, val); \
+} while (0)
+
+#define VIDC_IO_OUTI(reg, index, val) \
+do { \
+ VIDC_LOG_WRITEI(reg, index, (u32)val); \
+ VIDC_MSG2("\n(0x%08x:"#reg"=0x%08x)", \
+ (u32)(VIDC_##reg##_ADDR(index)-DDL_720P_REG_BASE), (u32)val); \
+ mb(); \
+ VIDC_720P_OUTI(reg, index, val); \
+} while (0)
+
+#define VIDC_IO_OUTF(reg, field, val) \
+do { \
+ VIDC_LOG_WRITEF(reg, field, val); \
+ VIDC_MSG3("\n(0x%08x:"#reg":0x%x:=0x%08x)", \
+ (u32)(VIDC_##reg##_ADDR - DDL_720P_REG_BASE), \
+ VIDC_##reg##_##field##_BMSK, (u32)val); \
+ mb(); \
+ VIDC_720P_OUTF(reg, field, val); \
+} while (0)
+
+#define VIDC_IO_IN(reg, pval) \
+do { \
+ mb(); \
+ *pval = (u32) VIDC_720P_IN(reg); \
+ VIDC_LOG_READ(reg, pval); \
+ VIDC_MSG2("\n(0x%08x:"#reg"==0x%08x)", \
+ (u32)(VIDC_##reg##_ADDR - DDL_720P_REG_BASE), (u32) *pval); \
+} while (0)
+
+#define VIDC_IO_INF(reg, mask, pval) \
+do { \
+ mb(); \
+ *pval = VIDC_720P_INF(reg, mask); \
+ VIDC_LOG_READ(reg, pval); \
+ VIDC_MSG2("\n(0x%08x:"#reg"==0x%08x)", \
+ (u32)(VIDC_##reg##_ADDR - DDL_720P_REG_BASE), *pval); \
+} while (0)
+
+#endif
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
new file mode 100644
index 0000000..12dcbf3
--- /dev/null
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
@@ -0,0 +1,722 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/firmware.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/regulator/consumer.h>
+#include <mach/clk.h>
+#include <mach/msm_reqs.h>
+#include <linux/interrupt.h>
+#include "vidc_type.h"
+#include "vcd_res_tracker.h"
+#include "vidc_init.h"
+
+#define MSM_AXI_QOS_NAME "msm_vidc_reg"
+#define AXI_CLK_SCALING
+
+#define QVGA_PERF_LEVEL (300 * 30)
+#define VGA_PERF_LEVEL (1200 * 30)
+#define WVGA_PERF_LEVEL (1500 * 30)
+
+static unsigned int mfc_clk_freq_table[3] = {
+ 61440000, 122880000, 170667000
+};
+
+#ifndef CONFIG_MSM_NPA_SYSTEM_BUS
+static unsigned int axi_clk_freq_table_enc[2] = {
+ 122880, 192000
+};
+static unsigned int axi_clk_freq_table_dec[2] = {
+ 122880, 192000
+};
+#else
+static unsigned int axi_clk_freq_table_enc[2] = {
+ MSM_AXI_FLOW_VIDEO_RECORDING_720P,
+ MSM_AXI_FLOW_VIDEO_RECORDING_720P
+};
+static unsigned int axi_clk_freq_table_dec[2] = {
+ MSM_AXI_FLOW_VIDEO_PLAYBACK_720P,
+ MSM_AXI_FLOW_VIDEO_PLAYBACK_720P
+};
+#endif
+
+static struct res_trk_context resource_context;
+
+#define VIDC_BOOT_FW "vidc_720p_command_control.fw"
+#define VIDC_MPG4_DEC_FW "vidc_720p_mp4_dec_mc.fw"
+#define VIDC_H263_DEC_FW "vidc_720p_h263_dec_mc.fw"
+#define VIDC_H264_DEC_FW "vidc_720p_h264_dec_mc.fw"
+#define VIDC_MPG4_ENC_FW "vidc_720p_mp4_enc_mc.fw"
+#define VIDC_H264_ENC_FW "vidc_720p_h264_enc_mc.fw"
+#define VIDC_VC1_DEC_FW "vidc_720p_vc1_dec_mc.fw"
+
+unsigned char *vidc_command_control_fw;
+u32 vidc_command_control_fw_size;
+
+unsigned char *vidc_mpg4_dec_fw;
+u32 vidc_mpg4_dec_fw_size;
+
+unsigned char *vidc_h263_dec_fw;
+u32 vidc_h263_dec_fw_size;
+
+unsigned char *vidc_h264_dec_fw;
+u32 vidc_h264_dec_fw_size;
+
+unsigned char *vidc_mpg4_enc_fw;
+u32 vidc_mpg4_enc_fw_size;
+
+unsigned char *vidc_h264_enc_fw;
+u32 vidc_h264_enc_fw_size;
+
+unsigned char *vidc_vc1_dec_fw;
+u32 vidc_vc1_dec_fw_size;
+
+static u32 res_trk_disable_videocore(void)
+{
+ int rc = -1;
+ mutex_lock(&resource_context.lock);
+
+ if (!resource_context.rail_enabled) {
+ mutex_unlock(&resource_context.lock);
+ return false;
+ }
+
+ if (!resource_context.clock_enabled &&
+ resource_context.pclk &&
+ resource_context.hclk &&
+ resource_context.hclk_div2) {
+
+ VCDRES_MSG_LOW("\nEnabling clk before disabling pwr rail\n");
+ if (clk_set_rate(resource_context.hclk,
+ mfc_clk_freq_table[0])) {
+ VCDRES_MSG_ERROR("\n pwr_rail_disable:"
+ " set clk rate failed\n");
+ goto bail_out;
+ }
+
+ if (clk_enable(resource_context.pclk)) {
+ VCDRES_MSG_ERROR("vidc pclk Enable failed\n");
+ goto bail_out;
+ }
+
+ if (clk_enable(resource_context.hclk)) {
+ VCDRES_MSG_ERROR("vidc hclk Enable failed\n");
+ goto disable_pclk;
+ }
+
+ if (clk_enable(resource_context.hclk_div2)) {
+ VCDRES_MSG_ERROR("vidc hclk_div2 Enable failed\n");
+ goto disable_hclk;
+ }
+ } else {
+ VCDRES_MSG_ERROR("\ndisabling pwr rail: Enabling clk failed\n");
+ goto bail_out;
+ }
+
+ resource_context.rail_enabled = 0;
+ rc = clk_reset(resource_context.pclk, CLK_RESET_ASSERT);
+ if (rc) {
+ VCDRES_MSG_ERROR("\n clk_reset failed %d\n", rc);
+ mutex_unlock(&resource_context.lock);
+ return false;
+ }
+ msleep(20);
+
+ clk_disable(resource_context.pclk);
+ clk_disable(resource_context.hclk);
+ clk_disable(resource_context.hclk_div2);
+
+ clk_put(resource_context.hclk_div2);
+ clk_put(resource_context.hclk);
+ clk_put(resource_context.pclk);
+
+ rc = regulator_disable(resource_context.regulator);
+ if (rc) {
+ VCDRES_MSG_ERROR("\n regulator disable failed %d\n", rc);
+ mutex_unlock(&resource_context.lock);
+ return false;
+ }
+
+ resource_context.hclk_div2 = NULL;
+ resource_context.hclk = NULL;
+ resource_context.pclk = NULL;
+
+ mutex_unlock(&resource_context.lock);
+
+ return true;
+
+disable_hclk:
+ clk_disable(resource_context.hclk);
+disable_pclk:
+ clk_disable(resource_context.pclk);
+bail_out:
+ if (resource_context.pclk) {
+ clk_put(resource_context.pclk);
+ resource_context.pclk = NULL;
+ }
+ if (resource_context.hclk) {
+ clk_put(resource_context.hclk);
+ resource_context.hclk = NULL;
+ }
+ if (resource_context.hclk_div2) {
+ clk_put(resource_context.hclk_div2);
+ resource_context.hclk_div2 = NULL;
+ }
+ mutex_unlock(&resource_context.lock);
+ return false;
+}
+
+u32 res_trk_enable_clocks(void)
+{
+ VCDRES_MSG_LOW("\n in res_trk_enable_clocks()");
+
+ mutex_lock(&resource_context.lock);
+ if (!resource_context.clock_enabled) {
+ VCDRES_MSG_LOW("Enabling IRQ in %s()\n", __func__);
+ enable_irq(resource_context.irq_num);
+
+ VCDRES_MSG_LOW("%s(): Enabling the clocks ...\n", __func__);
+
+ if (clk_enable(resource_context.pclk)) {
+ VCDRES_MSG_ERROR("vidc pclk Enable failed\n");
+
+ clk_put(resource_context.hclk);
+ clk_put(resource_context.hclk_div2);
+ mutex_unlock(&resource_context.lock);
+ return false;
+ }
+
+ if (clk_enable(resource_context.hclk)) {
+ VCDRES_MSG_ERROR("vidc hclk Enable failed\n");
+ clk_put(resource_context.pclk);
+ clk_put(resource_context.hclk_div2);
+ mutex_unlock(&resource_context.lock);
+ return false;
+ }
+
+ if (clk_enable(resource_context.hclk_div2)) {
+ VCDRES_MSG_ERROR("vidc hclk Enable failed\n");
+ clk_put(resource_context.hclk);
+ clk_put(resource_context.pclk);
+ mutex_unlock(&resource_context.lock);
+ return false;
+ }
+ }
+
+ resource_context.clock_enabled = 1;
+ mutex_unlock(&resource_context.lock);
+ return true;
+}
+
+static u32 res_trk_sel_clk_rate(unsigned long hclk_rate)
+{
+ mutex_lock(&resource_context.lock);
+ if (clk_set_rate(resource_context.hclk,
+ hclk_rate)) {
+ VCDRES_MSG_ERROR("vidc hclk set rate failed\n");
+ mutex_unlock(&resource_context.lock);
+ return false;
+ }
+ resource_context.hclk_rate = hclk_rate;
+ mutex_unlock(&resource_context.lock);
+ return true;
+}
+
+static u32 res_trk_get_clk_rate(unsigned long *phclk_rate)
+{
+ if (!phclk_rate) {
+ VCDRES_MSG_ERROR("%s(): phclk_rate is NULL\n", __func__);
+ return false;
+ }
+ mutex_lock(&resource_context.lock);
+ *phclk_rate = clk_get_rate(resource_context.hclk);
+ if (!(*phclk_rate)) {
+ VCDRES_MSG_ERROR("vidc hclk get rate failed\n");
+ mutex_unlock(&resource_context.lock);
+ return false;
+ }
+ mutex_unlock(&resource_context.lock);
+ return true;
+}
+
+u32 res_trk_disable_clocks(void)
+{
+ VCDRES_MSG_LOW("in res_trk_disable_clocks()\n");
+
+ mutex_lock(&resource_context.lock);
+
+ if (!resource_context.clock_enabled) {
+ mutex_unlock(&resource_context.lock);
+ return false;
+ }
+
+ VCDRES_MSG_LOW("Disabling IRQ in %s()\n", __func__);
+ disable_irq_nosync(resource_context.irq_num);
+ VCDRES_MSG_LOW("%s(): Disabling the clocks ...\n", __func__);
+
+ resource_context.clock_enabled = 0;
+ clk_disable(resource_context.hclk);
+ clk_disable(resource_context.hclk_div2);
+ clk_disable(resource_context.pclk);
+ mutex_unlock(&resource_context.lock);
+
+ return true;
+}
+
+static u32 res_trk_enable_videocore(void)
+{
+ mutex_lock(&resource_context.lock);
+ if (!resource_context.rail_enabled) {
+ int rc = -1;
+
+ rc = regulator_enable(resource_context.regulator);
+ if (rc) {
+ VCDRES_MSG_ERROR("%s(): regulator_enable failed %d\n",
+ __func__, rc);
+ goto bail_out;
+ }
+ VCDRES_MSG_LOW("%s(): regulator enable Success %d\n",
+ __func__, rc);
+
+ resource_context.pclk = clk_get(resource_context.device,
+ "mfc_pclk");
+
+ if (IS_ERR(resource_context.pclk)) {
+ VCDRES_MSG_ERROR("%s(): mfc_pclk get failed\n"
+ , __func__);
+ goto disable_regulator;
+ }
+
+ resource_context.hclk = clk_get(resource_context.device,
+ "mfc_clk");
+
+ if (IS_ERR(resource_context.hclk)) {
+ VCDRES_MSG_ERROR("%s(): mfc_clk get failed\n"
+ , __func__);
+
+ goto release_pclk;
+ }
+
+ resource_context.hclk_div2 =
+ clk_get(resource_context.device, "mfc_div2_clk");
+
+ if (IS_ERR(resource_context.hclk_div2)) {
+ VCDRES_MSG_ERROR("%s(): mfc_div2_clk get failed\n"
+ , __func__);
+ goto release_hclk_pclk;
+ }
+
+ if (clk_set_rate(resource_context.hclk,
+ mfc_clk_freq_table[0])) {
+ VCDRES_MSG_ERROR("\n pwr_rail_enable:"
+ " set clk rate failed\n");
+ goto release_all_clks;
+ }
+
+ if (clk_enable(resource_context.pclk)) {
+ VCDRES_MSG_ERROR("vidc pclk Enable failed\n");
+ goto release_all_clks;
+ }
+
+ if (clk_enable(resource_context.hclk)) {
+ VCDRES_MSG_ERROR("vidc hclk Enable failed\n");
+ goto disable_pclk;
+ }
+
+ if (clk_enable(resource_context.hclk_div2)) {
+ VCDRES_MSG_ERROR("vidc hclk_div2 Enable failed\n");
+ goto disable_hclk_pclk;
+ }
+
+ rc = clk_reset(resource_context.pclk, CLK_RESET_DEASSERT);
+ if (rc) {
+ VCDRES_MSG_ERROR("\n clk_reset failed %d\n", rc);
+ goto disable_and_release_all_clks;
+ }
+ msleep(20);
+
+ clk_disable(resource_context.pclk);
+ clk_disable(resource_context.hclk);
+ clk_disable(resource_context.hclk_div2);
+
+ }
+ resource_context.rail_enabled = 1;
+ mutex_unlock(&resource_context.lock);
+ return true;
+
+disable_and_release_all_clks:
+ clk_disable(resource_context.hclk_div2);
+disable_hclk_pclk:
+ clk_disable(resource_context.hclk);
+disable_pclk:
+ clk_disable(resource_context.pclk);
+release_all_clks:
+ clk_put(resource_context.hclk_div2);
+ resource_context.hclk_div2 = NULL;
+release_hclk_pclk:
+ clk_put(resource_context.hclk);
+ resource_context.hclk = NULL;
+release_pclk:
+ clk_put(resource_context.pclk);
+ resource_context.pclk = NULL;
+disable_regulator:
+ regulator_disable(resource_context.regulator);
+bail_out:
+ mutex_unlock(&resource_context.lock);
+ return false;
+}
+
+static u32 res_trk_convert_freq_to_perf_lvl(u64 freq)
+{
+ u64 perf_lvl;
+ u64 temp;
+
+ VCDRES_MSG_MED("\n %s():: freq = %u\n", __func__, (u32)freq);
+
+ if (!freq)
+ return 0;
+
+ temp = freq * 1000;
+ do_div(temp, VCD_RESTRK_HZ_PER_1000_PERFLVL);
+ perf_lvl = (u32)temp;
+ VCDRES_MSG_MED("\n %s(): perf_lvl = %u\n", __func__,
+ (u32)perf_lvl);
+
+ return (u32)perf_lvl;
+}
+
+static u32 res_trk_convert_perf_lvl_to_freq(u64 perf_lvl)
+{
+ u64 freq, temp;
+
+ VCDRES_MSG_MED("\n %s():: perf_lvl = %u\n", __func__,
+ (u32)perf_lvl);
+ temp = (perf_lvl * VCD_RESTRK_HZ_PER_1000_PERFLVL) + 999;
+ do_div(temp, 1000);
+ freq = (u32)temp;
+ VCDRES_MSG_MED("\n %s(): freq = %u\n", __func__, (u32)freq);
+
+ return (u32)freq;
+}
+
+static struct clk *ebi1_clk;
+
+u32 res_trk_power_up(void)
+{
+ VCDRES_MSG_LOW("clk_regime_rail_enable");
+ VCDRES_MSG_LOW("clk_regime_sel_rail_control");
+#ifdef AXI_CLK_SCALING
+{
+ VCDRES_MSG_MED("\n res_trk_power_up():: "
+ "Calling AXI add requirement\n");
+ ebi1_clk = clk_get(NULL, "ebi1_vcd_clk");
+ if (IS_ERR(ebi1_clk)) {
+ VCDRES_MSG_ERROR("Request AXI bus QOS fails.");
+ return false;
+ }
+ clk_enable(ebi1_clk);
+}
+#endif
+
+ VCDRES_MSG_MED("\n res_trk_power_up():: Calling "
+ "vidc_enable_pwr_rail()\n");
+ return res_trk_enable_videocore();
+}
+
+u32 res_trk_power_down(void)
+{
+ VCDRES_MSG_LOW("clk_regime_rail_disable");
+#ifdef AXI_CLK_SCALING
+ VCDRES_MSG_MED("\n res_trk_power_down()::"
+ "Calling AXI remove requirement\n");
+ clk_disable(ebi1_clk);
+ clk_put(ebi1_clk);
+#endif
+ VCDRES_MSG_MED("\n res_trk_power_down():: Calling "
+ "res_trk_disable_videocore()\n");
+ return res_trk_disable_videocore();
+}
+
+u32 res_trk_get_max_perf_level(u32 *pn_max_perf_lvl)
+{
+ if (!pn_max_perf_lvl) {
+ VCDRES_MSG_ERROR("%s(): pn_max_perf_lvl is NULL\n",
+ __func__);
+ return false;
+ }
+
+ *pn_max_perf_lvl = VCD_RESTRK_MAX_PERF_LEVEL;
+ return true;
+}
+
+u32 res_trk_set_perf_level(u32 req_perf_lvl, u32 *pn_set_perf_lvl,
+ struct vcd_dev_ctxt *dev_ctxt)
+{
+ struct vcd_clnt_ctxt *cctxt_itr = NULL;
+ u32 axi_freq = 0, mfc_freq = 0, calc_mfc_freq = 0;
+ u8 enc_clnt_present = false;
+
+ if (!pn_set_perf_lvl || !dev_ctxt) {
+ VCDRES_MSG_ERROR("%s(): NULL pointer! dev_ctxt(%p)\n",
+ __func__, dev_ctxt);
+ return false;
+ }
+
+ VCDRES_MSG_LOW("%s(), req_perf_lvl = %d", __func__, req_perf_lvl);
+ calc_mfc_freq = res_trk_convert_perf_lvl_to_freq(
+ (u64)req_perf_lvl);
+
+ if (calc_mfc_freq < VCD_RESTRK_MIN_FREQ_POINT)
+ calc_mfc_freq = VCD_RESTRK_MIN_FREQ_POINT;
+ else if (calc_mfc_freq > VCD_RESTRK_MAX_FREQ_POINT)
+ calc_mfc_freq = VCD_RESTRK_MAX_FREQ_POINT;
+
+ cctxt_itr = dev_ctxt->cctxt_list_head;
+ while (cctxt_itr) {
+ VCDRES_MSG_LOW("\n cctxt_itr = %p", cctxt_itr);
+ if (!cctxt_itr->decoding) {
+ VCDRES_MSG_LOW("\n Encoder client");
+ enc_clnt_present = true;
+ break;
+ } else {
+ VCDRES_MSG_LOW("\n Decoder client");
+ }
+ cctxt_itr = cctxt_itr->next;
+ }
+
+ if (enc_clnt_present) {
+ if (req_perf_lvl >= VGA_PERF_LEVEL) {
+ mfc_freq = mfc_clk_freq_table[2];
+ axi_freq = axi_clk_freq_table_enc[1];
+ } else {
+ mfc_freq = mfc_clk_freq_table[0];
+ axi_freq = axi_clk_freq_table_enc[0];
+ }
+ VCDRES_MSG_MED("\n ENCODER: axi_freq = %u"
+ ", mfc_freq = %u, calc_mfc_freq = %u,"
+ " req_perf_lvl = %u", axi_freq,
+ mfc_freq, calc_mfc_freq,
+ req_perf_lvl);
+ } else {
+ if (req_perf_lvl <= QVGA_PERF_LEVEL) {
+ mfc_freq = mfc_clk_freq_table[0];
+ axi_freq = axi_clk_freq_table_dec[0];
+ } else {
+ axi_freq = axi_clk_freq_table_dec[0];
+ if (req_perf_lvl <= VGA_PERF_LEVEL)
+ mfc_freq = mfc_clk_freq_table[0];
+ else if (req_perf_lvl <= WVGA_PERF_LEVEL)
+ mfc_freq = mfc_clk_freq_table[1];
+ else {
+ mfc_freq = mfc_clk_freq_table[2];
+ axi_freq = axi_clk_freq_table_dec[1];
+ }
+ }
+ VCDRES_MSG_MED("\n DECODER: axi_freq = %u"
+ ", mfc_freq = %u, calc_mfc_freq = %u,"
+ " req_perf_lvl = %u", axi_freq,
+ mfc_freq, calc_mfc_freq,
+ req_perf_lvl);
+ }
+
+#ifdef AXI_CLK_SCALING
+ if (req_perf_lvl != VCD_RESTRK_MIN_PERF_LEVEL) {
+ VCDRES_MSG_MED("\n %s(): Setting AXI freq to %u",
+ __func__, axi_freq);
+ clk_set_rate(ebi1_clk, axi_freq * 1000);
+ }
+#endif
+
+#ifdef USE_RES_TRACKER
+ if (req_perf_lvl != VCD_RESTRK_MIN_PERF_LEVEL) {
+ VCDRES_MSG_MED("\n %s(): Setting MFC freq to %u",
+ __func__, mfc_freq);
+ if (!res_trk_sel_clk_rate(mfc_freq)) {
+ VCDRES_MSG_ERROR("%s(): res_trk_sel_clk_rate FAILED\n",
+ __func__);
+ *pn_set_perf_lvl = 0;
+ return false;
+ }
+ }
+#endif
+
+ *pn_set_perf_lvl =
+ res_trk_convert_freq_to_perf_lvl((u64) mfc_freq);
+ return true;
+}
+
+u32 res_trk_get_curr_perf_level(u32 *pn_perf_lvl)
+{
+ unsigned long freq;
+
+ if (!pn_perf_lvl) {
+ VCDRES_MSG_ERROR("%s(): pn_perf_lvl is NULL\n",
+ __func__);
+ return false;
+ }
+ VCDRES_MSG_LOW("clk_regime_msm_get_clk_freq_hz");
+ if (!res_trk_get_clk_rate(&freq)) {
+ VCDRES_MSG_ERROR("%s(): res_trk_get_clk_rate FAILED\n",
+ __func__);
+ *pn_perf_lvl = 0;
+ return false;
+ }
+
+ *pn_perf_lvl = res_trk_convert_freq_to_perf_lvl((u64) freq);
+ VCDRES_MSG_MED("%s(): freq = %lu, *pn_perf_lvl = %u", __func__,
+ freq, *pn_perf_lvl);
+ return true;
+}
+
+u32 res_trk_download_firmware(void)
+{
+ const struct firmware *fw_boot = NULL;
+ const struct firmware *fw_mpg4_dec = NULL;
+ const struct firmware *fw_h263_dec = NULL;
+ const struct firmware *fw_h264_dec = NULL;
+ const struct firmware *fw_mpg4_enc = NULL;
+ const struct firmware *fw_h264_enc = NULL;
+ const struct firmware *fw_vc1_dec = NULL;
+ int rc = 0;
+ u32 status = true;
+
+ VCDRES_MSG_HIGH("%s(): Request firmware download\n",
+ __func__);
+ mutex_lock(&resource_context.lock);
+ rc = request_firmware(&fw_boot, VIDC_BOOT_FW,
+ resource_context.device);
+ if (rc) {
+ VCDRES_MSG_ERROR("request_firmware for %s error %d\n",
+ VIDC_BOOT_FW, rc);
+ mutex_unlock(&resource_context.lock);
+ return false;
+ }
+ vidc_command_control_fw = (unsigned char *)fw_boot->data;
+ vidc_command_control_fw_size = (u32) fw_boot->size;
+
+ rc = request_firmware(&fw_mpg4_dec, VIDC_MPG4_DEC_FW,
+ resource_context.device);
+ if (rc) {
+ VCDRES_MSG_ERROR("request_firmware for %s error %d\n",
+ VIDC_MPG4_DEC_FW, rc);
+ status = false;
+ goto boot_fw_free;
+ }
+ vidc_mpg4_dec_fw = (unsigned char *)fw_mpg4_dec->data;
+ vidc_mpg4_dec_fw_size = (u32) fw_mpg4_dec->size;
+
+
+ rc = request_firmware(&fw_h263_dec, VIDC_H263_DEC_FW,
+ resource_context.device);
+ if (rc) {
+ VCDRES_MSG_ERROR("request_firmware for %s error %d\n",
+ VIDC_H263_DEC_FW, rc);
+ status = false;
+ goto mp4dec_fw_free;
+ }
+ vidc_h263_dec_fw = (unsigned char *)fw_h263_dec->data;
+ vidc_h263_dec_fw_size = (u32) fw_h263_dec->size;
+
+ rc = request_firmware(&fw_h264_dec, VIDC_H264_DEC_FW,
+ resource_context.device);
+ if (rc) {
+ VCDRES_MSG_ERROR("request_firmware for %s error %d\n",
+ VIDC_H264_DEC_FW, rc);
+ status = false;
+ goto h263dec_fw_free;
+ }
+ vidc_h264_dec_fw = (unsigned char *)fw_h264_dec->data;
+ vidc_h264_dec_fw_size = (u32) fw_h264_dec->size;
+
+ rc = request_firmware(&fw_mpg4_enc, VIDC_MPG4_ENC_FW,
+ resource_context.device);
+ if (rc) {
+ VCDRES_MSG_ERROR("request_firmware for %s error %d\n",
+ VIDC_MPG4_ENC_FW, rc);
+ status = false;
+ goto h264dec_fw_free;
+ }
+ vidc_mpg4_enc_fw = (unsigned char *)fw_mpg4_enc->data;
+ vidc_mpg4_enc_fw_size = (u32) fw_mpg4_enc->size;
+
+ rc = request_firmware(&fw_h264_enc, VIDC_H264_ENC_FW,
+ resource_context.device);
+ if (rc) {
+ VCDRES_MSG_ERROR("request_firmware for %s error %d\n",
+ VIDC_H264_ENC_FW, rc);
+ status = false;
+ goto mp4enc_fw_free;
+ }
+ vidc_h264_enc_fw = (unsigned char *)fw_h264_enc->data;
+ vidc_h264_enc_fw_size = (u32) fw_h264_enc->size;
+
+ rc = request_firmware(&fw_vc1_dec, VIDC_VC1_DEC_FW,
+ resource_context.device);
+ if (rc) {
+ VCDRES_MSG_ERROR("request_firmware for %s error %d\n",
+ VIDC_VC1_DEC_FW, rc);
+ status = false;
+ goto h264enc_fw_free;
+ }
+ vidc_vc1_dec_fw = (unsigned char *)fw_vc1_dec->data;
+ vidc_vc1_dec_fw_size = (u32) fw_vc1_dec->size;
+ mutex_unlock(&resource_context.lock);
+ return status;
+
+h264enc_fw_free:
+ release_firmware(fw_h264_enc);
+mp4enc_fw_free:
+ release_firmware(fw_mpg4_enc);
+h264dec_fw_free:
+ release_firmware(fw_h264_dec);
+h263dec_fw_free:
+ release_firmware(fw_h263_dec);
+mp4dec_fw_free:
+ release_firmware(fw_mpg4_dec);
+boot_fw_free:
+ release_firmware(fw_boot);
+ mutex_unlock(&resource_context.lock);
+ return false;
+}
+
+void res_trk_init(struct device *device, u32 irq)
+{
+ if (resource_context.device || resource_context.irq_num ||
+ !device) {
+ VCDRES_MSG_ERROR("%s() Resource Tracker Init error\n",
+ __func__);
+ return;
+ }
+ memset(&resource_context, 0, sizeof(resource_context));
+ mutex_init(&resource_context.lock);
+ resource_context.device = device;
+ resource_context.irq_num = irq;
+ resource_context.core_type = VCD_CORE_720P;
+ resource_context.regulator = regulator_get(NULL, "fs_mfc");
+ resource_context.vidc_platform_data =
+ (struct msm_vidc_platform_data *) device->platform_data;
+ if (resource_context.vidc_platform_data) {
+ resource_context.memtype =
+ resource_context.vidc_platform_data->memtype;
+ } else {
+ resource_context.memtype = -1;
+ }
+}
+
+u32 res_trk_get_core_type(void){
+ return resource_context.core_type;
+}
+
+u32 res_trk_get_mem_type(void){
+ return resource_context.memtype;
+}
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.h b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.h
new file mode 100644
index 0000000..3012858
--- /dev/null
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.h
@@ -0,0 +1,56 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _VIDEO_720P_RESOURCE_TRACKER_H_
+#define _VIDEO_720P_RESOURCE_TRACKER_H_
+#include <mach/board.h>
+#include "vcd_res_tracker_api.h"
+
+#define VCD_RESTRK_MIN_PERF_LEVEL 37900
+#define VCD_RESTRK_MAX_PERF_LEVEL 108000
+#define VCD_RESTRK_MIN_FREQ_POINT 61440000
+#define VCD_RESTRK_MAX_FREQ_POINT 170667000
+#define VCD_RESTRK_HZ_PER_1000_PERFLVL 1580250
+
+struct res_trk_context {
+ struct device *device;
+ u32 irq_num;
+ struct mutex lock;
+ struct clk *hclk;
+ struct clk *hclk_div2;
+ struct clk *pclk;
+ unsigned long hclk_rate;
+ unsigned int clock_enabled;
+ unsigned int rail_enabled;
+ struct regulator *regulator;
+ struct msm_vidc_platform_data *vidc_platform_data;
+ u32 core_type;
+ int memtype;
+};
+
+#if DEBUG
+
+#define VCDRES_MSG_LOW(xx_fmt...) printk(KERN_INFO "\n\t* " xx_fmt)
+#define VCDRES_MSG_MED(xx_fmt...) printk(KERN_INFO "\n * " xx_fmt)
+
+#else
+
+#define VCDRES_MSG_LOW(xx_fmt...)
+#define VCDRES_MSG_MED(xx_fmt...)
+
+#endif
+
+#define VCDRES_MSG_HIGH(xx_fmt...) printk(KERN_WARNING "\n" xx_fmt)
+#define VCDRES_MSG_ERROR(xx_fmt...) printk(KERN_ERR "\n err: " xx_fmt)
+#define VCDRES_MSG_FATAL(xx_fmt...) printk(KERN_ERR "\n<FATAL> " xx_fmt)
+
+#endif
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h
new file mode 100644
index 0000000..db84743
--- /dev/null
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h
@@ -0,0 +1,30 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _VIDEO_720P_RESOURCE_TRACKER_API_H_
+#define _VIDEO_720P_RESOURCE_TRACKER_API_H_
+
+#include "vcd_core.h"
+
+void res_trk_init(struct device *device, u32 irq);
+u32 res_trk_power_up(void);
+u32 res_trk_power_down(void);
+u32 res_trk_enable_clocks(void);
+u32 res_trk_disable_clocks(void);
+u32 res_trk_get_max_perf_level(u32 *pn_max_perf_lvl);
+u32 res_trk_set_perf_level(u32 req_perf_lvl, u32 *pn_set_perf_lvl,
+ struct vcd_dev_ctxt *dev_ctxt);
+u32 res_trk_get_curr_perf_level(u32 *pn_perf_lvl);
+u32 res_trk_download_firmware(void);
+u32 res_trk_get_core_type(void);
+u32 res_trk_get_mem_type(void);
+#endif
diff --git a/drivers/video/msm/vidc/Kconfig b/drivers/video/msm/vidc/Kconfig
new file mode 100644
index 0000000..9ffcb15
--- /dev/null
+++ b/drivers/video/msm/vidc/Kconfig
@@ -0,0 +1,39 @@
+#
+# VIDEO CORE
+#
+menuconfig MSM_VIDC
+ bool "Video Core Driver"
+ depends on ARCH_MSM8X60 || ARCH_MSM7X30 || ARCH_MSM8960
+ default y
+ ---help---
+ Say Y here to see options for video device drivers.
+ If you say N, all options in this submenu will be skipped and disabled.
+
+config MSM_VIDC_720P
+ bool "720P Video Core"
+ depends on MSM_VIDC && ARCH_MSM7X30
+ default y
+ help
+ This option enables support for Video core.
+
+config MSM_VIDC_1080P
+ bool "1080P Video Core"
+ depends on MSM_VIDC && (ARCH_MSM8X60 || ARCH_MSM8960)
+ default y
+ help
+ This option enables support for Video core.
+
+config MSM_VIDC_VENC
+ tristate "Video encoder"
+ depends on MSM_VIDC
+ default y
+ help
+ This option enables support for Video encoder.
+
+config MSM_VIDC_VDEC
+ tristate "Video decoder"
+ depends on MSM_VIDC
+ default y
+ help
+ This option enables support for Video decoder.
+
diff --git a/drivers/video/msm/vidc/Makefile b/drivers/video/msm/vidc/Makefile
new file mode 100644
index 0000000..af41f18
--- /dev/null
+++ b/drivers/video/msm/vidc/Makefile
@@ -0,0 +1,62 @@
+ifdef CONFIG_MSM_VIDC_720P
+EXTRA_CFLAGS += -Idrivers/video/msm/vidc/720p/ddl
+EXTRA_CFLAGS += -Idrivers/video/msm/vidc/720p/resource_tracker
+endif
+
+ifdef CONFIG_MSM_VIDC_1080P
+EXTRA_CFLAGS += -Idrivers/video/msm/vidc/1080p/ddl
+EXTRA_CFLAGS += -Idrivers/video/msm/vidc/1080p/resource_tracker
+endif
+
+EXTRA_CFLAGS += -Idrivers/video/msm/vidc/common/dec
+EXTRA_CFLAGS += -Idrivers/video/msm/vidc/common/enc
+EXTRA_CFLAGS += -Idrivers/video/msm/vidc/common/vcd
+EXTRA_CFLAGS += -Idrivers/video/msm/vidc/common/init
+
+obj-$(CONFIG_MSM_VIDC) += vidc.o
+
+vidc-objs := common/init/vidc_init.o \
+ common/vcd/vcd_api.o \
+ common/vcd/vcd_power_sm.o \
+ common/vcd/vcd_client_sm.o \
+ common/vcd/vcd_device_sm.o \
+ common/vcd/vcd_scheduler.o \
+ common/vcd/vcd_sub.o \
+
+ifdef CONFIG_MSM_VIDC_720P
+vidc-objs += 720p/ddl/vcd_ddl_firmware.o \
+ 720p/ddl/vcd_ddl_metadata.o \
+ 720p/ddl/vidc.o \
+ 720p/ddl/vcd_ddl_utils.o \
+ 720p/ddl/vcd_ddl.o \
+ 720p/ddl/vcd_ddl_helper.o \
+ 720p/ddl/vcd_ddl_interrupt_handler.o \
+ 720p/ddl/vcd_ddl_hal.o \
+ 720p/ddl/vcd_ddl_properties.o \
+ 720p/resource_tracker/vcd_res_tracker.o \
+ 720p/ddl/vcd_ddl_errors.o
+endif
+
+ifdef CONFIG_MSM_VIDC_1080P
+vidc-objs += 1080p/ddl/vcd_ddl_helper.o \
+ 1080p/ddl/vcd_ddl_utils.o \
+ 1080p/ddl/vcd_ddl_interrupt_handler.o \
+ 1080p/ddl/vcd_ddl_properties.o \
+ 1080p/ddl/vcd_ddl_errors.o \
+ 1080p/ddl/vcd_ddl_shared_mem.o \
+ 1080p/ddl/vidc.o \
+ 1080p/ddl/vidc_pix_cache.o \
+ 1080p/ddl/vcd_ddl_vidc.o \
+ 1080p/ddl/vcd_ddl.o \
+ 1080p/ddl/vcd_ddl_metadata.o \
+ 1080p/resource_tracker/vcd_res_tracker.o
+endif
+
+obj-$(CONFIG_MSM_VIDC_VDEC) += vidc_vdec.o
+
+vidc_vdec-objs := common/dec/vdec.o
+
+obj-$(CONFIG_MSM_VIDC_VENC) += vidc_venc.o
+
+vidc_venc-objs := common/enc/venc.o \
+ common/enc/venc_internal.o
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
new file mode 100644
index 0000000..48d5119
--- /dev/null
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -0,0 +1,1904 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+#include <linux/android_pmem.h>
+#include <linux/clk.h>
+#include <linux/timer.h>
+
+#include "vidc_type.h"
+#include "vcd_api.h"
+#include "vdec_internal.h"
+#include "vidc_init.h"
+
+
+
+#if DEBUG
+#define DBG(x...) printk(KERN_DEBUG x)
+#else
+#define DBG(x...)
+#endif
+
+#define INFO(x...) printk(KERN_INFO x)
+#define ERR(x...) printk(KERN_ERR x)
+
+#define VID_DEC_NAME "msm_vidc_dec"
+
+static struct vid_dec_dev *vid_dec_device_p;
+static dev_t vid_dec_dev_num;
+static struct class *vid_dec_class;
+static s32 vid_dec_get_empty_client_index(void)
+{
+ u32 i, found = false;
+
+ for (i = 0; i < VIDC_MAX_NUM_CLIENTS; i++) {
+ if (!vid_dec_device_p->vdec_clients[i].vcd_handle) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ ERR("%s():ERROR No space for new client\n", __func__);
+ return -ENOMEM;
+ } else {
+ DBG("%s(): available client index = %u\n", __func__, i);
+ return i;
+ }
+}
+
+u32 vid_dec_get_status(u32 status)
+{
+ u32 vdec_status;
+
+ switch (status) {
+ case VCD_ERR_SEQHDR_PARSE_FAIL:
+ case VCD_ERR_BITSTREAM_ERR:
+ case VCD_S_SUCCESS:
+ vdec_status = VDEC_S_SUCCESS;
+ break;
+ case VCD_ERR_FAIL:
+ vdec_status = VDEC_S_EFAIL;
+ break;
+ case VCD_ERR_ALLOC_FAIL:
+ vdec_status = VDEC_S_ENOSWRES;
+ break;
+ case VCD_ERR_ILLEGAL_OP:
+ vdec_status = VDEC_S_EINVALCMD;
+ break;
+ case VCD_ERR_ILLEGAL_PARM:
+ vdec_status = VDEC_S_EBADPARAM;
+ break;
+ case VCD_ERR_BAD_POINTER:
+ case VCD_ERR_BAD_HANDLE:
+ vdec_status = VDEC_S_EFATAL;
+ break;
+ case VCD_ERR_NOT_SUPPORTED:
+ vdec_status = VDEC_S_ENOTSUPP;
+ break;
+ case VCD_ERR_BAD_STATE:
+ vdec_status = VDEC_S_EINVALSTATE;
+ break;
+ case VCD_ERR_BUSY:
+ vdec_status = VDEC_S_BUSY;
+ break;
+ case VCD_ERR_MAX_CLIENT:
+ vdec_status = VDEC_S_ENOHWRES;
+ break;
+ default:
+ vdec_status = VDEC_S_EFAIL;
+ break;
+ }
+
+ return vdec_status;
+}
+
+static void vid_dec_notify_client(struct video_client_ctx *client_ctx)
+{
+ if (client_ctx)
+ complete(&client_ctx->event);
+}
+
+void vid_dec_vcd_open_done(struct video_client_ctx *client_ctx,
+ struct vcd_handle_container *handle_container)
+{
+ DBG("vid_dec_vcd_open_done\n");
+
+ if (client_ctx) {
+ if (handle_container)
+ client_ctx->vcd_handle = handle_container->handle;
+ else
+ ERR("%s(): ERROR. handle_container is NULL\n",
+ __func__);
+
+ vid_dec_notify_client(client_ctx);
+ } else
+ ERR("%s(): ERROR. client_ctx is NULL\n", __func__);
+}
+
+static void vid_dec_input_frame_done(struct video_client_ctx *client_ctx,
+ u32 event, u32 status,
+ struct vcd_frame_data *vcd_frame_data)
+{
+ struct vid_dec_msg *vdec_msg;
+
+ if (!client_ctx || !vcd_frame_data) {
+ ERR("vid_dec_input_frame_done() NULL pointer\n");
+ return;
+ }
+
+ vdec_msg = kzalloc(sizeof(struct vid_dec_msg), GFP_KERNEL);
+ if (!vdec_msg) {
+ ERR("vid_dec_input_frame_done(): cannot allocate vid_dec_msg "
+ " buffer\n");
+ return;
+ }
+
+ vdec_msg->vdec_msg_info.status_code = vid_dec_get_status(status);
+
+ if (event == VCD_EVT_RESP_INPUT_DONE) {
+ vdec_msg->vdec_msg_info.msgcode =
+ VDEC_MSG_RESP_INPUT_BUFFER_DONE;
+ DBG("Send INPUT_DON message to client = %p\n", client_ctx);
+
+ } else if (event == VCD_EVT_RESP_INPUT_FLUSHED) {
+ vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_RESP_INPUT_FLUSHED;
+ DBG("Send INPUT_FLUSHED message to client = %p\n", client_ctx);
+ } else {
+ ERR("vid_dec_input_frame_done(): invalid event type: "
+ "%d\n", event);
+ vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_INVALID;
+ }
+
+ vdec_msg->vdec_msg_info.msgdata.input_frame_clientdata =
+ (void *)vcd_frame_data->frm_clnt_data;
+ vdec_msg->vdec_msg_info.msgdatasize = sizeof(void *);
+
+ mutex_lock(&client_ctx->msg_queue_lock);
+ list_add_tail(&vdec_msg->list, &client_ctx->msg_queue);
+ mutex_unlock(&client_ctx->msg_queue_lock);
+ wake_up(&client_ctx->msg_wait);
+}
+
+static void vid_dec_output_frame_done(struct video_client_ctx *client_ctx,
+ u32 event, u32 status,
+ struct vcd_frame_data *vcd_frame_data)
+{
+ struct vid_dec_msg *vdec_msg;
+
+ unsigned long kernel_vaddr = 0, phy_addr = 0, user_vaddr = 0;
+ int pmem_fd;
+ struct file *file;
+ s32 buffer_index = -1;
+ enum vdec_picture pic_type;
+
+ if (!client_ctx || !vcd_frame_data) {
+ ERR("vid_dec_input_frame_done() NULL pointer\n");
+ return;
+ }
+
+ vdec_msg = kzalloc(sizeof(struct vid_dec_msg), GFP_KERNEL);
+ if (!vdec_msg) {
+ ERR("vid_dec_input_frame_done(): cannot allocate vid_dec_msg "
+ " buffer\n");
+ return;
+ }
+
+ vdec_msg->vdec_msg_info.status_code = vid_dec_get_status(status);
+
+ if (event == VCD_EVT_RESP_OUTPUT_DONE)
+ vdec_msg->vdec_msg_info.msgcode =
+ VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
+ else if (event == VCD_EVT_RESP_OUTPUT_FLUSHED)
+ vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_RESP_OUTPUT_FLUSHED;
+ else {
+ ERR("QVD: vid_dec_output_frame_done invalid cmd type: "
+ "%d\n", event);
+ vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_INVALID;
+ }
+
+ kernel_vaddr = (unsigned long)vcd_frame_data->virtual;
+
+ if (vidc_lookup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT,
+ false, &user_vaddr, &kernel_vaddr,
+ &phy_addr, &pmem_fd, &file,
+ &buffer_index) ||
+ (vcd_frame_data->flags & VCD_FRAME_FLAG_EOS)) {
+
+ /* Buffer address in user space */
+ vdec_msg->vdec_msg_info.msgdata.output_frame.bufferaddr =
+ (u8 *) user_vaddr;
+ /* Data length */
+ vdec_msg->vdec_msg_info.msgdata.output_frame.len =
+ vcd_frame_data->data_len;
+ vdec_msg->vdec_msg_info.msgdata.output_frame.flags =
+ vcd_frame_data->flags;
+ /* Timestamp pass-through from input frame */
+ vdec_msg->vdec_msg_info.msgdata.output_frame.time_stamp =
+ vcd_frame_data->time_stamp;
+ /* Output frame client data */
+ vdec_msg->vdec_msg_info.msgdata.output_frame.client_data =
+ (void *)vcd_frame_data->frm_clnt_data;
+ /* Associated input frame client data */
+ vdec_msg->vdec_msg_info.msgdata.output_frame.
+ input_frame_clientdata =
+ (void *)vcd_frame_data->ip_frm_tag;
+ /* Decoded picture width and height */
+ vdec_msg->vdec_msg_info.msgdata.output_frame.framesize.
+ bottom =
+ vcd_frame_data->dec_op_prop.disp_frm.bottom;
+ vdec_msg->vdec_msg_info.msgdata.output_frame.framesize.left =
+ vcd_frame_data->dec_op_prop.disp_frm.left;
+ vdec_msg->vdec_msg_info.msgdata.output_frame.framesize.right =
+ vcd_frame_data->dec_op_prop.disp_frm.right;
+ vdec_msg->vdec_msg_info.msgdata.output_frame.framesize.top =
+ vcd_frame_data->dec_op_prop.disp_frm.top;
+ if (vcd_frame_data->interlaced) {
+ vdec_msg->vdec_msg_info.msgdata.
+ output_frame.interlaced_format =
+ VDEC_InterlaceInterleaveFrameTopFieldFirst;
+ } else {
+ vdec_msg->vdec_msg_info.msgdata.
+ output_frame.interlaced_format =
+ VDEC_InterlaceFrameProgressive;
+ }
+ /* Decoded picture type */
+ switch (vcd_frame_data->frame) {
+ case VCD_FRAME_I:
+ pic_type = PICTURE_TYPE_I;
+ break;
+ case VCD_FRAME_P:
+ pic_type = PICTURE_TYPE_P;
+ break;
+ case VCD_FRAME_B:
+ pic_type = PICTURE_TYPE_B;
+ break;
+ case VCD_FRAME_NOTCODED:
+ pic_type = PICTURE_TYPE_SKIP;
+ break;
+ default:
+ pic_type = PICTURE_TYPE_UNKNOWN;
+ }
+ vdec_msg->vdec_msg_info.msgdata.output_frame.pic_type =
+ pic_type;
+ vdec_msg->vdec_msg_info.msgdatasize =
+ sizeof(struct vdec_output_frameinfo);
+ } else {
+ ERR("vid_dec_output_frame_done UVA can not be found\n");
+ vdec_msg->vdec_msg_info.status_code = VDEC_S_EFATAL;
+ }
+
+ mutex_lock(&client_ctx->msg_queue_lock);
+ list_add_tail(&vdec_msg->list, &client_ctx->msg_queue);
+ mutex_unlock(&client_ctx->msg_queue_lock);
+ wake_up(&client_ctx->msg_wait);
+}
+
+static void vid_dec_lean_event(struct video_client_ctx *client_ctx,
+ u32 event, u32 status)
+{
+ struct vid_dec_msg *vdec_msg;
+
+ if (!client_ctx) {
+ ERR("%s(): !client_ctx pointer\n", __func__);
+ return;
+ }
+
+ vdec_msg = kzalloc(sizeof(struct vid_dec_msg), GFP_KERNEL);
+ if (!vdec_msg) {
+ ERR("%s(): cannot allocate vid_dec_msg buffer\n", __func__);
+ return;
+ }
+
+ vdec_msg->vdec_msg_info.status_code = vid_dec_get_status(status);
+
+ switch (event) {
+ case VCD_EVT_IND_OUTPUT_RECONFIG:
+ INFO("msm_vidc_dec: Sending VDEC_MSG_EVT_CONFIG_CHANGED"
+ " to client");
+ vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_EVT_CONFIG_CHANGED;
+ break;
+ case VCD_EVT_IND_RESOURCES_LOST:
+ INFO("msm_vidc_dec: Sending VDEC_EVT_RESOURCES_LOST"
+ " to client");
+ vdec_msg->vdec_msg_info.msgcode = VDEC_EVT_RESOURCES_LOST;
+ break;
+ case VCD_EVT_RESP_FLUSH_INPUT_DONE:
+ INFO("msm_vidc_dec: Sending VDEC_MSG_RESP_FLUSH_INPUT_DONE"
+ " to client");
+ vdec_msg->vdec_msg_info.msgcode =
+ VDEC_MSG_RESP_FLUSH_INPUT_DONE;
+ break;
+ case VCD_EVT_RESP_FLUSH_OUTPUT_DONE:
+ INFO("msm_vidc_dec: Sending VDEC_MSG_RESP_FLUSH_OUTPUT_DONE"
+ " to client");
+ vdec_msg->vdec_msg_info.msgcode =
+ VDEC_MSG_RESP_FLUSH_OUTPUT_DONE;
+ break;
+ case VCD_EVT_IND_HWERRFATAL:
+ INFO("msm_vidc_dec: Sending VDEC_MSG_EVT_HW_ERROR"
+ " to client");
+ vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_EVT_HW_ERROR;
+ break;
+ case VCD_EVT_RESP_START:
+ INFO("msm_vidc_dec: Sending VDEC_MSG_RESP_START_DONE"
+ " to client");
+ vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_RESP_START_DONE;
+ break;
+ case VCD_EVT_RESP_STOP:
+ INFO("msm_vidc_dec: Sending VDEC_MSG_RESP_STOP_DONE"
+ " to client");
+ vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_RESP_STOP_DONE;
+ break;
+ case VCD_EVT_RESP_PAUSE:
+ INFO("msm_vidc_dec: Sending VDEC_MSG_RESP_PAUSE_DONE"
+ " to client");
+ vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_RESP_PAUSE_DONE;
+ break;
+ case VCD_EVT_IND_INFO_OUTPUT_RECONFIG:
+ INFO("msm_vidc_dec: Sending VDEC_MSG_EVT_INFO_CONFIG_CHANGED"
+ " to client");
+ vdec_msg->vdec_msg_info.msgcode =
+ VDEC_MSG_EVT_INFO_CONFIG_CHANGED;
+ break;
+ default:
+ ERR("%s() : unknown event type\n", __func__);
+ break;
+ }
+
+ vdec_msg->vdec_msg_info.msgdatasize = 0;
+ if (client_ctx->stop_sync_cb &&
+ (event == VCD_EVT_RESP_STOP || event == VCD_EVT_IND_HWERRFATAL)) {
+ client_ctx->stop_sync_cb = false;
+ complete(&client_ctx->event);
+ kfree(vdec_msg);
+ return;
+ }
+ mutex_lock(&client_ctx->msg_queue_lock);
+ list_add_tail(&vdec_msg->list, &client_ctx->msg_queue);
+ mutex_unlock(&client_ctx->msg_queue_lock);
+ wake_up(&client_ctx->msg_wait);
+}
+
+
+void vid_dec_vcd_cb(u32 event, u32 status,
+ void *info, size_t sz, void *handle, void *const client_data)
+{
+ struct video_client_ctx *client_ctx =
+ (struct video_client_ctx *)client_data;
+
+ DBG("Entering %s()\n", __func__);
+
+ if (!client_ctx) {
+ ERR("%s(): client_ctx is NULL\n", __func__);
+ return;
+ }
+
+ client_ctx->event_status = status;
+
+ switch (event) {
+ case VCD_EVT_RESP_OPEN:
+ vid_dec_vcd_open_done(client_ctx,
+ (struct vcd_handle_container *)
+ info);
+ break;
+ case VCD_EVT_RESP_INPUT_DONE:
+ case VCD_EVT_RESP_INPUT_FLUSHED:
+ vid_dec_input_frame_done(client_ctx, event, status,
+ (struct vcd_frame_data *)info);
+ break;
+ case VCD_EVT_RESP_OUTPUT_DONE:
+ case VCD_EVT_RESP_OUTPUT_FLUSHED:
+ vid_dec_output_frame_done(client_ctx, event, status,
+ (struct vcd_frame_data *)info);
+ break;
+ case VCD_EVT_RESP_PAUSE:
+ case VCD_EVT_RESP_STOP:
+ case VCD_EVT_RESP_FLUSH_INPUT_DONE:
+ case VCD_EVT_RESP_FLUSH_OUTPUT_DONE:
+ case VCD_EVT_IND_OUTPUT_RECONFIG:
+ case VCD_EVT_IND_HWERRFATAL:
+ case VCD_EVT_IND_RESOURCES_LOST:
+ case VCD_EVT_IND_INFO_OUTPUT_RECONFIG:
+ vid_dec_lean_event(client_ctx, event, status);
+ break;
+ case VCD_EVT_RESP_START:
+ if (!client_ctx->seq_header_set)
+ vid_dec_lean_event(client_ctx, event, status);
+ else
+ vid_dec_notify_client(client_ctx);
+ break;
+ default:
+ ERR("%s() : Error - Invalid event type =%u\n", __func__,
+ event);
+ break;
+ }
+}
+
+static u32 vid_dec_set_codec(struct video_client_ctx *client_ctx,
+ enum vdec_codec *vdec_codec)
+{
+ u32 result = true;
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_codec codec;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !vdec_codec)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_CODEC;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_codec);
+
+ switch (*vdec_codec) {
+ case VDEC_CODECTYPE_MPEG4:
+ codec.codec = VCD_CODEC_MPEG4;
+ break;
+ case VDEC_CODECTYPE_H264:
+ codec.codec = VCD_CODEC_H264;
+ break;
+ case VDEC_CODECTYPE_DIVX_3:
+ codec.codec = VCD_CODEC_DIVX_3;
+ break;
+ case VDEC_CODECTYPE_DIVX_5:
+ codec.codec = VCD_CODEC_DIVX_5;
+ break;
+ case VDEC_CODECTYPE_XVID:
+ codec.codec = VCD_CODEC_XVID;
+ break;
+ case VDEC_CODECTYPE_H263:
+ codec.codec = VCD_CODEC_H263;
+ break;
+ case VDEC_CODECTYPE_MPEG2:
+ codec.codec = VCD_CODEC_MPEG2;
+ break;
+ case VDEC_CODECTYPE_VC1:
+ codec.codec = VCD_CODEC_VC1;
+ break;
+ case VDEC_CODECTYPE_VC1_RCV:
+ codec.codec = VCD_CODEC_VC1_RCV;
+ break;
+ default:
+ result = false;
+ break;
+ }
+
+ if (result) {
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &codec);
+ if (vcd_status)
+ result = false;
+ }
+ return result;
+}
+
+static u32 vid_dec_set_output_format(struct video_client_ctx *client_ctx,
+ enum vdec_output_fromat *output_format)
+{
+ u32 result = true;
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_buffer_format vcd_prop_buffer_format;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !output_format)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_BUFFER_FORMAT;;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_buffer_format);
+
+ switch (*output_format) {
+ case VDEC_YUV_FORMAT_NV12:
+ vcd_prop_buffer_format.buffer_format = VCD_BUFFER_FORMAT_NV12;
+ break;
+ case VDEC_YUV_FORMAT_TILE_4x2:
+ vcd_prop_buffer_format.buffer_format =
+ VCD_BUFFER_FORMAT_TILE_4x2;
+ break;
+ default:
+ result = false;
+ break;
+ }
+
+ if (result)
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr,
+ &vcd_prop_buffer_format);
+
+ if (vcd_status)
+ return false;
+ else
+ return true;
+}
+
+static u32 vid_dec_set_frame_resolution(struct video_client_ctx *client_ctx,
+ struct vdec_picsize *video_resoultion)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_frame_size frame_resolution;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !video_resoultion)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_FRAME_SIZE;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_frame_size);
+ frame_resolution.width = video_resoultion->frame_width;
+ frame_resolution.height = video_resoultion->frame_height;
+ frame_resolution.stride = video_resoultion->stride;
+ frame_resolution.scan_lines = video_resoultion->scan_lines;
+
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &frame_resolution);
+
+ if (vcd_status)
+ return false;
+ else
+ return true;
+}
+
+static u32 vid_dec_get_frame_resolution(struct video_client_ctx *client_ctx,
+ struct vdec_picsize *video_resoultion)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_frame_size frame_resolution;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !video_resoultion)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_FRAME_SIZE;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_frame_size);
+
+ vcd_status = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ &frame_resolution);
+
+ video_resoultion->frame_width = frame_resolution.width;
+ video_resoultion->frame_height = frame_resolution.height;
+ video_resoultion->scan_lines = frame_resolution.scan_lines;
+ video_resoultion->stride = frame_resolution.stride;
+
+ if (vcd_status)
+ return false;
+ else
+ return true;
+}
+
+static u32 vid_dec_get_progressive_only(struct video_client_ctx *client_ctx,
+ u32 *progressive_only)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ if (!client_ctx || !progressive_only)
+ return false;
+ vcd_property_hdr.prop_id = VCD_I_PROGRESSIVE_ONLY;
+ vcd_property_hdr.sz = sizeof(u32);
+ if (vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ progressive_only))
+ return false;
+ else
+ return true;
+}
+
+static u32 vid_dec_set_picture_order(struct video_client_ctx *client_ctx,
+ u32 *picture_order)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ u32 vcd_status = VCD_ERR_FAIL, vcd_picture_order, ret = true;
+ if (!client_ctx || !picture_order)
+ return false;
+ vcd_property_hdr.prop_id = VCD_I_OUTPUT_ORDER;
+ vcd_property_hdr.sz = sizeof(u32);
+ if (*picture_order == VDEC_ORDER_DISPLAY)
+ vcd_picture_order = VCD_DEC_ORDER_DISPLAY;
+ else if (*picture_order == VDEC_ORDER_DECODE)
+ vcd_picture_order = VCD_DEC_ORDER_DECODE;
+ else
+ ret = false;
+ if (ret) {
+ DBG("%s() : Setting output picture order: %d\n",
+ __func__, vcd_picture_order);
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_picture_order);
+ if (vcd_status != VCD_S_SUCCESS)
+ ret = false;
+ }
+ return ret;
+}
+
+static u32 vid_dec_set_frame_rate(struct video_client_ctx *client_ctx,
+ struct vdec_framerate *frame_rate)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_frame_rate vcd_frame_rate;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !frame_rate)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_FRAME_RATE;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_frame_rate);
+ vcd_frame_rate.fps_numerator = frame_rate->fps_numerator;
+ vcd_frame_rate.fps_denominator = frame_rate->fps_denominator;
+
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_frame_rate);
+
+ if (vcd_status)
+ return false;
+ else
+ return true;
+}
+
+static u32 vid_dec_set_extradata(struct video_client_ctx *client_ctx,
+ u32 *extradata_flag)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_meta_data_enable vcd_meta_data;
+ u32 vcd_status = VCD_ERR_FAIL;
+ if (!client_ctx || !extradata_flag)
+ return false;
+ vcd_property_hdr.prop_id = VCD_I_METADATA_ENABLE;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_meta_data_enable);
+ vcd_meta_data.meta_data_enable_flag = *extradata_flag;
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_meta_data);
+ if (vcd_status)
+ return false;
+ else
+ return true;
+}
+
+static u32 vid_dec_set_idr_only_decoding(struct video_client_ctx *client_ctx)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 enable = true;
+ if (!client_ctx)
+ return false;
+ vcd_property_hdr.prop_id = VCD_I_DEC_PICTYPE;
+ vcd_property_hdr.sz = sizeof(u32);
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &enable);
+ if (vcd_status)
+ return false;
+ return true;
+}
+
+static u32 vid_dec_set_h264_mv_buffers(struct video_client_ctx *client_ctx,
+ struct vdec_h264_mv *mv_data)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_h264_mv_buffer vcd_h264_mv_buffer;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 len;
+ struct file *file;
+
+ if (!client_ctx || !mv_data)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_H264_MV_BUFFER;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_h264_mv_buffer);
+
+ memset(&vcd_h264_mv_buffer, 0,
+ sizeof(struct vcd_property_h264_mv_buffer));
+ vcd_h264_mv_buffer.size = mv_data->size;
+ vcd_h264_mv_buffer.count = mv_data->count;
+ vcd_h264_mv_buffer.pmem_fd = mv_data->pmem_fd;
+ vcd_h264_mv_buffer.offset = mv_data->offset;
+
+ if (get_pmem_file(vcd_h264_mv_buffer.pmem_fd,
+ (unsigned long *) (&(vcd_h264_mv_buffer.physical_addr)),
+ (unsigned long *) (&vcd_h264_mv_buffer.kernel_virtual_addr),
+ (unsigned long *) (&len), &file)) {
+ ERR("%s(): get_pmem_file failed\n", __func__);
+ return false;
+ }
+ put_pmem_file(file);
+
+ DBG("Virt: %p, Phys %p, fd: %d\n", vcd_h264_mv_buffer.
+ kernel_virtual_addr, vcd_h264_mv_buffer.physical_addr,
+ vcd_h264_mv_buffer.pmem_fd);
+
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_h264_mv_buffer);
+
+ if (vcd_status)
+ return false;
+ else
+ return true;
+}
+
+static u32 vid_dec_set_cont_on_reconfig(struct video_client_ctx *client_ctx)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 enable = true;
+ if (!client_ctx)
+ return false;
+ vcd_property_hdr.prop_id = VCD_I_CONT_ON_RECONFIG;
+ vcd_property_hdr.sz = sizeof(u32);
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &enable);
+ if (vcd_status)
+ return false;
+ return true;
+}
+
+static u32 vid_dec_get_h264_mv_buffer_size(struct video_client_ctx *client_ctx,
+ struct vdec_mv_buff_size *mv_buff)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_buffer_size h264_mv_buffer_size;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !mv_buff)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_GET_H264_MV_SIZE;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_buffer_size);
+
+ h264_mv_buffer_size.width = mv_buff->width;
+ h264_mv_buffer_size.height = mv_buff->height;
+
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &h264_mv_buffer_size);
+
+ mv_buff->width = h264_mv_buffer_size.width;
+ mv_buff->height = h264_mv_buffer_size.height;
+ mv_buff->size = h264_mv_buffer_size.size;
+ mv_buff->alignment = h264_mv_buffer_size.alignment;
+
+ if (vcd_status)
+ return false;
+ else
+ return true;
+}
+
+static u32 vid_dec_free_h264_mv_buffers(struct video_client_ctx *client_ctx)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_buffer_size h264_mv_buffer_size;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_FREE_H264_MV_BUFFER;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_buffer_size);
+
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &h264_mv_buffer_size);
+ if (vcd_status)
+ return false;
+ else
+ return true;
+}
+
+static u32 vid_dec_get_buffer_req(struct video_client_ctx *client_ctx,
+ struct vdec_allocatorproperty *vdec_buf_req)
+{
+ u32 vcd_status = VCD_ERR_FAIL;
+ struct vcd_buffer_requirement vcd_buf_req;
+
+ if (!client_ctx || !vdec_buf_req)
+ return false;
+
+ if (vdec_buf_req->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
+ vcd_status = vcd_get_buffer_requirements(client_ctx->vcd_handle,
+ VCD_BUFFER_INPUT,
+ &vcd_buf_req);
+ } else {
+ vcd_status = vcd_get_buffer_requirements(client_ctx->vcd_handle,
+ VCD_BUFFER_OUTPUT,
+ &vcd_buf_req);
+ }
+
+ if (vcd_status) {
+ return false;
+ } else {
+ vdec_buf_req->mincount = vcd_buf_req.min_count;
+ vdec_buf_req->maxcount = vcd_buf_req.max_count;
+ vdec_buf_req->actualcount = vcd_buf_req.actual_count;
+ vdec_buf_req->buffer_size = vcd_buf_req.sz;
+ vdec_buf_req->alignment = vcd_buf_req.align;
+ vdec_buf_req->buf_poolid = vcd_buf_req.buf_pool_id;
+
+ return true;
+ }
+}
+
+static u32 vid_dec_set_buffer(struct video_client_ctx *client_ctx,
+ struct vdec_setbuffer_cmd *buffer_info)
+{
+ enum vcd_buffer_type buffer = VCD_BUFFER_INPUT;
+ enum buffer_dir dir_buffer = BUFFER_TYPE_INPUT;
+ u32 vcd_status = VCD_ERR_FAIL;
+ unsigned long kernel_vaddr, buf_adr_offset = 0;
+
+ if (!client_ctx || !buffer_info)
+ return false;
+
+ if (buffer_info->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
+ dir_buffer = BUFFER_TYPE_OUTPUT;
+ buffer = VCD_BUFFER_OUTPUT;
+ buf_adr_offset = (unsigned long)buffer_info->buffer.offset;
+ }
+
+ /*If buffer cannot be set, ignore */
+ if (!vidc_insert_addr_table(client_ctx, dir_buffer,
+ (unsigned long)buffer_info->buffer.bufferaddr,
+ &kernel_vaddr, buffer_info->buffer.pmem_fd,
+ buf_adr_offset, MAX_VIDEO_NUM_OF_BUFF)) {
+ DBG("%s() : user_virt_addr = %p cannot be set.",
+ __func__, buffer_info->buffer.bufferaddr);
+ return false;
+ }
+
+ vcd_status = vcd_set_buffer(client_ctx->vcd_handle,
+ buffer, (u8 *) kernel_vaddr,
+ buffer_info->buffer.buffer_len);
+
+ if (!vcd_status)
+ return true;
+ else
+ return false;
+}
+
+
+static u32 vid_dec_free_buffer(struct video_client_ctx *client_ctx,
+ struct vdec_setbuffer_cmd *buffer_info)
+{
+ enum vcd_buffer_type buffer = VCD_BUFFER_INPUT;
+ enum buffer_dir dir_buffer = BUFFER_TYPE_INPUT;
+ u32 vcd_status = VCD_ERR_FAIL;
+ unsigned long kernel_vaddr;
+
+ if (!client_ctx || !buffer_info)
+ return false;
+
+ if (buffer_info->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
+ dir_buffer = BUFFER_TYPE_OUTPUT;
+ buffer = VCD_BUFFER_OUTPUT;
+ }
+ /*If buffer NOT set, ignore */
+ if (!vidc_delete_addr_table(client_ctx, dir_buffer,
+ (unsigned long)buffer_info->buffer.bufferaddr,
+ &kernel_vaddr)) {
+ DBG("%s() : user_virt_addr = %p has not been set.",
+ __func__, buffer_info->buffer.bufferaddr);
+ return true;
+ }
+
+ vcd_status = vcd_free_buffer(client_ctx->vcd_handle, buffer,
+ (u8 *)kernel_vaddr);
+
+ if (!vcd_status)
+ return true;
+ else
+ return false;
+}
+
+static u32 vid_dec_pause_resume(struct video_client_ctx *client_ctx, u32 pause)
+{
+ u32 vcd_status;
+
+ if (!client_ctx) {
+ ERR("\n %s(): Invalid client_ctx", __func__);
+ return false;
+ }
+
+ if (pause) {
+ INFO("msm_vidc_dec: PAUSE command from client = %p\n",
+ client_ctx);
+ vcd_status = vcd_pause(client_ctx->vcd_handle);
+ } else{
+ INFO("msm_vidc_dec: RESUME command from client = %p\n",
+ client_ctx);
+ vcd_status = vcd_resume(client_ctx->vcd_handle);
+ }
+
+ if (vcd_status)
+ return false;
+
+ return true;
+
+}
+
+static u32 vid_dec_start_stop(struct video_client_ctx *client_ctx, u32 start)
+{
+ struct vid_dec_msg *vdec_msg = NULL;
+ u32 vcd_status;
+
+ INFO("msm_vidc_dec: Inside %s()", __func__);
+ if (!client_ctx) {
+ ERR("\n Invalid client_ctx");
+ return false;
+ }
+
+ if (start) {
+ if (client_ctx->seq_header_set) {
+ INFO("%s(): Seq Hdr set: Send START_DONE to client",
+ __func__);
+ vdec_msg = kzalloc(sizeof(*vdec_msg), GFP_KERNEL);
+ if (!vdec_msg) {
+ ERR("vid_dec_start_stop: cannot allocate"
+ "buffer\n");
+ return false;
+ }
+ vdec_msg->vdec_msg_info.msgcode =
+ VDEC_MSG_RESP_START_DONE;
+ vdec_msg->vdec_msg_info.status_code = VDEC_S_SUCCESS;
+ vdec_msg->vdec_msg_info.msgdatasize = 0;
+ mutex_lock(&client_ctx->msg_queue_lock);
+ list_add_tail(&vdec_msg->list, &client_ctx->msg_queue);
+ mutex_unlock(&client_ctx->msg_queue_lock);
+
+ wake_up(&client_ctx->msg_wait);
+
+ DBG("Send START_DONE message to client = %p\n",
+ client_ctx);
+
+ } else {
+ INFO("%s(): Calling decode_start()", __func__);
+ vcd_status =
+ vcd_decode_start(client_ctx->vcd_handle, NULL);
+
+ if (vcd_status) {
+ ERR("%s(): vcd_decode_start failed."
+ " vcd_status = %u\n", __func__, vcd_status);
+ return false;
+ }
+ }
+ } else {
+ INFO("%s(): Calling vcd_stop()", __func__);
+ mutex_lock(&vid_dec_device_p->lock);
+ vcd_status = VCD_ERR_FAIL;
+ if (!client_ctx->stop_called) {
+ client_ctx->stop_called = true;
+ vcd_status = vcd_stop(client_ctx->vcd_handle);
+ }
+ if (vcd_status) {
+ ERR("%s(): vcd_stop failed. vcd_status = %u\n",
+ __func__, vcd_status);
+ mutex_unlock(&vid_dec_device_p->lock);
+ return false;
+ }
+ DBG("Send STOP_DONE message to client = %p\n", client_ctx);
+ mutex_unlock(&vid_dec_device_p->lock);
+ }
+ return true;
+}
+
+static u32 vid_dec_decode_frame(struct video_client_ctx *client_ctx,
+ struct vdec_input_frameinfo *input_frame_info)
+{
+ struct vcd_frame_data vcd_input_buffer;
+ unsigned long kernel_vaddr, phy_addr, user_vaddr;
+ int pmem_fd;
+ struct file *file;
+ s32 buffer_index = -1;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !input_frame_info)
+ return false;
+
+ user_vaddr = (unsigned long)input_frame_info->bufferaddr;
+
+ if (vidc_lookup_addr_table(client_ctx, BUFFER_TYPE_INPUT,
+ true, &user_vaddr, &kernel_vaddr,
+ &phy_addr, &pmem_fd, &file,
+ &buffer_index)) {
+
+ /* kernel_vaddr is found. send the frame to VCD */
+ memset((void *)&vcd_input_buffer, 0,
+ sizeof(struct vcd_frame_data));
+ vcd_input_buffer.virtual =
+ (u8 *) (kernel_vaddr + input_frame_info->pmem_offset);
+ vcd_input_buffer.offset = input_frame_info->offset;
+ vcd_input_buffer.frm_clnt_data =
+ (u32) input_frame_info->client_data;
+ vcd_input_buffer.ip_frm_tag =
+ (u32) input_frame_info->client_data;
+ vcd_input_buffer.data_len = input_frame_info->datalen;
+ vcd_input_buffer.time_stamp = input_frame_info->timestamp;
+ /* Rely on VCD using the same flags as OMX */
+ vcd_input_buffer.flags = input_frame_info->flags;
+
+ vcd_status = vcd_decode_frame(client_ctx->vcd_handle,
+ &vcd_input_buffer);
+ if (!vcd_status)
+ return true;
+ else {
+ ERR("%s(): vcd_decode_frame failed = %u\n", __func__,
+ vcd_status);
+ return false;
+ }
+
+ } else {
+ ERR("%s(): kernel_vaddr not found\n", __func__);
+ return false;
+ }
+}
+
+static u32 vid_dec_fill_output_buffer(struct video_client_ctx *client_ctx,
+ struct vdec_fillbuffer_cmd *fill_buffer_cmd)
+{
+ unsigned long kernel_vaddr, phy_addr, user_vaddr;
+ int pmem_fd;
+ struct file *file;
+ s32 buffer_index = -1;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ struct vcd_frame_data vcd_frame;
+
+ if (!client_ctx || !fill_buffer_cmd)
+ return false;
+
+ user_vaddr = (unsigned long)fill_buffer_cmd->buffer.bufferaddr;
+
+ if (vidc_lookup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT,
+ true, &user_vaddr, &kernel_vaddr,
+ &phy_addr, &pmem_fd, &file,
+ &buffer_index)) {
+
+ memset((void *)&vcd_frame, 0,
+ sizeof(struct vcd_frame_data));
+ vcd_frame.virtual = (u8 *) kernel_vaddr;
+ vcd_frame.frm_clnt_data = (u32) fill_buffer_cmd->client_data;
+ vcd_frame.alloc_len = fill_buffer_cmd->buffer.buffer_len;
+
+ vcd_status = vcd_fill_output_buffer(client_ctx->vcd_handle,
+ &vcd_frame);
+ if (!vcd_status)
+ return true;
+ else {
+ ERR("%s(): vcd_fill_output_buffer failed = %u\n",
+ __func__, vcd_status);
+ return false;
+ }
+ } else {
+ ERR("%s(): kernel_vaddr not found\n", __func__);
+ return false;
+ }
+}
+
+
+static u32 vid_dec_flush(struct video_client_ctx *client_ctx,
+ enum vdec_bufferflush flush_dir)
+{
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ INFO("msm_vidc_dec: %s() called with dir = %u", __func__,
+ flush_dir);
+ if (!client_ctx) {
+ ERR("\n Invalid client_ctx");
+ return false;
+ }
+
+ switch (flush_dir) {
+ case VDEC_FLUSH_TYPE_INPUT:
+ vcd_status = vcd_flush(client_ctx->vcd_handle, VCD_FLUSH_INPUT);
+ break;
+ case VDEC_FLUSH_TYPE_OUTPUT:
+ vcd_status = vcd_flush(client_ctx->vcd_handle,
+ VCD_FLUSH_OUTPUT);
+ break;
+ case VDEC_FLUSH_TYPE_ALL:
+ vcd_status = vcd_flush(client_ctx->vcd_handle, VCD_FLUSH_ALL);
+ break;
+ default:
+ ERR("%s(): Inavlid flush cmd. flush_dir = %u\n", __func__,
+ flush_dir);
+ return false;
+ break;
+ }
+
+ if (!vcd_status)
+ return true;
+ else {
+ ERR("%s(): vcd_flush failed. vcd_status = %u "
+ " flush_dir = %u\n", __func__, vcd_status, flush_dir);
+ return false;
+ }
+}
+
+static u32 vid_dec_msg_pending(struct video_client_ctx *client_ctx)
+{
+ u32 islist_empty = 0;
+ mutex_lock(&client_ctx->msg_queue_lock);
+ islist_empty = list_empty(&client_ctx->msg_queue);
+ mutex_unlock(&client_ctx->msg_queue_lock);
+
+ if (islist_empty) {
+ DBG("%s(): vid_dec msg queue empty\n", __func__);
+ if (client_ctx->stop_msg) {
+ DBG("%s(): List empty and Stop Msg set\n",
+ __func__);
+ return client_ctx->stop_msg;
+ }
+ } else
+ DBG("%s(): vid_dec msg queue Not empty\n", __func__);
+
+ return !islist_empty;
+}
+
+static int vid_dec_get_next_msg(struct video_client_ctx *client_ctx,
+ struct vdec_msginfo *vdec_msg_info)
+{
+ int rc;
+ struct vid_dec_msg *vid_dec_msg = NULL;
+
+ if (!client_ctx)
+ return false;
+
+ rc = wait_event_interruptible(client_ctx->msg_wait,
+ vid_dec_msg_pending(client_ctx));
+ if (rc < 0) {
+ DBG("rc = %d, stop_msg = %u\n", rc, client_ctx->stop_msg);
+ return rc;
+ } else if (client_ctx->stop_msg) {
+ DBG("rc = %d, stop_msg = %u\n", rc, client_ctx->stop_msg);
+ return -EIO;
+ }
+
+ mutex_lock(&client_ctx->msg_queue_lock);
+ if (!list_empty(&client_ctx->msg_queue)) {
+ DBG("%s(): After Wait\n", __func__);
+ vid_dec_msg = list_first_entry(&client_ctx->msg_queue,
+ struct vid_dec_msg, list);
+ list_del(&vid_dec_msg->list);
+ memcpy(vdec_msg_info, &vid_dec_msg->vdec_msg_info,
+ sizeof(struct vdec_msginfo));
+ kfree(vid_dec_msg);
+ }
+ mutex_unlock(&client_ctx->msg_queue_lock);
+ return 0;
+}
+
+static long vid_dec_ioctl(struct file *file,
+ unsigned cmd, unsigned long u_arg)
+{
+ struct video_client_ctx *client_ctx = NULL;
+ struct vdec_ioctl_msg vdec_msg;
+ u32 vcd_status;
+ unsigned long kernel_vaddr, phy_addr, len;
+ struct file *pmem_file;
+ u32 result = true;
+ void __user *arg = (void __user *)u_arg;
+
+ DBG("%s\n", __func__);
+ if (_IOC_TYPE(cmd) != VDEC_IOCTL_MAGIC)
+ return -ENOTTY;
+
+ client_ctx = (struct video_client_ctx *)file->private_data;
+ if (!client_ctx) {
+ ERR("!client_ctx. Cannot attach to device handle\n");
+ return -ENODEV;
+ }
+
+ switch (cmd) {
+ case VDEC_IOCTL_SET_CODEC:
+ {
+ enum vdec_codec vdec_codec;
+ DBG("VDEC_IOCTL_SET_CODEC\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+ if (copy_from_user(&vdec_codec, vdec_msg.in,
+ sizeof(vdec_codec)))
+ return -EFAULT;
+ DBG("setting code type = %u\n", vdec_codec);
+ result = vid_dec_set_codec(client_ctx, &vdec_codec);
+ if (!result)
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_SET_OUTPUT_FORMAT:
+ {
+ enum vdec_output_fromat output_format;
+ DBG("VDEC_IOCTL_SET_OUTPUT_FORMAT\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+ if (copy_from_user(&output_format, vdec_msg.in,
+ sizeof(output_format)))
+ return -EFAULT;
+
+ result = vid_dec_set_output_format(client_ctx, &output_format);
+
+ if (!result)
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_SET_PICRES:
+ {
+ struct vdec_picsize video_resoultion;
+ DBG("VDEC_IOCTL_SET_PICRES\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+ if (copy_from_user(&video_resoultion, vdec_msg.in,
+ sizeof(video_resoultion)))
+ return -EFAULT;
+ result =
+ vid_dec_set_frame_resolution(client_ctx, &video_resoultion);
+ if (!result)
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_GET_PICRES:
+ {
+ struct vdec_picsize video_resoultion;
+ DBG("VDEC_IOCTL_GET_PICRES\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+ if (copy_from_user(&video_resoultion, vdec_msg.out,
+ sizeof(video_resoultion)))
+ return -EFAULT;
+
+ result = vid_dec_get_frame_resolution(client_ctx,
+ &video_resoultion);
+
+ if (result) {
+ if (copy_to_user(vdec_msg.out, &video_resoultion,
+ sizeof(video_resoultion)))
+ return -EFAULT;
+ } else
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_SET_BUFFER_REQ:
+ {
+ struct vdec_allocatorproperty vdec_buf_req;
+ struct vcd_buffer_requirement buffer_req;
+ DBG("VDEC_IOCTL_SET_BUFFER_REQ\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+
+ if (copy_from_user(&vdec_buf_req, vdec_msg.in,
+ sizeof(vdec_buf_req)))
+ return -EFAULT;
+
+ buffer_req.actual_count = vdec_buf_req.actualcount;
+ buffer_req.align = vdec_buf_req.alignment;
+ buffer_req.max_count = vdec_buf_req.maxcount;
+ buffer_req.min_count = vdec_buf_req.mincount;
+ buffer_req.sz = vdec_buf_req.buffer_size;
+
+ switch (vdec_buf_req.buffer_type) {
+ case VDEC_BUFFER_TYPE_INPUT:
+ vcd_status =
+ vcd_set_buffer_requirements(client_ctx->vcd_handle,
+ VCD_BUFFER_INPUT, &buffer_req);
+ break;
+ case VDEC_BUFFER_TYPE_OUTPUT:
+ vcd_status =
+ vcd_set_buffer_requirements(client_ctx->vcd_handle,
+ VCD_BUFFER_OUTPUT, &buffer_req);
+ break;
+ default:
+ vcd_status = VCD_ERR_BAD_POINTER;
+ break;
+ }
+
+ if (vcd_status)
+ return -EFAULT;
+ break;
+ }
+ case VDEC_IOCTL_GET_BUFFER_REQ:
+ {
+ struct vdec_allocatorproperty vdec_buf_req;
+ DBG("VDEC_IOCTL_GET_BUFFER_REQ\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+ if (copy_from_user(&vdec_buf_req, vdec_msg.out,
+ sizeof(vdec_buf_req)))
+ return -EFAULT;
+
+ result = vid_dec_get_buffer_req(client_ctx, &vdec_buf_req);
+
+ if (result) {
+ if (copy_to_user(vdec_msg.out, &vdec_buf_req,
+ sizeof(vdec_buf_req)))
+ return -EFAULT;
+ } else
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_SET_BUFFER:
+ {
+ struct vdec_setbuffer_cmd setbuffer;
+ DBG("VDEC_IOCTL_SET_BUFFER\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+ if (copy_from_user(&setbuffer, vdec_msg.in,
+ sizeof(setbuffer)))
+ return -EFAULT;
+ result = vid_dec_set_buffer(client_ctx, &setbuffer);
+ if (!result)
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_FREE_BUFFER:
+ {
+ struct vdec_setbuffer_cmd setbuffer;
+ DBG("VDEC_IOCTL_FREE_BUFFER\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+ if (copy_from_user(&setbuffer, vdec_msg.in,
+ sizeof(setbuffer)))
+ return -EFAULT;
+ result = vid_dec_free_buffer(client_ctx, &setbuffer);
+ if (!result)
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_CMD_START:
+ {
+ DBG(" VDEC_IOCTL_CMD_START\n");
+ result = vid_dec_start_stop(client_ctx, true);
+ if (!result)
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_CMD_STOP:
+ {
+ DBG("VDEC_IOCTL_CMD_STOP\n");
+ result = vid_dec_start_stop(client_ctx, false);
+ if (!result)
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_CMD_PAUSE:
+ {
+ result = vid_dec_pause_resume(client_ctx, true);
+ if (!result)
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_CMD_RESUME:
+ {
+ DBG("VDEC_IOCTL_CMD_PAUSE\n");
+ result = vid_dec_pause_resume(client_ctx, false);
+
+ if (!result)
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_DECODE_FRAME:
+ {
+ struct vdec_input_frameinfo input_frame_info;
+ DBG("VDEC_IOCTL_DECODE_FRAME\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+ if (copy_from_user(&input_frame_info, vdec_msg.in,
+ sizeof(input_frame_info)))
+ return -EFAULT;
+
+ result = vid_dec_decode_frame(client_ctx, &input_frame_info);
+
+ if (!result)
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_FILL_OUTPUT_BUFFER:
+ {
+ struct vdec_fillbuffer_cmd fill_buffer_cmd;
+ DBG("VDEC_IOCTL_FILL_OUTPUT_BUFFER\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+ if (copy_from_user(&fill_buffer_cmd, vdec_msg.in,
+ sizeof(fill_buffer_cmd)))
+ return -EFAULT;
+ result = vid_dec_fill_output_buffer(client_ctx,
+ &fill_buffer_cmd);
+ if (!result)
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_CMD_FLUSH:
+ {
+ enum vdec_bufferflush flush_dir;
+ DBG("VDEC_IOCTL_CMD_FLUSH\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+ if (copy_from_user(&flush_dir, vdec_msg.in,
+ sizeof(flush_dir)))
+ return -EFAULT;
+ result = vid_dec_flush(client_ctx, flush_dir);
+ if (!result)
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_GET_NEXT_MSG:
+ {
+ struct vdec_msginfo vdec_msg_info;
+ DBG("VDEC_IOCTL_GET_NEXT_MSG\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+ result = vid_dec_get_next_msg(client_ctx, &vdec_msg_info);
+ if (result)
+ return result;
+ if (copy_to_user(vdec_msg.out, &vdec_msg_info,
+ sizeof(vdec_msg_info)))
+ return -EFAULT;
+ break;
+ }
+ case VDEC_IOCTL_STOP_NEXT_MSG:
+ {
+ DBG("VDEC_IOCTL_STOP_NEXT_MSG\n");
+ client_ctx->stop_msg = 1;
+ wake_up(&client_ctx->msg_wait);
+ break;
+ }
+ case VDEC_IOCTL_SET_SEQUENCE_HEADER:
+ {
+ struct vdec_seqheader seq_header;
+ struct vcd_sequence_hdr vcd_seq_hdr;
+ DBG("VDEC_IOCTL_SET_SEQUENCE_HEADER\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg))) {
+ ERR("Copy from user vdec_msg failed\n");
+ return -EFAULT;
+ }
+ if (copy_from_user(&seq_header, vdec_msg.in,
+ sizeof(seq_header))) {
+ ERR("Copy from user seq_header failed\n");
+ return -EFAULT;
+ }
+ if (!seq_header.seq_header_len) {
+ ERR("Seq Len is Zero\n");
+ return -EFAULT;
+ }
+
+ if (get_pmem_file(seq_header.pmem_fd,
+ &phy_addr, &kernel_vaddr, &len, &pmem_file)) {
+ ERR("%s(): get_pmem_file failed\n", __func__);
+ return false;
+ }
+ put_pmem_file(pmem_file);
+
+ vcd_seq_hdr.sequence_header_len = seq_header.seq_header_len;
+ kernel_vaddr += (unsigned long)seq_header.pmem_offset;
+ vcd_seq_hdr.sequence_header = (u8 *)kernel_vaddr;
+ if (!vcd_seq_hdr.sequence_header) {
+ ERR("Sequence Header pointer failed\n");
+ return -EFAULT;
+ }
+ client_ctx->seq_header_set = true;
+ if (vcd_decode_start(client_ctx->vcd_handle, &vcd_seq_hdr)) {
+ ERR("Decode start Failed\n");
+ client_ctx->seq_header_set = false;
+ return -EFAULT;
+ }
+ DBG("Wait Client completion Sequence Header\n");
+ wait_for_completion(&client_ctx->event);
+ vcd_seq_hdr.sequence_header = NULL;
+ if (client_ctx->event_status) {
+ ERR("Set Seq Header status is failed");
+ return -EFAULT;
+ }
+ break;
+ }
+ case VDEC_IOCTL_GET_NUMBER_INSTANCES:
+ {
+ DBG("VDEC_IOCTL_GET_NUMBER_INSTANCES\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+ if (copy_to_user(vdec_msg.out,
+ &vid_dec_device_p->num_clients, sizeof(u32)))
+ return -EFAULT;
+ break;
+ }
+ case VDEC_IOCTL_GET_INTERLACE_FORMAT:
+ {
+ u32 progressive_only, interlace_format;
+ DBG("VDEC_IOCTL_GET_INTERLACE_FORMAT\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+ result = vid_dec_get_progressive_only(client_ctx,
+ &progressive_only);
+ if (result) {
+ interlace_format = progressive_only ?
+ VDEC_InterlaceFrameProgressive :
+ VDEC_InterlaceInterleaveFrameTopFieldFirst;
+ if (copy_to_user(vdec_msg.out, &interlace_format,
+ sizeof(u32)))
+ return -EFAULT;
+ } else
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_SET_PICTURE_ORDER:
+ {
+ u32 picture_order;
+ DBG("VDEC_IOCTL_SET_PICTURE_ORDER\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+ if (copy_from_user(&picture_order, vdec_msg.in,
+ sizeof(u32)))
+ return -EFAULT;
+ result = vid_dec_set_picture_order(client_ctx, &picture_order);
+ if (!result)
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_SET_FRAME_RATE:
+ {
+ struct vdec_framerate frame_rate;
+ DBG("VDEC_IOCTL_SET_FRAME_RATE\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+ if (copy_from_user(&frame_rate, vdec_msg.in,
+ sizeof(frame_rate)))
+ return -EFAULT;
+ result = vid_dec_set_frame_rate(client_ctx, &frame_rate);
+ if (!result)
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_SET_EXTRADATA:
+ {
+ u32 extradata_flag;
+ DBG("VDEC_IOCTL_SET_EXTRADATA\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+ if (copy_from_user(&extradata_flag, vdec_msg.in,
+ sizeof(u32)))
+ return -EFAULT;
+ result = vid_dec_set_extradata(client_ctx, &extradata_flag);
+ if (!result)
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_SET_H264_MV_BUFFER:
+ {
+ struct vdec_h264_mv mv_data;
+ DBG("VDEC_IOCTL_SET_H264_MV_BUFFER\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+ if (copy_from_user(&mv_data, vdec_msg.in,
+ sizeof(mv_data)))
+ return -EFAULT;
+ result = vid_dec_set_h264_mv_buffers(client_ctx, &mv_data);
+
+ if (!result)
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_FREE_H264_MV_BUFFER:
+ {
+ DBG("VDEC_IOCTL_FREE_H264_MV_BUFFER\n");
+ result = vid_dec_free_h264_mv_buffers(client_ctx);
+ if (!result)
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_GET_MV_BUFFER_SIZE:
+ {
+ struct vdec_mv_buff_size mv_buff;
+ DBG("VDEC_IOCTL_GET_MV_BUFFER_SIZE\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+ if (copy_from_user(&mv_buff, vdec_msg.out,
+ sizeof(mv_buff)))
+ return -EFAULT;
+ result = vid_dec_get_h264_mv_buffer_size(client_ctx, &mv_buff);
+ if (result) {
+ DBG(" Returning W: %d, H: %d, S: %d, A: %d",
+ mv_buff.width, mv_buff.height,
+ mv_buff.size, mv_buff.alignment);
+ if (copy_to_user(vdec_msg.out, &mv_buff,
+ sizeof(mv_buff)))
+ return -EFAULT;
+ } else
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_SET_IDR_ONLY_DECODING:
+ {
+ result = vid_dec_set_idr_only_decoding(client_ctx);
+ if (!result)
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_SET_CONT_ON_RECONFIG:
+ {
+ result = vid_dec_set_cont_on_reconfig(client_ctx);
+ if (!result)
+ return -EIO;
+ break;
+ }
+ default:
+ ERR("%s(): Unsupported ioctl\n", __func__);
+ return -ENOTTY;
+ break;
+ }
+
+ return 0;
+}
+
+static u32 vid_dec_close_client(struct video_client_ctx *client_ctx)
+{
+ struct vid_dec_msg *vdec_msg;
+ u32 vcd_status;
+
+ INFO("msm_vidc_dec: Inside %s()", __func__);
+ if (!client_ctx || (!client_ctx->vcd_handle)) {
+ ERR("\n Invalid client_ctx");
+ return false;
+ }
+
+ mutex_lock(&vid_dec_device_p->lock);
+ if (!client_ctx->stop_called) {
+ client_ctx->stop_called = true;
+ client_ctx->stop_sync_cb = true;
+ vcd_status = vcd_stop(client_ctx->vcd_handle);
+ DBG("\n Stuck at the stop call");
+ if (!vcd_status)
+ wait_for_completion(&client_ctx->event);
+ DBG("\n Came out of wait event");
+ }
+ mutex_lock(&client_ctx->msg_queue_lock);
+ while (!list_empty(&client_ctx->msg_queue)) {
+ DBG("%s(): Delete remaining entries\n", __func__);
+ vdec_msg = list_first_entry(&client_ctx->msg_queue,
+ struct vid_dec_msg, list);
+ if (vdec_msg) {
+ list_del(&vdec_msg->list);
+ kfree(vdec_msg);
+ }
+ }
+ mutex_unlock(&client_ctx->msg_queue_lock);
+ vcd_status = vcd_close(client_ctx->vcd_handle);
+
+ if (vcd_status) {
+ mutex_unlock(&vid_dec_device_p->lock);
+ return false;
+ }
+ memset((void *)client_ctx, 0, sizeof(struct video_client_ctx));
+ vid_dec_device_p->num_clients--;
+ mutex_unlock(&vid_dec_device_p->lock);
+ return true;
+}
+
+static int vid_dec_open(struct inode *inode, struct file *file)
+{
+ s32 client_index;
+ struct video_client_ctx *client_ctx;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u8 client_count = 0;
+
+ INFO("msm_vidc_dec: Inside %s()", __func__);
+ mutex_lock(&vid_dec_device_p->lock);
+
+ client_count = vcd_get_num_of_clients();
+ if (client_count == VIDC_MAX_NUM_CLIENTS) {
+ ERR("ERROR : vid_dec_open() max number of clients"
+ "limit reached\n");
+ mutex_unlock(&vid_dec_device_p->lock);
+ return -ENODEV;
+ }
+
+ DBG(" Virtual Address of ioremap is %p\n", vid_dec_device_p->virt_base);
+ if (!vid_dec_device_p->num_clients) {
+ if (!vidc_load_firmware())
+ return -ENODEV;
+ }
+
+ client_index = vid_dec_get_empty_client_index();
+ if (client_index == -1) {
+ ERR("%s() : No free clients client_index == -1\n", __func__);
+ return -ENODEV;
+ }
+ client_ctx = &vid_dec_device_p->vdec_clients[client_index];
+ vid_dec_device_p->num_clients++;
+ init_completion(&client_ctx->event);
+ mutex_init(&client_ctx->msg_queue_lock);
+ INIT_LIST_HEAD(&client_ctx->msg_queue);
+ init_waitqueue_head(&client_ctx->msg_wait);
+ client_ctx->stop_msg = 0;
+ client_ctx->stop_called = false;
+ client_ctx->stop_sync_cb = false;
+ vcd_status = vcd_open(vid_dec_device_p->device_handle, true,
+ vid_dec_vcd_cb, client_ctx);
+ if (!vcd_status) {
+ wait_for_completion(&client_ctx->event);
+ if (client_ctx->event_status) {
+ ERR("callback for vcd_open returned error: %u",
+ client_ctx->event_status);
+ mutex_unlock(&vid_dec_device_p->lock);
+ return -EFAULT;
+ }
+ } else {
+ ERR("vcd_open returned error: %u", vcd_status);
+ mutex_unlock(&vid_dec_device_p->lock);
+ return -EFAULT;
+ }
+
+ client_ctx->seq_header_set = false;
+ file->private_data = client_ctx;
+ mutex_unlock(&vid_dec_device_p->lock);
+ return 0;
+}
+
+static int vid_dec_release(struct inode *inode, struct file *file)
+{
+ struct video_client_ctx *client_ctx = file->private_data;
+
+ INFO("msm_vidc_dec: Inside %s()", __func__);
+ vid_dec_close_client(client_ctx);
+ vidc_release_firmware();
+#ifndef USE_RES_TRACKER
+ vidc_disable_clk();
+#endif
+ INFO("msm_vidc_dec: Return from %s()", __func__);
+ return 0;
+}
+
+static const struct file_operations vid_dec_fops = {
+ .owner = THIS_MODULE,
+ .open = vid_dec_open,
+ .release = vid_dec_release,
+ .unlocked_ioctl = vid_dec_ioctl,
+};
+
+void vid_dec_interrupt_deregister(void)
+{
+}
+
+void vid_dec_interrupt_register(void *device_name)
+{
+}
+
+void vid_dec_interrupt_clear(void)
+{
+}
+
+void *vid_dec_map_dev_base_addr(void *device_name)
+{
+ return vid_dec_device_p->virt_base;
+}
+
+static int vid_dec_vcd_init(void)
+{
+ int rc;
+ struct vcd_init_config vcd_init_config;
+ u32 i;
+
+ /* init_timer(&hw_timer); */
+ INFO("msm_vidc_dec: Inside %s()", __func__);
+ vid_dec_device_p->num_clients = 0;
+
+ for (i = 0; i < VIDC_MAX_NUM_CLIENTS; i++) {
+ memset((void *)&vid_dec_device_p->vdec_clients[i], 0,
+ sizeof(vid_dec_device_p->vdec_clients[i]));
+ }
+
+ mutex_init(&vid_dec_device_p->lock);
+ vid_dec_device_p->virt_base = vidc_get_ioaddr();
+ DBG("%s() : base address for VIDC core %u\n", __func__, \
+ (int)vid_dec_device_p->virt_base);
+
+ if (!vid_dec_device_p->virt_base) {
+ ERR("%s() : ioremap failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ vcd_init_config.device_name = "VIDC";
+ vcd_init_config.map_dev_base_addr = vid_dec_map_dev_base_addr;
+ vcd_init_config.interrupt_clr = vid_dec_interrupt_clear;
+ vcd_init_config.register_isr = vid_dec_interrupt_register;
+ vcd_init_config.deregister_isr = vid_dec_interrupt_deregister;
+ vcd_init_config.timer_create = vidc_timer_create;
+ vcd_init_config.timer_release = vidc_timer_release;
+ vcd_init_config.timer_start = vidc_timer_start;
+ vcd_init_config.timer_stop = vidc_timer_stop;
+
+ rc = vcd_init(&vcd_init_config, &vid_dec_device_p->device_handle);
+
+ if (rc) {
+ ERR("%s() : vcd_init failed\n", __func__);
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static int __init vid_dec_init(void)
+{
+ int rc = 0;
+ struct device *class_devp;
+
+ INFO("msm_vidc_dec: Inside %s()", __func__);
+ vid_dec_device_p = kzalloc(sizeof(struct vid_dec_dev), GFP_KERNEL);
+ if (!vid_dec_device_p) {
+ ERR("%s Unable to allocate memory for vid_dec_dev\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ rc = alloc_chrdev_region(&vid_dec_dev_num, 0, 1, VID_DEC_NAME);
+ if (rc < 0) {
+ ERR("%s: alloc_chrdev_region Failed rc = %d\n",
+ __func__, rc);
+ goto error_vid_dec_alloc_chrdev_region;
+ }
+
+ vid_dec_class = class_create(THIS_MODULE, VID_DEC_NAME);
+ if (IS_ERR(vid_dec_class)) {
+ rc = PTR_ERR(vid_dec_class);
+ ERR("%s: couldn't create vid_dec_class rc = %d\n",
+ __func__, rc);
+
+ goto error_vid_dec_class_create;
+ }
+
+ class_devp = device_create(vid_dec_class, NULL, vid_dec_dev_num, NULL,
+ VID_DEC_NAME);
+
+ if (IS_ERR(class_devp)) {
+ rc = PTR_ERR(class_devp);
+ ERR("%s: class device_create failed %d\n",
+ __func__, rc);
+ goto error_vid_dec_class_device_create;
+ }
+
+ vid_dec_device_p->device = class_devp;
+
+ cdev_init(&vid_dec_device_p->cdev, &vid_dec_fops);
+ vid_dec_device_p->cdev.owner = THIS_MODULE;
+ rc = cdev_add(&(vid_dec_device_p->cdev), vid_dec_dev_num, 1);
+
+ if (rc < 0) {
+ ERR("%s: cdev_add failed %d\n", __func__, rc);
+ goto error_vid_dec_cdev_add;
+ }
+ vid_dec_vcd_init();
+ return 0;
+
+error_vid_dec_cdev_add:
+ device_destroy(vid_dec_class, vid_dec_dev_num);
+error_vid_dec_class_device_create:
+ class_destroy(vid_dec_class);
+error_vid_dec_class_create:
+ unregister_chrdev_region(vid_dec_dev_num, 1);
+error_vid_dec_alloc_chrdev_region:
+ kfree(vid_dec_device_p);
+
+ return rc;
+}
+
+static void __exit vid_dec_exit(void)
+{
+ INFO("msm_vidc_dec: Inside %s()", __func__);
+ cdev_del(&(vid_dec_device_p->cdev));
+ device_destroy(vid_dec_class, vid_dec_dev_num);
+ class_destroy(vid_dec_class);
+ unregister_chrdev_region(vid_dec_dev_num, 1);
+ kfree(vid_dec_device_p);
+ INFO("msm_vidc_dec: Return from %s()", __func__);
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Video decoder driver");
+MODULE_VERSION("1.0");
+
+module_init(vid_dec_init);
+module_exit(vid_dec_exit);
diff --git a/drivers/video/msm/vidc/common/dec/vdec_internal.h b/drivers/video/msm/vidc/common/dec/vdec_internal.h
new file mode 100644
index 0000000..867c3b3
--- /dev/null
+++ b/drivers/video/msm/vidc/common/dec/vdec_internal.h
@@ -0,0 +1,43 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef VDEC_INTERNAL_H
+#define VDEC_INTERNAL_H
+
+#include <linux/msm_vidc_dec.h>
+#include <linux/cdev.h>
+#include "vidc_init.h"
+
+struct vid_dec_msg {
+ struct list_head list;
+ struct vdec_msginfo vdec_msg_info;
+};
+
+struct vid_dec_dev {
+ struct cdev cdev;
+ struct device *device;
+ resource_size_t phys_base;
+ void __iomem *virt_base;
+ unsigned int irq;
+ struct clk *hclk;
+ struct clk *hclk_div2;
+ struct clk *pclk;
+ unsigned long hclk_rate;
+ struct mutex lock;
+ s32 device_handle;
+ struct video_client_ctx vdec_clients[VIDC_MAX_NUM_CLIENTS];
+ u32 num_clients;
+ void(*timer_handler)(void *);
+};
+
+#endif
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
new file mode 100644
index 0000000..a69b810
--- /dev/null
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -0,0 +1,1549 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+#include <linux/android_pmem.h>
+#include <linux/clk.h>
+
+#include "vidc_type.h"
+#include "vcd_api.h"
+#include "venc_internal.h"
+#include "vidc_init.h"
+
+#define VID_ENC_NAME "msm_vidc_enc"
+
+#if DEBUG
+#define DBG(x...) printk(KERN_DEBUG x)
+#else
+#define DBG(x...)
+#endif
+
+#define INFO(x...) printk(KERN_INFO x)
+#define ERR(x...) printk(KERN_ERR x)
+
+static struct vid_enc_dev *vid_enc_device_p;
+static dev_t vid_enc_dev_num;
+static struct class *vid_enc_class;
+static long vid_enc_ioctl(struct file *file,
+ unsigned cmd, unsigned long arg);
+static int stop_cmd;
+
+static s32 vid_enc_get_empty_client_index(void)
+{
+ u32 i;
+ u32 found = false;
+
+ for (i = 0; i < VIDC_MAX_NUM_CLIENTS; i++) {
+ if (!vid_enc_device_p->venc_clients[i].vcd_handle) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ ERR("%s():ERROR No space for new client\n",
+ __func__);
+ return -ENOMEM;
+ } else {
+ DBG("%s(): available client index = %u\n",
+ __func__, i);
+ return i;
+ }
+}
+
+
+u32 vid_enc_get_status(u32 status)
+{
+ u32 venc_status;
+
+ switch (status) {
+ case VCD_S_SUCCESS:
+ venc_status = VEN_S_SUCCESS;
+ break;
+ case VCD_ERR_FAIL:
+ venc_status = VEN_S_EFAIL;
+ break;
+ case VCD_ERR_ALLOC_FAIL:
+ venc_status = VEN_S_ENOSWRES;
+ break;
+ case VCD_ERR_ILLEGAL_OP:
+ venc_status = VEN_S_EINVALCMD;
+ break;
+ case VCD_ERR_ILLEGAL_PARM:
+ venc_status = VEN_S_EBADPARAM;
+ break;
+ case VCD_ERR_BAD_POINTER:
+ case VCD_ERR_BAD_HANDLE:
+ venc_status = VEN_S_EFATAL;
+ break;
+ case VCD_ERR_NOT_SUPPORTED:
+ venc_status = VEN_S_ENOTSUPP;
+ break;
+ case VCD_ERR_BAD_STATE:
+ venc_status = VEN_S_EINVALSTATE;
+ break;
+ case VCD_ERR_MAX_CLIENT:
+ venc_status = VEN_S_ENOHWRES;
+ break;
+ default:
+ venc_status = VEN_S_EFAIL;
+ break;
+ }
+ return venc_status;
+}
+
+static void vid_enc_notify_client(struct video_client_ctx *client_ctx)
+{
+ if (client_ctx)
+ complete(&client_ctx->event);
+}
+
+void vid_enc_vcd_open_done(struct video_client_ctx *client_ctx,
+ struct vcd_handle_container *handle_container)
+{
+ DBG("vid_enc_vcd_open_done\n");
+
+ if (client_ctx) {
+ if (handle_container)
+ client_ctx->vcd_handle = handle_container->handle;
+ else
+ ERR("%s(): ERROR. handle_container is NULL\n",
+ __func__);
+ vid_enc_notify_client(client_ctx);
+ } else
+ ERR("%s(): ERROR. client_ctx is NULL\n",
+ __func__);
+}
+
+static void vid_enc_input_frame_done(struct video_client_ctx *client_ctx,
+ u32 event, u32 status,
+ struct vcd_frame_data *vcd_frame_data)
+{
+ struct vid_enc_msg *venc_msg;
+
+ if (!client_ctx || !vcd_frame_data) {
+ ERR("vid_enc_input_frame_done() NULL pointer\n");
+ return;
+ }
+
+ venc_msg = kzalloc(sizeof(struct vid_enc_msg),
+ GFP_KERNEL);
+ if (!venc_msg) {
+ ERR("vid_enc_input_frame_done(): cannot allocate vid_enc_msg "
+ " buffer\n");
+ return;
+ }
+
+ venc_msg->venc_msg_info.statuscode = vid_enc_get_status(status);
+
+ venc_msg->venc_msg_info.msgcode = VEN_MSG_INPUT_BUFFER_DONE;
+
+ switch (event) {
+ case VCD_EVT_RESP_INPUT_DONE:
+ DBG("Send INPUT_DON message to client = %p\n",
+ client_ctx);
+ break;
+ case VCD_EVT_RESP_INPUT_FLUSHED:
+ DBG("Send INPUT_FLUSHED message to client = %p\n",
+ client_ctx);
+ break;
+ default:
+ ERR("vid_enc_input_frame_done(): invalid event type: "
+ "%d\n", event);
+ venc_msg->venc_msg_info.statuscode = VEN_S_EFATAL;
+ break;
+ }
+
+ venc_msg->venc_msg_info.buf.clientdata =
+ (void *)vcd_frame_data->frm_clnt_data;
+ venc_msg->venc_msg_info.msgdata_size =
+ sizeof(struct vid_enc_msg);
+
+ mutex_lock(&client_ctx->msg_queue_lock);
+ list_add_tail(&venc_msg->list, &client_ctx->msg_queue);
+ mutex_unlock(&client_ctx->msg_queue_lock);
+ wake_up(&client_ctx->msg_wait);
+}
+
+static void vid_enc_output_frame_done(struct video_client_ctx *client_ctx,
+ u32 event, u32 status,
+ struct vcd_frame_data *vcd_frame_data)
+{
+ struct vid_enc_msg *venc_msg;
+ unsigned long kernel_vaddr, phy_addr, user_vaddr;
+ int pmem_fd;
+ struct file *file;
+ s32 buffer_index = -1;
+
+ if (!client_ctx || !vcd_frame_data) {
+ ERR("vid_enc_input_frame_done() NULL pointer\n");
+ return;
+ }
+
+ venc_msg = kzalloc(sizeof(struct vid_enc_msg),
+ GFP_KERNEL);
+ if (!venc_msg) {
+ ERR("vid_enc_input_frame_done(): cannot allocate vid_enc_msg "
+ " buffer\n");
+ return;
+ }
+
+ venc_msg->venc_msg_info.statuscode = vid_enc_get_status(status);
+ venc_msg->venc_msg_info.msgcode = VEN_MSG_OUTPUT_BUFFER_DONE;
+
+ switch (event) {
+ case VCD_EVT_RESP_OUTPUT_DONE:
+ DBG("Send INPUT_DON message to client = %p\n",
+ client_ctx);
+ break;
+ case VCD_EVT_RESP_OUTPUT_FLUSHED:
+ DBG("Send INPUT_FLUSHED message to client = %p\n",
+ client_ctx);
+ break;
+ default:
+ ERR("QVD: vid_enc_output_frame_done invalid cmd type: %d\n", event);
+ venc_msg->venc_msg_info.statuscode = VEN_S_EFATAL;
+ break;
+ }
+
+ kernel_vaddr =
+ (unsigned long)vcd_frame_data->virtual;
+
+ if (vidc_lookup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT,
+ false, &user_vaddr, &kernel_vaddr,
+ &phy_addr, &pmem_fd, &file,
+ &buffer_index)) {
+
+ /* Buffer address in user space */
+ venc_msg->venc_msg_info.buf.ptrbuffer = (u8 *) user_vaddr;
+ /* Buffer address in user space */
+ venc_msg->venc_msg_info.buf.clientdata = (void *)
+ vcd_frame_data->frm_clnt_data;
+ /* Data length */
+ venc_msg->venc_msg_info.buf.len =
+ vcd_frame_data->data_len;
+ venc_msg->venc_msg_info.buf.flags =
+ vcd_frame_data->flags;
+ /* Timestamp pass-through from input frame */
+ venc_msg->venc_msg_info.buf.timestamp =
+ vcd_frame_data->time_stamp;
+
+ /* Decoded picture width and height */
+ venc_msg->venc_msg_info.msgdata_size =
+ sizeof(struct venc_buffer);
+ } else {
+ ERR("vid_enc_output_frame_done UVA can not be found\n");
+ venc_msg->venc_msg_info.statuscode =
+ VEN_S_EFATAL;
+ }
+
+ mutex_lock(&client_ctx->msg_queue_lock);
+ list_add_tail(&venc_msg->list, &client_ctx->msg_queue);
+ mutex_unlock(&client_ctx->msg_queue_lock);
+ wake_up(&client_ctx->msg_wait);
+}
+
+static void vid_enc_lean_event(struct video_client_ctx *client_ctx,
+ u32 event, u32 status)
+{
+ struct vid_enc_msg *venc_msg;
+ if (!client_ctx) {
+ ERR("%s(): !client_ctx pointer\n",
+ __func__);
+ return;
+ }
+
+ venc_msg = kzalloc(sizeof(struct vid_enc_msg),
+ GFP_KERNEL);
+ if (!venc_msg) {
+ ERR("%s(): cannot allocate vid_enc_msg buffer\n",
+ __func__);
+ return;
+ }
+
+ venc_msg->venc_msg_info.statuscode =
+ vid_enc_get_status(status);
+
+ switch (event) {
+ case VCD_EVT_RESP_FLUSH_INPUT_DONE:
+ INFO("\n msm_vidc_enc: Sending VCD_EVT_RESP_FLUSH_INPUT_DONE"
+ " to client");
+ venc_msg->venc_msg_info.msgcode =
+ VEN_MSG_FLUSH_INPUT_DONE;
+ break;
+ case VCD_EVT_RESP_FLUSH_OUTPUT_DONE:
+ INFO("\n msm_vidc_enc: Sending VCD_EVT_RESP_FLUSH_OUTPUT_DONE"
+ " to client");
+ venc_msg->venc_msg_info.msgcode =
+ VEN_MSG_FLUSH_OUPUT_DONE;
+ break;
+
+ case VCD_EVT_RESP_START:
+ INFO("\n msm_vidc_enc: Sending VCD_EVT_RESP_START"
+ " to client");
+ venc_msg->venc_msg_info.msgcode =
+ VEN_MSG_START;
+ break;
+
+ case VCD_EVT_RESP_STOP:
+ INFO("\n msm_vidc_enc: Sending VCD_EVT_RESP_STOP"
+ " to client");
+ venc_msg->venc_msg_info.msgcode =
+ VEN_MSG_STOP;
+ break;
+
+ case VCD_EVT_RESP_PAUSE:
+ INFO("\n msm_vidc_enc: Sending VCD_EVT_RESP_PAUSE"
+ " to client");
+ venc_msg->venc_msg_info.msgcode =
+ VEN_MSG_PAUSE;
+ break;
+
+ default:
+ ERR("%s() : unknown event type %u\n",
+ __func__, event);
+ break;
+ }
+
+ venc_msg->venc_msg_info.msgdata_size = 0;
+
+ mutex_lock(&client_ctx->msg_queue_lock);
+ list_add_tail(&venc_msg->list, &client_ctx->msg_queue);
+ mutex_unlock(&client_ctx->msg_queue_lock);
+ wake_up(&client_ctx->msg_wait);
+}
+
+
+void vid_enc_vcd_cb(u32 event, u32 status,
+ void *info, size_t sz, void *handle,
+ void *const client_data)
+{
+ struct video_client_ctx *client_ctx =
+ (struct video_client_ctx *)client_data;
+
+ DBG("Entering %s()\n", __func__);
+
+ if (!client_ctx) {
+ ERR("%s(): client_ctx is NULL\n", __func__);
+ return;
+ }
+
+ client_ctx->event_status = status;
+
+ switch (event) {
+ case VCD_EVT_RESP_OPEN:
+ vid_enc_vcd_open_done(client_ctx,
+ (struct vcd_handle_container *)info);
+ break;
+
+ case VCD_EVT_RESP_INPUT_DONE:
+ case VCD_EVT_RESP_INPUT_FLUSHED:
+ vid_enc_input_frame_done(client_ctx, event,
+ status, (struct vcd_frame_data *)info);
+ break;
+
+ case VCD_EVT_RESP_OUTPUT_DONE:
+ case VCD_EVT_RESP_OUTPUT_FLUSHED:
+ vid_enc_output_frame_done(client_ctx, event, status,
+ (struct vcd_frame_data *)info);
+ break;
+
+ case VCD_EVT_RESP_PAUSE:
+ case VCD_EVT_RESP_START:
+ case VCD_EVT_RESP_STOP:
+ case VCD_EVT_RESP_FLUSH_INPUT_DONE:
+ case VCD_EVT_RESP_FLUSH_OUTPUT_DONE:
+ case VCD_EVT_IND_OUTPUT_RECONFIG:
+ case VCD_EVT_IND_HWERRFATAL:
+ case VCD_EVT_IND_RESOURCES_LOST:
+ vid_enc_lean_event(client_ctx, event, status);
+ break;
+
+ default:
+ ERR("%s() : Error - Invalid event type =%u\n",
+ __func__, event);
+ break;
+ }
+}
+
+static u32 vid_enc_msg_pending(struct video_client_ctx *client_ctx)
+{
+ u32 islist_empty = 0;
+
+ mutex_lock(&client_ctx->msg_queue_lock);
+ islist_empty = list_empty(&client_ctx->msg_queue);
+ mutex_unlock(&client_ctx->msg_queue_lock);
+
+ if (islist_empty) {
+ DBG("%s(): vid_enc msg queue empty\n",
+ __func__);
+ if (client_ctx->stop_msg) {
+ DBG("%s(): List empty and Stop Msg set\n",
+ __func__);
+ return client_ctx->stop_msg;
+ }
+ } else
+ DBG("%s(): vid_enc msg queue Not empty\n",
+ __func__);
+
+ return !islist_empty;
+}
+
+static u32 vid_enc_get_next_msg(struct video_client_ctx *client_ctx,
+ struct venc_msg *venc_msg_info)
+{
+ int rc;
+ struct vid_enc_msg *vid_enc_msg = NULL;
+
+ if (!client_ctx)
+ return false;
+
+ rc = wait_event_interruptible(client_ctx->msg_wait,
+ vid_enc_msg_pending(client_ctx));
+
+ if (rc < 0 || client_ctx->stop_msg) {
+ DBG("rc = %d, stop_msg = %u\n", rc, client_ctx->stop_msg);
+ return false;
+ }
+
+ mutex_lock(&client_ctx->msg_queue_lock);
+
+ if (!list_empty(&client_ctx->msg_queue)) {
+ DBG("%s(): After Wait\n", __func__);
+ vid_enc_msg = list_first_entry(&client_ctx->msg_queue,
+ struct vid_enc_msg, list);
+ list_del(&vid_enc_msg->list);
+ memcpy(venc_msg_info, &vid_enc_msg->venc_msg_info,
+ sizeof(struct venc_msg));
+ kfree(vid_enc_msg);
+ }
+ mutex_unlock(&client_ctx->msg_queue_lock);
+ return true;
+}
+
+static u32 vid_enc_close_client(struct video_client_ctx *client_ctx)
+{
+ struct vid_enc_msg *vid_enc_msg = NULL;
+ u32 vcd_status;
+ int rc;
+
+ INFO("\n msm_vidc_enc: Inside %s()", __func__);
+ if (!client_ctx || (!client_ctx->vcd_handle)) {
+ ERR("\n %s(): Invalid client_ctx", __func__);
+ return false;
+ }
+
+ mutex_lock(&vid_enc_device_p->lock);
+
+ if (!stop_cmd) {
+ vcd_status = vcd_stop(client_ctx->vcd_handle);
+ DBG("Waiting for VCD_STOP: Before Timeout\n");
+ if (!vcd_status) {
+ rc = wait_for_completion_timeout(&client_ctx->event,
+ 5 * HZ);
+ if (!rc) {
+ ERR("%s:ERROR vcd_stop time out"
+ "rc = %d\n", __func__, rc);
+ }
+
+ if (client_ctx->event_status) {
+ ERR("%s:ERROR "
+ "vcd_stop Not successs\n", __func__);
+ }
+ }
+ }
+ DBG("VCD_STOPPED: After Timeout, calling VCD_CLOSE\n");
+ mutex_lock(&client_ctx->msg_queue_lock);
+ while (!list_empty(&client_ctx->msg_queue)) {
+ DBG("%s(): Delete remaining entries\n", __func__);
+ vid_enc_msg = list_first_entry(&client_ctx->msg_queue,
+ struct vid_enc_msg, list);
+ list_del(&vid_enc_msg->list);
+ kfree(vid_enc_msg);
+ }
+ mutex_unlock(&client_ctx->msg_queue_lock);
+ vcd_status = vcd_close(client_ctx->vcd_handle);
+
+ if (vcd_status) {
+ mutex_unlock(&vid_enc_device_p->lock);
+ return false;
+ }
+
+ memset((void *)client_ctx, 0,
+ sizeof(struct video_client_ctx));
+
+ vid_enc_device_p->num_clients--;
+ stop_cmd = 0;
+ mutex_unlock(&vid_enc_device_p->lock);
+ return true;
+}
+
+
+static int vid_enc_open(struct inode *inode, struct file *file)
+{
+ s32 client_index;
+ struct video_client_ctx *client_ctx;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u8 client_count = 0;
+
+ INFO("\n msm_vidc_enc: Inside %s()", __func__);
+
+ mutex_lock(&vid_enc_device_p->lock);
+
+ stop_cmd = 0;
+ client_count = vcd_get_num_of_clients();
+ if (client_count == VIDC_MAX_NUM_CLIENTS) {
+ ERR("ERROR : vid_enc_open() max number of clients"
+ "limit reached\n");
+ mutex_unlock(&vid_enc_device_p->lock);
+ return -ENODEV;
+ }
+
+ DBG(" Virtual Address of ioremap is %p\n", vid_enc_device_p->virt_base);
+ if (!vid_enc_device_p->num_clients) {
+ if (!vidc_load_firmware())
+ return -ENODEV;
+ }
+
+ client_index = vid_enc_get_empty_client_index();
+
+ if (client_index == -1) {
+ ERR("%s() : No free clients client_index == -1\n",
+ __func__);
+ return -ENODEV;
+ }
+
+ client_ctx =
+ &vid_enc_device_p->venc_clients[client_index];
+ vid_enc_device_p->num_clients++;
+
+ init_completion(&client_ctx->event);
+ mutex_init(&client_ctx->msg_queue_lock);
+ INIT_LIST_HEAD(&client_ctx->msg_queue);
+ init_waitqueue_head(&client_ctx->msg_wait);
+ vcd_status = vcd_open(vid_enc_device_p->device_handle, false,
+ vid_enc_vcd_cb, client_ctx);
+ client_ctx->stop_msg = 0;
+
+ if (!vcd_status) {
+ wait_for_completion(&client_ctx->event);
+ if (client_ctx->event_status) {
+ ERR("callback for vcd_open returned error: %u",
+ client_ctx->event_status);
+ mutex_unlock(&vid_enc_device_p->lock);
+ return -EFAULT;
+ }
+ } else {
+ ERR("vcd_open returned error: %u", vcd_status);
+ mutex_unlock(&vid_enc_device_p->lock);
+ return -EFAULT;
+ }
+ file->private_data = client_ctx;
+ mutex_unlock(&vid_enc_device_p->lock);
+ return 0;
+}
+
+static int vid_enc_release(struct inode *inode, struct file *file)
+{
+ struct video_client_ctx *client_ctx = file->private_data;
+ INFO("\n msm_vidc_enc: Inside %s()", __func__);
+ vid_enc_close_client(client_ctx);
+ vidc_release_firmware();
+#ifndef USE_RES_TRACKER
+ vidc_disable_clk();
+#endif
+ INFO("\n msm_vidc_enc: Return from %s()", __func__);
+ return 0;
+}
+
+static const struct file_operations vid_enc_fops = {
+ .owner = THIS_MODULE,
+ .open = vid_enc_open,
+ .release = vid_enc_release,
+ .unlocked_ioctl = vid_enc_ioctl,
+};
+
+void vid_enc_interrupt_deregister(void)
+{
+}
+
+void vid_enc_interrupt_register(void *device_name)
+{
+}
+
+void vid_enc_interrupt_clear(void)
+{
+}
+
+void *vid_enc_map_dev_base_addr(void *device_name)
+{
+ return vid_enc_device_p->virt_base;
+}
+
+static int vid_enc_vcd_init(void)
+{
+ int rc;
+ struct vcd_init_config vcd_init_config;
+ u32 i;
+
+ INFO("\n msm_vidc_enc: Inside %s()", __func__);
+ vid_enc_device_p->num_clients = 0;
+
+ for (i = 0; i < VIDC_MAX_NUM_CLIENTS; i++) {
+ memset((void *)&vid_enc_device_p->venc_clients[i], 0,
+ sizeof(vid_enc_device_p->venc_clients[i]));
+ }
+
+ mutex_init(&vid_enc_device_p->lock);
+ vid_enc_device_p->virt_base = vidc_get_ioaddr();
+
+ if (!vid_enc_device_p->virt_base) {
+ ERR("%s() : ioremap failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ vcd_init_config.device_name = "VIDC";
+ vcd_init_config.map_dev_base_addr =
+ vid_enc_map_dev_base_addr;
+ vcd_init_config.interrupt_clr =
+ vid_enc_interrupt_clear;
+ vcd_init_config.register_isr =
+ vid_enc_interrupt_register;
+ vcd_init_config.deregister_isr =
+ vid_enc_interrupt_deregister;
+
+ rc = vcd_init(&vcd_init_config,
+ &vid_enc_device_p->device_handle);
+
+ if (rc) {
+ ERR("%s() : vcd_init failed\n",
+ __func__);
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static int __init vid_enc_init(void)
+{
+ int rc = 0;
+ struct device *class_devp;
+
+ INFO("\n msm_vidc_enc: Inside %s()", __func__);
+ vid_enc_device_p = kzalloc(sizeof(struct vid_enc_dev),
+ GFP_KERNEL);
+ if (!vid_enc_device_p) {
+ ERR("%s Unable to allocate memory for vid_enc_dev\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ rc = alloc_chrdev_region(&vid_enc_dev_num, 0, 1, VID_ENC_NAME);
+ if (rc < 0) {
+ ERR("%s: alloc_chrdev_region Failed rc = %d\n",
+ __func__, rc);
+ goto error_vid_enc_alloc_chrdev_region;
+ }
+
+ vid_enc_class = class_create(THIS_MODULE, VID_ENC_NAME);
+ if (IS_ERR(vid_enc_class)) {
+ rc = PTR_ERR(vid_enc_class);
+ ERR("%s: couldn't create vid_enc_class rc = %d\n",
+ __func__, rc);
+ goto error_vid_enc_class_create;
+ }
+
+ class_devp = device_create(vid_enc_class, NULL,
+ vid_enc_dev_num, NULL, VID_ENC_NAME);
+
+ if (IS_ERR(class_devp)) {
+ rc = PTR_ERR(class_devp);
+ ERR("%s: class device_create failed %d\n",
+ __func__, rc);
+ goto error_vid_enc_class_device_create;
+ }
+
+ vid_enc_device_p->device = class_devp;
+
+ cdev_init(&vid_enc_device_p->cdev, &vid_enc_fops);
+ vid_enc_device_p->cdev.owner = THIS_MODULE;
+ rc = cdev_add(&(vid_enc_device_p->cdev), vid_enc_dev_num, 1);
+
+ if (rc < 0) {
+ ERR("%s: cdev_add failed %d\n",
+ __func__, rc);
+ goto error_vid_enc_cdev_add;
+ }
+ vid_enc_vcd_init();
+ return 0;
+
+error_vid_enc_cdev_add:
+ device_destroy(vid_enc_class, vid_enc_dev_num);
+error_vid_enc_class_device_create:
+ class_destroy(vid_enc_class);
+error_vid_enc_class_create:
+ unregister_chrdev_region(vid_enc_dev_num, 1);
+error_vid_enc_alloc_chrdev_region:
+ kfree(vid_enc_device_p);
+
+ return rc;
+}
+
+static void __exit vid_enc_exit(void)
+{
+ INFO("\n msm_vidc_enc: Inside %s()", __func__);
+ cdev_del(&(vid_enc_device_p->cdev));
+ device_destroy(vid_enc_class, vid_enc_dev_num);
+ class_destroy(vid_enc_class);
+ unregister_chrdev_region(vid_enc_dev_num, 1);
+ kfree(vid_enc_device_p);
+ INFO("\n msm_vidc_enc: Return from %s()", __func__);
+}
+static long vid_enc_ioctl(struct file *file,
+ unsigned cmd, unsigned long u_arg)
+{
+ struct video_client_ctx *client_ctx = NULL;
+ struct venc_ioctl_msg venc_msg;
+ void __user *arg = (void __user *)u_arg;
+ u32 result = true;
+
+ DBG("%s\n", __func__);
+
+ client_ctx = (struct video_client_ctx *)file->private_data;
+ if (!client_ctx) {
+ ERR("!client_ctx. Cannot attach to device handle\n");
+ return -ENODEV;
+ }
+
+ switch (cmd) {
+ case VEN_IOCTL_CMD_READ_NEXT_MSG:
+ {
+ struct venc_msg cb_msg;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ DBG("VEN_IOCTL_CMD_READ_NEXT_MSG\n");
+ result = vid_enc_get_next_msg(client_ctx, &cb_msg);
+ if (!result)
+ return -EIO;
+ if (copy_to_user(venc_msg.out, &cb_msg, sizeof(cb_msg)))
+ return -EFAULT;
+ break;
+ }
+ case VEN_IOCTL_CMD_STOP_READ_MSG:
+ {
+ DBG("VEN_IOCTL_CMD_STOP_READ_MSG\n");
+ client_ctx->stop_msg = 1;
+ wake_up(&client_ctx->msg_wait);
+ break;
+ }
+ case VEN_IOCTL_CMD_ENCODE_FRAME:
+ case VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER:
+ {
+ struct venc_buffer enc_buffer;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ DBG("VEN_IOCTL_CMD_ENCODE_FRAME"
+ "/VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER\n");
+ if (copy_from_user(&enc_buffer, venc_msg.in,
+ sizeof(enc_buffer)))
+ return -EFAULT;
+ if (cmd == VEN_IOCTL_CMD_ENCODE_FRAME)
+ result = vid_enc_encode_frame(client_ctx,
+ &enc_buffer);
+ else
+ result = vid_enc_fill_output_buffer(client_ctx,
+ &enc_buffer);
+ if (!result) {
+ DBG("\n VEN_IOCTL_CMD_ENCODE_FRAME/"
+ "VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER failed");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_INPUT_BUFFER:
+ case VEN_IOCTL_SET_OUTPUT_BUFFER:
+ {
+ enum venc_buffer_dir buffer_dir;
+ struct venc_bufferpayload buffer_info;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ DBG("VEN_IOCTL_SET_INPUT_BUFFER/VEN_IOCTL_SET_OUTPUT_BUFFER\n");
+ if (copy_from_user(&buffer_info, venc_msg.in,
+ sizeof(buffer_info)))
+ return -EFAULT;
+ buffer_dir = VEN_BUFFER_TYPE_INPUT;
+ if (cmd == VEN_IOCTL_SET_OUTPUT_BUFFER)
+ buffer_dir = VEN_BUFFER_TYPE_OUTPUT;
+ result = vid_enc_set_buffer(client_ctx, &buffer_info,
+ buffer_dir);
+ if (!result) {
+ DBG("\n VEN_IOCTL_SET_INPUT_BUFFER"
+ "/VEN_IOCTL_SET_OUTPUT_BUFFER failed");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_CMD_FREE_INPUT_BUFFER:
+ case VEN_IOCTL_CMD_FREE_OUTPUT_BUFFER:
+ {
+ enum venc_buffer_dir buffer_dir;
+ struct venc_bufferpayload buffer_info;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+
+ DBG("VEN_IOCTL_CMD_FREE_INPUT_BUFFER/"
+ "VEN_IOCTL_CMD_FREE_OUTPUT_BUFFER\n");
+
+ if (copy_from_user(&buffer_info, venc_msg.in,
+ sizeof(buffer_info)))
+ return -EFAULT;
+
+ buffer_dir = VEN_BUFFER_TYPE_INPUT;
+ if (cmd == VEN_IOCTL_CMD_FREE_OUTPUT_BUFFER)
+ buffer_dir = VEN_BUFFER_TYPE_OUTPUT;
+
+ result = vid_enc_free_buffer(client_ctx, &buffer_info,
+ buffer_dir);
+ if (!result) {
+ DBG("\n VEN_IOCTL_CMD_FREE_OUTPUT_BUFFER"
+ "/VEN_IOCTL_CMD_FREE_OUTPUT_BUFFER failed");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_INPUT_BUFFER_REQ:
+ case VEN_IOCTL_SET_OUTPUT_BUFFER_REQ:
+ {
+ struct venc_allocatorproperty allocatorproperty;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+
+ DBG("VEN_IOCTL_SET_INPUT_BUFFER_REQ"
+ "/VEN_IOCTL_SET_OUTPUT_BUFFER_REQ\n");
+
+ if (copy_from_user(&allocatorproperty, venc_msg.in,
+ sizeof(allocatorproperty)))
+ return -EFAULT;
+
+ if (cmd == VEN_IOCTL_SET_OUTPUT_BUFFER_REQ)
+ result = vid_enc_set_buffer_req(client_ctx,
+ &allocatorproperty, false);
+ else
+ result = vid_enc_set_buffer_req(client_ctx,
+ &allocatorproperty, true);
+ if (!result) {
+ DBG("setting VEN_IOCTL_SET_OUTPUT_BUFFER_REQ/"
+ "VEN_IOCTL_SET_INPUT_BUFFER_REQ failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_GET_INPUT_BUFFER_REQ:
+ case VEN_IOCTL_GET_OUTPUT_BUFFER_REQ:
+ {
+ struct venc_allocatorproperty allocatorproperty;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+
+ DBG("VEN_IOCTL_GET_INPUT_BUFFER_REQ/"
+ "VEN_IOCTL_GET_OUTPUT_BUFFER_REQ\n");
+
+ if (cmd == VEN_IOCTL_GET_OUTPUT_BUFFER_REQ)
+ result = vid_enc_get_buffer_req(client_ctx,
+ &allocatorproperty, false);
+ else
+ result = vid_enc_get_buffer_req(client_ctx,
+ &allocatorproperty, true);
+ if (!result)
+ return -EIO;
+ if (copy_to_user(venc_msg.out, &allocatorproperty,
+ sizeof(allocatorproperty)))
+ return -EFAULT;
+ break;
+ }
+ case VEN_IOCTL_CMD_FLUSH:
+ {
+ struct venc_bufferflush bufferflush;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+
+ DBG("VEN_IOCTL_CMD_FLUSH\n");
+ if (copy_from_user(&bufferflush, venc_msg.in,
+ sizeof(bufferflush)))
+ return -EFAULT;
+ INFO("\n %s(): Calling vid_enc_flush with mode = %lu",
+ __func__, bufferflush.flush_mode);
+ result = vid_enc_flush(client_ctx, &bufferflush);
+
+ if (!result) {
+ ERR("setting VEN_IOCTL_CMD_FLUSH failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_CMD_START:
+ {
+ INFO("\n %s(): Executing VEN_IOCTL_CMD_START", __func__);
+ result = vid_enc_start_stop(client_ctx, true);
+ if (!result) {
+ ERR("setting VEN_IOCTL_CMD_START failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_CMD_STOP:
+ {
+ INFO("\n %s(): Executing VEN_IOCTL_CMD_STOP", __func__);
+ result = vid_enc_start_stop(client_ctx, false);
+ if (!result) {
+ ERR("setting VEN_IOCTL_CMD_STOP failed\n");
+ return -EIO;
+ }
+ stop_cmd = 1;
+ break;
+ }
+ case VEN_IOCTL_CMD_PAUSE:
+ {
+ INFO("\n %s(): Executing VEN_IOCTL_CMD_PAUSE", __func__);
+ result = vid_enc_pause_resume(client_ctx, true);
+ if (!result) {
+ ERR("setting VEN_IOCTL_CMD_PAUSE failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_CMD_RESUME:
+ {
+ INFO("\n %s(): Executing VEN_IOCTL_CMD_RESUME", __func__);
+ result = vid_enc_pause_resume(client_ctx, false);
+ if (!result) {
+ ERR("setting VEN_IOCTL_CMD_RESUME failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_RECON_BUFFER:
+ {
+ struct venc_recon_addr venc_recon;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ DBG("VEN_IOCTL_SET_RECON_BUFFER\n");
+ if (copy_from_user(&venc_recon, venc_msg.in,
+ sizeof(venc_recon)))
+ return -EFAULT;
+ result = vid_enc_set_recon_buffers(client_ctx,
+ &venc_recon);
+ if (!result) {
+ ERR("setting VEN_IOCTL_SET_RECON_BUFFER failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_FREE_RECON_BUFFER:
+ {
+ DBG("VEN_IOCTL_FREE_RECON_BUFFER\n");
+ result = vid_enc_free_recon_buffers(client_ctx);
+ if (!result) {
+ ERR("VEN_IOCTL_FREE_RECON_BUFFER failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_GET_RECON_BUFFER_SIZE:
+ {
+ struct venc_recon_buff_size venc_recon_size;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ DBG("VEN_IOCTL_GET_RECON_BUFFER_SIZE\n");
+ if (copy_from_user(&venc_recon_size, venc_msg.out,
+ sizeof(venc_recon_size)))
+ return -EFAULT;
+ result = vid_enc_get_recon_buffer_size(client_ctx,
+ &venc_recon_size);
+ if (result) {
+ if (copy_to_user(venc_msg.out, &venc_recon_size,
+ sizeof(venc_recon_size)))
+ return -EFAULT;
+ } else {
+ ERR("setting VEN_IOCTL_GET_RECON_BUFFER_SIZE"
+ "failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_QP_RANGE:
+ case VEN_IOCTL_GET_QP_RANGE:
+ {
+ struct venc_qprange qprange;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ DBG("VEN_IOCTL_G(S)ET_QP_RANGE\n");
+ if (cmd == VEN_IOCTL_SET_QP_RANGE) {
+ if (copy_from_user(&qprange, venc_msg.in,
+ sizeof(qprange)))
+ return -EFAULT;
+ result = vid_enc_set_get_qprange(client_ctx,
+ &qprange, true);
+ } else {
+ result = vid_enc_set_get_qprange(client_ctx,
+ &qprange, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out, &qprange,
+ sizeof(qprange)))
+ return -EFAULT;
+ }
+ }
+ if (!result) {
+ ERR("setting VEN_IOCTL_G(S)ET_QP_RANGE failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_HEC:
+ case VEN_IOCTL_GET_HEC:
+ {
+ struct venc_headerextension headerextension;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ DBG("VEN_IOCTL_(G)SET_HEC\n");
+ if (cmd == VEN_IOCTL_SET_HEC) {
+ if (copy_from_user(&headerextension, venc_msg.in,
+ sizeof(headerextension)))
+ return -EFAULT;
+
+ result = vid_enc_set_get_headerextension(client_ctx,
+ &headerextension, true);
+ } else {
+ result = vid_enc_set_get_headerextension(client_ctx,
+ &headerextension, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out, &headerextension,
+ sizeof(headerextension)))
+ return -EFAULT;
+ }
+ }
+
+ if (!result) {
+ ERR("setting VEN_IOCTL_(G)SET_HEC failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_TARGET_BITRATE:
+ case VEN_IOCTL_GET_TARGET_BITRATE:
+ {
+ struct venc_targetbitrate targetbitrate;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ DBG("VEN_IOCTL_(G)SET_TARGET_BITRATE\n");
+ if (cmd == VEN_IOCTL_SET_TARGET_BITRATE) {
+ if (copy_from_user(&targetbitrate, venc_msg.in,
+ sizeof(targetbitrate)))
+ return -EFAULT;
+
+ result = vid_enc_set_get_bitrate(client_ctx,
+ &targetbitrate, true);
+ } else {
+ result = vid_enc_set_get_bitrate(client_ctx,
+ &targetbitrate, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out, &targetbitrate,
+ sizeof(targetbitrate)))
+ return -EFAULT;
+ }
+ }
+ if (!result) {
+ ERR("setting VEN_IOCTL_(G)SET_TARGET_BITRATE failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_FRAME_RATE:
+ case VEN_IOCTL_GET_FRAME_RATE:
+ {
+ struct venc_framerate framerate;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ DBG("VEN_IOCTL_(G)SET_FRAME_RATE\n");
+ if (cmd == VEN_IOCTL_SET_FRAME_RATE) {
+ if (copy_from_user(&framerate, venc_msg.in,
+ sizeof(framerate)))
+ return -EFAULT;
+ result = vid_enc_set_get_framerate(client_ctx,
+ &framerate, true);
+ } else {
+ result = vid_enc_set_get_framerate(client_ctx,
+ &framerate, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out, &framerate,
+ sizeof(framerate)))
+ return -EFAULT;
+ }
+ }
+
+ if (!result) {
+ ERR("VEN_IOCTL_(G)SET_FRAME_RATE failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_VOP_TIMING_CFG:
+ case VEN_IOCTL_GET_VOP_TIMING_CFG:
+ {
+ struct venc_voptimingcfg voptimingcfg;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+
+ DBG("VEN_IOCTL_(G)SET_VOP_TIMING_CFG\n");
+ if (cmd == VEN_IOCTL_SET_VOP_TIMING_CFG) {
+ if (copy_from_user(&voptimingcfg, venc_msg.in,
+ sizeof(voptimingcfg)))
+ return -EFAULT;
+ result = vid_enc_set_get_voptimingcfg(client_ctx,
+ &voptimingcfg, true);
+ } else {
+ result = vid_enc_set_get_voptimingcfg(client_ctx,
+ &voptimingcfg, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out, &voptimingcfg,
+ sizeof(voptimingcfg)))
+ return -EFAULT;
+ }
+ }
+ if (!result) {
+ ERR("VEN_IOCTL_(G)SET_VOP_TIMING_CFG failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_RATE_CTRL_CFG:
+ case VEN_IOCTL_GET_RATE_CTRL_CFG:
+ {
+ struct venc_ratectrlcfg ratectrlcfg;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ DBG("VEN_IOCTL_(G)SET_RATE_CTRL_CFG\n");
+ if (cmd == VEN_IOCTL_SET_RATE_CTRL_CFG) {
+ if (copy_from_user(&ratectrlcfg, venc_msg.in,
+ sizeof(ratectrlcfg)))
+ return -EFAULT;
+
+ result = vid_enc_set_get_ratectrlcfg(client_ctx,
+ &ratectrlcfg, true);
+ } else {
+ result = vid_enc_set_get_ratectrlcfg(client_ctx,
+ &ratectrlcfg, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out, &ratectrlcfg,
+ sizeof(ratectrlcfg)))
+ return -EFAULT;
+ }
+ }
+ if (!result) {
+ ERR("setting VEN_IOCTL_(G)SET_RATE_CTRL_CFG failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_MULTI_SLICE_CFG:
+ case VEN_IOCTL_GET_MULTI_SLICE_CFG:
+ {
+ struct venc_multiclicecfg multiclicecfg;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ DBG("VEN_IOCTL_(G)SET_MULTI_SLICE_CFG\n");
+ if (cmd == VEN_IOCTL_SET_MULTI_SLICE_CFG) {
+ if (copy_from_user(&multiclicecfg, venc_msg.in,
+ sizeof(multiclicecfg)))
+ return -EFAULT;
+
+ result = vid_enc_set_get_multiclicecfg(client_ctx,
+ &multiclicecfg, true);
+ } else {
+ result = vid_enc_set_get_multiclicecfg(client_ctx,
+ &multiclicecfg, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out, &multiclicecfg,
+ sizeof(multiclicecfg)))
+ return -EFAULT;
+ }
+ }
+ if (!result) {
+ ERR("VEN_IOCTL_(G)SET_MULTI_SLICE_CFG failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_INTRA_REFRESH:
+ case VEN_IOCTL_GET_INTRA_REFRESH:
+ {
+ struct venc_intrarefresh intrarefresh;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ DBG("VEN_IOCTL_(G)SET_INTRA_REFRESH\n");
+ if (cmd == VEN_IOCTL_SET_INTRA_REFRESH) {
+ if (copy_from_user(&intrarefresh, venc_msg.in,
+ sizeof(intrarefresh)))
+ return -EFAULT;
+ result = vid_enc_set_get_intrarefresh(client_ctx,
+ &intrarefresh, true);
+ } else {
+ result = vid_enc_set_get_intrarefresh(client_ctx,
+ &intrarefresh, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out, &intrarefresh,
+ sizeof(intrarefresh)))
+ return -EFAULT;
+ }
+ }
+ if (!result) {
+ ERR("setting VEN_IOCTL_SET_INTRA_REFRESH failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_DEBLOCKING_CFG:
+ case VEN_IOCTL_GET_DEBLOCKING_CFG:
+ {
+ struct venc_dbcfg dbcfg;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+
+ DBG("VEN_IOCTL_(G)SET_DEBLOCKING_CFG\n");
+ if (cmd == VEN_IOCTL_SET_DEBLOCKING_CFG) {
+ if (copy_from_user(&dbcfg, venc_msg.in,
+ sizeof(dbcfg)))
+ return -EFAULT;
+ result = vid_enc_set_get_dbcfg(client_ctx,
+ &dbcfg, true);
+ } else {
+ result = vid_enc_set_get_dbcfg(client_ctx,
+ &dbcfg, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out, &dbcfg,
+ sizeof(dbcfg)))
+ return -EFAULT;
+ }
+ }
+ if (!result) {
+ ERR("setting VEN_IOCTL_SET_DEBLOCKING_CFG failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_ENTROPY_CFG:
+ case VEN_IOCTL_GET_ENTROPY_CFG:
+ {
+ struct venc_entropycfg entropy_cfg;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ DBG("VEN_IOCTL_(G)SET_ENTROPY_CFG\n");
+ if (cmd == VEN_IOCTL_SET_ENTROPY_CFG) {
+ if (copy_from_user(&entropy_cfg, venc_msg.in,
+ sizeof(entropy_cfg)))
+ return -EFAULT;
+ result = vid_enc_set_get_entropy_cfg(client_ctx,
+ &entropy_cfg, true);
+ } else {
+ result = vid_enc_set_get_entropy_cfg(client_ctx,
+ &entropy_cfg, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out, &entropy_cfg,
+ sizeof(entropy_cfg)))
+ return -EFAULT;
+ }
+ }
+ if (!result) {
+ ERR("setting VEN_IOCTL_(G)SET_ENTROPY_CFG failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_GET_SEQUENCE_HDR:
+ {
+ struct venc_seqheader seq_header, seq_header_user;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+
+ DBG("VEN_IOCTL_GET_SEQUENCE_HDR\n");
+ if (copy_from_user(&seq_header_user, venc_msg.in,
+ sizeof(seq_header_user)))
+ return -EFAULT;
+ seq_header.hdrbufptr = NULL;
+ result = vid_enc_get_sequence_header(client_ctx,
+ &seq_header);
+ if (result && ((copy_to_user(seq_header_user.hdrbufptr,
+ seq_header.hdrbufptr, seq_header.hdrlen)) ||
+ (copy_to_user(&seq_header_user.hdrlen,
+ &seq_header.hdrlen,
+ sizeof(seq_header.hdrlen)))))
+ result = false;
+ kfree(seq_header.hdrbufptr);
+ if (!result)
+ return -EIO;
+ break;
+ }
+ case VEN_IOCTL_CMD_REQUEST_IFRAME:
+ {
+ result = vid_enc_request_iframe(client_ctx);
+ if (!result) {
+ ERR("setting VEN_IOCTL_CMD_REQUEST_IFRAME failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_INTRA_PERIOD:
+ case VEN_IOCTL_GET_INTRA_PERIOD:
+ {
+ struct venc_intraperiod intraperiod;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ DBG("VEN_IOCTL_(G)SET_INTRA_PERIOD\n");
+ if (cmd == VEN_IOCTL_SET_INTRA_PERIOD) {
+ if (copy_from_user(&intraperiod, venc_msg.in,
+ sizeof(intraperiod)))
+ return -EFAULT;
+ result = vid_enc_set_get_intraperiod(client_ctx,
+ &intraperiod, true);
+ } else {
+ result = vid_enc_set_get_intraperiod(client_ctx,
+ &intraperiod, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out, &intraperiod,
+ sizeof(intraperiod)))
+ return -EFAULT;
+ }
+ }
+ if (!result) {
+ ERR("setting VEN_IOCTL_(G)SET_INTRA_PERIOD failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_SESSION_QP:
+ case VEN_IOCTL_GET_SESSION_QP:
+ {
+ struct venc_sessionqp session_qp;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ DBG("VEN_IOCTL_(G)SET_SESSION_QP\n");
+ if (cmd == VEN_IOCTL_SET_SESSION_QP) {
+ if (copy_from_user(&session_qp, venc_msg.in,
+ sizeof(session_qp)))
+ return -EFAULT;
+ result = vid_enc_set_get_session_qp(client_ctx,
+ &session_qp, true);
+ } else {
+ result = vid_enc_set_get_session_qp(client_ctx,
+ &session_qp, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out, &session_qp,
+ sizeof(session_qp)))
+ return -EFAULT;
+ }
+ }
+ if (!result) {
+ ERR("setting VEN_IOCTL_(G)SET_SESSION_QP failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_PROFILE_LEVEL:
+ case VEN_IOCTL_GET_PROFILE_LEVEL:
+ {
+ struct ven_profilelevel profile_level;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+
+ DBG("VEN_IOCTL_(G)SET_PROFILE_LEVEL\n");
+ if (cmd == VEN_IOCTL_SET_PROFILE_LEVEL) {
+ if (copy_from_user(&profile_level, venc_msg.in,
+ sizeof(profile_level)))
+ return -EFAULT;
+ result = vid_enc_set_get_profile_level(client_ctx,
+ &profile_level, true);
+ } else {
+ result = vid_enc_set_get_profile_level(client_ctx,
+ &profile_level, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out,
+ &profile_level, sizeof(profile_level)))
+ return -EFAULT;
+ }
+ }
+ if (!result) {
+ ERR("setting VEN_IOCTL_SET_PROFILE_LEVEL failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_CODEC_PROFILE:
+ case VEN_IOCTL_GET_CODEC_PROFILE:
+ {
+ struct venc_profile profile;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+
+ DBG("VEN_IOCTL_(G)SET_CODEC_PROFILE\n");
+ if (cmd == VEN_IOCTL_SET_CODEC_PROFILE) {
+ if (copy_from_user(&profile, venc_msg.in,
+ sizeof(profile)))
+ return -EFAULT;
+ result = vid_enc_set_get_profile(client_ctx,
+ &profile, true);
+ } else {
+ result = vid_enc_set_get_profile(client_ctx,
+ &profile, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out, &profile,
+ sizeof(profile)))
+ return -EFAULT;
+ }
+ }
+ if (!result) {
+ ERR("setting VEN_IOCTL_SET_CODEC_PROFILE failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_SHORT_HDR:
+ case VEN_IOCTL_GET_SHORT_HDR:
+ {
+ struct venc_switch encoder_switch;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ DBG("Getting VEN_IOCTL_(G)SET_SHORT_HDR\n");
+ if (cmd == VEN_IOCTL_SET_SHORT_HDR) {
+ if (copy_from_user(&encoder_switch, venc_msg.in,
+ sizeof(encoder_switch)))
+ return -EFAULT;
+
+ result = vid_enc_set_get_short_header(client_ctx,
+ &encoder_switch, true);
+ } else {
+ result = vid_enc_set_get_short_header(client_ctx,
+ &encoder_switch, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out, &encoder_switch,
+ sizeof(encoder_switch)))
+ return -EFAULT;
+ }
+ }
+ if (!result) {
+ ERR("setting VEN_IOCTL_(G)SET_SHORT_HDR failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_BASE_CFG:
+ case VEN_IOCTL_GET_BASE_CFG:
+ {
+ struct venc_basecfg base_config;
+ DBG("VEN_IOCTL_SET_BASE_CFG\n");
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ if (cmd == VEN_IOCTL_SET_BASE_CFG) {
+ if (copy_from_user(&base_config, venc_msg.in,
+ sizeof(base_config)))
+ return -EFAULT;
+ result = vid_enc_set_get_base_cfg(client_ctx,
+ &base_config, true);
+ } else {
+ result = vid_enc_set_get_base_cfg(client_ctx,
+ &base_config, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out, &base_config,
+ sizeof(base_config)))
+ return -EFAULT;
+ }
+ }
+ if (!result) {
+ ERR("setting VEN_IOCTL_SET_BASE_CFG failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_LIVE_MODE:
+ case VEN_IOCTL_GET_LIVE_MODE:
+ {
+ struct venc_switch encoder_switch;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+
+ DBG("Getting VEN_IOCTL_(G)SET_LIVE_MODE\n");
+ if (cmd == VEN_IOCTL_SET_LIVE_MODE) {
+ if (copy_from_user(&encoder_switch, venc_msg.in,
+ sizeof(encoder_switch)))
+ return -EFAULT;
+ result = vid_enc_set_get_live_mode(client_ctx,
+ &encoder_switch, true);
+ } else {
+ result = vid_enc_set_get_live_mode(client_ctx,
+ &encoder_switch, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out, &encoder_switch,
+ sizeof(encoder_switch)))
+ return -EFAULT;
+ }
+ }
+ if (!result) {
+ ERR("setting VEN_IOCTL_(G)SET_LIVE_MODE failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_GET_NUMBER_INSTANCES:
+ {
+ DBG("VEN_IOCTL_GET_NUMBER_INSTANCES\n");
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ if (copy_to_user(venc_msg.out,
+ &vid_enc_device_p->num_clients, sizeof(u32)))
+ return -EFAULT;
+ break;
+ }
+ case VEN_IOCTL_SET_AC_PREDICTION:
+ case VEN_IOCTL_GET_AC_PREDICTION:
+ case VEN_IOCTL_SET_RVLC:
+ case VEN_IOCTL_GET_RVLC:
+ case VEN_IOCTL_SET_ROTATION:
+ case VEN_IOCTL_GET_ROTATION:
+ case VEN_IOCTL_SET_DATA_PARTITION:
+ case VEN_IOCTL_GET_DATA_PARTITION:
+ case VEN_IOCTL_GET_CAPABILITY:
+ default:
+ ERR("%s(): Unsupported ioctl %d\n", __func__, cmd);
+ return -ENOTTY;
+
+ break;
+ }
+ return 0;
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Video encoder driver");
+MODULE_VERSION("1.0");
+
+module_init(vid_enc_init);
+module_exit(vid_enc_exit);
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.c b/drivers/video/msm/vidc/common/enc/venc_internal.c
new file mode 100644
index 0000000..d202d81
--- /dev/null
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.c
@@ -0,0 +1,1784 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+#include <linux/android_pmem.h>
+#include <linux/clk.h>
+
+#include "vidc_type.h"
+#include "vcd_api.h"
+#include "venc_internal.h"
+#include "vidc_init.h"
+
+#if DEBUG
+#define DBG(x...) printk(KERN_DEBUG x)
+#else
+#define DBG(x...)
+#endif
+
+#define ERR(x...) printk(KERN_ERR x)
+
+u32 vid_enc_set_get_base_cfg(struct video_client_ctx *client_ctx,
+ struct venc_basecfg *base_config, u32 set_flag)
+{
+ struct venc_targetbitrate venc_bitrate;
+ struct venc_framerate frame_rate;
+ u32 current_codec;
+
+ if (!client_ctx || !base_config)
+ return false;
+
+ if (!vid_enc_set_get_codec(client_ctx, ¤t_codec, false))
+ return false;
+
+ DBG("%s(): Current Codec Type = %u\n", __func__, current_codec);
+ if (current_codec != base_config->codectype) {
+ if (!vid_enc_set_get_codec(client_ctx,
+ (u32 *)&base_config->codectype, set_flag))
+ return false;
+ }
+
+ if (!vid_enc_set_get_inputformat(client_ctx,
+ (u32 *)&base_config->inputformat, set_flag))
+ return false;
+
+ if (!vid_enc_set_get_framesize(client_ctx,
+ (u32 *)&base_config->input_height,
+ (u32 *)&base_config->input_width, set_flag))
+ return false;
+
+ if (set_flag)
+ venc_bitrate.target_bitrate = base_config->targetbitrate;
+
+ if (!vid_enc_set_get_bitrate(client_ctx, &venc_bitrate, set_flag))
+ return false;
+
+ if (!set_flag)
+ base_config->targetbitrate = venc_bitrate.target_bitrate;
+
+ if (set_flag) {
+ frame_rate.fps_denominator = base_config->fps_den;
+ frame_rate.fps_numerator = base_config->fps_num;
+ }
+
+ if (!vid_enc_set_get_framerate(client_ctx, &frame_rate, set_flag))
+ return false;
+
+ if (!set_flag) {
+ base_config->fps_den = frame_rate.fps_denominator;
+ base_config->fps_num = frame_rate.fps_numerator;
+ }
+
+ return true;
+}
+
+u32 vid_enc_set_get_inputformat(struct video_client_ctx *client_ctx,
+ u32 *input_format, u32 set_flag)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_buffer_format format;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 status = true;
+
+ if (!client_ctx || !input_format)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_BUFFER_FORMAT;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_buffer_format);
+
+ if (set_flag) {
+ switch (*input_format) {
+ case VEN_INPUTFMT_NV12:
+ format.buffer_format = VCD_BUFFER_FORMAT_NV12;
+ break;
+ case VEN_INPUTFMT_NV12_16M2KA:
+ format.buffer_format =
+ VCD_BUFFER_FORMAT_NV12_16M2KA;
+ break;
+ default:
+ status = false;
+ break;
+ }
+
+ if (status) {
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &format);
+ if (vcd_status) {
+ status = false;
+ ERR("%s(): Set VCD_I_BUFFER_FORMAT Failed\n",
+ __func__);
+ }
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &format);
+
+ if (vcd_status) {
+ status = false;
+ ERR("%s(): Get VCD_I_BUFFER_FORMAT Failed\n", __func__);
+ } else {
+ switch (format.buffer_format) {
+ case VCD_BUFFER_FORMAT_NV12:
+ *input_format = VEN_INPUTFMT_NV12;
+ break;
+ case VCD_BUFFER_FORMAT_TILE_4x2:
+ *input_format = VEN_INPUTFMT_NV21;
+ break;
+ default:
+ status = false;
+ break;
+ }
+ }
+ }
+ return status;
+}
+
+u32 vid_enc_set_get_codec(struct video_client_ctx *client_ctx, u32 *codec,
+ u32 set_flag)
+{
+ struct vcd_property_codec vcd_property_codec;
+ struct vcd_property_hdr vcd_property_hdr;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 status = true;
+
+ if (!client_ctx || !codec)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_CODEC;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_codec);
+
+ if (set_flag) {
+ switch (*codec) {
+ case VEN_CODEC_MPEG4:
+ vcd_property_codec.codec = VCD_CODEC_MPEG4;
+ break;
+ case VEN_CODEC_H263:
+ vcd_property_codec.codec = VCD_CODEC_H263;
+ break;
+ case VEN_CODEC_H264:
+ vcd_property_codec.codec = VCD_CODEC_H264;
+ break;
+ default:
+ status = false;
+ break;
+ }
+
+ if (status) {
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_property_codec);
+ if (vcd_status) {
+ status = false;
+ ERR("%s(): Set VCD_I_CODEC Failed\n", __func__);
+ }
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_property_codec);
+
+ if (vcd_status) {
+ status = false;
+ ERR("%s(): Get VCD_I_CODEC Failed\n",
+ __func__);
+ } else {
+ switch (vcd_property_codec.codec) {
+ case VCD_CODEC_H263:
+ *codec = VEN_CODEC_H263;
+ break;
+ case VCD_CODEC_H264:
+ *codec = VEN_CODEC_H264;
+ break;
+ case VCD_CODEC_MPEG4:
+ *codec = VEN_CODEC_MPEG4;
+ break;
+ case VCD_CODEC_DIVX_3:
+ case VCD_CODEC_DIVX_4:
+ case VCD_CODEC_DIVX_5:
+ case VCD_CODEC_DIVX_6:
+ case VCD_CODEC_MPEG1:
+ case VCD_CODEC_MPEG2:
+ case VCD_CODEC_VC1:
+ case VCD_CODEC_VC1_RCV:
+ case VCD_CODEC_XVID:
+ default:
+ status = false;
+ break;
+ }
+ }
+ }
+ return status;
+}
+
+u32 vid_enc_set_get_framesize(struct video_client_ctx *client_ctx,
+ u32 *height, u32 *width, u32 set_flag)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_frame_size frame_size;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !height || !width)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_FRAME_SIZE;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_frame_size);
+
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &frame_size);
+
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_FRAME_SIZE Failed\n",
+ __func__);
+ return false;
+ }
+ if (set_flag) {
+ if (frame_size.height != *height ||
+ frame_size.width != *width) {
+ DBG("%s(): ENC Set Size (%d x %d)\n",
+ __func__, *height, *width);
+ frame_size.height = *height;
+ frame_size.width = *width;
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &frame_size);
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_FRAME_SIZE Failed\n",
+ __func__);
+ return false;
+ }
+ }
+ } else {
+ *height = frame_size.height;
+ *width = frame_size.width;
+ }
+ return true;
+}
+
+u32 vid_enc_set_get_bitrate(struct video_client_ctx *client_ctx,
+ struct venc_targetbitrate *venc_bitrate, u32 set_flag)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_target_bitrate bit_rate;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !venc_bitrate)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_TARGET_BITRATE;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_target_bitrate);
+ if (set_flag) {
+ bit_rate.target_bitrate = venc_bitrate->target_bitrate;
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &bit_rate);
+
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_TARGET_BITRATE Failed\n",
+ __func__);
+ return false;
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &bit_rate);
+
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_TARGET_BITRATE Failed\n",
+ __func__);
+ return false;
+ }
+ venc_bitrate->target_bitrate = bit_rate.target_bitrate;
+ }
+ return true;
+}
+
+u32 vid_enc_set_get_framerate(struct video_client_ctx *client_ctx,
+ struct venc_framerate *frame_rate, u32 set_flag)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_frame_rate vcd_frame_rate;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !frame_rate)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_FRAME_RATE;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_frame_rate);
+
+ if (set_flag) {
+ vcd_frame_rate.fps_denominator = frame_rate->fps_denominator;
+ vcd_frame_rate.fps_numerator = frame_rate->fps_numerator;
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_frame_rate);
+
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_FRAME_RATE Failed\n",
+ __func__);
+ return false;
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_frame_rate);
+
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_FRAME_RATE Failed\n",
+ __func__);
+ return false;
+ }
+ frame_rate->fps_denominator = vcd_frame_rate.fps_denominator;
+ frame_rate->fps_numerator = vcd_frame_rate.fps_numerator;
+ }
+ return true;
+}
+
+u32 vid_enc_set_get_live_mode(struct video_client_ctx *client_ctx,
+ struct venc_switch *encoder_switch, u32 set_flag)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_live live_mode;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_LIVE;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_live);
+
+ if (set_flag) {
+ live_mode.live = 1;
+ if (!encoder_switch->status)
+ live_mode.live = 0;
+
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &live_mode);
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_LIVE Failed\n",
+ __func__);
+ return false;
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &live_mode);
+
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_LIVE Failed\n",
+ __func__);
+ return false;
+ } else {
+ encoder_switch->status = 1;
+ if (!live_mode.live)
+ encoder_switch->status = 0;
+ }
+ }
+ return true;
+}
+
+u32 vid_enc_set_get_short_header(struct video_client_ctx *client_ctx,
+ struct venc_switch *encoder_switch, u32 set_flag)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_short_header short_header;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !encoder_switch)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_SHORT_HEADER;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_short_header);
+
+ if (set_flag) {
+ short_header.short_header = (u32) encoder_switch->status;
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &short_header);
+
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_SHORT_HEADER Failed\n",
+ __func__);
+ return false;
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &short_header);
+
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_SHORT_HEADER Failed\n",
+ __func__);
+ return false;
+ } else {
+ encoder_switch->status =
+ (u8) short_header.short_header;
+ }
+ }
+ return true;
+}
+
+u32 vid_enc_set_get_profile(struct video_client_ctx *client_ctx,
+ struct venc_profile *profile, u32 set_flag)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_profile profile_type;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 status = true;
+
+ if (!client_ctx || !profile)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_PROFILE;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_profile);
+
+ if (set_flag) {
+ switch (profile->profile) {
+ case VEN_PROFILE_MPEG4_SP:
+ profile_type.profile = VCD_PROFILE_MPEG4_SP;
+ break;
+ case VEN_PROFILE_MPEG4_ASP:
+ profile_type.profile = VCD_PROFILE_MPEG4_ASP;
+ break;
+ case VEN_PROFILE_H264_BASELINE:
+ profile_type.profile = VCD_PROFILE_H264_BASELINE;
+ break;
+ case VEN_PROFILE_H264_MAIN:
+ profile_type.profile = VCD_PROFILE_H264_MAIN;
+ break;
+ case VEN_PROFILE_H264_HIGH:
+ profile_type.profile = VCD_PROFILE_H264_HIGH;
+ break;
+ case VEN_PROFILE_H263_BASELINE:
+ profile_type.profile = VCD_PROFILE_H263_BASELINE;
+ break;
+ default:
+ status = false;
+ break;
+ }
+
+ if (status) {
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &profile_type);
+
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_PROFILE Failed\n",
+ __func__);
+ return false;
+ }
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &profile_type);
+
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_PROFILE Failed\n",
+ __func__);
+ return false;
+ } else {
+ switch (profile_type.profile) {
+ case VCD_PROFILE_H263_BASELINE:
+ profile->profile = VEN_PROFILE_H263_BASELINE;
+ break;
+ case VCD_PROFILE_H264_BASELINE:
+ profile->profile = VEN_PROFILE_H264_BASELINE;
+ break;
+ case VCD_PROFILE_H264_HIGH:
+ profile->profile = VEN_PROFILE_H264_HIGH;
+ break;
+ case VCD_PROFILE_H264_MAIN:
+ profile->profile = VEN_PROFILE_H264_MAIN;
+ break;
+ case VCD_PROFILE_MPEG4_ASP:
+ profile->profile = VEN_PROFILE_MPEG4_ASP;
+ break;
+ case VCD_PROFILE_MPEG4_SP:
+ profile->profile = VEN_PROFILE_MPEG4_SP;
+ break;
+ default:
+ status = false;
+ break;
+ }
+ }
+ }
+ return status;
+}
+
+u32 vid_enc_set_get_profile_level(struct video_client_ctx *client_ctx,
+ struct ven_profilelevel *profile_level, u32 set_flag)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_level level;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 status = true;
+
+ if (!client_ctx || !profile_level)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_LEVEL;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_level);
+
+ if (set_flag) {
+ switch (profile_level->level) {
+ case VEN_LEVEL_MPEG4_0:
+ level.level = VCD_LEVEL_MPEG4_0;
+ break;
+ case VEN_LEVEL_MPEG4_1:
+ level.level = VCD_LEVEL_MPEG4_1;
+ break;
+ case VEN_LEVEL_MPEG4_2:
+ level.level = VCD_LEVEL_MPEG4_2;
+ break;
+ case VEN_LEVEL_MPEG4_3:
+ level.level = VCD_LEVEL_MPEG4_3;
+ break;
+ case VEN_LEVEL_MPEG4_4:
+ level.level = VCD_LEVEL_MPEG4_4;
+ break;
+ case VEN_LEVEL_MPEG4_5:
+ level.level = VCD_LEVEL_MPEG4_5;
+ break;
+ case VEN_LEVEL_MPEG4_3b:
+ level.level = VCD_LEVEL_MPEG4_3b;
+ break;
+ case VEN_LEVEL_MPEG4_6:
+ level.level = VCD_LEVEL_MPEG4_6;
+ break;
+ case VEN_LEVEL_H264_1:
+ level.level = VCD_LEVEL_H264_1;
+ break;
+ case VEN_LEVEL_H264_1b:
+ level.level = VCD_LEVEL_H264_1b;
+ break;
+ case VEN_LEVEL_H264_1p1:
+ level.level = VCD_LEVEL_H264_1p1;
+ break;
+ case VEN_LEVEL_H264_1p2:
+ level.level = VCD_LEVEL_H264_1p2;
+ break;
+ case VEN_LEVEL_H264_1p3:
+ level.level = VCD_LEVEL_H264_1p3;
+ break;
+ case VEN_LEVEL_H264_2:
+ level.level = VCD_LEVEL_H264_2;
+ break;
+ case VEN_LEVEL_H264_2p1:
+ level.level = VCD_LEVEL_H264_2p1;
+ break;
+ case VEN_LEVEL_H264_2p2:
+ level.level = VCD_LEVEL_H264_2p2;
+ break;
+ case VEN_LEVEL_H264_3:
+ level.level = VCD_LEVEL_H264_3;
+ break;
+ case VEN_LEVEL_H264_3p1:
+ level.level = VCD_LEVEL_H264_3p1;
+ break;
+ case VEN_LEVEL_H264_4:
+ level.level = VCD_LEVEL_H264_4;
+ break;
+ case VEN_LEVEL_H263_10:
+ level.level = VCD_LEVEL_H263_10;
+ break;
+ case VEN_LEVEL_H263_20:
+ level.level = VCD_LEVEL_H263_20;
+ break;
+ case VEN_LEVEL_H263_30:
+ level.level = VCD_LEVEL_H263_30;
+ break;
+ case VEN_LEVEL_H263_40:
+ level.level = VCD_LEVEL_H263_40;
+ break;
+ case VEN_LEVEL_H263_45:
+ level.level = VCD_LEVEL_H263_45;
+ break;
+ case VEN_LEVEL_H263_50:
+ level.level = VCD_LEVEL_H263_50;
+ break;
+ case VEN_LEVEL_H263_60:
+ level.level = VCD_LEVEL_H263_60;
+ break;
+ case VEN_LEVEL_H263_70:
+ level.level = VCD_LEVEL_H263_70;
+ break;
+ default:
+ status = false;
+ break;
+ }
+ if (status) {
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &level);
+
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_LEVEL Failed\n",
+ __func__);
+ return false;
+ }
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &level);
+
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_LEVEL Failed\n",
+ __func__);
+ return false;
+ } else {
+ switch (level.level) {
+ case VCD_LEVEL_MPEG4_0:
+ profile_level->level = VEN_LEVEL_MPEG4_0;
+ break;
+ case VCD_LEVEL_MPEG4_1:
+ profile_level->level = VEN_LEVEL_MPEG4_1;
+ break;
+ case VCD_LEVEL_MPEG4_2:
+ profile_level->level = VEN_LEVEL_MPEG4_2;
+ break;
+ case VCD_LEVEL_MPEG4_3:
+ profile_level->level = VEN_LEVEL_MPEG4_3;
+ break;
+ case VCD_LEVEL_MPEG4_4:
+ profile_level->level = VEN_LEVEL_MPEG4_4;
+ break;
+ case VCD_LEVEL_MPEG4_5:
+ profile_level->level = VEN_LEVEL_MPEG4_5;
+ break;
+ case VCD_LEVEL_MPEG4_3b:
+ profile_level->level = VEN_LEVEL_MPEG4_3b;
+ break;
+ case VCD_LEVEL_H264_1:
+ profile_level->level = VEN_LEVEL_H264_1;
+ break;
+ case VCD_LEVEL_H264_1b:
+ profile_level->level = VEN_LEVEL_H264_1b;
+ break;
+ case VCD_LEVEL_H264_1p1:
+ profile_level->level = VEN_LEVEL_H264_1p1;
+ break;
+ case VCD_LEVEL_H264_1p2:
+ profile_level->level = VEN_LEVEL_H264_1p2;
+ break;
+ case VCD_LEVEL_H264_1p3:
+ profile_level->level = VEN_LEVEL_H264_1p3;
+ break;
+ case VCD_LEVEL_H264_2:
+ profile_level->level = VEN_LEVEL_H264_2;
+ break;
+ case VCD_LEVEL_H264_2p1:
+ profile_level->level = VEN_LEVEL_H264_2p1;
+ break;
+ case VCD_LEVEL_H264_2p2:
+ profile_level->level = VEN_LEVEL_H264_2p2;
+ break;
+ case VCD_LEVEL_H264_3:
+ profile_level->level = VEN_LEVEL_H264_3;
+ break;
+ case VCD_LEVEL_H264_3p1:
+ profile_level->level = VEN_LEVEL_H264_3p1;
+ break;
+ case VCD_LEVEL_H264_3p2:
+ status = false;
+ break;
+ case VCD_LEVEL_H264_4:
+ profile_level->level = VEN_LEVEL_H264_4;
+ break;
+ case VCD_LEVEL_H263_10:
+ profile_level->level = VEN_LEVEL_H263_10;
+ break;
+ case VCD_LEVEL_H263_20:
+ profile_level->level = VEN_LEVEL_H263_20;
+ break;
+ case VCD_LEVEL_H263_30:
+ profile_level->level = VEN_LEVEL_H263_30;
+ break;
+ case VCD_LEVEL_H263_40:
+ profile_level->level = VEN_LEVEL_H263_40;
+ break;
+ case VCD_LEVEL_H263_45:
+ profile_level->level = VEN_LEVEL_H263_45;
+ break;
+ case VCD_LEVEL_H263_50:
+ profile_level->level = VEN_LEVEL_H263_50;
+ break;
+ case VCD_LEVEL_H263_60:
+ profile_level->level = VEN_LEVEL_H263_60;
+ break;
+ case VCD_LEVEL_H263_70:
+ status = false;
+ break;
+ default:
+ status = false;
+ break;
+ }
+ }
+ }
+ return status;
+}
+
+u32 vid_enc_set_get_session_qp(struct video_client_ctx *client_ctx,
+ struct venc_sessionqp *session_qp, u32 set_flag)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_session_qp qp;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !session_qp)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_SESSION_QP;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_session_qp);
+
+ if (set_flag) {
+ qp.i_frame_qp = session_qp->iframeqp;
+ qp.p_frame_qp = session_qp->pframqp;
+
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &qp);
+
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_SESSION_QP Failed\n",
+ __func__);
+ return false;
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &qp);
+
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_SESSION_QP Failed\n",
+ __func__);
+ return false;
+ } else {
+ session_qp->iframeqp = qp.i_frame_qp;
+ session_qp->pframqp = qp.p_frame_qp;
+ }
+ }
+ return true;
+}
+
+u32 vid_enc_set_get_intraperiod(struct video_client_ctx *client_ctx,
+ struct venc_intraperiod *intraperiod, u32 set_flag)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_i_period period;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !intraperiod)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_INTRA_PERIOD;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_i_period);
+
+ if (set_flag) {
+ period.p_frames = intraperiod->num_pframes;
+ period.b_frames = intraperiod->num_bframes;
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &period);
+
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_INTRA_PERIOD Failed\n",
+ __func__);
+ return false;
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &period);
+
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_INTRA_PERIOD Failed\n",
+ __func__);
+ return false;
+ } else
+ intraperiod->num_pframes = period.p_frames;
+ }
+ return true;
+}
+
+u32 vid_enc_request_iframe(struct video_client_ctx *client_ctx)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_req_i_frame request;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 status = true;
+
+ if (!client_ctx)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_REQ_IFRAME;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_req_i_frame);
+ request.req_i_frame = 1;
+
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &request);
+
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_REQ_IFRAME Failed\n",
+ __func__);
+ return false;
+ }
+ return status;
+}
+
+u32 vid_enc_get_sequence_header(struct video_client_ctx *client_ctx,
+ struct venc_seqheader *seq_header)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_sequence_hdr hdr;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 status = true;
+
+ if (!client_ctx ||
+ !seq_header || !seq_header->bufsize)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_SEQ_HEADER;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_sequence_hdr);
+
+ hdr.sequence_header =
+ kzalloc(seq_header->bufsize, GFP_KERNEL);
+ seq_header->hdrbufptr = hdr.sequence_header;
+
+ if (!hdr.sequence_header)
+ return false;
+ hdr.sequence_header_len = seq_header->bufsize;
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &hdr);
+
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_SEQ_HEADER Failed\n",
+ __func__);
+ status = false;
+ }
+ return true;
+}
+
+u32 vid_enc_set_get_entropy_cfg(struct video_client_ctx *client_ctx,
+ struct venc_entropycfg *entropy_cfg, u32 set_flag)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_entropy_control control;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 status = true;
+
+ if (!client_ctx || !entropy_cfg)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_ENTROPY_CTRL;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_entropy_control);
+ if (set_flag) {
+ switch (entropy_cfg->longentropysel) {
+ case VEN_ENTROPY_MODEL_CAVLC:
+ control.entropy_sel = VCD_ENTROPY_SEL_CAVLC;
+ break;
+ case VEN_ENTROPY_MODEL_CABAC:
+ control.entropy_sel = VCD_ENTROPY_SEL_CABAC;
+ break;
+ default:
+ status = false;
+ break;
+ }
+
+ if (status && entropy_cfg->cabacmodel ==
+ VCD_ENTROPY_SEL_CABAC) {
+ switch (entropy_cfg->cabacmodel) {
+ case VEN_CABAC_MODEL_0:
+ control.cabac_model =
+ VCD_CABAC_MODEL_NUMBER_0;
+ break;
+ case VEN_CABAC_MODEL_1:
+ control.cabac_model =
+ VCD_CABAC_MODEL_NUMBER_1;
+ break;
+ case VEN_CABAC_MODEL_2:
+ control.cabac_model =
+ VCD_CABAC_MODEL_NUMBER_2;
+ break;
+ default:
+ status = false;
+ break;
+ }
+ }
+ if (status) {
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &control);
+
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_ENTROPY_CTRL Failed\n",
+ __func__);
+ status = false;
+ }
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &control);
+
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_ENTROPY_CTRL Failed\n",
+ __func__);
+ status = false;
+ } else {
+ switch (control.entropy_sel) {
+ case VCD_ENTROPY_SEL_CABAC:
+ entropy_cfg->cabacmodel =
+ VEN_ENTROPY_MODEL_CABAC;
+ break;
+ case VCD_ENTROPY_SEL_CAVLC:
+ entropy_cfg->cabacmodel =
+ VEN_ENTROPY_MODEL_CAVLC;
+ break;
+ default:
+ status = false;
+ break;
+ }
+
+ if (status && control.entropy_sel ==
+ VCD_ENTROPY_SEL_CABAC) {
+ switch (control.cabac_model) {
+ case VCD_CABAC_MODEL_NUMBER_0:
+ entropy_cfg->cabacmodel =
+ VEN_CABAC_MODEL_0;
+ break;
+ case VCD_CABAC_MODEL_NUMBER_1:
+ entropy_cfg->cabacmodel =
+ VEN_CABAC_MODEL_1;
+ break;
+ case VCD_CABAC_MODEL_NUMBER_2:
+ entropy_cfg->cabacmodel =
+ VEN_CABAC_MODEL_2;
+ break;
+ default:
+ status = false;
+ break;
+ }
+ }
+ }
+ }
+ return status;
+}
+
+u32 vid_enc_set_get_dbcfg(struct video_client_ctx *client_ctx,
+ struct venc_dbcfg *dbcfg, u32 set_flag)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_db_config control;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 status = true;
+
+ if (!client_ctx || !dbcfg)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_DEBLOCKING;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_db_config);
+
+ if (set_flag) {
+ switch (dbcfg->db_mode) {
+ case VEN_DB_DISABLE:
+ control.db_config = VCD_DB_DISABLE;
+ break;
+ case VEN_DB_ALL_BLKG_BNDRY:
+ control.db_config = VCD_DB_ALL_BLOCKING_BOUNDARY;
+ break;
+ case VEN_DB_SKIP_SLICE_BNDRY:
+ control.db_config = VCD_DB_SKIP_SLICE_BOUNDARY;
+ break;
+ default:
+ status = false;
+ break;
+ }
+
+ if (status) {
+ control.slice_alpha_offset =
+ dbcfg->slicealpha_offset;
+ control.slice_beta_offset =
+ dbcfg->slicebeta_offset;
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &control);
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_DEBLOCKING Failed\n",
+ __func__);
+ status = false;
+ }
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &control);
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_DEBLOCKING Failed\n",
+ __func__);
+ status = false;
+ } else {
+ switch (control.db_config) {
+ case VCD_DB_ALL_BLOCKING_BOUNDARY:
+ dbcfg->db_mode = VEN_DB_ALL_BLKG_BNDRY;
+ break;
+ case VCD_DB_DISABLE:
+ dbcfg->db_mode = VEN_DB_DISABLE;
+ break;
+ case VCD_DB_SKIP_SLICE_BOUNDARY:
+ dbcfg->db_mode = VEN_DB_SKIP_SLICE_BNDRY;
+ break;
+ default:
+ status = false;
+ break;
+ }
+ dbcfg->slicealpha_offset =
+ control.slice_alpha_offset;
+ dbcfg->slicebeta_offset =
+ control.slice_beta_offset;
+ }
+ }
+ return status;
+}
+
+u32 vid_enc_set_get_intrarefresh(struct video_client_ctx *client_ctx,
+ struct venc_intrarefresh *intrarefresh, u32 set_flag)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_intra_refresh_mb_number control;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !intrarefresh)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_INTRA_REFRESH;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_intra_refresh_mb_number);
+
+ if (set_flag) {
+ control.cir_mb_number = intrarefresh->mbcount;
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &control);
+
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_INTRA_REFRESH Failed\n",
+ __func__);
+ return false;
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &control);
+
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_INTRA_REFRESH Failed\n",
+ __func__);
+ return false;
+ } else
+ intrarefresh->mbcount = control.cir_mb_number;
+ }
+ return true;
+}
+
+u32 vid_enc_set_get_multiclicecfg(struct video_client_ctx *client_ctx,
+ struct venc_multiclicecfg *multiclicecfg, u32 set_flag)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_multi_slice control;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 status = true;
+
+ if (!client_ctx || !multiclicecfg)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_MULTI_SLICE;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_multi_slice);
+
+ if (set_flag) {
+ switch (multiclicecfg->mslice_mode) {
+ case VEN_MSLICE_OFF:
+ control.m_slice_sel =
+ VCD_MSLICE_OFF;
+ break;
+ case VEN_MSLICE_CNT_MB:
+ control.m_slice_sel =
+ VCD_MSLICE_BY_MB_COUNT;
+ break;
+ case VEN_MSLICE_CNT_BYTE:
+ control.m_slice_sel =
+ VCD_MSLICE_BY_BYTE_COUNT;
+ break;
+ case VEN_MSLICE_GOB:
+ control.m_slice_sel =
+ VCD_MSLICE_BY_GOB;
+ break;
+ default:
+ status = false;
+ break;
+ }
+
+ if (status) {
+ control.m_slice_size =
+ multiclicecfg->mslice_size;
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &control);
+
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_MULTI_SLICE Failed\n",
+ __func__);
+ status = false;
+ }
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &control);
+
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_MULTI_SLICE Failed\n",
+ __func__);
+ status = false;
+ } else {
+ multiclicecfg->mslice_size =
+ control.m_slice_size;
+ switch (control.m_slice_sel) {
+ case VCD_MSLICE_OFF:
+ multiclicecfg->mslice_mode = VEN_MSLICE_OFF;
+ break;
+ case VCD_MSLICE_BY_MB_COUNT:
+ multiclicecfg->mslice_mode = VEN_MSLICE_CNT_MB;
+ break;
+ case VCD_MSLICE_BY_BYTE_COUNT:
+ multiclicecfg->mslice_mode =
+ VEN_MSLICE_CNT_BYTE;
+ break;
+ case VCD_MSLICE_BY_GOB:
+ multiclicecfg->mslice_mode =
+ VEN_MSLICE_GOB;
+ break;
+ default:
+ status = false;
+ break;
+ }
+ }
+ }
+ return status;
+}
+
+u32 vid_enc_set_get_ratectrlcfg(struct video_client_ctx *client_ctx,
+ struct venc_ratectrlcfg *ratectrlcfg, u32 set_flag)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_rate_control control;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 status = true;
+
+ if (!client_ctx || !ratectrlcfg)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_RATE_CONTROL;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_rate_control);
+
+ if (set_flag) {
+ switch (ratectrlcfg->rcmode) {
+ case VEN_RC_OFF:
+ control.rate_control = VCD_RATE_CONTROL_OFF;
+ break;
+ case VEN_RC_CBR_VFR:
+ control.rate_control = VCD_RATE_CONTROL_CBR_VFR;
+ break;
+ case VEN_RC_VBR_CFR:
+ control.rate_control = VCD_RATE_CONTROL_VBR_CFR;
+ break;
+ case VEN_RC_VBR_VFR:
+ control.rate_control = VCD_RATE_CONTROL_VBR_VFR;
+ break;
+ case VEN_RC_CBR_CFR:
+ control.rate_control = VCD_RATE_CONTROL_CBR_CFR;
+ break;
+ default:
+ status = false;
+ break;
+ }
+
+ if (status) {
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &control);
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_RATE_CONTROL Failed\n",
+ __func__);
+ status = false;
+ }
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &control);
+
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_RATE_CONTROL Failed\n",
+ __func__);
+ status = false;
+ } else {
+ switch (control.rate_control) {
+ case VCD_RATE_CONTROL_OFF:
+ ratectrlcfg->rcmode = VEN_RC_OFF;
+ break;
+ case VCD_RATE_CONTROL_CBR_VFR:
+ ratectrlcfg->rcmode = VEN_RC_CBR_VFR;
+ break;
+ case VCD_RATE_CONTROL_VBR_CFR:
+ ratectrlcfg->rcmode = VEN_RC_VBR_CFR;
+ break;
+ case VCD_RATE_CONTROL_VBR_VFR:
+ ratectrlcfg->rcmode = VEN_RC_VBR_VFR;
+ break;
+ case VCD_RATE_CONTROL_CBR_CFR:
+ ratectrlcfg->rcmode = VEN_RC_CBR_CFR;
+ break;
+ default:
+ status = false;
+ break;
+ }
+ }
+ }
+ return status;
+}
+
+u32 vid_enc_set_get_voptimingcfg(struct video_client_ctx *client_ctx,
+ struct venc_voptimingcfg *voptimingcfg, u32 set_flag)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_vop_timing control;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 status = true;
+
+ if (!client_ctx || !voptimingcfg)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_VOP_TIMING;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_vop_timing);
+
+ if (set_flag) {
+ control.vop_time_resolution =
+ voptimingcfg->voptime_resolution;
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &control);
+
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_VOP_TIMING Failed\n",
+ __func__);
+ status = false;
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &control);
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_VOP_TIMING Failed\n",
+ __func__);
+ status = false;
+ } else
+ voptimingcfg->voptime_resolution =
+ control.vop_time_resolution;
+ }
+ return status;
+}
+
+u32 vid_enc_set_get_headerextension(struct video_client_ctx *client_ctx,
+ struct venc_headerextension *headerextension, u32 set_flag)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ u32 control;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 status = true;
+
+ if (!client_ctx || !headerextension)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_HEADER_EXTENSION;
+ vcd_property_hdr.sz = sizeof(u32);
+
+ if (set_flag) {
+ control = headerextension->header_extension;
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &control);
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_HEADER_EXTENSION Failed\n",
+ __func__);
+ status = false;
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &control);
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_HEADER_EXTENSION Failed\n",
+ __func__);
+ status = false;
+ } else {
+ headerextension->header_extension = control;
+ }
+ }
+ return status;
+}
+
+u32 vid_enc_set_get_qprange(struct video_client_ctx *client_ctx,
+ struct venc_qprange *qprange, u32 set_flag)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_qp_range control;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 status = true;
+
+ if (!client_ctx || !qprange)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_QP_RANGE;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_qp_range);
+
+ if (set_flag) {
+ control.max_qp = qprange->maxqp;
+ control.min_qp = qprange->minqp;
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &control);
+
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_QP_RANGE Failed\n",
+ __func__);
+ status = false;
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &control);
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_QP_RANGE Failed\n",
+ __func__);
+ status = false;
+ } else {
+ qprange->maxqp = control.max_qp;
+ qprange->minqp = control.min_qp;
+ }
+ }
+ return status;
+}
+
+u32 vid_enc_start_stop(struct video_client_ctx *client_ctx, u32 start)
+{
+ u32 vcd_status;
+
+ if (!client_ctx)
+ return false;
+
+ if (start) {
+ vcd_status = vcd_encode_start(client_ctx->vcd_handle);
+
+ if (vcd_status) {
+ ERR("%s(): vcd_encode_start failed."
+ " vcd_status = %u\n", __func__, vcd_status);
+ return false;
+ }
+ } else {
+ vcd_status = vcd_stop(client_ctx->vcd_handle);
+ if (vcd_status) {
+ ERR("%s(): vcd_stop failed. vcd_status = %u\n",
+ __func__, vcd_status);
+ return false;
+ }
+ DBG("Send STOP_DONE message to client = %p\n",
+ client_ctx);
+ }
+ return true;
+}
+
+u32 vid_enc_pause_resume(struct video_client_ctx *client_ctx, u32 pause)
+{
+ u32 vcd_status;
+
+ if (!client_ctx)
+ return false;
+
+ if (pause) {
+ DBG("PAUSE command from client = %p\n",
+ client_ctx);
+ vcd_status = vcd_pause(client_ctx->vcd_handle);
+ } else {
+ DBG("Resume command from client = %p\n",
+ client_ctx);
+ vcd_status = vcd_resume(client_ctx->vcd_handle);
+ }
+
+ if (vcd_status)
+ return false;
+
+ return true;
+}
+
+u32 vid_enc_flush(struct video_client_ctx *client_ctx,
+ struct venc_bufferflush *bufferflush)
+{
+ u32 status = true, mode, vcd_status;
+
+ if (!client_ctx || !bufferflush)
+ return false;
+
+ switch (bufferflush->flush_mode) {
+ case VEN_FLUSH_INPUT:
+ mode = VCD_FLUSH_INPUT;
+ break;
+ case VEN_FLUSH_OUTPUT:
+ mode = VCD_FLUSH_OUTPUT;
+ break;
+ case VEN_FLUSH_ALL:
+ mode = VCD_FLUSH_ALL;
+ break;
+ default:
+ status = false;
+ break;
+ }
+ if (status) {
+ vcd_status = vcd_flush(client_ctx->vcd_handle, mode);
+ if (vcd_status)
+ status = false;
+ }
+ return status;
+}
+
+u32 vid_enc_get_buffer_req(struct video_client_ctx *client_ctx,
+ struct venc_allocatorproperty *venc_buf_req, u32 input_dir)
+{
+ enum vcd_buffer_type buffer;
+ struct vcd_buffer_requirement buffer_req;
+ u32 status = true;
+ u32 vcd_status;
+
+ if (!client_ctx || !venc_buf_req)
+ return false;
+
+ buffer = VCD_BUFFER_OUTPUT;
+ if (input_dir)
+ buffer = VCD_BUFFER_INPUT;
+
+ vcd_status = vcd_get_buffer_requirements(client_ctx->vcd_handle,
+ buffer, &buffer_req);
+
+ if (vcd_status)
+ status = false;
+
+ if (status) {
+ venc_buf_req->actualcount = buffer_req.actual_count;
+ venc_buf_req->alignment = buffer_req.align;
+ venc_buf_req->datasize = buffer_req.sz;
+ venc_buf_req->mincount = buffer_req.min_count;
+ venc_buf_req->maxcount = buffer_req.max_count;
+ venc_buf_req->alignment = buffer_req.align;
+ venc_buf_req->bufpoolid = buffer_req.buf_pool_id;
+ venc_buf_req->suffixsize = 0;
+ }
+ return status;
+}
+
+u32 vid_enc_set_buffer_req(struct video_client_ctx *client_ctx,
+ struct venc_allocatorproperty *venc_buf_req, u32 input_dir)
+{
+ enum vcd_buffer_type buffer;
+ struct vcd_buffer_requirement buffer_req;
+ u32 status = true;
+ u32 vcd_status;
+
+ if (!client_ctx || !venc_buf_req)
+ return false;
+
+ buffer = VCD_BUFFER_OUTPUT;
+ if (input_dir)
+ buffer = VCD_BUFFER_INPUT;
+
+ buffer_req.actual_count = venc_buf_req->actualcount;
+ buffer_req.align = venc_buf_req->alignment;
+ buffer_req.sz = venc_buf_req->datasize;
+ buffer_req.min_count = venc_buf_req->mincount;
+ buffer_req.max_count = venc_buf_req->maxcount;
+ buffer_req.align = venc_buf_req->alignment;
+ buffer_req.buf_pool_id = 0;
+
+ vcd_status = vcd_set_buffer_requirements(client_ctx->vcd_handle,
+ buffer, &buffer_req);
+
+ if (vcd_status)
+ status = false;
+ return status;
+}
+
+u32 vid_enc_set_buffer(struct video_client_ctx *client_ctx,
+ struct venc_bufferpayload *buffer_info,
+ enum venc_buffer_dir buffer)
+{
+ enum vcd_buffer_type vcd_buffer_t = VCD_BUFFER_INPUT;
+ enum buffer_dir dir_buffer = BUFFER_TYPE_INPUT;
+ u32 vcd_status = VCD_ERR_FAIL;
+ unsigned long kernel_vaddr;
+
+ if (!client_ctx || !buffer_info)
+ return false;
+
+ if (buffer == VEN_BUFFER_TYPE_OUTPUT) {
+ dir_buffer = BUFFER_TYPE_OUTPUT;
+ vcd_buffer_t = VCD_BUFFER_OUTPUT;
+ }
+
+ /*If buffer cannot be set, ignore */
+ if (!vidc_insert_addr_table(client_ctx, dir_buffer,
+ (unsigned long)buffer_info->pbuffer,
+ &kernel_vaddr,
+ buffer_info->fd,
+ (unsigned long)buffer_info->offset,
+ VID_ENC_MAX_NUM_OF_BUFF)) {
+ DBG("%s() : user_virt_addr = %p cannot be set.",
+ __func__, buffer_info->pbuffer);
+ return false;
+ }
+
+ vcd_status = vcd_set_buffer(client_ctx->vcd_handle,
+ vcd_buffer_t, (u8 *) kernel_vaddr,
+ buffer_info->sz);
+
+ if (!vcd_status)
+ return true;
+ else
+ return false;
+}
+
+u32 vid_enc_free_buffer(struct video_client_ctx *client_ctx,
+ struct venc_bufferpayload *buffer_info,
+ enum venc_buffer_dir buffer)
+{
+ enum vcd_buffer_type buffer_vcd = VCD_BUFFER_INPUT;
+ enum buffer_dir dir_buffer = BUFFER_TYPE_INPUT;
+ u32 vcd_status = VCD_ERR_FAIL;
+ unsigned long kernel_vaddr;
+
+ if (!client_ctx || !buffer_info)
+ return false;
+
+ if (buffer == VEN_BUFFER_TYPE_OUTPUT) {
+ dir_buffer = BUFFER_TYPE_OUTPUT;
+ buffer_vcd = VCD_BUFFER_OUTPUT;
+ }
+ /*If buffer NOT set, ignore */
+ if (!vidc_delete_addr_table(client_ctx, dir_buffer,
+ (unsigned long)buffer_info->pbuffer,
+ &kernel_vaddr)) {
+ DBG("%s() : user_virt_addr = %p has not been set.",
+ __func__, buffer_info->pbuffer);
+ return true;
+ }
+
+ vcd_status = vcd_free_buffer(client_ctx->vcd_handle, buffer_vcd,
+ (u8 *)kernel_vaddr);
+
+ if (!vcd_status)
+ return true;
+ else
+ return false;
+}
+
+u32 vid_enc_encode_frame(struct video_client_ctx *client_ctx,
+ struct venc_buffer *input_frame_info)
+{
+ struct vcd_frame_data vcd_input_buffer;
+ unsigned long kernel_vaddr, phy_addr, user_vaddr;
+ int pmem_fd;
+ struct file *file;
+ s32 buffer_index = -1;
+
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !input_frame_info)
+ return false;
+
+ user_vaddr = (unsigned long)input_frame_info->ptrbuffer;
+
+ if (vidc_lookup_addr_table(client_ctx, BUFFER_TYPE_INPUT,
+ true, &user_vaddr, &kernel_vaddr,
+ &phy_addr, &pmem_fd, &file,
+ &buffer_index)) {
+
+ /* kernel_vaddr is found. send the frame to VCD */
+ memset((void *)&vcd_input_buffer, 0,
+ sizeof(struct vcd_frame_data));
+
+ vcd_input_buffer.virtual =
+ (u8 *) (kernel_vaddr + input_frame_info->offset);
+
+ vcd_input_buffer.offset = input_frame_info->offset;
+ vcd_input_buffer.frm_clnt_data =
+ (u32) input_frame_info->clientdata;
+ vcd_input_buffer.ip_frm_tag =
+ (u32) input_frame_info->clientdata;
+ vcd_input_buffer.data_len = input_frame_info->len;
+ vcd_input_buffer.time_stamp = input_frame_info->timestamp;
+
+ /* Rely on VCD using the same flags as OMX */
+ vcd_input_buffer.flags = input_frame_info->flags;
+
+ vcd_status = vcd_encode_frame(client_ctx->vcd_handle,
+ &vcd_input_buffer);
+ if (!vcd_status)
+ return true;
+ else {
+ ERR("%s(): vcd_encode_frame failed = %u\n",
+ __func__, vcd_status);
+ return false;
+ }
+
+ } else {
+ ERR("%s(): kernel_vaddr not found\n",
+ __func__);
+ return false;
+ }
+}
+
+u32 vid_enc_fill_output_buffer(struct video_client_ctx *client_ctx,
+ struct venc_buffer *output_frame_info)
+{
+ unsigned long kernel_vaddr, phy_addr, user_vaddr;
+ int pmem_fd;
+ struct file *file;
+ s32 buffer_index = -1;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ struct vcd_frame_data vcd_frame;
+
+ if (!client_ctx || !output_frame_info)
+ return false;
+
+ user_vaddr = (unsigned long)output_frame_info->ptrbuffer;
+
+ if (vidc_lookup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT,
+ true, &user_vaddr, &kernel_vaddr,
+ &phy_addr, &pmem_fd, &file,
+ &buffer_index)) {
+
+ memset((void *)&vcd_frame, 0,
+ sizeof(struct vcd_frame_data));
+ vcd_frame.virtual = (u8 *) kernel_vaddr;
+ vcd_frame.frm_clnt_data = (u32) output_frame_info->clientdata;
+ vcd_frame.alloc_len = output_frame_info->sz;
+
+ vcd_status = vcd_fill_output_buffer(client_ctx->vcd_handle,
+ &vcd_frame);
+ if (!vcd_status)
+ return true;
+ else {
+ ERR("%s(): vcd_fill_output_buffer failed = %u\n",
+ __func__, vcd_status);
+ return false;
+ }
+ } else {
+ ERR("%s(): kernel_vaddr not found\n", __func__);
+ return false;
+ }
+}
+u32 vid_enc_set_recon_buffers(struct video_client_ctx *client_ctx,
+ struct venc_recon_addr *venc_recon)
+{
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 len;
+ struct file *file;
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_enc_recon_buffer control;
+
+ control.buffer_size = venc_recon->buffer_size;
+ control.kernel_virtual_addr = NULL;
+ control.physical_addr = NULL;
+ control.pmem_fd = venc_recon->pmem_fd;
+ control.offset = venc_recon->offset;
+
+ if (get_pmem_file(control.pmem_fd, (unsigned long *)
+ (&(control.physical_addr)), (unsigned long *)
+ (&control.kernel_virtual_addr),
+ (unsigned long *) (&len), &file)) {
+ ERR("%s(): get_pmem_file failed\n", __func__);
+ return false;
+ }
+ put_pmem_file(file);
+ DBG("Virt: %p, Phys %p, fd: %d", control.kernel_virtual_addr,
+ control.physical_addr, control.pmem_fd);
+
+ vcd_property_hdr.prop_id = VCD_I_RECON_BUFFERS;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_enc_recon_buffer);
+
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &control);
+ if (!vcd_status) {
+ DBG("vcd_set_property returned success\n");
+ return true;
+ } else {
+ ERR("%s(): vid_enc_set_recon_buffers failed = %u\n",
+ __func__, vcd_status);
+ return false;
+ }
+}
+
+u32 vid_enc_free_recon_buffers(struct video_client_ctx *client_ctx)
+{
+ u32 vcd_status = VCD_ERR_FAIL;
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_enc_recon_buffer control;
+
+ vcd_property_hdr.prop_id = VCD_I_FREE_RECON_BUFFERS;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_buffer_size);
+
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &control);
+ return true;
+}
+
+u32 vid_enc_get_recon_buffer_size(struct video_client_ctx *client_ctx,
+ struct venc_recon_buff_size *venc_recon_size)
+{
+ u32 vcd_status = VCD_ERR_FAIL;
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_buffer_size control;
+
+ control.width = venc_recon_size->width;
+ control.height = venc_recon_size->height;
+
+ vcd_property_hdr.prop_id = VCD_I_GET_RECON_BUFFER_SIZE;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_buffer_size);
+
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &control);
+
+ venc_recon_size->width = control.width;
+ venc_recon_size->height = control.height;
+ venc_recon_size->size = control.size;
+ venc_recon_size->alignment = control.alignment;
+ DBG("W: %d, H: %d, S: %d, A: %d", venc_recon_size->width,
+ venc_recon_size->height, venc_recon_size->size,
+ venc_recon_size->alignment);
+
+ if (!vcd_status) {
+ DBG("vcd_set_property returned success\n");
+ return true;
+ } else {
+ ERR("%s(): vid_enc_get_recon_buffer_size failed = %u\n",
+ __func__, vcd_status);
+ return false;
+ }
+}
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.h b/drivers/video/msm/vidc/common/enc/venc_internal.h
new file mode 100644
index 0000000..7d4ebca
--- /dev/null
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.h
@@ -0,0 +1,151 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef VENC_INTERNAL_H
+#define VENC_INTERNAL_H
+
+#include <linux/msm_vidc_enc.h>
+#include <linux/cdev.h>
+
+#include "vidc_init.h"
+
+#define VID_ENC_MAX_NUM_OF_BUFF 100
+
+enum venc_buffer_dir{
+ VEN_BUFFER_TYPE_INPUT,
+ VEN_BUFFER_TYPE_OUTPUT
+};
+
+struct vid_enc_msg {
+ struct list_head list;
+ struct venc_msg venc_msg_info;
+};
+
+struct vid_enc_dev {
+
+ struct cdev cdev;
+ struct device *device;
+ resource_size_t phys_base;
+ void __iomem *virt_base;
+ unsigned int irq;
+ struct clk *hclk;
+ struct clk *hclk_div2;
+ struct clk *pclk;
+ unsigned long hclk_rate;
+ struct mutex lock;
+ s32 device_handle;
+ struct video_client_ctx venc_clients[VIDC_MAX_NUM_CLIENTS];
+ u32 num_clients;
+};
+
+u32 vid_enc_set_get_base_cfg(struct video_client_ctx *client_ctx,
+ struct venc_basecfg *base_config, u32 set_flag);
+
+u32 vid_enc_set_get_inputformat(struct video_client_ctx *client_ctx,
+ u32 *input_format, u32 set_flag);
+
+u32 vid_enc_set_get_codec(struct video_client_ctx *client_ctx, u32 *codec,
+ u32 set_flag);
+
+u32 vid_enc_set_get_framesize(struct video_client_ctx *client_ctx,
+ u32 *height, u32 *width, u32 set_flag);
+
+u32 vid_enc_set_get_bitrate(struct video_client_ctx *client_ctx,
+ struct venc_targetbitrate *venc_bitrate, u32 set_flag);
+
+u32 vid_enc_set_get_framerate(struct video_client_ctx *client_ctx,
+ struct venc_framerate *frame_rate, u32 set_flag);
+
+u32 vid_enc_set_get_live_mode(struct video_client_ctx *client_ctx,
+ struct venc_switch *encoder_switch, u32 set_flag);
+
+u32 vid_enc_set_get_short_header(struct video_client_ctx *client_ctx,
+ struct venc_switch *encoder_switch, u32 set_flag);
+
+u32 vid_enc_set_get_profile(struct video_client_ctx *client_ctx,
+ struct venc_profile *profile, u32 set_flag);
+
+u32 vid_enc_set_get_profile_level(struct video_client_ctx *client_ctx,
+ struct ven_profilelevel *profile_level, u32 set_flag);
+
+u32 vid_enc_set_get_session_qp(struct video_client_ctx *client_ctx,
+ struct venc_sessionqp *session_qp, u32 set_flag);
+
+u32 vid_enc_set_get_intraperiod(struct video_client_ctx *client_ctx,
+ struct venc_intraperiod *intraperiod, u32 set_flag);
+
+u32 vid_enc_request_iframe(struct video_client_ctx *client_ctx);
+
+u32 vid_enc_get_sequence_header(struct video_client_ctx *client_ctx,
+ struct venc_seqheader *seq_header);
+
+u32 vid_enc_set_get_entropy_cfg(struct video_client_ctx *client_ctx,
+ struct venc_entropycfg *entropy_cfg, u32 set_flag);
+
+u32 vid_enc_set_get_dbcfg(struct video_client_ctx *client_ctx,
+ struct venc_dbcfg *dbcfg, u32 set_flag);
+
+u32 vid_enc_set_get_intrarefresh(struct video_client_ctx *client_ctx,
+ struct venc_intrarefresh *intrarefresh, u32 set_flag);
+
+u32 vid_enc_set_get_multiclicecfg(struct video_client_ctx *client_ctx,
+ struct venc_multiclicecfg *multiclicecfg, u32 set_flag);
+
+u32 vid_enc_set_get_ratectrlcfg(struct video_client_ctx *client_ctx,
+ struct venc_ratectrlcfg *ratectrlcfg, u32 set_flag);
+
+u32 vid_enc_set_get_voptimingcfg(struct video_client_ctx *client_ctx,
+ struct venc_voptimingcfg *voptimingcfg, u32 set_flag);
+
+u32 vid_enc_set_get_headerextension(struct video_client_ctx *client_ctx,
+ struct venc_headerextension *headerextension, u32 set_flag);
+
+u32 vid_enc_set_get_qprange(struct video_client_ctx *client_ctx,
+ struct venc_qprange *qprange, u32 set_flag);
+
+u32 vid_enc_start_stop(struct video_client_ctx *client_ctx, u32 start);
+
+u32 vid_enc_pause_resume(struct video_client_ctx *client_ctx, u32 pause);
+
+u32 vid_enc_flush(struct video_client_ctx *client_ctx,
+ struct venc_bufferflush *bufferflush);
+
+u32 vid_enc_get_buffer_req(struct video_client_ctx *client_ctx,
+ struct venc_allocatorproperty *venc_buf_req, u32 input_dir);
+
+u32 vid_enc_set_buffer_req(struct video_client_ctx *client_ctx,
+ struct venc_allocatorproperty *venc_buf_req, u32 input_dir);
+
+u32 vid_enc_set_buffer(struct video_client_ctx *client_ctx,
+ struct venc_bufferpayload *buffer_info,
+ enum venc_buffer_dir buffer);
+
+u32 vid_enc_free_buffer(struct video_client_ctx *client_ctx,
+ struct venc_bufferpayload *buffer_info,
+ enum venc_buffer_dir buffer);
+
+u32 vid_enc_encode_frame(struct video_client_ctx *client_ctx,
+ struct venc_buffer *input_frame_info);
+
+u32 vid_enc_fill_output_buffer(struct video_client_ctx *client_ctx,
+ struct venc_buffer *output_frame_info);
+
+u32 vid_enc_set_recon_buffers(struct video_client_ctx *client_ctx,
+ struct venc_recon_addr *venc_recon);
+
+u32 vid_enc_free_recon_buffers(struct video_client_ctx *client_ctx);
+
+u32 vid_enc_get_recon_buffer_size(struct video_client_ctx *client_ctx,
+ struct venc_recon_buff_size *venc_recon_size);
+
+#endif
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.c b/drivers/video/msm/vidc/common/init/vidc_init.c
new file mode 100644
index 0000000..cda3a91
--- /dev/null
+++ b/drivers/video/msm/vidc/common/init/vidc_init.c
@@ -0,0 +1,620 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+#include <linux/android_pmem.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/debugfs.h>
+#include <mach/clk.h>
+#include <linux/pm_runtime.h>
+
+#include "vcd_api.h"
+#include "vidc_init_internal.h"
+#include "vidc_init.h"
+#include "vcd_res_tracker_api.h"
+
+#if DEBUG
+#define DBG(x...) printk(KERN_DEBUG x)
+#else
+#define DBG(x...)
+#endif
+
+#define VIDC_NAME "msm_vidc_reg"
+
+#define ERR(x...) printk(KERN_ERR x)
+
+static struct vidc_dev *vidc_device_p;
+static dev_t vidc_dev_num;
+static struct class *vidc_class;
+
+static const struct file_operations vidc_fops = {
+ .owner = THIS_MODULE,
+ .open = NULL,
+ .release = NULL,
+ .unlocked_ioctl = NULL,
+};
+
+struct workqueue_struct *vidc_wq;
+struct workqueue_struct *vidc_timer_wq;
+static irqreturn_t vidc_isr(int irq, void *dev);
+static spinlock_t vidc_spin_lock;
+
+u32 vidc_msg_timing, vidc_msg_pmem;
+
+#ifdef VIDC_ENABLE_DBGFS
+struct dentry *vidc_debugfs_root;
+
+struct dentry *vidc_get_debugfs_root(void)
+{
+ if (vidc_debugfs_root == NULL)
+ vidc_debugfs_root = debugfs_create_dir("vidc", NULL);
+ return vidc_debugfs_root;
+}
+
+void vidc_debugfs_file_create(struct dentry *root, const char *name,
+ u32 *var)
+{
+ struct dentry *vidc_debugfs_file =
+ debugfs_create_u32(name, S_IRUGO | S_IWUSR, root, var);
+ if (!vidc_debugfs_file)
+ ERR("%s(): Error creating/opening file %s\n", __func__, name);
+}
+#endif
+
+static void vidc_timer_fn(unsigned long data)
+{
+ unsigned long flag;
+ struct vidc_timer *hw_timer = NULL;
+ ERR("%s() Timer expired\n", __func__);
+ spin_lock_irqsave(&vidc_spin_lock, flag);
+ hw_timer = (struct vidc_timer *)data;
+ list_add_tail(&hw_timer->list, &vidc_device_p->vidc_timer_queue);
+ spin_unlock_irqrestore(&vidc_spin_lock, flag);
+ DBG("Queue the work for timer\n");
+ queue_work(vidc_timer_wq, &vidc_device_p->vidc_timer_worker);
+}
+
+static void vidc_timer_handler(struct work_struct *work)
+{
+ unsigned long flag = 0;
+ u32 islist_empty = 0;
+ struct vidc_timer *hw_timer = NULL;
+
+ ERR("%s() Timer expired\n", __func__);
+ do {
+ spin_lock_irqsave(&vidc_spin_lock, flag);
+ islist_empty = list_empty(&vidc_device_p->vidc_timer_queue);
+ if (!islist_empty) {
+ hw_timer = list_first_entry(
+ &vidc_device_p->vidc_timer_queue,
+ struct vidc_timer, list);
+ list_del(&hw_timer->list);
+ }
+ spin_unlock_irqrestore(&vidc_spin_lock, flag);
+ if (!islist_empty && hw_timer && hw_timer->cb_func)
+ hw_timer->cb_func(hw_timer->userdata);
+ } while (!islist_empty);
+}
+
+static void vidc_work_handler(struct work_struct *work)
+{
+ DBG("vidc_work_handler()");
+ vcd_read_and_clear_interrupt();
+ vcd_response_handler();
+ enable_irq(vidc_device_p->irq);
+ DBG("vidc_work_handler() done");
+}
+
+static DECLARE_WORK(vidc_work, vidc_work_handler);
+
+static int __devinit vidc_720p_probe(struct platform_device *pdev)
+{
+ struct resource *resource;
+ DBG("Enter %s()\n", __func__);
+
+ if (pdev->id) {
+ ERR("Invalid plaform device ID = %d\n", pdev->id);
+ return -EINVAL;
+ }
+ vidc_device_p->irq = platform_get_irq(pdev, 0);
+ if (unlikely(vidc_device_p->irq < 0)) {
+ ERR("%s(): Invalid irq = %d\n", __func__,
+ vidc_device_p->irq);
+ return -ENXIO;
+ }
+
+ resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (unlikely(!resource)) {
+ ERR("%s(): Invalid resource\n", __func__);
+ return -ENXIO;
+ }
+
+ vidc_device_p->phys_base = resource->start;
+ vidc_device_p->virt_base = ioremap(resource->start,
+ resource->end - resource->start + 1);
+
+ if (!vidc_device_p->virt_base) {
+ ERR("%s() : ioremap failed\n", __func__);
+ return -ENOMEM;
+ }
+ vidc_device_p->device = &pdev->dev;
+ mutex_init(&vidc_device_p->lock);
+
+ vidc_wq = create_singlethread_workqueue("vidc_worker_queue");
+ if (!vidc_wq) {
+ ERR("%s: create workque failed\n", __func__);
+ return -ENOMEM;
+ }
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ return 0;
+}
+
+static int __devexit vidc_720p_remove(struct platform_device *pdev)
+{
+ if (pdev->id) {
+ ERR("Invalid plaform device ID = %d\n", pdev->id);
+ return -EINVAL;
+ }
+ pm_runtime_disable(&pdev->dev);
+
+ return 0;
+}
+
+static int vidc_runtime_suspend(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: suspending...\n");
+ return 0;
+}
+
+static int vidc_runtime_resume(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: resuming...\n");
+ return 0;
+}
+
+static const struct dev_pm_ops vidc_dev_pm_ops = {
+ .runtime_suspend = vidc_runtime_suspend,
+ .runtime_resume = vidc_runtime_resume,
+};
+
+static struct platform_driver msm_vidc_720p_platform_driver = {
+ .probe = vidc_720p_probe,
+ .remove = vidc_720p_remove,
+ .driver = {
+ .name = "msm_vidc",
+ .pm = &vidc_dev_pm_ops,
+ },
+};
+
+static void __exit vidc_exit(void)
+{
+ platform_driver_unregister(&msm_vidc_720p_platform_driver);
+}
+
+static irqreturn_t vidc_isr(int irq, void *dev)
+{
+ DBG("\n vidc_isr() %d ", irq);
+ disable_irq_nosync(irq);
+ queue_work(vidc_wq, &vidc_work);
+ return IRQ_HANDLED;
+}
+
+static int __init vidc_init(void)
+{
+ int rc = 0;
+ struct device *class_devp;
+#ifdef VIDC_ENABLE_DBGFS
+ struct dentry *root = NULL;
+#endif
+
+ vidc_device_p = kzalloc(sizeof(struct vidc_dev), GFP_KERNEL);
+ if (!vidc_device_p) {
+ ERR("%s Unable to allocate memory for vidc_dev\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ rc = alloc_chrdev_region(&vidc_dev_num, 0, 1, VIDC_NAME);
+ if (rc < 0) {
+ ERR("%s: alloc_chrdev_region Failed rc = %d\n",
+ __func__, rc);
+ goto error_vidc_alloc_chrdev_region;
+ }
+
+ vidc_class = class_create(THIS_MODULE, VIDC_NAME);
+ if (IS_ERR(vidc_class)) {
+ rc = PTR_ERR(vidc_class);
+ ERR("%s: couldn't create vidc_class rc = %d\n",
+ __func__, rc);
+
+ goto error_vidc_class_create;
+ }
+
+ class_devp = device_create(vidc_class, NULL, vidc_dev_num, NULL,
+ VIDC_NAME);
+
+ if (IS_ERR(class_devp)) {
+ rc = PTR_ERR(class_devp);
+ ERR("%s: class device_create failed %d\n",
+ __func__, rc);
+ goto error_vidc_class_device_create;
+ }
+
+ cdev_init(&vidc_device_p->cdev, &vidc_fops);
+ vidc_device_p->cdev.owner = THIS_MODULE;
+ rc = cdev_add(&(vidc_device_p->cdev), vidc_dev_num, 1);
+
+ if (rc < 0) {
+ ERR("%s: cdev_add failed %d\n", __func__, rc);
+ goto error_vidc_cdev_add;
+ }
+
+ rc = platform_driver_register(&msm_vidc_720p_platform_driver);
+ if (rc) {
+ ERR("%s failed to load\n", __func__);
+ goto error_vidc_platfom_register;
+ }
+
+ rc = request_irq(vidc_device_p->irq, vidc_isr, IRQF_TRIGGER_HIGH,
+ "vidc", vidc_device_p->device);
+
+ if (unlikely(rc)) {
+ ERR("%s() :request_irq failed\n", __func__);
+ goto error_vidc_platfom_register;
+ }
+ res_trk_init(vidc_device_p->device, vidc_device_p->irq);
+ vidc_timer_wq = create_singlethread_workqueue("vidc_timer_wq");
+ if (!vidc_timer_wq) {
+ ERR("%s: create workque failed\n", __func__);
+ rc = -ENOMEM;
+ goto error_vidc_platfom_register;
+ }
+ DBG("Disabling IRQ in %s()\n", __func__);
+ disable_irq_nosync(vidc_device_p->irq);
+ INIT_WORK(&vidc_device_p->vidc_timer_worker,
+ vidc_timer_handler);
+ spin_lock_init(&vidc_spin_lock);
+ INIT_LIST_HEAD(&vidc_device_p->vidc_timer_queue);
+
+ vidc_device_p->ref_count = 0;
+ vidc_device_p->firmware_refcount = 0;
+ vidc_device_p->get_firmware = 0;
+#ifdef VIDC_ENABLE_DBGFS
+ root = vidc_get_debugfs_root();
+ if (root) {
+ vidc_debugfs_file_create(root, "vidc_msg_timing",
+ (u32 *) &vidc_msg_timing);
+ vidc_debugfs_file_create(root, "vidc_msg_pmem",
+ (u32 *) &vidc_msg_pmem);
+ }
+#endif
+ return 0;
+
+error_vidc_platfom_register:
+ cdev_del(&(vidc_device_p->cdev));
+error_vidc_cdev_add:
+ device_destroy(vidc_class, vidc_dev_num);
+error_vidc_class_device_create:
+ class_destroy(vidc_class);
+error_vidc_class_create:
+ unregister_chrdev_region(vidc_dev_num, 1);
+error_vidc_alloc_chrdev_region:
+ kfree(vidc_device_p);
+
+ return rc;
+}
+
+void __iomem *vidc_get_ioaddr(void)
+{
+ return (u8 *)vidc_device_p->virt_base;
+}
+EXPORT_SYMBOL(vidc_get_ioaddr);
+
+int vidc_load_firmware(void)
+{
+ u32 status = true;
+
+ mutex_lock(&vidc_device_p->lock);
+ if (!vidc_device_p->get_firmware) {
+ status = res_trk_download_firmware();
+ if (!status)
+ goto error;
+ vidc_device_p->get_firmware = 1;
+ }
+ vidc_device_p->firmware_refcount++;
+error:
+ mutex_unlock(&vidc_device_p->lock);
+ return status;
+}
+EXPORT_SYMBOL(vidc_load_firmware);
+
+void vidc_release_firmware(void)
+{
+ mutex_lock(&vidc_device_p->lock);
+ if (vidc_device_p->firmware_refcount > 0)
+ vidc_device_p->firmware_refcount--;
+ else
+ vidc_device_p->firmware_refcount = 0;
+ mutex_unlock(&vidc_device_p->lock);
+}
+EXPORT_SYMBOL(vidc_release_firmware);
+
+u32 vidc_lookup_addr_table(struct video_client_ctx *client_ctx,
+ enum buffer_dir buffer,
+ u32 search_with_user_vaddr,
+ unsigned long *user_vaddr,
+ unsigned long *kernel_vaddr,
+ unsigned long *phy_addr, int *pmem_fd,
+ struct file **file, s32 *buffer_index)
+{
+ u32 num_of_buffers;
+ u32 i;
+ struct buf_addr_table *buf_addr_table;
+ u32 found = false;
+
+ if (!client_ctx)
+ return false;
+
+ if (buffer == BUFFER_TYPE_INPUT) {
+ buf_addr_table = client_ctx->input_buf_addr_table;
+ num_of_buffers = client_ctx->num_of_input_buffers;
+ DBG("%s(): buffer = INPUT\n", __func__);
+
+ } else {
+ buf_addr_table = client_ctx->output_buf_addr_table;
+ num_of_buffers = client_ctx->num_of_output_buffers;
+ DBG("%s(): buffer = OUTPUT\n", __func__);
+ }
+
+ for (i = 0; i < num_of_buffers; ++i) {
+ if (search_with_user_vaddr) {
+ if (*user_vaddr == buf_addr_table[i].user_vaddr) {
+ *kernel_vaddr = buf_addr_table[i].kernel_vaddr;
+ found = true;
+ DBG("%s() : client_ctx = %p."
+ " user_virt_addr = 0x%08lx is found",
+ __func__, client_ctx, *user_vaddr);
+ break;
+ }
+ } else {
+ if (*kernel_vaddr == buf_addr_table[i].kernel_vaddr) {
+ *user_vaddr = buf_addr_table[i].user_vaddr;
+ found = true;
+ DBG("%s() : client_ctx = %p."
+ " kernel_virt_addr = 0x%08lx is found",
+ __func__, client_ctx, *kernel_vaddr);
+ break;
+ }
+ }
+ }
+
+ if (found) {
+ *phy_addr = buf_addr_table[i].phy_addr;
+ *pmem_fd = buf_addr_table[i].pmem_fd;
+ *file = buf_addr_table[i].file;
+ *buffer_index = i;
+
+ if (search_with_user_vaddr)
+ DBG("kernel_vaddr = 0x%08lx, phy_addr = 0x%08lx "
+ " pmem_fd = %d, struct *file = %p "
+ "buffer_index = %d\n", *kernel_vaddr,
+ *phy_addr, *pmem_fd, *file, *buffer_index);
+ else
+ DBG("user_vaddr = 0x%08lx, phy_addr = 0x%08lx "
+ " pmem_fd = %d, struct *file = %p "
+ "buffer_index = %d\n", *user_vaddr, *phy_addr,
+ *pmem_fd, *file, *buffer_index);
+ return true;
+ } else {
+ if (search_with_user_vaddr)
+ DBG("%s() : client_ctx = %p user_virt_addr = 0x%08lx"
+ " Not Found.\n", __func__, client_ctx, *user_vaddr);
+ else
+ DBG("%s() : client_ctx = %p kernel_virt_addr = 0x%08lx"
+ " Not Found.\n", __func__, client_ctx,
+ *kernel_vaddr);
+ return false;
+ }
+}
+EXPORT_SYMBOL(vidc_lookup_addr_table);
+
+u32 vidc_insert_addr_table(struct video_client_ctx *client_ctx,
+ enum buffer_dir buffer, unsigned long user_vaddr,
+ unsigned long *kernel_vaddr, int pmem_fd,
+ unsigned long buffer_addr_offset, unsigned int max_num_buffers)
+{
+ unsigned long len, phys_addr;
+ struct file *file;
+ u32 *num_of_buffers = NULL;
+ u32 i;
+ struct buf_addr_table *buf_addr_table;
+
+ if (!client_ctx)
+ return false;
+
+ if (buffer == BUFFER_TYPE_INPUT) {
+ buf_addr_table = client_ctx->input_buf_addr_table;
+ num_of_buffers = &client_ctx->num_of_input_buffers;
+ DBG("%s(): buffer = INPUT #Buf = %d\n",
+ __func__, *num_of_buffers);
+
+ } else {
+ buf_addr_table = client_ctx->output_buf_addr_table;
+ num_of_buffers = &client_ctx->num_of_output_buffers;
+ DBG("%s(): buffer = OUTPUT #Buf = %d\n",
+ __func__, *num_of_buffers);
+ }
+
+ if (*num_of_buffers == max_num_buffers) {
+ ERR("%s(): Num of buffers reached max value : %d",
+ __func__, max_num_buffers);
+ return false;
+ }
+
+ i = 0;
+ while (i < *num_of_buffers &&
+ user_vaddr != buf_addr_table[i].user_vaddr)
+ i++;
+ if (i < *num_of_buffers) {
+ DBG("%s() : client_ctx = %p."
+ " user_virt_addr = 0x%08lx already set",
+ __func__, client_ctx, user_vaddr);
+ return false;
+ } else {
+ if (get_pmem_file(pmem_fd, &phys_addr,
+ kernel_vaddr, &len, &file)) {
+ ERR("%s(): get_pmem_file failed\n", __func__);
+ return false;
+ }
+ put_pmem_file(file);
+ phys_addr += buffer_addr_offset;
+ (*kernel_vaddr) += buffer_addr_offset;
+ buf_addr_table[*num_of_buffers].user_vaddr = user_vaddr;
+ buf_addr_table[*num_of_buffers].kernel_vaddr = *kernel_vaddr;
+ buf_addr_table[*num_of_buffers].pmem_fd = pmem_fd;
+ buf_addr_table[*num_of_buffers].file = file;
+ buf_addr_table[*num_of_buffers].phy_addr = phys_addr;
+ *num_of_buffers = *num_of_buffers + 1;
+ DBG("%s() : client_ctx = %p, user_virt_addr = 0x%08lx, "
+ "kernel_vaddr = 0x%08lx inserted!", __func__,
+ client_ctx, user_vaddr, *kernel_vaddr);
+ }
+ return true;
+}
+EXPORT_SYMBOL(vidc_insert_addr_table);
+
+u32 vidc_delete_addr_table(struct video_client_ctx *client_ctx,
+ enum buffer_dir buffer,
+ unsigned long user_vaddr,
+ unsigned long *kernel_vaddr)
+{
+ u32 *num_of_buffers = NULL;
+ u32 i;
+ struct buf_addr_table *buf_addr_table;
+
+ if (!client_ctx)
+ return false;
+
+ if (buffer == BUFFER_TYPE_INPUT) {
+ buf_addr_table = client_ctx->input_buf_addr_table;
+ num_of_buffers = &client_ctx->num_of_input_buffers;
+ DBG("%s(): buffer = INPUT\n", __func__);
+
+ } else {
+ buf_addr_table = client_ctx->output_buf_addr_table;
+ num_of_buffers = &client_ctx->num_of_output_buffers;
+ DBG("%s(): buffer = OUTPUT\n", __func__);
+ }
+
+ if (!*num_of_buffers)
+ return false;
+
+ i = 0;
+ while (i < *num_of_buffers &&
+ user_vaddr != buf_addr_table[i].user_vaddr)
+ i++;
+ if (i == *num_of_buffers) {
+ DBG("%s() : client_ctx = %p."
+ " user_virt_addr = 0x%08lx NOT found",
+ __func__, client_ctx, user_vaddr);
+ return false;
+ }
+ *kernel_vaddr = buf_addr_table[i].kernel_vaddr;
+ if (i < (*num_of_buffers - 1)) {
+ buf_addr_table[i].user_vaddr =
+ buf_addr_table[*num_of_buffers - 1].user_vaddr;
+ buf_addr_table[i].kernel_vaddr =
+ buf_addr_table[*num_of_buffers - 1].kernel_vaddr;
+ buf_addr_table[i].phy_addr =
+ buf_addr_table[*num_of_buffers - 1].phy_addr;
+ buf_addr_table[i].pmem_fd =
+ buf_addr_table[*num_of_buffers - 1].pmem_fd;
+ buf_addr_table[i].file =
+ buf_addr_table[*num_of_buffers - 1].file;
+ }
+ *num_of_buffers = *num_of_buffers - 1;
+ DBG("%s() : client_ctx = %p."
+ " user_virt_addr = 0x%08lx is found and deleted",
+ __func__, client_ctx, user_vaddr);
+ return true;
+}
+EXPORT_SYMBOL(vidc_delete_addr_table);
+
+u32 vidc_timer_create(void (*timer_handler)(void *),
+ void *user_data, void **timer_handle)
+{
+ struct vidc_timer *hw_timer = NULL;
+ if (!timer_handler || !timer_handle) {
+ DBG("%s(): timer creation failed\n ", __func__);
+ return false;
+ }
+ hw_timer = kzalloc(sizeof(struct vidc_timer), GFP_KERNEL);
+ if (!hw_timer) {
+ DBG("%s(): timer creation failed in allocation\n ", __func__);
+ return false;
+ }
+ init_timer(&hw_timer->hw_timeout);
+ hw_timer->hw_timeout.data = (unsigned long)hw_timer;
+ hw_timer->hw_timeout.function = vidc_timer_fn;
+ hw_timer->cb_func = timer_handler;
+ hw_timer->userdata = user_data;
+ *timer_handle = hw_timer;
+ return true;
+}
+EXPORT_SYMBOL(vidc_timer_create);
+
+void vidc_timer_release(void *timer_handle)
+{
+ kfree(timer_handle);
+}
+EXPORT_SYMBOL(vidc_timer_release);
+
+void vidc_timer_start(void *timer_handle, u32 time_out)
+{
+ struct vidc_timer *hw_timer = (struct vidc_timer *)timer_handle;
+ DBG("%s(): start timer\n ", __func__);
+ if (hw_timer) {
+ hw_timer->hw_timeout.expires = jiffies + 1*HZ;
+ add_timer(&hw_timer->hw_timeout);
+ }
+}
+EXPORT_SYMBOL(vidc_timer_start);
+
+void vidc_timer_stop(void *timer_handle)
+{
+ struct vidc_timer *hw_timer = (struct vidc_timer *)timer_handle;
+ DBG("%s(): stop timer\n ", __func__);
+ if (hw_timer)
+ del_timer(&hw_timer->hw_timeout);
+}
+EXPORT_SYMBOL(vidc_timer_stop);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Video decoder/encoder driver Init Module");
+MODULE_VERSION("1.0");
+module_init(vidc_init);
+module_exit(vidc_exit);
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.h b/drivers/video/msm/vidc/common/init/vidc_init.h
new file mode 100644
index 0000000..c472718
--- /dev/null
+++ b/drivers/video/msm/vidc/common/init/vidc_init.h
@@ -0,0 +1,76 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef VIDC_INIT_H
+#define VIDC_INIT_H
+
+#include "vidc_type.h"
+
+#define VIDC_MAX_NUM_CLIENTS 4
+#define MAX_VIDEO_NUM_OF_BUFF 100
+
+enum buffer_dir {
+ BUFFER_TYPE_INPUT,
+ BUFFER_TYPE_OUTPUT
+};
+
+struct buf_addr_table {
+ unsigned long user_vaddr;
+ unsigned long kernel_vaddr;
+ unsigned long phy_addr;
+ int pmem_fd;
+ struct file *file;
+};
+
+struct video_client_ctx {
+ void *vcd_handle;
+ u32 num_of_input_buffers;
+ u32 num_of_output_buffers;
+ struct buf_addr_table input_buf_addr_table[MAX_VIDEO_NUM_OF_BUFF];
+ struct buf_addr_table output_buf_addr_table[MAX_VIDEO_NUM_OF_BUFF];
+ struct list_head msg_queue;
+ struct mutex msg_queue_lock;
+ wait_queue_head_t msg_wait;
+ struct completion event;
+ u32 event_status;
+ u32 seq_header_set;
+ u32 stop_msg;
+ u32 stop_called;
+ u32 stop_sync_cb;
+};
+
+void __iomem *vidc_get_ioaddr(void);
+int vidc_load_firmware(void);
+void vidc_release_firmware(void);
+u32 vidc_lookup_addr_table(struct video_client_ctx *client_ctx,
+ enum buffer_dir buffer, u32 search_with_user_vaddr,
+ unsigned long *user_vaddr, unsigned long *kernel_vaddr,
+ unsigned long *phy_addr, int *pmem_fd, struct file **file,
+ s32 *buffer_index);
+u32 vidc_insert_addr_table(struct video_client_ctx *client_ctx,
+ enum buffer_dir buffer, unsigned long user_vaddr,
+ unsigned long *kernel_vaddr, int pmem_fd,
+ unsigned long buffer_addr_offset,
+ unsigned int max_num_buffers);
+u32 vidc_delete_addr_table(struct video_client_ctx *client_ctx,
+ enum buffer_dir buffer, unsigned long user_vaddr,
+ unsigned long *kernel_vaddr);
+
+u32 vidc_timer_create(void (*timer_handler)(void *),
+ void *user_data, void **timer_handle);
+void vidc_timer_release(void *timer_handle);
+void vidc_timer_start(void *timer_handle, u32 time_out);
+void vidc_timer_stop(void *timer_handle);
+
+
+#endif
diff --git a/drivers/video/msm/vidc/common/init/vidc_init_internal.h b/drivers/video/msm/vidc/common/init/vidc_init_internal.h
new file mode 100644
index 0000000..1d903ad
--- /dev/null
+++ b/drivers/video/msm/vidc/common/init/vidc_init_internal.h
@@ -0,0 +1,41 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef VIDC_INIT_INTERNAL_H
+#define VIDC_INIT_INTERNAL_H
+
+#include <linux/cdev.h>
+
+struct vidc_timer {
+ struct list_head list;
+ struct timer_list hw_timeout;
+ void (*cb_func)(void *);
+ void *userdata;
+};
+
+struct vidc_dev {
+ struct cdev cdev;
+ struct device *device;
+ resource_size_t phys_base;
+ void __iomem *virt_base;
+ unsigned int irq;
+ unsigned int ref_count;
+ unsigned int firmware_refcount;
+ unsigned int get_firmware;
+ struct mutex lock;
+ s32 device_handle;
+ struct list_head vidc_timer_queue;
+ struct work_struct vidc_timer_worker;
+};
+
+#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd.h b/drivers/video/msm/vidc/common/vcd/vcd.h
new file mode 100644
index 0000000..b557752
--- /dev/null
+++ b/drivers/video/msm/vidc/common/vcd/vcd.h
@@ -0,0 +1,393 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _VCD_H_
+#define _VCD_H_
+
+#include "vcd_api.h"
+#include "vcd_ddl_api.h"
+#include "vcd_res_tracker_api.h"
+#include "vcd_util.h"
+#include "vcd_client_sm.h"
+#include "vcd_core.h"
+#include "vcd_device_sm.h"
+
+void vcd_reset_device_channels(struct vcd_dev_ctxt *dev_ctxt);
+
+u32 vcd_get_command_channel
+ (struct vcd_dev_ctxt *dev_ctxt, struct vcd_transc **transc);
+
+u32 vcd_get_command_channel_in_loop
+ (struct vcd_dev_ctxt *dev_ctxt, struct vcd_transc **transc);
+
+void vcd_mark_command_channel
+ (struct vcd_dev_ctxt *dev_ctxt, struct vcd_transc *transc);
+
+void vcd_release_command_channel
+ (struct vcd_dev_ctxt *dev_ctxt, struct vcd_transc *transc);
+
+void vcd_release_multiple_command_channels(struct vcd_dev_ctxt *dev_ctxt,
+ u32 channels);
+
+void vcd_release_interim_command_channels(struct vcd_dev_ctxt *dev_ctxt);
+
+u32 vcd_get_frame_channel
+ (struct vcd_dev_ctxt *dev_ctxt, struct vcd_transc **transc);
+
+u32 vcd_get_frame_channel_in_loop
+ (struct vcd_dev_ctxt *dev_ctxt, struct vcd_transc **transc);
+
+void vcd_mark_frame_channel(struct vcd_dev_ctxt *dev_ctxt);
+
+void vcd_release_frame_channel
+ (struct vcd_dev_ctxt *dev_ctxt, struct vcd_transc *transc);
+
+void vcd_release_multiple_frame_channels(struct vcd_dev_ctxt *dev_ctxt,
+ u32 channels);
+
+void vcd_release_interim_frame_channels(struct vcd_dev_ctxt *dev_ctxt);
+u32 vcd_core_is_busy(struct vcd_dev_ctxt *dev_ctxt);
+
+void vcd_device_timer_start(struct vcd_dev_ctxt *dev_ctxt);
+void vcd_device_timer_stop(struct vcd_dev_ctxt *dev_ctxt);
+
+
+u32 vcd_init_device_context
+ (struct vcd_drv_ctxt *drv_ctxt, u32 ev_code);
+
+u32 vcd_deinit_device_context
+ (struct vcd_drv_ctxt *drv_ctxt, u32 ev_code);
+
+u32 vcd_init_client_context(struct vcd_clnt_ctxt *cctxt);
+
+void vcd_destroy_client_context(struct vcd_clnt_ctxt *cctxt);
+
+u32 vcd_check_for_client_context
+ (struct vcd_dev_ctxt *dev_ctxt, s32 driver_id);
+
+u32 vcd_validate_driver_handle
+ (struct vcd_dev_ctxt *dev_ctxt, s32 driver_handle);
+
+void vcd_handle_for_last_clnt_close
+ (struct vcd_dev_ctxt *dev_ctxt, u32 send_deinit);
+
+u32 vcd_common_allocate_set_buffer
+ (struct vcd_clnt_ctxt *cctxt,
+ enum vcd_buffer_type buffer,
+ u32 buf_size, struct vcd_buffer_pool **buf_pool);
+
+u32 vcd_set_buffer_internal
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_buffer_pool *buf_pool, u8 *buffer, u32 buf_size);
+
+u32 vcd_allocate_buffer_internal
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_buffer_pool *buf_pool,
+ u32 buf_size, u8 **vir_buf_addr, u8 **phy_buf_addr);
+
+u32 vcd_free_one_buffer_internal
+ (struct vcd_clnt_ctxt *cctxt,
+ enum vcd_buffer_type buffer_type, u8 *buffer);
+
+u32 vcd_free_buffers_internal
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_buffer_pool *buf_pool);
+
+u32 vcd_alloc_buffer_pool_entries
+ (struct vcd_buffer_pool *buf_pool,
+ struct vcd_buffer_requirement *buf_req);
+
+void vcd_free_buffer_pool_entries(struct vcd_buffer_pool *buf_pool);
+
+void vcd_flush_in_use_buffer_pool_entries(struct vcd_clnt_ctxt *cctxt,
+ struct vcd_buffer_pool *buf_pool, u32 event);
+
+void vcd_reset_buffer_pool_for_reuse(struct vcd_buffer_pool *buf_pool);
+
+struct vcd_buffer_entry *vcd_get_free_buffer_pool_entry
+ (struct vcd_buffer_pool *pool);
+
+struct vcd_buffer_entry *vcd_find_buffer_pool_entry
+ (struct vcd_buffer_pool *pool, u8 *v_addr);
+
+struct vcd_buffer_entry *vcd_buffer_pool_entry_de_q
+ (struct vcd_buffer_pool *pool);
+
+u32 vcd_buffer_pool_entry_en_q
+ (struct vcd_buffer_pool *pool,
+ struct vcd_buffer_entry *entry);
+
+u32 vcd_check_if_buffer_req_met(struct vcd_clnt_ctxt *cctxt,
+ enum vcd_buffer_type buffer_type);
+
+u32 vcd_client_cmd_en_q
+ (struct vcd_clnt_ctxt *cctxt, enum vcd_command command);
+
+void vcd_client_cmd_flush_and_en_q
+ (struct vcd_clnt_ctxt *cctxt, enum vcd_command command);
+
+u32 vcd_client_cmd_de_q
+ (struct vcd_clnt_ctxt *cctxt, enum vcd_command *command);
+
+u32 vcd_handle_recvd_eos
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *input_frame, u32 * pb_eos_handled);
+
+u32 vcd_handle_first_decode_frame(struct vcd_clnt_ctxt *cctxt);
+
+u32 vcd_handle_input_frame
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *input_frame);
+
+u32 vcd_store_seq_hdr
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_sequence_hdr *seq_hdr);
+
+u32 vcd_set_frame_size
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_property_frame_size *frm_size);
+
+u32 vcd_set_frame_rate
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_property_frame_rate *fps);
+
+u32 vcd_calculate_frame_delta
+ (struct vcd_clnt_ctxt *cctxt, struct vcd_frame_data *frame);
+
+struct vcd_buffer_entry *vcd_check_fill_output_buffer
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *buffer);
+
+u32 vcd_handle_first_fill_output_buffer
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *buffer, u32 *b_handled);
+
+u32 vcd_handle_first_fill_output_buffer_for_enc
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *frm_entry, u32 *b_handled);
+
+u32 vcd_handle_first_fill_output_buffer_for_dec
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *frm_entry, u32 *b_handled);
+
+u32 vcd_schedule_frame(struct vcd_dev_ctxt *dev_ctxt,
+ struct vcd_clnt_ctxt **cctxt, struct vcd_buffer_entry
+ **ip_buf_entry);
+
+u32 vcd_submit_command_in_continue
+ (struct vcd_dev_ctxt *dev_ctxt, struct vcd_transc *transc);
+
+u32 vcd_submit_cmd_sess_start(struct vcd_transc *transc);
+
+u32 vcd_submit_cmd_sess_end(struct vcd_transc *transc);
+
+void vcd_submit_cmd_client_close(struct vcd_clnt_ctxt *cctxt);
+
+u32 vcd_submit_frame
+ (struct vcd_dev_ctxt *dev_ctxt, struct vcd_transc *transc);
+
+u32 vcd_try_submit_frame_in_continue(struct vcd_dev_ctxt *dev_ctxt,
+ struct vcd_transc *transc);
+
+u32 vcd_process_cmd_sess_start(struct vcd_clnt_ctxt *cctxt);
+
+void vcd_try_submit_frame(struct vcd_dev_ctxt *dev_ctxt);
+
+u32 vcd_setup_with_ddl_capabilities(struct vcd_dev_ctxt *dev_ctxt);
+void vcd_handle_submit_frame_failed(struct vcd_dev_ctxt *dev_ctxt,
+ struct vcd_transc *transc);
+
+struct vcd_transc *vcd_get_free_trans_tbl_entry
+ (struct vcd_dev_ctxt *dev_ctxt);
+
+void vcd_release_trans_tbl_entry(struct vcd_transc *trans_entry);
+
+void vcd_release_all_clnt_frm_transc(struct vcd_clnt_ctxt *cctxt);
+void vcd_release_all_clnt_transc(struct vcd_clnt_ctxt *cctxt);
+
+u32 vcd_handle_input_done
+ (struct vcd_clnt_ctxt *cctxt,
+ void *payload, u32 event, u32 status);
+
+u32 vcd_handle_input_done_in_eos
+ (struct vcd_clnt_ctxt *cctxt, void *payload, u32 status);
+
+void vcd_handle_input_done_failed
+ (struct vcd_clnt_ctxt *cctxt, struct vcd_transc *transc);
+
+void vcd_handle_input_done_with_codec_config
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_transc *transc,
+ struct ddl_frame_data_tag *frm);
+
+void vcd_handle_input_done_for_interlacing
+ (struct vcd_clnt_ctxt *cctxt);
+
+void vcd_handle_input_done_with_trans_end
+ (struct vcd_clnt_ctxt *cctxt);
+
+u32 vcd_handle_frame_done
+ (struct vcd_clnt_ctxt *cctxt,
+ void *payload, u32 event, u32 status);
+
+void vcd_handle_frame_done_for_interlacing
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_transc *transc_ip1,
+ struct ddl_frame_data_tag *op_frm, u32 status);
+
+
+u32 vcd_handle_frame_done_in_eos
+ (struct vcd_clnt_ctxt *cctxt, void *payload, u32 status);
+
+u32 vcd_handle_output_required(struct vcd_clnt_ctxt *cctxt,
+ void *payload, u32 status);
+
+u32 vcd_handle_output_required_in_flushing(struct vcd_clnt_ctxt *cctxt,
+ void *payload);
+
+u32 vcd_handle_output_req_tran_end_in_eos(struct vcd_clnt_ctxt *cctxt);
+
+u32 vcd_validate_io_done_pyld
+ (struct vcd_clnt_ctxt *cctxt, void *payload, u32 status);
+
+void vcd_handle_eos_trans_end(struct vcd_clnt_ctxt *cctxt);
+
+
+void vcd_handle_eos_done
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_transc *transc, u32 status);
+
+void vcd_send_frame_done_in_eos
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *input_frame, u32 valid_opbuf);
+
+void vcd_send_frame_done_in_eos_for_dec
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *input_frame);
+
+void vcd_send_frame_done_in_eos_for_enc
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *input_frame);
+
+void vcd_handle_start_done(struct vcd_clnt_ctxt *cctxt,
+ struct vcd_transc *transc, u32 status);
+
+void vcd_handle_stop_done(struct vcd_clnt_ctxt *cctxt,
+ struct vcd_transc *transc, u32 status);
+
+void vcd_handle_stop_done_in_starting(struct vcd_clnt_ctxt *cctxt,
+ struct vcd_transc *transc, u32 status);
+
+void vcd_handle_stop_done_in_invalid(struct vcd_clnt_ctxt *cctxt,
+ struct vcd_transc *transc, u32 status);
+
+void vcd_send_flush_done(struct vcd_clnt_ctxt *cctxt, u32 status);
+
+void vcd_process_pending_flush_in_eos(struct vcd_clnt_ctxt *cctxt);
+
+void vcd_process_pending_stop_in_eos(struct vcd_clnt_ctxt *cctxt);
+
+void vcd_handle_trans_pending(struct vcd_clnt_ctxt *cctxt);
+
+u32 vcd_handle_ind_output_reconfig
+ (struct vcd_clnt_ctxt *cctxt, void* payload, u32 status);
+
+u32 vcd_handle_ind_output_reconfig_in_flushing
+ (struct vcd_clnt_ctxt *cctxt, void* payload, u32 status);
+
+void vcd_flush_output_buffers(struct vcd_clnt_ctxt *cctxt);
+
+void vcd_flush_bframe_buffers(struct vcd_clnt_ctxt *cctxt, u32 mode);
+
+u32 vcd_flush_buffers(struct vcd_clnt_ctxt *cctxt, u32 mode);
+void vcd_flush_buffers_in_err_fatal(struct vcd_clnt_ctxt *cctxt);
+
+u32 vcd_power_event
+ (struct vcd_dev_ctxt *dev_ctxt,
+ struct vcd_clnt_ctxt *cctxt, u32 event);
+
+u32 vcd_device_power_event(struct vcd_dev_ctxt *dev_ctxt, u32 event,
+ struct vcd_clnt_ctxt *cctxt);
+
+u32 vcd_client_power_event
+ (struct vcd_dev_ctxt *dev_ctxt,
+ struct vcd_clnt_ctxt *cctxt, u32 event);
+
+u32 vcd_enable_clock(struct vcd_dev_ctxt *dev_ctxt,
+ struct vcd_clnt_ctxt *cctxt);
+
+u32 vcd_disable_clock(struct vcd_dev_ctxt *dev_ctxt);
+
+u32 vcd_set_perf_level(struct vcd_dev_ctxt *dev_ctxt, u32 perf_lvl);
+
+u32 vcd_update_clnt_perf_lvl
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_property_frame_rate *fps, u32 frm_p_units);
+
+u32 vcd_gate_clock(struct vcd_dev_ctxt *dev_ctxt);
+
+u32 vcd_un_gate_clock(struct vcd_dev_ctxt *dev_ctxt);
+
+void vcd_handle_err_fatal(struct vcd_clnt_ctxt *cctxt,
+ u32 event, u32 status);
+
+void vcd_handle_device_err_fatal(struct vcd_dev_ctxt *dev_ctxt,
+ struct vcd_clnt_ctxt *cctxt);
+
+void vcd_clnt_handle_device_err_fatal(struct vcd_clnt_ctxt *cctxt,
+ u32 event);
+
+void vcd_handle_err_in_starting(struct vcd_clnt_ctxt *cctxt,
+ u32 status);
+
+void vcd_handle_ind_hw_err_fatal(struct vcd_clnt_ctxt *cctxt,
+ u32 event, u32 status);
+
+u32 vcd_return_op_buffer_to_hw(struct vcd_clnt_ctxt *cctxt,
+ struct vcd_buffer_entry *buf_entry);
+
+u32 vcd_sched_create(struct list_head *sched_list);
+
+void vcd_sched_destroy(struct list_head *sched_clnt_list);
+
+u32 vcd_sched_add_client(struct vcd_clnt_ctxt *cctxt);
+
+u32 vcd_sched_remove_client(struct vcd_sched_clnt_ctx *sched_cctxt);
+
+u32 vcd_sched_update_config(struct vcd_clnt_ctxt *cctxt);
+
+u32 vcd_sched_queue_buffer(
+ struct vcd_sched_clnt_ctx *sched_cctxt,
+ struct vcd_buffer_entry *buffer, u32 b_tail);
+
+u32 vcd_sched_dequeue_buffer(
+ struct vcd_sched_clnt_ctx *sched_cctxt,
+ struct vcd_buffer_entry **buffer);
+
+u32 vcd_sched_mark_client_eof(struct vcd_sched_clnt_ctx *sched_cctxt);
+
+u32 vcd_sched_suspend_resume_clnt(
+ struct vcd_clnt_ctxt *cctxt, u32 b_state);
+
+u32 vcd_sched_get_client_frame(struct list_head *sched_clnt_list,
+ struct vcd_clnt_ctxt **cctxt,
+ struct vcd_buffer_entry **buffer);
+
+void vcd_handle_clnt_fatal(struct vcd_clnt_ctxt *cctxt, u32 trans_end);
+
+void vcd_handle_clnt_fatal_input_done(struct vcd_clnt_ctxt *cctxt,
+ u32 trans_end);
+
+void vcd_handle_ind_info_output_reconfig
+ (struct vcd_clnt_ctxt *cctxt, u32 status);
+
+#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_api.c b/drivers/video/msm/vidc/common/vcd/vcd_api.c
new file mode 100644
index 0000000..a57675e
--- /dev/null
+++ b/drivers/video/msm/vidc/common/vcd/vcd_api.c
@@ -0,0 +1,881 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "vidc_type.h"
+#include "vcd.h"
+
+u32 vcd_init(struct vcd_init_config *config, s32 *driver_handle)
+{
+ u32 rc = VCD_S_SUCCESS;
+ struct vcd_drv_ctxt *drv_ctxt;
+
+ VCD_MSG_MED("vcd_init:");
+
+ if (!config ||
+ !driver_handle || !config->map_dev_base_addr) {
+ VCD_MSG_ERROR("Bad parameters");
+
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+
+ drv_ctxt = vcd_get_drv_context();
+ mutex_init(&drv_ctxt->dev_mutex);
+ mutex_lock(&drv_ctxt->dev_mutex);
+
+ if (drv_ctxt->dev_state.state_table->ev_hdlr.init) {
+ rc = drv_ctxt->dev_state.state_table->ev_hdlr.
+ init(drv_ctxt, config, driver_handle);
+ } else {
+ VCD_MSG_ERROR("Unsupported API in device state %d",
+ drv_ctxt->dev_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+
+ mutex_unlock(&drv_ctxt->dev_mutex);
+
+ return rc;
+
+}
+EXPORT_SYMBOL(vcd_init);
+
+u32 vcd_term(s32 driver_handle)
+{
+ u32 rc = VCD_S_SUCCESS;
+ struct vcd_drv_ctxt *drv_ctxt;
+
+ VCD_MSG_MED("vcd_term:");
+
+ drv_ctxt = vcd_get_drv_context();
+ mutex_lock(&drv_ctxt->dev_mutex);
+
+ if (drv_ctxt->dev_state.state_table->ev_hdlr.term) {
+ rc = drv_ctxt->dev_state.state_table->ev_hdlr.
+ term(drv_ctxt, driver_handle);
+ } else {
+ VCD_MSG_ERROR("Unsupported API in device state %d",
+ drv_ctxt->dev_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+ mutex_unlock(&drv_ctxt->dev_mutex);
+ return rc;
+
+}
+EXPORT_SYMBOL(vcd_term);
+
+u32 vcd_open(s32 driver_handle, u32 decoding,
+ void (*callback) (u32 event, u32 status, void *info, size_t sz,
+ void *handle, void *const client_data),
+ void *client_data)
+{
+ u32 rc = VCD_S_SUCCESS;
+ struct vcd_drv_ctxt *drv_ctxt;
+
+ VCD_MSG_MED("vcd_open:");
+
+ if (!callback) {
+ VCD_MSG_ERROR("Bad parameters");
+
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+
+ drv_ctxt = vcd_get_drv_context();
+ mutex_lock(&drv_ctxt->dev_mutex);
+
+ if (drv_ctxt->dev_state.state_table->ev_hdlr.open) {
+ rc = drv_ctxt->dev_state.state_table->ev_hdlr.
+ open(drv_ctxt, driver_handle, decoding, callback,
+ client_data);
+ } else {
+ VCD_MSG_ERROR("Unsupported API in device state %d",
+ drv_ctxt->dev_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+
+ mutex_unlock(&drv_ctxt->dev_mutex);
+
+ return rc;
+
+}
+EXPORT_SYMBOL(vcd_open);
+
+u32 vcd_close(void *handle)
+{
+ struct vcd_clnt_ctxt *cctxt =
+ (struct vcd_clnt_ctxt *)handle;
+ struct vcd_drv_ctxt *drv_ctxt;
+ u32 rc;
+
+ VCD_MSG_MED("vcd_close:");
+
+ if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
+ VCD_MSG_ERROR("Bad client handle");
+
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ drv_ctxt = vcd_get_drv_context();
+ mutex_lock(&drv_ctxt->dev_mutex);
+ if (drv_ctxt->dev_state.state_table->ev_hdlr.close) {
+ rc = drv_ctxt->dev_state.state_table->ev_hdlr.
+ close(drv_ctxt, cctxt);
+ } else {
+ VCD_MSG_ERROR("Unsupported API in device state %d",
+ drv_ctxt->dev_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+ mutex_unlock(&drv_ctxt->dev_mutex);
+ return rc;
+
+}
+EXPORT_SYMBOL(vcd_close);
+
+u32 vcd_encode_start(void *handle)
+{
+ struct vcd_clnt_ctxt *cctxt =
+ (struct vcd_clnt_ctxt *)handle;
+ struct vcd_drv_ctxt *drv_ctxt;
+ u32 rc;
+
+ VCD_MSG_MED("vcd_encode_start:");
+
+ if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
+ VCD_MSG_ERROR("Bad client handle");
+
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ drv_ctxt = vcd_get_drv_context();
+
+ mutex_lock(&drv_ctxt->dev_mutex);
+
+ if (cctxt->clnt_state.state_table->ev_hdlr.encode_start &&
+ drv_ctxt->dev_ctxt.pwr_state != VCD_PWR_STATE_SLEEP) {
+ rc = cctxt->clnt_state.state_table->ev_hdlr.
+ encode_start(cctxt);
+ } else {
+ VCD_MSG_ERROR
+ ("Unsupported API in dev power state %d OR client state %d",
+ drv_ctxt->dev_ctxt.pwr_state,
+ cctxt->clnt_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+
+ mutex_unlock(&drv_ctxt->dev_mutex);
+
+ return rc;
+
+}
+EXPORT_SYMBOL(vcd_encode_start);
+
+u32 vcd_encode_frame(void *handle, struct vcd_frame_data *input_frame)
+{
+ struct vcd_clnt_ctxt *cctxt =
+ (struct vcd_clnt_ctxt *)handle;
+ struct vcd_drv_ctxt *drv_ctxt;
+ u32 rc;
+
+ VCD_MSG_MED("vcd_encode_frame:");
+
+ if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
+ VCD_MSG_ERROR("Bad client handle");
+
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ if (!input_frame) {
+ VCD_MSG_ERROR("Bad parameters");
+
+ return VCD_ERR_BAD_POINTER;
+ }
+
+ drv_ctxt = vcd_get_drv_context();
+
+ mutex_lock(&drv_ctxt->dev_mutex);
+
+ if (cctxt->clnt_state.state_table->ev_hdlr.encode_frame) {
+ rc = cctxt->clnt_state.state_table->ev_hdlr.
+ encode_frame(cctxt, input_frame);
+ } else {
+ VCD_MSG_ERROR("Unsupported API in client state %d",
+ cctxt->clnt_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+
+ mutex_unlock(&drv_ctxt->dev_mutex);
+
+ return rc;
+
+}
+EXPORT_SYMBOL(vcd_encode_frame);
+
+u32 vcd_decode_start(void *handle, struct vcd_sequence_hdr *seq_hdr)
+{
+ struct vcd_clnt_ctxt *cctxt =
+ (struct vcd_clnt_ctxt *)handle;
+ struct vcd_drv_ctxt *drv_ctxt;
+ u32 rc;
+
+ VCD_MSG_MED("vcd_decode_start:");
+
+ if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
+ VCD_MSG_ERROR("Bad client handle");
+
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ drv_ctxt = vcd_get_drv_context();
+
+ mutex_lock(&drv_ctxt->dev_mutex);
+
+ if (cctxt->clnt_state.state_table->ev_hdlr.decode_start &&
+ drv_ctxt->dev_ctxt.pwr_state != VCD_PWR_STATE_SLEEP) {
+ rc = cctxt->clnt_state.state_table->ev_hdlr.
+ decode_start(cctxt, seq_hdr);
+ } else {
+ VCD_MSG_ERROR
+ ("Unsupported API in dev power state %d OR client state %d",
+ drv_ctxt->dev_ctxt.pwr_state,
+ cctxt->clnt_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+
+ mutex_unlock(&drv_ctxt->dev_mutex);
+
+ return rc;
+
+}
+EXPORT_SYMBOL(vcd_decode_start);
+
+u32 vcd_decode_frame(void *handle, struct vcd_frame_data *input_frame)
+{
+ struct vcd_clnt_ctxt *cctxt =
+ (struct vcd_clnt_ctxt *)handle;
+ struct vcd_drv_ctxt *drv_ctxt;
+ u32 rc;
+
+ VCD_MSG_MED("vcd_decode_frame:");
+
+ if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
+ VCD_MSG_ERROR("Bad client handle");
+
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ if (!input_frame) {
+ VCD_MSG_ERROR("Bad parameters");
+
+ return VCD_ERR_BAD_POINTER;
+ }
+
+ drv_ctxt = vcd_get_drv_context();
+
+ mutex_lock(&drv_ctxt->dev_mutex);
+
+ if (cctxt->clnt_state.state_table->ev_hdlr.decode_frame) {
+ rc = cctxt->clnt_state.state_table->ev_hdlr.
+ decode_frame(cctxt, input_frame);
+ } else {
+ VCD_MSG_ERROR("Unsupported API in client state %d",
+ cctxt->clnt_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+
+ mutex_unlock(&drv_ctxt->dev_mutex);
+
+ return rc;
+
+}
+EXPORT_SYMBOL(vcd_decode_frame);
+
+u32 vcd_pause(void *handle)
+{
+ struct vcd_drv_ctxt *drv_ctxt;
+ struct vcd_clnt_ctxt *cctxt =
+ (struct vcd_clnt_ctxt *)handle;
+ u32 rc;
+
+ VCD_MSG_MED("vcd_pause:");
+
+ if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
+ VCD_MSG_ERROR("Bad client handle");
+
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ drv_ctxt = vcd_get_drv_context();
+
+ mutex_lock(&drv_ctxt->dev_mutex);
+
+ if (cctxt->clnt_state.state_table->ev_hdlr.pause) {
+ rc = cctxt->clnt_state.state_table->ev_hdlr.
+ pause(cctxt);
+ } else {
+ VCD_MSG_ERROR("Unsupported API in client state %d",
+ cctxt->clnt_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+
+ mutex_unlock(&drv_ctxt->dev_mutex);
+
+ return rc;
+
+}
+EXPORT_SYMBOL(vcd_pause);
+
+u32 vcd_resume(void *handle)
+{
+ struct vcd_drv_ctxt *drv_ctxt;
+ struct vcd_clnt_ctxt *cctxt =
+ (struct vcd_clnt_ctxt *)handle;
+ u32 rc;
+
+ VCD_MSG_MED("vcd_resume:");
+
+ if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
+ VCD_MSG_ERROR("Bad client handle");
+
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ drv_ctxt = vcd_get_drv_context();
+
+ mutex_lock(&drv_ctxt->dev_mutex);
+
+ if (drv_ctxt->dev_state.state_table->ev_hdlr.resume &&
+ drv_ctxt->dev_ctxt.pwr_state != VCD_PWR_STATE_SLEEP) {
+ rc = drv_ctxt->dev_state.state_table->ev_hdlr.
+ resume(drv_ctxt, cctxt);
+ } else {
+ VCD_MSG_ERROR
+ ("Unsupported API in dev power state %d OR client state %d",
+ drv_ctxt->dev_ctxt.pwr_state,
+ cctxt->clnt_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+
+ mutex_unlock(&drv_ctxt->dev_mutex);
+
+ return rc;
+
+}
+EXPORT_SYMBOL(vcd_resume);
+
+u32 vcd_flush(void *handle, u32 mode)
+{
+ struct vcd_clnt_ctxt *cctxt =
+ (struct vcd_clnt_ctxt *)handle;
+ struct vcd_drv_ctxt *drv_ctxt;
+ u32 rc;
+
+ VCD_MSG_MED("vcd_flush:");
+
+ if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
+ VCD_MSG_ERROR("Bad client handle");
+
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ drv_ctxt = vcd_get_drv_context();
+
+ mutex_lock(&drv_ctxt->dev_mutex);
+
+ if (cctxt->clnt_state.state_table->ev_hdlr.flush) {
+ rc = cctxt->clnt_state.state_table->ev_hdlr.
+ flush(cctxt, mode);
+ } else {
+ VCD_MSG_ERROR("Unsupported API in client state %d",
+ cctxt->clnt_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+
+ mutex_unlock(&drv_ctxt->dev_mutex);
+
+ return rc;
+
+}
+EXPORT_SYMBOL(vcd_flush);
+
+u32 vcd_stop(void *handle)
+{
+ struct vcd_clnt_ctxt *cctxt =
+ (struct vcd_clnt_ctxt *)handle;
+ struct vcd_drv_ctxt *drv_ctxt;
+ u32 rc;
+
+ VCD_MSG_MED("vcd_stop:");
+
+ if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
+ VCD_MSG_ERROR("Bad client handle");
+
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ drv_ctxt = vcd_get_drv_context();
+
+ mutex_lock(&drv_ctxt->dev_mutex);
+
+ if (cctxt->clnt_state.state_table->ev_hdlr.stop &&
+ drv_ctxt->dev_ctxt.pwr_state != VCD_PWR_STATE_SLEEP) {
+ rc = cctxt->clnt_state.state_table->ev_hdlr.
+ stop(cctxt);
+ } else {
+ VCD_MSG_ERROR
+ ("Unsupported API in dev power state %d OR client state %d",
+ drv_ctxt->dev_ctxt.pwr_state,
+ cctxt->clnt_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+
+ mutex_unlock(&drv_ctxt->dev_mutex);
+
+ return rc;
+
+}
+EXPORT_SYMBOL(vcd_stop);
+
+u32 vcd_set_property(void *handle,
+ struct vcd_property_hdr *prop_hdr, void *prop_val)
+{
+ struct vcd_clnt_ctxt *cctxt =
+ (struct vcd_clnt_ctxt *)handle;
+ struct vcd_drv_ctxt *drv_ctxt;
+ u32 rc;
+
+ VCD_MSG_MED("vcd_set_property:");
+
+ if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
+ VCD_MSG_ERROR("Bad client handle");
+
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ if (!prop_hdr || !prop_val) {
+ VCD_MSG_ERROR("Bad parameters");
+
+ return VCD_ERR_BAD_POINTER;
+ }
+
+ drv_ctxt = vcd_get_drv_context();
+
+ mutex_lock(&drv_ctxt->dev_mutex);
+
+ if (cctxt->clnt_state.state_table->ev_hdlr.set_property) {
+ rc = cctxt->clnt_state.state_table->ev_hdlr.
+ set_property(cctxt, prop_hdr, prop_val);
+ } else {
+ VCD_MSG_ERROR("Unsupported API in client state %d",
+ cctxt->clnt_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+
+ mutex_unlock(&drv_ctxt->dev_mutex);
+
+ return rc;
+
+}
+EXPORT_SYMBOL(vcd_set_property);
+
+u32 vcd_get_property(void *handle,
+ struct vcd_property_hdr *prop_hdr, void *prop_val)
+{
+ struct vcd_clnt_ctxt *cctxt =
+ (struct vcd_clnt_ctxt *)handle;
+ struct vcd_drv_ctxt *drv_ctxt;
+ u32 rc;
+
+ VCD_MSG_MED("vcd_get_property:");
+
+ if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
+ VCD_MSG_ERROR("Bad client handle");
+
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ if (!prop_hdr || !prop_val) {
+ VCD_MSG_ERROR("Bad parameters");
+
+ return VCD_ERR_BAD_POINTER;
+ }
+
+ drv_ctxt = vcd_get_drv_context();
+
+ mutex_lock(&drv_ctxt->dev_mutex);
+
+ if (cctxt->clnt_state.state_table->ev_hdlr.get_property) {
+ rc = cctxt->clnt_state.state_table->ev_hdlr.
+ get_property(cctxt, prop_hdr, prop_val);
+ } else {
+ VCD_MSG_ERROR("Unsupported API in client state %d",
+ cctxt->clnt_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+
+ mutex_unlock(&drv_ctxt->dev_mutex);
+
+ return rc;
+
+}
+EXPORT_SYMBOL(vcd_get_property);
+
+u32 vcd_set_buffer_requirements(void *handle,
+ enum vcd_buffer_type buffer,
+ struct vcd_buffer_requirement *buffer_req)
+{
+ struct vcd_clnt_ctxt *cctxt =
+ (struct vcd_clnt_ctxt *)handle;
+ struct vcd_drv_ctxt *drv_ctxt;
+ u32 rc;
+
+ VCD_MSG_MED("vcd_set_buffer_requirements:");
+
+ if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
+ VCD_MSG_ERROR("Bad client handle");
+
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ if (!buffer_req) {
+ VCD_MSG_ERROR("Bad parameters");
+
+ return VCD_ERR_BAD_POINTER;
+ }
+
+ drv_ctxt = vcd_get_drv_context();
+
+ mutex_lock(&drv_ctxt->dev_mutex);
+
+ if (cctxt->clnt_state.state_table->ev_hdlr.
+ set_buffer_requirements) {
+ rc = cctxt->clnt_state.state_table->ev_hdlr.
+ set_buffer_requirements(cctxt, buffer, buffer_req);
+ } else {
+ VCD_MSG_ERROR("Unsupported API in client state %d",
+ cctxt->clnt_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+
+ mutex_unlock(&drv_ctxt->dev_mutex);
+
+ return rc;
+
+}
+EXPORT_SYMBOL(vcd_set_buffer_requirements);
+
+u32 vcd_get_buffer_requirements(void *handle,
+ enum vcd_buffer_type buffer,
+ struct vcd_buffer_requirement *buffer_req)
+{
+ struct vcd_clnt_ctxt *cctxt =
+ (struct vcd_clnt_ctxt *)handle;
+ struct vcd_drv_ctxt *drv_ctxt;
+ u32 rc;
+
+ VCD_MSG_MED("vcd_get_buffer_requirements:");
+
+ if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
+ VCD_MSG_ERROR("Bad client handle");
+
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ if (!buffer_req) {
+ VCD_MSG_ERROR("Bad parameters");
+
+ return VCD_ERR_BAD_POINTER;
+ }
+
+ drv_ctxt = vcd_get_drv_context();
+
+ mutex_lock(&drv_ctxt->dev_mutex);
+
+ if (cctxt->clnt_state.state_table->ev_hdlr.
+ get_buffer_requirements) {
+ rc = cctxt->clnt_state.state_table->ev_hdlr.
+ get_buffer_requirements(cctxt, buffer, buffer_req);
+ } else {
+ VCD_MSG_ERROR("Unsupported API in client state %d",
+ cctxt->clnt_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+
+ mutex_unlock(&drv_ctxt->dev_mutex);
+
+ return rc;
+
+}
+EXPORT_SYMBOL(vcd_get_buffer_requirements);
+
+u32 vcd_set_buffer(void *handle,
+ enum vcd_buffer_type buffer_type, u8 *buffer, u32 buf_size)
+{
+ struct vcd_clnt_ctxt *cctxt =
+ (struct vcd_clnt_ctxt *)handle;
+ struct vcd_drv_ctxt *drv_ctxt;
+ u32 rc;
+
+ VCD_MSG_MED("vcd_set_buffer:");
+
+ if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
+ VCD_MSG_ERROR("Bad client handle");
+
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ if (!buffer || !buf_size) {
+ VCD_MSG_ERROR("Bad parameters");
+
+ return VCD_ERR_BAD_POINTER;
+ }
+
+ drv_ctxt = vcd_get_drv_context();
+
+ mutex_lock(&drv_ctxt->dev_mutex);
+
+ if (cctxt->clnt_state.state_table->ev_hdlr.set_buffer) {
+ rc = cctxt->clnt_state.state_table->ev_hdlr.
+ set_buffer(cctxt, buffer_type, buffer, buf_size);
+ } else {
+ VCD_MSG_ERROR("Unsupported API in client state %d",
+ cctxt->clnt_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+
+ mutex_unlock(&drv_ctxt->dev_mutex);
+
+ return rc;
+
+}
+EXPORT_SYMBOL(vcd_set_buffer);
+
+u32 vcd_allocate_buffer(void *handle,
+ enum vcd_buffer_type buffer,
+ u32 buf_size, u8 **vir_buf_addr, u8 **phy_buf_addr)
+{
+ struct vcd_clnt_ctxt *cctxt =
+ (struct vcd_clnt_ctxt *)handle;
+ struct vcd_drv_ctxt *drv_ctxt;
+ u32 rc;
+
+ VCD_MSG_MED("vcd_allocate_buffer:");
+
+ if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
+ VCD_MSG_ERROR("Bad client handle");
+
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ if (!vir_buf_addr || !phy_buf_addr
+ || !buf_size) {
+ VCD_MSG_ERROR("Bad parameters");
+
+ return VCD_ERR_BAD_POINTER;
+ }
+
+ drv_ctxt = vcd_get_drv_context();
+
+ mutex_lock(&drv_ctxt->dev_mutex);
+
+ if (cctxt->clnt_state.state_table->ev_hdlr.allocate_buffer) {
+ rc = cctxt->clnt_state.state_table->ev_hdlr.
+ allocate_buffer(cctxt, buffer, buf_size,
+ vir_buf_addr, phy_buf_addr);
+ } else {
+ VCD_MSG_ERROR("Unsupported API in client state %d",
+ cctxt->clnt_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+
+ mutex_unlock(&drv_ctxt->dev_mutex);
+
+ return rc;
+
+}
+EXPORT_SYMBOL(vcd_allocate_buffer);
+
+u32 vcd_free_buffer(void *handle, enum vcd_buffer_type buffer_type, u8 *buffer)
+{
+ struct vcd_clnt_ctxt *cctxt =
+ (struct vcd_clnt_ctxt *)handle;
+ struct vcd_drv_ctxt *drv_ctxt;
+ u32 rc;
+
+ VCD_MSG_MED("vcd_free_buffer:");
+
+ if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
+ VCD_MSG_ERROR("Bad client handle");
+
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ drv_ctxt = vcd_get_drv_context();
+
+ mutex_lock(&drv_ctxt->dev_mutex);
+
+ if (cctxt->clnt_state.state_table->ev_hdlr.free_buffer) {
+ rc = cctxt->clnt_state.state_table->ev_hdlr.
+ free_buffer(cctxt, buffer_type, buffer);
+ } else {
+ VCD_MSG_ERROR("Unsupported API in client state %d",
+ cctxt->clnt_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+
+ mutex_unlock(&drv_ctxt->dev_mutex);
+
+ return rc;
+
+}
+EXPORT_SYMBOL(vcd_free_buffer);
+
+u32 vcd_fill_output_buffer(void *handle, struct vcd_frame_data *buffer)
+{
+ struct vcd_clnt_ctxt *cctxt =
+ (struct vcd_clnt_ctxt *)handle;
+ struct vcd_drv_ctxt *drv_ctxt;
+ u32 rc;
+
+ VCD_MSG_MED("vcd_fill_output_buffer:");
+
+ if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
+ VCD_MSG_ERROR("Bad client handle");
+
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ if (!buffer) {
+ VCD_MSG_ERROR("Bad parameters");
+
+ return VCD_ERR_BAD_POINTER;
+ }
+
+ drv_ctxt = vcd_get_drv_context();
+
+ mutex_lock(&drv_ctxt->dev_mutex);
+
+ if (cctxt->clnt_state.state_table->ev_hdlr.fill_output_buffer) {
+ rc = cctxt->clnt_state.state_table->ev_hdlr.
+ fill_output_buffer(cctxt, buffer);
+ } else {
+ VCD_MSG_ERROR("Unsupported API in client state %d",
+ cctxt->clnt_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+
+ mutex_unlock(&drv_ctxt->dev_mutex);
+
+ return rc;
+
+}
+EXPORT_SYMBOL(vcd_fill_output_buffer);
+
+u32 vcd_set_device_power(s32 driver_handle,
+ enum vcd_power_state pwr_state)
+{
+ u32 rc = VCD_S_SUCCESS;
+ struct vcd_drv_ctxt *drv_ctxt;
+
+ VCD_MSG_MED("vcd_set_device_power:");
+
+ drv_ctxt = vcd_get_drv_context();
+ mutex_lock(&drv_ctxt->dev_mutex);
+
+ if (drv_ctxt->dev_state.state_table->ev_hdlr.set_dev_pwr) {
+ rc = drv_ctxt->dev_state.state_table->ev_hdlr.
+ set_dev_pwr(drv_ctxt, pwr_state);
+ } else {
+ VCD_MSG_ERROR("Unsupported API in device state %d",
+ drv_ctxt->dev_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+
+ mutex_unlock(&drv_ctxt->dev_mutex);
+
+ return rc;
+
+}
+EXPORT_SYMBOL(vcd_set_device_power);
+
+void vcd_read_and_clear_interrupt(void)
+{
+ VCD_MSG_LOW("vcd_read_and_clear_interrupt:");
+ ddl_read_and_clear_interrupt();
+}
+
+
+void vcd_response_handler(void)
+{
+ struct vcd_drv_ctxt *drv_ctxt;
+
+ VCD_MSG_LOW("vcd_response_handler:");
+ drv_ctxt = vcd_get_drv_context();
+
+ mutex_lock(&drv_ctxt->dev_mutex);
+
+ if (!ddl_process_core_response()) {
+ VCD_MSG_HIGH
+ ("ddl_process_core_response indicated no further"
+ "processing");
+ mutex_unlock(&drv_ctxt->dev_mutex);
+ return;
+ }
+
+ if (drv_ctxt->dev_ctxt.command_continue)
+ vcd_continue();
+ mutex_unlock(&drv_ctxt->dev_mutex);
+}
+EXPORT_SYMBOL(vcd_response_handler);
+
+u8 vcd_get_num_of_clients(void)
+{
+ struct vcd_drv_ctxt *drv_ctxt;
+ struct vcd_clnt_ctxt *cctxt;
+ u8 count = 0;
+
+ VCD_MSG_LOW("vcd_get_num_of_clients:");
+ drv_ctxt = vcd_get_drv_context();
+
+ mutex_lock(&drv_ctxt->dev_mutex);
+ cctxt = drv_ctxt->dev_ctxt.cctxt_list_head;
+ while (cctxt) {
+ count++;
+ cctxt = cctxt->next;
+ }
+ mutex_unlock(&drv_ctxt->dev_mutex);
+ return count;
+}
+EXPORT_SYMBOL(vcd_get_num_of_clients);
+
+
+
+
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_api.h b/drivers/video/msm/vidc/common/vcd/vcd_api.h
new file mode 100644
index 0000000..38ea202
--- /dev/null
+++ b/drivers/video/msm/vidc/common/vcd/vcd_api.h
@@ -0,0 +1,140 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _VCD_API_H_
+#define _VCD_API_H_
+#include "vcd_property.h"
+#include "vcd_status.h"
+
+#define VCD_FRAME_FLAG_EOS 0x00000001
+#define VCD_FRAME_FLAG_DECODEONLY 0x00000004
+#define VCD_FRAME_FLAG_ENDOFFRAME 0x00000010
+#define VCD_FRAME_FLAG_SYNCFRAME 0x00000020
+#define VCD_FRAME_FLAG_EXTRADATA 0x00000040
+#define VCD_FRAME_FLAG_CODECCONFIG 0x00000080
+#define VCD_FRAME_FLAG_BFRAME 0x00100000
+
+#define VCD_FLUSH_INPUT 0x0001
+#define VCD_FLUSH_OUTPUT 0x0002
+#define VCD_FLUSH_ALL 0x0003
+
+#define VCD_FRAMETAG_INVALID 0xffffffff
+
+struct vcd_handle_container {
+ void *handle;
+};
+struct vcd_flush_cmd {
+ u32 mode;
+};
+
+enum vcd_frame {
+ VCD_FRAME_YUV = 1,
+ VCD_FRAME_I,
+ VCD_FRAME_P,
+ VCD_FRAME_B,
+ VCD_FRAME_NOTCODED,
+ VCD_FRAME_32BIT = 0x7fffffff
+};
+
+enum vcd_power_state {
+ VCD_PWR_STATE_ON = 1,
+ VCD_PWR_STATE_SLEEP,
+};
+
+struct vcd_frame_data {
+ u8 *virtual;
+ u8 *physical;
+ u32 alloc_len;
+ u32 data_len;
+ u32 offset;
+ s64 time_stamp;
+ u32 flags;
+ u32 frm_clnt_data;
+ struct vcd_property_dec_output_buffer dec_op_prop;
+ u32 interlaced;
+ enum vcd_frame frame;
+ u32 ip_frm_tag;
+ u32 intrlcd_ip_frm_tag;
+};
+
+struct vcd_sequence_hdr {
+ u8 *sequence_header;
+ u32 sequence_header_len;
+
+};
+
+enum vcd_buffer_type {
+ VCD_BUFFER_INPUT = 0x1,
+ VCD_BUFFER_OUTPUT = 0x2,
+ VCD_BUFFER_INVALID = 0x3,
+ VCD_BUFFER_32BIT = 0x7FFFFFFF
+};
+
+struct vcd_buffer_requirement {
+ u32 min_count;
+ u32 actual_count;
+ u32 max_count;
+ size_t sz;
+ u32 align;
+ u32 buf_pool_id;
+};
+
+struct vcd_init_config {
+ void *device_name;
+ void *(*map_dev_base_addr) (void *device_name);
+ void (*un_map_dev_base_addr) (void);
+ void (*interrupt_clr) (void);
+ void (*register_isr) (void *device_name);
+ void (*deregister_isr) (void);
+ u32 (*timer_create) (void (*timer_handler)(void *),
+ void *user_data, void **timer_handle);
+ void (*timer_release) (void *timer_handle);
+ void (*timer_start) (void *timer_handle, u32 time_out);
+ void (*timer_stop) (void *timer_handle);
+};
+
+u32 vcd_init(struct vcd_init_config *config, s32 *driver_handle);
+u32 vcd_term(s32 driver_handle);
+u32 vcd_open(s32 driver_handle, u32 decoding,
+ void (*callback) (u32 event, u32 status, void *info, size_t sz,
+ void *handle, void *const client_data), void *client_data);
+u32 vcd_close(void *handle);
+u32 vcd_encode_start(void *handle);
+u32 vcd_encode_frame(void *handle, struct vcd_frame_data *input_frame);
+u32 vcd_decode_start(void *handle, struct vcd_sequence_hdr *seq_hdr);
+u32 vcd_decode_frame(void *handle, struct vcd_frame_data *input_frame);
+u32 vcd_pause(void *handle);
+u32 vcd_resume(void *handle);
+u32 vcd_flush(void *handle, u32 mode);
+u32 vcd_stop(void *handle);
+u32 vcd_set_property(void *handle, struct vcd_property_hdr *prop_hdr,
+ void *prop_val);
+u32 vcd_get_property(void *handle, struct vcd_property_hdr *prop_hdr,
+ void *prop_val);
+u32 vcd_set_buffer_requirements(void *handle, enum vcd_buffer_type buffer,
+ struct vcd_buffer_requirement *buffer_req);
+u32 vcd_get_buffer_requirements(void *handle, enum vcd_buffer_type buffer,
+ struct vcd_buffer_requirement *buffer_req);
+u32 vcd_set_buffer(void *handle, enum vcd_buffer_type buffer_type,
+ u8 *buffer, u32 buf_size);
+u32 vcd_allocate_buffer(void *handle, enum vcd_buffer_type buffer,
+ u32 buf_size, u8 **vir_buf_addr, u8 **phy_buf_addr);
+
+u32 vcd_free_buffer(void *handle, enum vcd_buffer_type buffer_type, u8 *buffer);
+u32 vcd_fill_output_buffer(void *handle, struct vcd_frame_data *buffer);
+u32 vcd_set_device_power(s32 driver_handle,
+ enum vcd_power_state pwr_state);
+void vcd_read_and_clear_interrupt(void);
+void vcd_response_handler(void);
+u8 vcd_get_num_of_clients(void);
+
+#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
new file mode 100644
index 0000000..973ed48
--- /dev/null
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
@@ -0,0 +1,1827 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "vidc_type.h"
+#include "vcd.h"
+
+static const struct vcd_clnt_state_table *vcd_clnt_state_table[];
+
+void vcd_clnt_handle_device_err_fatal(struct vcd_clnt_ctxt *cctxt,
+ u32 event)
+{
+ if (cctxt->clnt_state.state == VCD_CLIENT_STATE_NULL) {
+ cctxt->callback(VCD_EVT_RESP_OPEN, VCD_ERR_HW_FATAL, NULL, 0,
+ cctxt, cctxt->client_data);
+ vcd_destroy_client_context(cctxt);
+ return;
+ }
+ if (event == VCD_EVT_RESP_BASE)
+ event = VCD_EVT_IND_HWERRFATAL;
+ if (cctxt->clnt_state.state != VCD_CLIENT_STATE_INVALID) {
+ cctxt->callback(event, VCD_ERR_HW_FATAL, NULL, 0,
+ cctxt, cctxt->client_data);
+ vcd_flush_buffers_in_err_fatal(cctxt);
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_INVALID,
+ CLIENT_STATE_EVENT_NUMBER(clnt_cb));
+ }
+}
+
+static u32 vcd_close_in_open(struct vcd_clnt_ctxt *cctxt)
+{
+ u32 rc = VCD_S_SUCCESS;
+
+ VCD_MSG_LOW("vcd_close_in_open:");
+ if (cctxt->in_buf_pool.allocated ||
+ cctxt->out_buf_pool.allocated) {
+ VCD_MSG_ERROR("\n Allocated buffers are not freed yet");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ vcd_destroy_client_context(cctxt);
+ return rc;
+}
+
+static u32 vcd_close_in_invalid(struct vcd_clnt_ctxt *cctxt)
+{
+ VCD_MSG_LOW("vcd_close_in_invalid:");
+ if (cctxt->in_buf_pool.allocated ||
+ cctxt->out_buf_pool.allocated){
+ VCD_MSG_ERROR("Allocated buffers are not freed yet");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+
+ if (cctxt->status.mask & VCD_CLEANING_UP)
+ cctxt->status.mask |= VCD_CLOSE_PENDING;
+ else
+ vcd_destroy_client_context(cctxt);
+ return VCD_S_SUCCESS;
+}
+
+static u32 vcd_start_in_run_cmn(struct vcd_clnt_ctxt *cctxt)
+{
+ VCD_MSG_LOW("vcd_start_in_run_cmn:");
+ cctxt->callback(VCD_EVT_RESP_START, VCD_S_SUCCESS, NULL, 0,
+ cctxt, cctxt->client_data);
+ return VCD_S_SUCCESS;
+
+}
+
+static u32 vcd_encode_start_in_open(struct vcd_clnt_ctxt *cctxt)
+{
+ u32 rc = VCD_S_SUCCESS;
+ struct vcd_property_hdr prop_hdr;
+ struct vcd_property_vop_timing timing;
+
+ VCD_MSG_LOW("vcd_encode_start_in_open:");
+
+ if (cctxt->decoding) {
+ VCD_MSG_ERROR("vcd_encode_init for decoder client");
+
+ return VCD_ERR_ILLEGAL_OP;
+ }
+
+ if (!cctxt->in_buf_pool.entries ||
+ !cctxt->out_buf_pool.entries ||
+ cctxt->in_buf_pool.validated != cctxt->in_buf_pool.count ||
+ cctxt->out_buf_pool.validated !=
+ cctxt->out_buf_pool.count) {
+ VCD_MSG_ERROR("Buffer pool is not completely setup yet");
+
+ return VCD_ERR_BAD_STATE;
+ }
+
+ rc = vcd_sched_add_client(cctxt);
+ VCD_FAILED_RETURN(rc, "Failed: vcd_sched_add_client");
+
+ prop_hdr.prop_id = VCD_I_VOP_TIMING;
+ prop_hdr.sz = sizeof(struct vcd_property_vop_timing);
+ rc = ddl_get_property(cctxt->ddl_handle, &prop_hdr, &timing);
+
+ VCD_FAILED_RETURN(rc, "Failed: Get VCD_I_VOP_TIMING");
+ if (!timing.vop_time_resolution) {
+ VCD_MSG_ERROR("Vop_time_resolution value is zero");
+ return VCD_ERR_FAIL;
+ }
+ cctxt->time_resoln = timing.vop_time_resolution;
+
+ rc = vcd_process_cmd_sess_start(cctxt);
+
+ if (!VCD_FAILED(rc)) {
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_STARTING,
+ CLIENT_STATE_EVENT_NUMBER
+ (encode_start));
+ }
+
+ return rc;
+}
+
+static u32 vcd_encode_start_in_run(struct vcd_clnt_ctxt
+ *cctxt)
+{
+ VCD_MSG_LOW("vcd_encode_start_in_run:");
+ (void) vcd_start_in_run_cmn(cctxt);
+ return VCD_S_SUCCESS;
+}
+
+
+static u32 vcd_encode_frame_cmn(struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *input_frame)
+{
+ VCD_MSG_LOW("vcd_encode_frame_cmn in %d:", cctxt->clnt_state.state);
+
+ if (cctxt->decoding) {
+ VCD_MSG_ERROR("vcd_encode_frame for decoder client");
+
+ return VCD_ERR_ILLEGAL_OP;
+ }
+
+ return vcd_handle_input_frame(cctxt, input_frame);
+}
+
+static u32 vcd_decode_start_in_open
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_sequence_hdr *seq_hdr)
+{
+ u32 rc = VCD_S_SUCCESS;
+
+ VCD_MSG_LOW("vcd_decode_start_in_open:");
+
+ if (!cctxt->decoding) {
+ VCD_MSG_ERROR("vcd_decode_init for encoder client");
+
+ return VCD_ERR_ILLEGAL_OP;
+ }
+
+ if (seq_hdr) {
+ VCD_MSG_HIGH("Seq hdr supplied. len = %d",
+ seq_hdr->sequence_header_len);
+
+ rc = vcd_store_seq_hdr(cctxt, seq_hdr);
+
+ } else {
+ VCD_MSG_HIGH("Seq hdr not supplied");
+
+ cctxt->seq_hdr.sequence_header_len = 0;
+ cctxt->seq_hdr.sequence_header = NULL;
+ }
+
+ VCD_FAILED_RETURN(rc, "Err processing seq hdr");
+
+ rc = vcd_process_cmd_sess_start(cctxt);
+
+ if (!VCD_FAILED(rc)) {
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_STARTING,
+ CLIENT_STATE_EVENT_NUMBER
+ (decode_start));
+ }
+
+ return rc;
+}
+
+static u32 vcd_decode_start_in_run(struct vcd_clnt_ctxt *cctxt,
+ struct vcd_sequence_hdr *seqhdr)
+{
+ VCD_MSG_LOW("vcd_decode_start_in_run:");
+ (void) vcd_start_in_run_cmn(cctxt);
+ return VCD_S_SUCCESS;
+}
+
+static u32 vcd_decode_frame_cmn
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *input_frame)
+{
+ VCD_MSG_LOW("vcd_decode_frame_cmn in %d:", cctxt->clnt_state.state);
+
+ if (!cctxt->decoding) {
+ VCD_MSG_ERROR("Decode_frame api called for Encoder client");
+
+ return VCD_ERR_ILLEGAL_OP;
+ }
+
+ return vcd_handle_input_frame(cctxt, input_frame);
+}
+
+static u32 vcd_pause_in_run(struct vcd_clnt_ctxt *cctxt)
+{
+ u32 rc = VCD_S_SUCCESS;
+
+ VCD_MSG_LOW("vcd_pause_in_run:");
+
+ if (cctxt->sched_clnt_hdl) {
+ rc = vcd_sched_suspend_resume_clnt(cctxt, false);
+ VCD_FAILED_RETURN(rc, "Failed: vcd_sched_suspend_resume_clnt");
+ }
+
+ if (cctxt->status.frame_submitted > 0) {
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_PAUSING,
+ CLIENT_STATE_EVENT_NUMBER
+ (pause));
+
+ } else {
+ VCD_MSG_HIGH("No client frames are currently being processed");
+
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_PAUSED,
+ CLIENT_STATE_EVENT_NUMBER
+ (pause));
+
+ cctxt->callback(VCD_EVT_RESP_PAUSE,
+ VCD_S_SUCCESS,
+ NULL, 0, cctxt, cctxt->client_data);
+
+ rc = vcd_power_event(cctxt->dev_ctxt, cctxt,
+ VCD_EVT_PWR_CLNT_PAUSE);
+
+ if (VCD_FAILED(rc))
+ VCD_MSG_ERROR("VCD_EVT_PWR_CLNT_PAUSE_END failed");
+
+ }
+
+ return VCD_S_SUCCESS;
+}
+
+static u32 vcd_resume_in_paused(struct vcd_clnt_ctxt *cctxt)
+{
+ struct vcd_dev_ctxt *dev_ctxt = cctxt->dev_ctxt;
+ u32 rc = VCD_S_SUCCESS;
+
+ VCD_MSG_LOW("vcd_resume_in_paused:");
+
+
+ if (cctxt->sched_clnt_hdl) {
+ rc = vcd_power_event(cctxt->dev_ctxt,
+ cctxt, VCD_EVT_PWR_CLNT_RESUME);
+
+ if (VCD_FAILED(rc)) {
+ VCD_MSG_ERROR("VCD_EVT_PWR_CLNT_RESUME failed");
+ } else {
+ rc = vcd_sched_suspend_resume_clnt(cctxt, true);
+ if (VCD_FAILED(rc)) {
+ VCD_MSG_ERROR
+ ("rc = 0x%x. Failed: "
+ "vcd_sched_suspend_resume_clnt",
+ rc);
+ }
+
+ }
+ if (!VCD_FAILED(rc)) {
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_RUN,
+ CLIENT_STATE_EVENT_NUMBER
+ (resume));
+ vcd_try_submit_frame(dev_ctxt);
+ }
+ } else {
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_RUN,
+ CLIENT_STATE_EVENT_NUMBER
+ (resume));
+ }
+
+ return rc;
+}
+
+static u32 vcd_flush_cmn(struct vcd_clnt_ctxt *cctxt, u32 mode)
+{
+ u32 rc = VCD_S_SUCCESS;
+
+ VCD_MSG_LOW("vcd_flush_cmn in %d:", cctxt->clnt_state.state);
+
+ rc = vcd_flush_buffers(cctxt, mode);
+
+ VCD_FAILED_RETURN(rc, "Failed: vcd_flush_buffers");
+
+ if (cctxt->status.frame_submitted > 0) {
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_FLUSHING,
+ CLIENT_STATE_EVENT_NUMBER
+ (flush));
+ } else {
+ VCD_MSG_HIGH("All buffers are flushed");
+ cctxt->status.mask |= (mode & VCD_FLUSH_ALL);
+ vcd_send_flush_done(cctxt, VCD_S_SUCCESS);
+ }
+
+ return rc;
+}
+
+static u32 vcd_flush_inopen(struct vcd_clnt_ctxt *cctxt,
+ u32 mode)
+{
+ VCD_MSG_LOW("vcd_flush_inopen:");
+ cctxt->status.mask |= (mode & VCD_FLUSH_ALL);
+ vcd_send_flush_done(cctxt, VCD_S_SUCCESS);
+ return VCD_S_SUCCESS;
+}
+
+static u32 vcd_flush_in_flushing
+ (struct vcd_clnt_ctxt *cctxt, u32 mode)
+{
+ u32 rc = VCD_S_SUCCESS;
+
+ VCD_MSG_LOW("vcd_flush_in_flushing:");
+
+ rc = vcd_flush_buffers(cctxt, mode);
+
+ return rc;
+}
+
+static u32 vcd_flush_in_eos(struct vcd_clnt_ctxt *cctxt,
+ u32 mode)
+{
+ VCD_MSG_LOW("vcd_flush_in_eos:");
+
+ if (mode > VCD_FLUSH_ALL || !mode) {
+ VCD_MSG_ERROR("Invalid flush mode %d", mode);
+
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+
+ VCD_MSG_MED("Flush mode requested %d", mode);
+
+ cctxt->status.mask |= (mode & VCD_FLUSH_ALL);
+
+ return VCD_S_SUCCESS;
+}
+
+static u32 vcd_flush_in_invalid(struct vcd_clnt_ctxt *cctxt,
+ u32 mode)
+{
+ u32 rc = VCD_S_SUCCESS;
+ VCD_MSG_LOW("vcd_flush_in_invalid:");
+ if (!(cctxt->status.mask & VCD_CLEANING_UP)) {
+ rc = vcd_flush_buffers(cctxt, mode);
+ if (!VCD_FAILED(rc)) {
+ VCD_MSG_HIGH("All buffers are flushed");
+ cctxt->status.mask |= (mode & VCD_FLUSH_ALL);
+ vcd_send_flush_done(cctxt, VCD_S_SUCCESS);
+ }
+ } else
+ cctxt->status.mask |= (mode & VCD_FLUSH_ALL);
+ return rc;
+}
+
+static u32 vcd_stop_cmn(struct vcd_clnt_ctxt *cctxt)
+{
+ struct vcd_dev_ctxt *dev_ctxt = cctxt->dev_ctxt;
+ u32 rc = VCD_S_SUCCESS;
+ struct vcd_transc *transc;
+
+ VCD_MSG_LOW("vcd_stop_cmn in %d:", cctxt->clnt_state.state);
+
+ rc = vcd_flush_buffers(cctxt, VCD_FLUSH_ALL);
+
+ VCD_FAILED_RETURN(rc, "Failed: vcd_flush_buffers");
+
+ if (!cctxt->status.frame_submitted) {
+
+ if (vcd_get_command_channel(dev_ctxt, &transc)) {
+ rc = vcd_power_event(dev_ctxt, cctxt,
+ VCD_EVT_PWR_CLNT_CMD_BEGIN);
+
+ if (!VCD_FAILED(rc)) {
+ transc->type = VCD_CMD_CODEC_STOP;
+ transc->cctxt = cctxt;
+
+ rc = vcd_submit_cmd_sess_end(transc);
+ } else {
+ VCD_MSG_ERROR("Failed:"
+ " VCD_EVT_PWR_CLNT_CMD_BEGIN");
+ }
+
+ if (VCD_FAILED(rc)) {
+ vcd_release_command_channel(dev_ctxt,
+ transc);
+ }
+
+ } else {
+ vcd_client_cmd_flush_and_en_q(cctxt,
+ VCD_CMD_CODEC_STOP);
+ }
+ }
+
+ if (VCD_FAILED(rc)) {
+ (void)vcd_power_event(dev_ctxt, cctxt,
+ VCD_EVT_PWR_CLNT_CMD_FAIL);
+ } else {
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_STOPPING,
+ CLIENT_STATE_EVENT_NUMBER
+ (stop));
+ }
+
+ return rc;
+}
+
+
+static u32 vcd_stop_inopen(struct vcd_clnt_ctxt *cctxt)
+{
+ VCD_MSG_LOW("vcd_stop_inopen:");
+
+ cctxt->callback(VCD_EVT_RESP_STOP, VCD_S_SUCCESS,
+ NULL, 0, cctxt,
+ cctxt->client_data);
+
+ return VCD_S_SUCCESS;
+}
+
+static u32 vcd_stop_in_run(struct vcd_clnt_ctxt *cctxt)
+{
+ u32 rc = VCD_S_SUCCESS;
+ VCD_MSG_LOW("vcd_stop_in_run:");
+ rc = vcd_stop_cmn(cctxt);
+ if (!VCD_FAILED(rc) &&
+ (cctxt->status.mask & VCD_FIRST_IP_RCVD)) {
+ rc = vcd_power_event(cctxt->dev_ctxt,
+ cctxt, VCD_EVT_PWR_CLNT_LAST_FRAME);
+ }
+ return rc;
+}
+
+static u32 vcd_stop_in_eos(struct vcd_clnt_ctxt *cctxt)
+{
+ u32 rc = VCD_S_SUCCESS;
+ VCD_MSG_LOW("vcd_stop_in_eos:");
+ if (cctxt->status.mask & VCD_EOS_WAIT_OP_BUF) {
+ rc = vcd_stop_cmn(cctxt);
+ if (!VCD_FAILED(rc)) {
+ rc = vcd_power_event(cctxt->dev_ctxt,
+ cctxt, VCD_EVT_PWR_CLNT_LAST_FRAME);
+ cctxt->status.mask &= ~VCD_EOS_WAIT_OP_BUF;
+ }
+ } else
+ cctxt->status.mask |= VCD_STOP_PENDING;
+ return rc;
+}
+
+static u32 vcd_stop_in_invalid(struct vcd_clnt_ctxt *cctxt)
+{
+ VCD_MSG_LOW("vcd_stop_in_invalid:");
+ if (cctxt->status.mask & VCD_CLEANING_UP) {
+ cctxt->status.mask |= VCD_STOP_PENDING;
+ } else {
+ (void) vcd_flush_buffers(cctxt, VCD_FLUSH_ALL);
+ cctxt->callback(VCD_EVT_RESP_STOP, VCD_S_SUCCESS, NULL,
+ 0, cctxt, cctxt->client_data);
+ }
+ return VCD_S_SUCCESS;
+}
+
+static u32 vcd_set_property_cmn
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_property_hdr *prop_hdr, void *prop_val)
+{
+ u32 rc;
+ VCD_MSG_LOW("vcd_set_property_cmn in %d:", cctxt->clnt_state.state);
+ VCD_MSG_LOW("property Id = %d", prop_hdr->prop_id);
+ if (!prop_hdr->sz || !prop_hdr->prop_id) {
+ VCD_MSG_MED("Bad parameters");
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+
+ rc = ddl_set_property(cctxt->ddl_handle, prop_hdr, prop_val);
+ VCD_FAILED_RETURN(rc, "Failed: ddl_set_property");
+ switch (prop_hdr->prop_id) {
+ case VCD_I_LIVE:
+ {
+ struct vcd_property_live *live =
+ (struct vcd_property_live *)prop_val;
+ cctxt->live = live->live;
+ break;
+ }
+ case VCD_I_FRAME_RATE:
+ {
+ if (cctxt->sched_clnt_hdl) {
+ rc = vcd_set_frame_rate(cctxt,
+ (struct vcd_property_frame_rate *)
+ prop_val);
+ }
+ break;
+ }
+ case VCD_I_FRAME_SIZE:
+ {
+ if (cctxt->sched_clnt_hdl) {
+ rc = vcd_set_frame_size(cctxt,
+ (struct vcd_property_frame_size *)
+ prop_val);
+ }
+ break;
+ }
+ case VCD_I_INTRA_PERIOD:
+ {
+ struct vcd_property_i_period *iperiod =
+ (struct vcd_property_i_period *)prop_val;
+ cctxt->bframe = iperiod->b_frames;
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ return rc;
+}
+
+static u32 vcd_get_property_cmn
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_property_hdr *prop_hdr, void *prop_val)
+{
+ VCD_MSG_LOW("vcd_get_property_cmn in %d:", cctxt->clnt_state.state);
+ VCD_MSG_LOW("property Id = %d", prop_hdr->prop_id);
+ if (!prop_hdr->sz || !prop_hdr->prop_id) {
+ VCD_MSG_MED("Bad parameters");
+
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+ return ddl_get_property(cctxt->ddl_handle, prop_hdr, prop_val);
+}
+
+static u32 vcd_set_buffer_requirements_cmn
+ (struct vcd_clnt_ctxt *cctxt,
+ enum vcd_buffer_type buffer,
+ struct vcd_buffer_requirement *buffer_req)
+{
+ struct vcd_property_hdr Prop_hdr;
+ u32 rc = VCD_S_SUCCESS;
+ struct vcd_buffer_pool *buf_pool;
+ u32 first_frm_recvd = 0;
+
+ VCD_MSG_LOW("vcd_set_buffer_requirements_cmn in %d:",
+ cctxt->clnt_state.state);
+
+ if (!cctxt->decoding &&
+ cctxt->clnt_state.state != VCD_CLIENT_STATE_OPEN) {
+ VCD_MSG_ERROR("Bad state (%d) for encoder",
+ cctxt->clnt_state.state);
+
+ return VCD_ERR_BAD_STATE;
+ }
+
+ VCD_MSG_MED("Buffer type = %d", buffer);
+
+ if (buffer == VCD_BUFFER_INPUT) {
+ Prop_hdr.prop_id = DDL_I_INPUT_BUF_REQ;
+ buf_pool = &cctxt->in_buf_pool;
+ first_frm_recvd = VCD_FIRST_IP_RCVD;
+ } else if (buffer == VCD_BUFFER_OUTPUT) {
+ Prop_hdr.prop_id = DDL_I_OUTPUT_BUF_REQ;
+ buf_pool = &cctxt->out_buf_pool;
+ first_frm_recvd = VCD_FIRST_OP_RCVD;
+ } else {
+ rc = VCD_ERR_ILLEGAL_PARM;
+ }
+
+ VCD_FAILED_RETURN(rc, "Invalid buffer type provided");
+
+ if (buf_pool->validated > 0) {
+ VCD_MSG_ERROR("Need to free allocated buffers");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+
+ first_frm_recvd &= cctxt->status.mask;
+ if (first_frm_recvd) {
+ VCD_MSG_ERROR("VCD SetBufReq called when data path is active");
+ return VCD_ERR_BAD_STATE;
+ }
+ Prop_hdr.sz = sizeof(*buffer_req);
+ rc = ddl_set_property(cctxt->ddl_handle, &Prop_hdr, buffer_req);
+ VCD_FAILED_RETURN(rc, "Failed: ddl_set_property");
+ if (buf_pool->entries) {
+ VCD_MSG_MED("Resetting buffer requirements");
+ vcd_free_buffer_pool_entries(buf_pool);
+ }
+ return rc;
+}
+
+static u32 vcd_get_buffer_requirements_cmn
+ (struct vcd_clnt_ctxt *cctxt,
+ enum vcd_buffer_type buffer,
+ struct vcd_buffer_requirement *buffer_req)
+{
+ struct vcd_property_hdr Prop_hdr;
+ u32 rc = VCD_S_SUCCESS;
+
+ VCD_MSG_LOW("vcd_get_buffer_requirements_cmn in %d:",
+ cctxt->clnt_state.state);
+
+ VCD_MSG_MED("Buffer type = %d", buffer);
+
+ if (buffer == VCD_BUFFER_INPUT)
+ Prop_hdr.prop_id = DDL_I_INPUT_BUF_REQ;
+ else if (buffer == VCD_BUFFER_OUTPUT)
+ Prop_hdr.prop_id = DDL_I_OUTPUT_BUF_REQ;
+ else
+ rc = VCD_ERR_ILLEGAL_PARM;
+
+ VCD_FAILED_RETURN(rc, "Invalid buffer type provided");
+
+ Prop_hdr.sz = sizeof(*buffer_req);
+
+ return ddl_get_property(cctxt->ddl_handle, &Prop_hdr, buffer_req);
+
+}
+
+static u32 vcd_set_buffer_cmn
+ (struct vcd_clnt_ctxt *cctxt,
+ enum vcd_buffer_type buffer_type, u8 *buffer, u32 buf_size)
+{
+ u32 rc;
+ struct vcd_buffer_pool *buf_pool;
+
+ VCD_MSG_LOW("vcd_set_buffer_cmn in %d:", cctxt->clnt_state.state);
+
+ rc = vcd_common_allocate_set_buffer(cctxt, buffer_type, buf_size,
+ &buf_pool);
+
+ if (!VCD_FAILED(rc)) {
+ rc = vcd_set_buffer_internal(cctxt, buf_pool, buffer,
+ buf_size);
+ }
+
+ return rc;
+}
+
+static u32 vcd_allocate_buffer_cmn
+ (struct vcd_clnt_ctxt *cctxt,
+ enum vcd_buffer_type buffer,
+ u32 buf_size, u8 **vir_buf_addr, u8 **phy_buf_addr)
+{
+ u32 rc;
+ struct vcd_buffer_pool *buf_pool;
+
+ VCD_MSG_LOW("vcd_allocate_buffer_cmn in %d:",
+ cctxt->clnt_state.state);
+
+ rc = vcd_common_allocate_set_buffer(cctxt, buffer, buf_size,
+ &buf_pool);
+
+ if (!VCD_FAILED(rc)) {
+ rc = vcd_allocate_buffer_internal(cctxt,
+ buf_pool,
+ buf_size,
+ vir_buf_addr,
+ phy_buf_addr);
+ }
+
+ return rc;
+}
+
+static u32 vcd_free_buffer_cmn
+ (struct vcd_clnt_ctxt *cctxt,
+ enum vcd_buffer_type buffer_type, u8 *buffer)
+{
+
+ VCD_MSG_LOW("vcd_free_buffer_cmn in %d:", cctxt->clnt_state.state);
+
+ return vcd_free_one_buffer_internal(cctxt, buffer_type, buffer);
+}
+
+static u32 vcd_fill_output_buffer_cmn
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *buffer)
+{
+ u32 rc = VCD_S_SUCCESS;
+ struct vcd_buffer_entry *buf_entry;
+ u32 result = true;
+ u32 handled = true;
+ if (!cctxt || !buffer) {
+ VCD_MSG_ERROR("%s(): Inavlid params cctxt %p buffer %p",
+ __func__, cctxt, buffer);
+ return VCD_ERR_BAD_POINTER;
+ }
+ VCD_MSG_LOW("vcd_fill_output_buffer_cmn in %d:",
+ cctxt->clnt_state.state);
+ if (cctxt->status.mask & VCD_IN_RECONFIG) {
+ buffer->time_stamp = 0;
+ buffer->data_len = 0;
+ VCD_MSG_LOW("In reconfig: Return output buffer");
+ cctxt->callback(VCD_EVT_RESP_OUTPUT_DONE,
+ VCD_S_SUCCESS,
+ buffer,
+ sizeof(struct vcd_frame_data),
+ cctxt, cctxt->client_data);
+ return rc;
+ }
+ buf_entry = vcd_check_fill_output_buffer(cctxt, buffer);
+ if (!buf_entry)
+ return VCD_ERR_BAD_POINTER;
+
+ if (!(cctxt->status.mask & VCD_FIRST_OP_RCVD)) {
+ rc = vcd_handle_first_fill_output_buffer(cctxt, buffer,
+ &handled);
+ VCD_FAILED_RETURN(rc,
+ "Failed: vcd_handle_first_fill_output_buffer");
+ if (handled)
+ return rc ;
+ }
+
+ result =
+ vcd_buffer_pool_entry_en_q(&cctxt->out_buf_pool, buf_entry);
+
+ if (!result && !cctxt->decoding) {
+ VCD_MSG_ERROR("Failed: vcd_buffer_pool_entry_en_q");
+
+ return VCD_ERR_FAIL;
+ }
+
+ buf_entry->frame = *buffer;
+ rc = vcd_return_op_buffer_to_hw(cctxt, buf_entry);
+ if (!VCD_FAILED(rc) && cctxt->sched_clnt_hdl) {
+ cctxt->sched_clnt_hdl->tkns++;
+ vcd_try_submit_frame(cctxt->dev_ctxt);
+ }
+ return rc;
+}
+
+static u32 vcd_fill_output_buffer_in_eos
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *buffer)
+{
+ u32 rc = VCD_S_SUCCESS;
+ struct vcd_buffer_entry *buf_entry;
+
+ VCD_MSG_LOW("vcd_fill_output_buffer_in_eos:");
+
+ buf_entry = vcd_check_fill_output_buffer(cctxt, buffer);
+ if (!buf_entry)
+ return VCD_ERR_BAD_POINTER;
+
+ if (cctxt->status.mask & VCD_EOS_WAIT_OP_BUF) {
+ VCD_MSG_HIGH("Got an output buffer we were waiting for");
+
+ buf_entry->frame = *buffer;
+
+ buf_entry->frame.data_len = 0;
+ buf_entry->frame.flags |= VCD_FRAME_FLAG_EOS;
+ buf_entry->frame.ip_frm_tag =
+ cctxt->status.eos_trig_ip_frm.ip_frm_tag;
+ buf_entry->frame.time_stamp =
+ cctxt->status.eos_trig_ip_frm.time_stamp;
+
+ cctxt->callback(VCD_EVT_RESP_OUTPUT_DONE,
+ VCD_S_SUCCESS,
+ &buf_entry->frame,
+ sizeof(struct vcd_frame_data),
+ cctxt, cctxt->client_data);
+
+ cctxt->status.mask &= ~VCD_EOS_WAIT_OP_BUF;
+
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_RUN,
+ CLIENT_STATE_EVENT_NUMBER
+ (fill_output_buffer));
+
+ } else {
+ rc = vcd_fill_output_buffer_cmn(cctxt, buffer);
+ }
+
+ return rc;
+}
+
+static void vcd_clnt_cb_in_starting
+ (struct vcd_clnt_ctxt *cctxt,
+ u32 event, u32 status, void *payload, size_t sz,
+ u32 *ddl_handle, void *const client_data)
+{
+ struct vcd_dev_ctxt *dev_ctxt = cctxt->dev_ctxt;
+ struct vcd_transc *transc =
+ (struct vcd_transc *)client_data;
+ VCD_MSG_LOW("vcd_clnt_cb_in_starting:");
+ if (cctxt->ddl_handle != ddl_handle) {
+ VCD_MSG_ERROR("vcd_clnt_cb_in_initing: Wrong DDL handle %p",
+ ddl_handle);
+ return;
+ }
+
+ switch (event) {
+ case VCD_EVT_RESP_START:
+ {
+ vcd_handle_start_done(cctxt,
+ (struct vcd_transc *)client_data,
+ status);
+ break;
+ }
+ case VCD_EVT_RESP_STOP:
+ {
+ vcd_handle_stop_done_in_starting(cctxt,
+ (struct vcd_transc *)client_data,
+ status);
+ break;
+ }
+ case VCD_EVT_IND_HWERRFATAL:
+ {
+ cctxt->status.cmd_submitted--;
+ vcd_mark_command_channel(cctxt->dev_ctxt, transc);
+ vcd_handle_err_fatal(cctxt, VCD_EVT_RESP_START,
+ status);
+ break;
+ }
+ default:
+ {
+ VCD_MSG_ERROR("Unexpected callback event=%d status=%d "
+ "from DDL", event, status);
+ dev_ctxt->command_continue = false;
+ break;
+ }
+ }
+}
+
+static void vcd_clnt_cb_in_run
+ (struct vcd_clnt_ctxt *cctxt,
+ u32 event,
+ u32 status,
+ void *payload, size_t sz, u32 *ddl_handle, void *const client_data)
+{
+ struct vcd_dev_ctxt *dev_ctxt = cctxt->dev_ctxt;
+ u32 rc = VCD_S_SUCCESS;
+
+ if (cctxt->ddl_handle != ddl_handle) {
+ VCD_MSG_ERROR("ddl_handle mismatch");
+
+ return;
+ }
+
+ switch (event) {
+ case VCD_EVT_RESP_INPUT_DONE:
+ {
+ rc = vcd_handle_input_done(cctxt, payload, event,
+ status);
+
+ break;
+ }
+
+ case VCD_EVT_RESP_OUTPUT_DONE:
+ {
+
+ rc = vcd_handle_frame_done(cctxt, payload, event,
+ status);
+
+ break;
+ }
+ case VCD_EVT_RESP_OUTPUT_REQ:
+ {
+ rc = vcd_handle_output_required(cctxt, payload,
+ status);
+ break;
+ }
+
+ case VCD_EVT_IND_OUTPUT_RECONFIG:
+ {
+ rc = vcd_handle_ind_output_reconfig(cctxt, payload,
+ status);
+ break;
+ }
+ case VCD_EVT_RESP_TRANSACTION_PENDING:
+ {
+ vcd_handle_trans_pending(cctxt);
+ break;
+ }
+
+ case VCD_EVT_IND_HWERRFATAL:
+ {
+ vcd_handle_ind_hw_err_fatal(cctxt,
+ VCD_EVT_IND_HWERRFATAL, status);
+ break;
+ }
+ case VCD_EVT_IND_INFO_OUTPUT_RECONFIG:
+ {
+ vcd_handle_ind_info_output_reconfig(cctxt, status);
+ break;
+ }
+ default:
+ {
+ VCD_MSG_ERROR
+ ("Unexpected callback event=%d status=%d from DDL",
+ event, status);
+ dev_ctxt->command_continue = false;
+
+ break;
+ }
+ }
+
+ if (!VCD_FAILED(rc) &&
+ (event == VCD_EVT_RESP_INPUT_DONE ||
+ event == VCD_EVT_RESP_OUTPUT_DONE ||
+ event == VCD_EVT_RESP_OUTPUT_REQ)) {
+
+ if (((struct ddl_frame_data_tag *)
+ payload)->frm_trans_end)
+ vcd_mark_frame_channel(cctxt->dev_ctxt);
+ }
+}
+
+static void vcd_clnt_cb_in_eos
+ (struct vcd_clnt_ctxt *cctxt,
+ u32 event,
+ u32 status,
+ void *payload, size_t sz, u32 *ddl_handle, void *const client_data) {
+ struct vcd_dev_ctxt *dev_ctxt = cctxt->dev_ctxt;
+ struct vcd_transc *transc = NULL;
+ u32 frm_trans_end = false, rc = VCD_S_SUCCESS;
+
+ if (cctxt->ddl_handle != ddl_handle) {
+ VCD_MSG_ERROR("ddl_handle mismatch");
+
+ return;
+ }
+
+ switch (event) {
+ case VCD_EVT_RESP_INPUT_DONE:
+ {
+ rc = vcd_handle_input_done_in_eos(cctxt, payload,
+ status);
+
+ break;
+ }
+
+ case VCD_EVT_RESP_OUTPUT_DONE:
+ {
+ rc = vcd_handle_frame_done_in_eos(cctxt, payload,
+ status);
+
+ break;
+ }
+ case VCD_EVT_RESP_OUTPUT_REQ:
+ {
+ rc = vcd_handle_output_required(cctxt, payload,
+ status);
+ break;
+ }
+ case VCD_EVT_RESP_EOS_DONE:
+ {
+ transc = (struct vcd_transc *)client_data;
+ vcd_handle_eos_done(cctxt, transc, status);
+ vcd_mark_frame_channel(cctxt->dev_ctxt);
+ break;
+ }
+ case VCD_EVT_IND_OUTPUT_RECONFIG:
+ {
+ rc = vcd_handle_ind_output_reconfig(cctxt,
+ payload, status);
+ if (!VCD_FAILED(rc)) {
+ frm_trans_end = true;
+ payload = NULL;
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_RUN,
+ CLIENT_STATE_EVENT_NUMBER
+ (clnt_cb));
+ VCD_MSG_LOW
+ ("RECONFIGinEOS:Suspending Client");
+ rc = vcd_sched_suspend_resume_clnt(cctxt,
+ false);
+ if (VCD_FAILED(rc)) {
+ VCD_MSG_ERROR
+ ("Failed: suspend_resume_clnt. rc=0x%x",
+ rc);
+ }
+ }
+ break;
+ }
+ case VCD_EVT_IND_HWERRFATAL:
+ {
+ vcd_handle_ind_hw_err_fatal(cctxt,
+ VCD_EVT_IND_HWERRFATAL, status);
+ break;
+ }
+ case VCD_EVT_IND_INFO_OUTPUT_RECONFIG:
+ {
+ vcd_handle_ind_info_output_reconfig(cctxt, status);
+ break;
+ }
+ default:
+ {
+ VCD_MSG_ERROR
+ ("Unexpected callback event=%d status=%d from DDL",
+ event, status);
+
+ dev_ctxt->command_continue = false;
+
+ break;
+ }
+
+ }
+ if (!VCD_FAILED(rc) &&
+ (event == VCD_EVT_RESP_INPUT_DONE ||
+ event == VCD_EVT_RESP_OUTPUT_DONE ||
+ event == VCD_EVT_RESP_OUTPUT_REQ ||
+ event == VCD_EVT_IND_OUTPUT_RECONFIG)) {
+ if (payload && ((struct ddl_frame_data_tag *)
+ payload)->frm_trans_end) {
+ vcd_mark_frame_channel(cctxt->dev_ctxt);
+ frm_trans_end = true;
+ }
+ if (frm_trans_end && !cctxt->status.frame_submitted)
+ vcd_handle_eos_trans_end(cctxt);
+ }
+}
+
+static void vcd_clnt_cb_in_flushing
+ (struct vcd_clnt_ctxt *cctxt,
+ u32 event,
+ u32 status,
+ void *payload, size_t sz, u32 *ddl_handle, void *const client_data) {
+ struct vcd_dev_ctxt *dev_ctxt = cctxt->dev_ctxt;
+ u32 rc = VCD_S_SUCCESS;
+ u32 frm_trans_end = false;
+
+ VCD_MSG_LOW("vcd_clnt_cb_in_flushing:");
+
+ if (cctxt->ddl_handle != ddl_handle) {
+ VCD_MSG_ERROR("ddl_handle mismatch");
+
+ return;
+ }
+
+ switch (event) {
+ case VCD_EVT_RESP_INPUT_DONE:
+ {
+ rc = vcd_handle_input_done(cctxt,
+ payload,
+ VCD_EVT_RESP_INPUT_FLUSHED,
+ status);
+
+ break;
+ }
+
+ case VCD_EVT_RESP_OUTPUT_DONE:
+ {
+
+ rc = vcd_handle_frame_done(cctxt,
+ payload,
+ VCD_EVT_RESP_OUTPUT_FLUSHED,
+ status);
+
+ break;
+ }
+ case VCD_EVT_RESP_OUTPUT_REQ:
+ {
+ rc = vcd_handle_output_required_in_flushing(cctxt,
+ payload);
+ break;
+ }
+ case VCD_EVT_IND_OUTPUT_RECONFIG:
+ {
+ rc = vcd_handle_ind_output_reconfig(cctxt,
+ payload, status);
+ if (!VCD_FAILED(rc)) {
+ frm_trans_end = true;
+ payload = NULL;
+ }
+ break;
+ }
+ case VCD_EVT_IND_HWERRFATAL:
+ {
+ vcd_handle_ind_hw_err_fatal(cctxt,
+ VCD_EVT_IND_HWERRFATAL, status);
+ break;
+ }
+ default:
+ {
+ VCD_MSG_ERROR
+ ("Unexpected callback event=%d status=%d from DDL",
+ event, status);
+
+ dev_ctxt->command_continue = false;
+
+ break;
+ }
+ }
+ if (!VCD_FAILED(rc) && ((event == VCD_EVT_RESP_INPUT_DONE ||
+ event == VCD_EVT_RESP_OUTPUT_DONE ||
+ event == VCD_EVT_RESP_OUTPUT_REQ ||
+ event == VCD_EVT_IND_OUTPUT_RECONFIG))) {
+ if (payload &&
+ ((struct ddl_frame_data_tag *)\
+ payload)->frm_trans_end) {
+
+ vcd_mark_frame_channel(cctxt->dev_ctxt);
+ frm_trans_end = true;
+ }
+ if (frm_trans_end && !cctxt->status.frame_submitted) {
+ VCD_MSG_HIGH
+ ("All pending frames recvd from DDL");
+ if (cctxt->status.mask & VCD_FLUSH_INPUT)
+ vcd_flush_bframe_buffers(cctxt,
+ VCD_FLUSH_INPUT);
+ if (cctxt->status.mask & VCD_FLUSH_OUTPUT)
+ vcd_flush_output_buffers(cctxt);
+ vcd_send_flush_done(cctxt, VCD_S_SUCCESS);
+ vcd_release_interim_frame_channels(dev_ctxt);
+ VCD_MSG_HIGH("Flush complete");
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_RUN,
+ CLIENT_STATE_EVENT_NUMBER
+ (clnt_cb));
+ }
+ }
+}
+
+static void vcd_clnt_cb_in_stopping
+ (struct vcd_clnt_ctxt *cctxt,
+ u32 event,
+ u32 status,
+ void *payload, size_t sz, u32 *ddl_handle, void *const client_data) {
+ struct vcd_dev_ctxt *dev_ctxt = cctxt->dev_ctxt;
+ u32 rc = VCD_S_SUCCESS;
+ u32 frm_trans_end = false;
+
+ VCD_MSG_LOW("vcd_clnt_cb_in_stopping:");
+
+ if (cctxt->ddl_handle != ddl_handle) {
+ VCD_MSG_ERROR("ddl_handle mismatch");
+
+ return;
+ }
+
+ switch (event) {
+
+ case VCD_EVT_RESP_INPUT_DONE:
+ {
+ rc = vcd_handle_input_done(cctxt,
+ payload,
+ VCD_EVT_RESP_INPUT_FLUSHED,
+ status);
+
+ break;
+ }
+
+ case VCD_EVT_RESP_OUTPUT_DONE:
+ {
+
+ rc = vcd_handle_frame_done(cctxt,
+ payload,
+ VCD_EVT_RESP_OUTPUT_FLUSHED,
+ status);
+
+ break;
+ }
+ case VCD_EVT_RESP_OUTPUT_REQ:
+ {
+ rc = vcd_handle_output_required_in_flushing(cctxt,
+ payload);
+ break;
+ }
+ case VCD_EVT_RESP_STOP:
+ {
+ vcd_handle_stop_done(cctxt,
+ (struct vcd_transc *)
+ client_data, status);
+
+ break;
+ }
+ case VCD_EVT_IND_OUTPUT_RECONFIG:
+ {
+ (void) vcd_handle_ind_output_reconfig(cctxt,
+ payload, status);
+
+ frm_trans_end = true;
+ payload = NULL;
+
+ break;
+ }
+ case VCD_EVT_IND_HWERRFATAL:
+ {
+ vcd_handle_ind_hw_err_fatal(cctxt, VCD_EVT_RESP_STOP,
+ status);
+ break;
+ }
+
+ default:
+ {
+ VCD_MSG_ERROR
+ ("Unexpected callback event=%d status=%d from DDL",
+ event, status);
+
+ dev_ctxt->command_continue = false;
+
+ break;
+ }
+ }
+
+ if (!VCD_FAILED(rc) && ((event == VCD_EVT_RESP_INPUT_DONE ||
+ event == VCD_EVT_RESP_OUTPUT_DONE) ||
+ event == VCD_EVT_RESP_OUTPUT_REQ ||
+ event == VCD_EVT_IND_OUTPUT_RECONFIG)) {
+
+ if (payload &&
+ ((struct ddl_frame_data_tag *)\
+ payload)->frm_trans_end) {
+
+ vcd_mark_frame_channel(cctxt->dev_ctxt);
+ frm_trans_end = true;
+ }
+ if (frm_trans_end && !cctxt->status.frame_submitted) {
+ VCD_MSG_HIGH
+ ("All pending frames recvd from DDL");
+ vcd_flush_bframe_buffers(cctxt,
+ VCD_FLUSH_INPUT);
+ vcd_flush_output_buffers(cctxt);
+ cctxt->status.mask &= ~VCD_FLUSH_ALL;
+ vcd_release_all_clnt_frm_transc(cctxt);
+ VCD_MSG_HIGH
+ ("All buffers flushed. Enqueuing stop cmd");
+ vcd_client_cmd_flush_and_en_q(cctxt,
+ VCD_CMD_CODEC_STOP);
+ }
+ }
+}
+
+static void vcd_clnt_cb_in_pausing
+ (struct vcd_clnt_ctxt *cctxt,
+ u32 event,
+ u32 status,
+ void *payload, size_t sz, u32 *ddl_handle, void *const client_data)
+{
+ struct vcd_dev_ctxt *dev_ctxt = cctxt->dev_ctxt;
+ u32 rc = VCD_S_SUCCESS;
+ u32 frm_trans_end = false;
+
+ VCD_MSG_LOW("vcd_clnt_cb_in_pausing:");
+
+ if (cctxt->ddl_handle != ddl_handle) {
+ VCD_MSG_ERROR("ddl_handle mismatch");
+
+ return;
+ }
+
+ switch (event) {
+ case VCD_EVT_RESP_INPUT_DONE:
+ {
+ rc = vcd_handle_input_done(cctxt, payload, event,
+ status);
+
+ break;
+ }
+
+ case VCD_EVT_RESP_OUTPUT_DONE:
+ {
+ rc = vcd_handle_frame_done(cctxt, payload, event,
+ status);
+ break;
+ }
+ case VCD_EVT_RESP_OUTPUT_REQ:
+ {
+ rc = vcd_handle_output_required(cctxt, payload,
+ status);
+ break;
+ }
+ case VCD_EVT_IND_OUTPUT_RECONFIG:
+ {
+ rc = vcd_handle_ind_output_reconfig(cctxt,
+ payload, status);
+ if (!VCD_FAILED(rc)) {
+ frm_trans_end = true;
+ payload = NULL;
+ }
+ break;
+ }
+ case VCD_EVT_IND_HWERRFATAL:
+ {
+ vcd_handle_ind_hw_err_fatal(cctxt,
+ VCD_EVT_RESP_PAUSE, status);
+ rc = VCD_ERR_FAIL;
+ break;
+ }
+ default:
+ {
+ VCD_MSG_ERROR
+ ("Unexpected callback event=%d status=%d from DDL",
+ event, status);
+
+ dev_ctxt->command_continue = false;
+
+ break;
+ }
+
+ }
+
+ if (!VCD_FAILED(rc)) {
+
+ if (payload &&
+ ((struct ddl_frame_data_tag *)\
+ payload)->frm_trans_end) {
+
+ vcd_mark_frame_channel(cctxt->dev_ctxt);
+ frm_trans_end = true;
+ }
+ if (frm_trans_end && !cctxt->status.frame_submitted) {
+ VCD_MSG_HIGH
+ ("All pending frames recvd from DDL");
+
+ cctxt->callback(VCD_EVT_RESP_PAUSE,
+ VCD_S_SUCCESS,
+ NULL,
+ 0,
+ cctxt,
+ cctxt->client_data);
+
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_PAUSED,
+ CLIENT_STATE_EVENT_NUMBER
+ (clnt_cb));
+
+ rc = vcd_power_event(cctxt->dev_ctxt,
+ cctxt,
+ VCD_EVT_PWR_CLNT_PAUSE);
+
+ if (VCD_FAILED(rc)) {
+ VCD_MSG_ERROR
+ ("VCD_EVT_PWR_CLNT_PAUSE_END"
+ "failed");
+ }
+ }
+ }
+}
+
+static void vcd_clnt_cb_in_invalid(
+ struct vcd_clnt_ctxt *cctxt, u32 event, u32 status,
+ void *payload, size_t sz, u32 *ddl_handle,
+ void *const client_data
+)
+{
+ struct vcd_dev_ctxt *dev_ctxt = cctxt->dev_ctxt;
+ VCD_MSG_LOW("vcd_clnt_cb_in_invalid:");
+ if (cctxt->ddl_handle != ddl_handle) {
+ VCD_MSG_ERROR("ddl_handle mismatch");
+ return;
+ }
+ switch (event) {
+ case VCD_EVT_RESP_STOP:
+ {
+ vcd_handle_stop_done_in_invalid(cctxt,
+ (struct vcd_transc *)client_data,
+ status);
+ break;
+ }
+ case VCD_EVT_RESP_INPUT_DONE:
+ case VCD_EVT_RESP_OUTPUT_REQ:
+ {
+ if (cctxt->status.frame_submitted)
+ cctxt->status.frame_submitted--;
+ if (payload && ((struct ddl_frame_data_tag *)
+ payload)->frm_trans_end)
+ vcd_mark_frame_channel(cctxt->dev_ctxt);
+ break;
+ }
+ case VCD_EVT_RESP_OUTPUT_DONE:
+ {
+ if (payload && ((struct ddl_frame_data_tag *)
+ payload)->frm_trans_end)
+ vcd_mark_frame_channel(cctxt->dev_ctxt);
+ break;
+ }
+ case VCD_EVT_RESP_TRANSACTION_PENDING:
+ {
+ if (cctxt->status.frame_submitted)
+ cctxt->status.frame_submitted--;
+ vcd_mark_frame_channel(cctxt->dev_ctxt);
+ break;
+ }
+ case VCD_EVT_IND_HWERRFATAL:
+ {
+ if (status == VCD_ERR_HW_FATAL)
+ vcd_handle_stop_done_in_invalid(cctxt,
+ (struct vcd_transc *)client_data,
+ status);
+
+ break;
+ }
+ case VCD_EVT_RESP_EOS_DONE:
+ {
+ vcd_mark_frame_channel(cctxt->dev_ctxt);
+ break;
+ }
+ case VCD_EVT_IND_OUTPUT_RECONFIG:
+ {
+ if (cctxt->status.frame_submitted > 0)
+ cctxt->status.frame_submitted--;
+ else
+ cctxt->status.frame_delayed--;
+ vcd_mark_frame_channel(cctxt->dev_ctxt);
+ break;
+ }
+ default:
+ {
+ VCD_MSG_ERROR("Unexpected callback event=%d status=%d"
+ "from DDL", event, status);
+ dev_ctxt->command_continue = false;
+ break;
+ }
+ }
+}
+
+static void vcd_clnt_enter_open
+ (struct vcd_clnt_ctxt *cctxt, s32 state_event) {
+ VCD_MSG_MED("Entering CLIENT_STATE_OPEN on api %d", state_event);
+}
+
+static void vcd_clnt_enter_starting
+ (struct vcd_clnt_ctxt *cctxt, s32 state_event) {
+ VCD_MSG_MED("Entering CLIENT_STATE_STARTING on api %d",
+ state_event);
+ cctxt->status.last_evt = VCD_EVT_RESP_START;
+}
+
+static void vcd_clnt_enter_run
+ (struct vcd_clnt_ctxt *cctxt, s32 state_event) {
+ VCD_MSG_MED("Entering CLIENT_STATE_RUN on api %d", state_event);
+}
+
+static void vcd_clnt_enter_flushing
+ (struct vcd_clnt_ctxt *cctxt, s32 state_event) {
+ VCD_MSG_MED("Entering CLIENT_STATE_FLUSHING on api %d",
+ state_event);
+}
+
+static void vcd_clnt_enter_stopping
+ (struct vcd_clnt_ctxt *cctxt, s32 state_event) {
+ VCD_MSG_MED("Entering CLIENT_STATE_STOPPING on api %d",
+ state_event);
+ cctxt->status.last_evt = VCD_EVT_RESP_STOP;
+}
+
+static void vcd_clnt_enter_eos(struct vcd_clnt_ctxt *cctxt,
+ s32 state_event)
+{
+ u32 rc;
+ VCD_MSG_MED("Entering CLIENT_STATE_EOS on api %d", state_event);
+ rc = vcd_sched_suspend_resume_clnt(cctxt, false);
+ if (VCD_FAILED(rc))
+ VCD_MSG_ERROR("Failed: vcd_sched_suspend_resume_clnt."
+ "rc=0x%x", rc);
+}
+
+static void vcd_clnt_enter_pausing
+ (struct vcd_clnt_ctxt *cctxt, s32 state_event) {
+ VCD_MSG_MED("Entering CLIENT_STATE_PAUSING on api %d",
+ state_event);
+ cctxt->status.last_evt = VCD_EVT_RESP_PAUSE;
+}
+
+static void vcd_clnt_enter_paused
+ (struct vcd_clnt_ctxt *cctxt, s32 state_event)
+{
+ VCD_MSG_MED("Entering CLIENT_STATE_PAUSED on api %d",
+ state_event);
+}
+
+static void vcd_clnt_enter_invalid(struct vcd_clnt_ctxt *cctxt,
+ s32 state_event)
+{
+ VCD_MSG_MED("Entering CLIENT_STATE_INVALID on api %d",
+ state_event);
+ cctxt->ddl_hdl_valid = false;
+ cctxt->status.mask &= ~(VCD_FIRST_IP_RCVD | VCD_FIRST_OP_RCVD);
+ if (cctxt->sched_clnt_hdl)
+ vcd_sched_suspend_resume_clnt(cctxt, false);
+}
+
+static void vcd_clnt_exit_open
+ (struct vcd_clnt_ctxt *cctxt, s32 state_event)
+{
+ VCD_MSG_MED("Exiting CLIENT_STATE_OPEN on api %d", state_event);
+}
+
+static void vcd_clnt_exit_starting
+ (struct vcd_clnt_ctxt *cctxt, s32 state_event) {
+ VCD_MSG_MED("Exiting CLIENT_STATE_STARTING on api %d",
+ state_event);
+ cctxt->status.last_evt = VCD_EVT_RESP_BASE;
+}
+
+static void vcd_clnt_exit_run
+ (struct vcd_clnt_ctxt *cctxt, s32 state_event) {
+ VCD_MSG_MED("Exiting CLIENT_STATE_RUN on api %d", state_event);
+}
+
+static void vcd_clnt_exit_flushing
+ (struct vcd_clnt_ctxt *cctxt, s32 state_event) {
+ VCD_MSG_MED("Exiting CLIENT_STATE_FLUSHING on api %d",
+ state_event);
+}
+
+static void vcd_clnt_exit_stopping
+ (struct vcd_clnt_ctxt *cctxt, s32 state_event) {
+ VCD_MSG_MED("Exiting CLIENT_STATE_STOPPING on api %d",
+ state_event);
+ cctxt->status.last_evt = VCD_EVT_RESP_BASE;
+}
+
+static void vcd_clnt_exit_eos
+ (struct vcd_clnt_ctxt *cctxt, s32 state_event)
+{
+ u32 rc;
+ VCD_MSG_MED("Exiting CLIENT_STATE_EOS on api %d", state_event);
+ rc = vcd_sched_suspend_resume_clnt(cctxt, true);
+ if (VCD_FAILED(rc))
+ VCD_MSG_ERROR("Failed: vcd_sched_suspend_resume_clnt. rc=0x%x",
+ rc);
+}
+
+static void vcd_clnt_exit_pausing
+ (struct vcd_clnt_ctxt *cctxt, s32 state_event) {
+ VCD_MSG_MED("Exiting CLIENT_STATE_PAUSING on api %d",
+ state_event);
+ cctxt->status.last_evt = VCD_EVT_RESP_BASE;
+}
+
+static void vcd_clnt_exit_paused
+ (struct vcd_clnt_ctxt *cctxt, s32 state_event) {
+ VCD_MSG_MED("Exiting CLIENT_STATE_PAUSED on api %d",
+ state_event);
+}
+
+static void vcd_clnt_exit_invalid(struct vcd_clnt_ctxt *cctxt,
+ s32 state_event)
+{
+ VCD_MSG_MED("Exiting CLIENT_STATE_INVALID on api %d",
+ state_event);
+}
+
+void vcd_do_client_state_transition(struct vcd_clnt_ctxt *cctxt,
+ enum vcd_clnt_state_enum to_state, u32 ev_code)
+{
+ struct vcd_clnt_state_ctxt *state_ctxt;
+
+ if (!cctxt || to_state >= VCD_CLIENT_STATE_MAX) {
+ VCD_MSG_ERROR("Bad parameters. cctxt=%p, to_state=%d",
+ cctxt, to_state);
+ }
+
+ state_ctxt = &cctxt->clnt_state;
+
+ if (state_ctxt->state == to_state) {
+ VCD_MSG_HIGH("Client already in requested to_state=%d",
+ to_state);
+
+ return;
+ }
+
+ VCD_MSG_MED("vcd_do_client_state_transition: C%d -> C%d, for api %d",
+ (int)state_ctxt->state, (int)to_state, ev_code);
+
+ if (state_ctxt->state_table->exit)
+ state_ctxt->state_table->exit(cctxt, ev_code);
+
+
+ state_ctxt->state = to_state;
+ state_ctxt->state_table = vcd_clnt_state_table[to_state];
+
+ if (state_ctxt->state_table->entry)
+ state_ctxt->state_table->entry(cctxt, ev_code);
+}
+
+const struct vcd_clnt_state_table *vcd_get_client_state_table
+ (enum vcd_clnt_state_enum state) {
+ return vcd_clnt_state_table[state];
+}
+
+static const struct vcd_clnt_state_table vcd_clnt_table_open = {
+ {
+ vcd_close_in_open,
+ vcd_encode_start_in_open,
+ NULL,
+ vcd_decode_start_in_open,
+ NULL,
+ NULL,
+ NULL,
+ vcd_flush_inopen,
+ vcd_stop_inopen,
+ vcd_set_property_cmn,
+ vcd_get_property_cmn,
+ vcd_set_buffer_requirements_cmn,
+ vcd_get_buffer_requirements_cmn,
+ vcd_set_buffer_cmn,
+ vcd_allocate_buffer_cmn,
+ vcd_free_buffer_cmn,
+ vcd_fill_output_buffer_cmn,
+ NULL,
+ },
+ vcd_clnt_enter_open,
+ vcd_clnt_exit_open
+};
+
+static const struct vcd_clnt_state_table vcd_clnt_table_starting = {
+ {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ vcd_get_property_cmn,
+ NULL,
+ vcd_get_buffer_requirements_cmn,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ vcd_clnt_cb_in_starting,
+ },
+ vcd_clnt_enter_starting,
+ vcd_clnt_exit_starting
+};
+
+static const struct vcd_clnt_state_table vcd_clnt_table_run = {
+ {
+ NULL,
+ vcd_encode_start_in_run,
+ vcd_encode_frame_cmn,
+ vcd_decode_start_in_run,
+ vcd_decode_frame_cmn,
+ vcd_pause_in_run,
+ NULL,
+ vcd_flush_cmn,
+ vcd_stop_in_run,
+ vcd_set_property_cmn,
+ vcd_get_property_cmn,
+ vcd_set_buffer_requirements_cmn,
+ vcd_get_buffer_requirements_cmn,
+ vcd_set_buffer_cmn,
+ vcd_allocate_buffer_cmn,
+ vcd_free_buffer_cmn,
+ vcd_fill_output_buffer_cmn,
+ vcd_clnt_cb_in_run,
+ },
+ vcd_clnt_enter_run,
+ vcd_clnt_exit_run
+};
+
+static const struct vcd_clnt_state_table vcd_clnt_table_flushing = {
+ {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ vcd_flush_in_flushing,
+ NULL,
+ vcd_set_property_cmn,
+ vcd_get_property_cmn,
+ NULL,
+ vcd_get_buffer_requirements_cmn,
+ NULL,
+ NULL,
+ NULL,
+ vcd_fill_output_buffer_cmn,
+ vcd_clnt_cb_in_flushing,
+ },
+ vcd_clnt_enter_flushing,
+ vcd_clnt_exit_flushing
+};
+
+static const struct vcd_clnt_state_table vcd_clnt_table_stopping = {
+ {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ vcd_get_property_cmn,
+ NULL,
+ vcd_get_buffer_requirements_cmn,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ vcd_clnt_cb_in_stopping,
+ },
+ vcd_clnt_enter_stopping,
+ vcd_clnt_exit_stopping
+};
+
+static const struct vcd_clnt_state_table vcd_clnt_table_eos = {
+ {
+ NULL,
+ NULL,
+ vcd_encode_frame_cmn,
+ NULL,
+ vcd_decode_frame_cmn,
+ NULL,
+ NULL,
+ vcd_flush_in_eos,
+ vcd_stop_in_eos,
+ NULL,
+ vcd_get_property_cmn,
+ NULL,
+ vcd_get_buffer_requirements_cmn,
+ NULL,
+ NULL,
+ NULL,
+ vcd_fill_output_buffer_in_eos,
+ vcd_clnt_cb_in_eos,
+ },
+ vcd_clnt_enter_eos,
+ vcd_clnt_exit_eos
+};
+
+static const struct vcd_clnt_state_table vcd_clnt_table_pausing = {
+ {
+ NULL,
+ NULL,
+ vcd_encode_frame_cmn,
+ NULL,
+ vcd_decode_frame_cmn,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ vcd_set_property_cmn,
+ vcd_get_property_cmn,
+ NULL,
+ vcd_get_buffer_requirements_cmn,
+ NULL,
+ NULL,
+ NULL,
+ vcd_fill_output_buffer_cmn,
+ vcd_clnt_cb_in_pausing,
+ },
+ vcd_clnt_enter_pausing,
+ vcd_clnt_exit_pausing
+};
+
+static const struct vcd_clnt_state_table vcd_clnt_table_paused = {
+ {
+ NULL,
+ NULL,
+ vcd_encode_frame_cmn,
+ NULL,
+ vcd_decode_frame_cmn,
+ NULL,
+ vcd_resume_in_paused,
+ vcd_flush_cmn,
+ vcd_stop_cmn,
+ vcd_set_property_cmn,
+ vcd_get_property_cmn,
+ vcd_set_buffer_requirements_cmn,
+ vcd_get_buffer_requirements_cmn,
+ vcd_set_buffer_cmn,
+ vcd_allocate_buffer_cmn,
+ NULL,
+ vcd_fill_output_buffer_cmn,
+ NULL,
+ },
+ vcd_clnt_enter_paused,
+ vcd_clnt_exit_paused
+};
+static const struct vcd_clnt_state_table vcd_clnt_table_invalid = {
+ {
+ vcd_close_in_invalid,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ vcd_flush_in_invalid,
+ vcd_stop_in_invalid,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ vcd_free_buffer_cmn,
+ NULL,
+ vcd_clnt_cb_in_invalid,
+ },
+ vcd_clnt_enter_invalid,
+ vcd_clnt_exit_invalid
+};
+
+static const struct vcd_clnt_state_table *vcd_clnt_state_table[] = {
+ NULL,
+ &vcd_clnt_table_open,
+ &vcd_clnt_table_starting,
+ &vcd_clnt_table_run,
+ &vcd_clnt_table_flushing,
+ &vcd_clnt_table_pausing,
+ &vcd_clnt_table_paused,
+ &vcd_clnt_table_stopping,
+ &vcd_clnt_table_eos,
+ &vcd_clnt_table_invalid
+};
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.h b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.h
new file mode 100644
index 0000000..e9ab41c
--- /dev/null
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.h
@@ -0,0 +1,110 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _VCD_CLIENT_SM_H_
+#define _VCD_CLIENT_SM_H_
+#include "vcd_api.h"
+#include "vcd_ddl_api.h"
+
+struct vcd_clnt_state_table;
+struct vcd_clnt_state_ctxt;
+struct vcd_clnt_ctxt;
+
+enum vcd_clnt_state_enum {
+ VCD_CLIENT_STATE_NULL = 0,
+ VCD_CLIENT_STATE_OPEN,
+ VCD_CLIENT_STATE_STARTING,
+ VCD_CLIENT_STATE_RUN,
+ VCD_CLIENT_STATE_FLUSHING,
+ VCD_CLIENT_STATE_PAUSING,
+ VCD_CLIENT_STATE_PAUSED,
+ VCD_CLIENT_STATE_STOPPING,
+ VCD_CLIENT_STATE_EOS,
+ VCD_CLIENT_STATE_INVALID,
+ VCD_CLIENT_STATE_MAX,
+ VCD_CLIENT_STATE_32BIT = 0x7FFFFFFF
+};
+
+#define CLIENT_STATE_EVENT_NUMBER(ppf) \
+ ((u32 *) (&(((struct vcd_clnt_state_table*)0)->ev_hdlr.ppf)) - \
+ (u32 *) (&(((struct vcd_clnt_state_table*)0)->ev_hdlr.close)) \
+ + 1)
+
+struct vcd_clnt_state_table {
+ struct {
+ u32(*close) (struct vcd_clnt_ctxt *cctxt);
+ u32(*encode_start) (struct vcd_clnt_ctxt *cctxt);
+ u32(*encode_frame) (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *input_frame);
+ u32(*decode_start) (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_sequence_hdr *seq_hdr);
+ u32(*decode_frame) (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *input_frame);
+ u32(*pause) (struct vcd_clnt_ctxt *cctxt);
+ u32(*resume) (struct vcd_clnt_ctxt *cctxt);
+ u32(*flush) (struct vcd_clnt_ctxt *cctxt,
+ u32 mode);
+ u32(*stop) (struct vcd_clnt_ctxt *cctxt);
+ u32(*set_property) (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_property_hdr *prop_hdr,
+ void *prop);
+ u32(*get_property) (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_property_hdr *prop_hdr,
+ void *prop);
+ u32(*set_buffer_requirements) (struct vcd_clnt_ctxt *
+ cctxt,
+ enum vcd_buffer_type buffer,
+ struct
+ vcd_buffer_requirement *
+ buffer_req);
+ u32(*get_buffer_requirements) (struct vcd_clnt_ctxt *
+ cctxt,
+ enum vcd_buffer_type buffer,
+ struct
+ vcd_buffer_requirement *
+ buffer_req);
+ u32(*set_buffer) (struct vcd_clnt_ctxt *cctxt,
+ enum vcd_buffer_type buffer_type, u8 *buffer,
+ u32 buf_size);
+ u32(*allocate_buffer) (struct vcd_clnt_ctxt *cctxt,
+ enum vcd_buffer_type buffer, u32 buf_size,
+ u8 **vir_buf_addr, u8 **phy_buf_addr);
+ u32(*free_buffer) (struct vcd_clnt_ctxt *cctxt,
+ enum vcd_buffer_type buffer_type, u8 *buffer);
+ u32(*fill_output_buffer) (
+ struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *buffer);
+ void (*clnt_cb) (struct vcd_clnt_ctxt *cctxt,
+ u32 event, u32 status, void *payload,
+ size_t sz, u32 *ddl_handle,
+ void *const client_data);
+ } ev_hdlr;
+
+ void (*entry) (struct vcd_clnt_ctxt *cctxt,
+ s32 state_event);
+ void (*exit) (struct vcd_clnt_ctxt *cctxt,
+ s32 state_event);
+};
+
+struct vcd_clnt_state_ctxt {
+ const struct vcd_clnt_state_table *state_table;
+ enum vcd_clnt_state_enum state;
+};
+
+extern void vcd_do_client_state_transition
+ (struct vcd_clnt_ctxt *cctxt,
+ enum vcd_clnt_state_enum to_state, u32 ev_code);
+
+extern const struct vcd_clnt_state_table *vcd_get_client_state_table(
+ enum vcd_clnt_state_enum state);
+
+#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_core.h b/drivers/video/msm/vidc/common/vcd/vcd_core.h
new file mode 100644
index 0000000..e681feb
--- /dev/null
+++ b/drivers/video/msm/vidc/common/vcd/vcd_core.h
@@ -0,0 +1,220 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _VCD_CORE_H_
+#define _VCD_CORE_H_
+
+#include "vcd_api.h"
+#include "vcd_ddl_api.h"
+
+#include "vcd_util.h"
+#include "vcd_client_sm.h"
+#include "vcd_power_sm.h"
+
+#define VCD_SIGNATURE 0x75017591U
+
+#define VCD_MIN_PERF_LEVEL 37900
+
+#define VCD_DRIVER_INSTANCE_MAX 4
+
+#define VCD_MAX_CLIENT_TRANSACTIONS 32
+
+#define VCD_MAX_BUFFER_ENTRIES 32
+
+#define VCD_SEQ_HDR_PADDING_BYTES 256
+
+#define VCD_DEC_NUM_INTERLACED_FIELDS 2
+
+#define VCD_TIMESTAMP_RESOLUTION 1000000
+#define VCD_DEC_INITIAL_FRAME_RATE 30
+
+#define VCD_FIRST_IP_RCVD 0x00000004
+#define VCD_FIRST_OP_RCVD 0x00000008
+#define VCD_EOS_PREV_VALID 0x00000010
+#define VCD_EOS_WAIT_OP_BUF 0x00000020
+#define VCD_CLEANING_UP 0x00000040
+#define VCD_STOP_PENDING 0x00000080
+#define VCD_CLOSE_PENDING 0x00000100
+#define VCD_IN_RECONFIG 0x00000200
+#define VCD_FIRST_IP_DONE 0x00000400
+
+enum vcd_command {
+ VCD_CMD_NONE,
+ VCD_CMD_DEVICE_INIT,
+ VCD_CMD_DEVICE_TERM,
+ VCD_CMD_DEVICE_RESET,
+ VCD_CMD_CODEC_START,
+ VCD_CMD_CODEC_STOP,
+ VCD_CMD_CODE_FRAME,
+ VCD_CMD_OUTPUT_FLUSH,
+ VCD_CMD_CLIENT_CLOSE
+};
+
+enum vcd_core_type {
+ VCD_CORE_1080P,
+ VCD_CORE_720P
+};
+
+struct vcd_cmd_q_element {
+ enum vcd_command pending_cmd;
+};
+
+struct vcd_buffer_entry {
+ struct list_head sched_list;
+ struct list_head list;
+ u32 valid;
+ u8 *alloc;
+ u8 *virtual;
+ u8 *physical;
+ size_t sz;
+ u32 allocated;
+ u32 in_use;
+ struct vcd_frame_data frame;
+
+};
+
+struct vcd_buffer_pool {
+ struct vcd_buffer_entry *entries;
+ u32 count;
+ struct vcd_buffer_requirement buf_req;
+ u32 validated;
+ u32 allocated;
+ u32 in_use;
+ struct list_head queue;
+ u16 q_len;
+};
+
+struct vcd_transc {
+ u32 in_use;
+ enum vcd_command type;
+ struct vcd_clnt_ctxt *cctxt;
+
+ struct vcd_buffer_entry *ip_buf_entry;
+
+ s64 time_stamp;
+ u32 ip_frm_tag;
+ enum vcd_frame frame;
+
+ struct vcd_buffer_entry *op_buf_entry;
+
+ u32 input_done;
+ u32 frame_done;
+};
+
+struct vcd_dev_ctxt {
+ u32 ddl_cmd_concurrency;
+ u32 ddl_frame_ch_depth;
+ u32 ddl_cmd_ch_depth;
+ u32 ddl_frame_ch_interim;
+ u32 ddl_cmd_ch_interim;
+ u32 ddl_frame_ch_free;
+ u32 ddl_cmd_ch_free;
+
+ struct list_head sched_clnt_list;
+
+ struct vcd_init_config config;
+
+ u32 driver_ids[VCD_DRIVER_INSTANCE_MAX];
+ u32 refs;
+ u8 *device_base_addr;
+ void *hw_timer_handle;
+ u32 hw_time_out;
+ struct vcd_clnt_ctxt *cctxt_list_head;
+
+ enum vcd_command pending_cmd;
+
+ u32 command_continue;
+
+ struct vcd_transc *trans_tbl;
+ u32 trans_tbl_size;
+
+ enum vcd_power_state pwr_state;
+ enum vcd_pwr_clk_state pwr_clk_state;
+ u32 active_clnts;
+ u32 max_perf_lvl;
+ u32 reqd_perf_lvl;
+ u32 curr_perf_lvl;
+ u32 set_perf_lvl_pending;
+
+};
+
+struct vcd_clnt_status {
+ u32 req_perf_lvl;
+ u32 frame_submitted;
+ u32 frame_delayed;
+ u32 cmd_submitted;
+ u32 int_field_cnt;
+ s64 first_ts;
+ s64 prev_ts;
+ u64 time_elapsed;
+ struct vcd_frame_data eos_trig_ip_frm;
+ struct ddl_frame_data_tag eos_prev_op_frm;
+ u32 eos_prev_op_frm_status;
+ u32 last_err;
+ u32 last_evt;
+ u32 mask;
+};
+
+struct vcd_sched_clnt_ctx {
+ struct list_head list;
+ u32 clnt_active;
+ void *clnt_data;
+ u32 tkns;
+ u32 round_perfrm;
+ u32 rounds;
+ struct list_head ip_frm_list;
+};
+
+struct vcd_clnt_ctxt {
+ u32 signature;
+ struct vcd_clnt_state_ctxt clnt_state;
+
+ s32 driver_id;
+
+ u32 live;
+ u32 decoding;
+ u32 bframe;
+
+ struct vcd_property_frame_rate frm_rate;
+ u32 frm_p_units;
+ u32 reqd_perf_lvl;
+ u32 time_resoln;
+
+ struct vcd_buffer_pool in_buf_pool;
+ struct vcd_buffer_pool out_buf_pool;
+
+ void (*callback) (u32 event, u32 status, void *info, size_t sz,
+ void *handle, void *const client_data);
+ void *client_data;
+ struct vcd_sched_clnt_ctx *sched_clnt_hdl;
+ u32 ddl_hdl_valid;
+ u32 *ddl_handle;
+ struct vcd_dev_ctxt *dev_ctxt;
+ struct vcd_cmd_q_element cmd_q;
+ struct vcd_sequence_hdr seq_hdr;
+ u8 *seq_hdr_phy_addr;
+ struct vcd_clnt_status status;
+
+ struct vcd_clnt_ctxt *next;
+};
+
+#define VCD_BUFFERPOOL_INUSE_DECREMENT(val) \
+do { \
+ if ((val) > 0) \
+ val--; \
+ else { \
+ VCD_MSG_ERROR("%s(): Inconsistent val given in " \
+ " VCD_BUFFERPOOL_INUSE_DECREMENT\n", __func__); \
+ } \
+} while (0)
+
+#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
new file mode 100644
index 0000000..f8fb0fa
--- /dev/null
+++ b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
@@ -0,0 +1,1203 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "vidc_type.h"
+#include "vcd.h"
+
+static const struct vcd_dev_state_table *vcd_dev_state_table[];
+static const struct vcd_dev_state_table vcd_dev_table_null;
+
+struct vcd_drv_ctxt *vcd_get_drv_context(void)
+{
+ static struct vcd_drv_ctxt drv_context = {
+ {&vcd_dev_table_null, VCD_DEVICE_STATE_NULL},
+ {0},
+ };
+
+ return &drv_context;
+
+}
+
+void vcd_do_device_state_transition(struct vcd_drv_ctxt *drv_ctxt,
+ enum vcd_dev_state_enum to_state, u32 ev_code)
+{
+ struct vcd_dev_state_ctxt *state_ctxt;
+
+ if (!drv_ctxt || to_state >= VCD_DEVICE_STATE_MAX) {
+ VCD_MSG_ERROR("Bad parameters. drv_ctxt=%p, to_state=%d",
+ drv_ctxt, to_state);
+ }
+
+ state_ctxt = &drv_ctxt->dev_state;
+
+ if (state_ctxt->state == to_state) {
+ VCD_MSG_HIGH("Device already in requested to_state=%d",
+ to_state);
+
+ return;
+ }
+
+ VCD_MSG_MED("vcd_do_device_state_transition: D%d -> D%d, for api %d",
+ (int)state_ctxt->state, (int)to_state, ev_code);
+
+ if (state_ctxt->state_table->exit)
+ state_ctxt->state_table->exit(drv_ctxt, ev_code);
+
+
+ state_ctxt->state = to_state;
+ state_ctxt->state_table = vcd_dev_state_table[to_state];
+
+ if (state_ctxt->state_table->entry)
+ state_ctxt->state_table->entry(drv_ctxt, ev_code);
+}
+
+void vcd_hw_timeout_handler(void *user_data)
+{
+ struct vcd_drv_ctxt *drv_ctxt;
+
+ VCD_MSG_HIGH("vcd_hw_timeout_handler:");
+ user_data = NULL;
+ drv_ctxt = vcd_get_drv_context();
+ mutex_lock(&drv_ctxt->dev_mutex);
+ if (drv_ctxt->dev_state.state_table->ev_hdlr.timeout)
+ drv_ctxt->dev_state.state_table->ev_hdlr.
+ timeout(drv_ctxt, user_data);
+ else
+ VCD_MSG_ERROR("hw_timeout unsupported in device state %d",
+ drv_ctxt->dev_state.state);
+ mutex_unlock(&drv_ctxt->dev_mutex);
+}
+
+void vcd_ddl_callback(u32 event, u32 status, void *payload,
+ size_t sz, u32 *ddl_handle, void *const client_data)
+{
+ struct vcd_drv_ctxt *drv_ctxt;
+ struct vcd_dev_ctxt *dev_ctxt;
+ struct vcd_dev_state_ctxt *dev_state;
+ struct vcd_clnt_ctxt *cctxt;
+ struct vcd_transc *transc;
+
+ VCD_MSG_LOW("vcd_ddl_callback:");
+
+ VCD_MSG_LOW("event=0x%x status=0x%x", event, status);
+
+ drv_ctxt = vcd_get_drv_context();
+ dev_ctxt = &drv_ctxt->dev_ctxt;
+ dev_state = &drv_ctxt->dev_state;
+
+ dev_ctxt->command_continue = true;
+ vcd_device_timer_stop(dev_ctxt);
+
+ switch (dev_state->state) {
+ case VCD_DEVICE_STATE_NULL:
+ {
+ VCD_MSG_HIGH("Callback unexpected in NULL state");
+ break;
+ }
+
+ case VCD_DEVICE_STATE_NOT_INIT:
+ {
+ VCD_MSG_HIGH("Callback unexpected in NOT_INIT state");
+ break;
+ }
+
+ case VCD_DEVICE_STATE_INITING:
+ {
+ if (dev_state->state_table->ev_hdlr.dev_cb) {
+ dev_state->state_table->ev_hdlr.
+ dev_cb(drv_ctxt, event, status,
+ payload, sz, ddl_handle,
+ client_data);
+ } else {
+ VCD_MSG_HIGH("No device handler in %d state",
+ dev_state->state);
+ }
+ break;
+ }
+
+ case VCD_DEVICE_STATE_READY:
+ {
+ transc = (struct vcd_transc *)client_data;
+
+ if (!transc || !transc->in_use
+ || !transc->cctxt) {
+ VCD_MSG_ERROR("Invalid clientdata "
+ "received from DDL ");
+ } else {
+ cctxt = transc->cctxt;
+
+ if (cctxt->clnt_state.state_table->ev_hdlr.
+ clnt_cb) {
+ cctxt->clnt_state.state_table->
+ ev_hdlr.clnt_cb(cctxt,
+ event, status, payload,
+ sz, ddl_handle,
+ client_data);
+ } else {
+ VCD_MSG_HIGH
+ ("No client handler in"
+ " (dsm:READY, csm:%d) state",
+ (int)cctxt->clnt_state.state);
+
+ if (VCD_FAILED(status)) {
+ VCD_MSG_FATAL("DDL callback"
+ " returned failure 0x%x",
+ status);
+ }
+ }
+ }
+ break;
+ }
+
+ default:
+ {
+ VCD_MSG_ERROR("Unknown state");
+ break;
+ }
+
+ }
+
+}
+
+u32 vcd_init_device_context(struct vcd_drv_ctxt *drv_ctxt,
+ u32 ev_code)
+{
+ struct vcd_dev_ctxt *dev_ctxt = &drv_ctxt->dev_ctxt;
+ u32 rc;
+ struct ddl_init_config ddl_init;
+
+ VCD_MSG_LOW("vcd_init_device_context:");
+
+ dev_ctxt->pending_cmd = VCD_CMD_NONE;
+
+ rc = vcd_power_event(dev_ctxt, NULL, VCD_EVT_PWR_DEV_INIT_BEGIN);
+ VCD_FAILED_RETURN(rc, "VCD_EVT_PWR_DEV_INIT_BEGIN failed");
+
+ VCD_MSG_HIGH("Device powered ON and clocked");
+ rc = vcd_sched_create(&dev_ctxt->sched_clnt_list);
+ if (VCD_FAILED(rc)) {
+ VCD_MSG_ERROR("rc = 0x%x. Failed: vcd_sched_create", rc);
+
+ (void)vcd_power_event(dev_ctxt, NULL,
+ VCD_EVT_PWR_DEV_INIT_FAIL);
+
+ return rc;
+ }
+
+ VCD_MSG_HIGH("Created scheduler instance.");
+
+ ddl_init.core_virtual_base_addr = dev_ctxt->device_base_addr;
+ ddl_init.interrupt_clr = dev_ctxt->config.interrupt_clr;
+ ddl_init.ddl_callback = vcd_ddl_callback;
+
+ rc = ddl_device_init(&ddl_init, NULL);
+
+ if (VCD_FAILED(rc)) {
+ VCD_MSG_ERROR("rc = 0x%x. Failed: ddl_device_init", rc);
+ vcd_sched_destroy(&dev_ctxt->sched_clnt_list);
+ (void)vcd_power_event(dev_ctxt, NULL,
+ VCD_EVT_PWR_DEV_INIT_FAIL);
+ } else {
+ vcd_device_timer_start(dev_ctxt);
+ vcd_do_device_state_transition(drv_ctxt,
+ VCD_DEVICE_STATE_INITING,
+ ev_code);
+ }
+
+ return rc;
+}
+
+void vcd_handle_device_init_failed(struct vcd_drv_ctxt *drv_ctxt,
+ u32 status)
+{
+ struct vcd_clnt_ctxt *client;
+ struct vcd_clnt_ctxt *tmp_client;
+
+ VCD_MSG_ERROR("Device init failed. status = %d", status);
+
+ client = drv_ctxt->dev_ctxt.cctxt_list_head;
+ while (client) {
+ client->callback(VCD_EVT_RESP_OPEN,
+ status, NULL, 0, 0, client->client_data);
+
+ tmp_client = client;
+ client = client->next;
+
+ vcd_destroy_client_context(tmp_client);
+ }
+ if (ddl_device_release(NULL))
+ VCD_MSG_ERROR("Failed: ddl_device_release");
+
+ vcd_sched_destroy(&drv_ctxt->dev_ctxt.sched_clnt_list);
+ if (vcd_power_event(&drv_ctxt->dev_ctxt,
+ NULL, VCD_EVT_PWR_DEV_INIT_FAIL))
+ VCD_MSG_ERROR("VCD_EVT_PWR_DEV_INIT_FAIL failed");
+
+ vcd_do_device_state_transition(drv_ctxt,
+ VCD_DEVICE_STATE_NOT_INIT,
+ DEVICE_STATE_EVENT_NUMBER(dev_cb));
+}
+
+u32 vcd_deinit_device_context(struct vcd_drv_ctxt *drv_ctxt,
+ u32 ev_code)
+{
+ struct vcd_dev_ctxt *dev_ctxt = &drv_ctxt->dev_ctxt;
+ u32 rc = VCD_S_SUCCESS;
+
+ VCD_MSG_LOW("vcd_deinit_device_context:");
+
+ rc = vcd_power_event(&drv_ctxt->dev_ctxt, NULL,
+ VCD_EVT_PWR_DEV_TERM_BEGIN);
+
+ VCD_FAILED_RETURN(rc, "VCD_EVT_PWR_DEV_TERM_BEGIN failed");
+
+ rc = ddl_device_release(NULL);
+
+ if (VCD_FAILED(rc)) {
+ VCD_MSG_ERROR("rc = 0x%x. Failed: ddl_device_release", rc);
+
+ (void)vcd_power_event(dev_ctxt, NULL,
+ VCD_EVT_PWR_DEV_TERM_FAIL);
+ } else {
+ vcd_sched_destroy(&dev_ctxt->sched_clnt_list);
+ (void) vcd_power_event(dev_ctxt, NULL,
+ VCD_EVT_PWR_DEV_TERM_END);
+
+ vcd_do_device_state_transition(drv_ctxt,
+ VCD_DEVICE_STATE_NOT_INIT, ev_code);
+ }
+ return rc;
+}
+
+void vcd_term_driver_context(struct vcd_drv_ctxt *drv_ctxt)
+{
+ struct vcd_dev_ctxt *dev_ctxt = &drv_ctxt->dev_ctxt;
+
+ VCD_MSG_HIGH("All driver instances terminated");
+
+ if (dev_ctxt->config.deregister_isr)
+ dev_ctxt->config.deregister_isr();
+
+ if (dev_ctxt->config.un_map_dev_base_addr)
+ dev_ctxt->config.un_map_dev_base_addr();
+
+ if (dev_ctxt->config.timer_release)
+ dev_ctxt->config.timer_release(
+ dev_ctxt->hw_timer_handle);
+
+ kfree(dev_ctxt->trans_tbl);
+
+ memset(dev_ctxt, 0, sizeof(struct vcd_dev_ctxt));
+
+ vcd_do_device_state_transition(drv_ctxt,
+ VCD_DEVICE_STATE_NULL,
+ DEVICE_STATE_EVENT_NUMBER(term));
+
+}
+
+u32 vcd_reset_device_context(struct vcd_drv_ctxt *drv_ctxt,
+ u32 ev_code)
+{
+ struct vcd_dev_ctxt *dev_ctxt = &drv_ctxt->dev_ctxt;
+ u32 rc = VCD_S_SUCCESS;
+
+ VCD_MSG_LOW("vcd_reset_device_context:");
+ vcd_reset_device_channels(dev_ctxt);
+ rc = vcd_power_event(&drv_ctxt->dev_ctxt, NULL,
+ VCD_EVT_PWR_DEV_TERM_BEGIN);
+ VCD_FAILED_RETURN(rc, "VCD_EVT_PWR_DEV_TERM_BEGIN failed");
+ if (ddl_reset_hw(0))
+ VCD_MSG_HIGH("HW Reset done");
+ else
+ VCD_MSG_FATAL("HW Reset failed");
+
+ (void)vcd_power_event(dev_ctxt, NULL, VCD_EVT_PWR_DEV_TERM_END);
+
+ return VCD_S_SUCCESS;
+}
+
+void vcd_handle_device_err_fatal(struct vcd_dev_ctxt *dev_ctxt,
+ struct vcd_clnt_ctxt *trig_clnt)
+{
+ struct vcd_clnt_ctxt *cctxt = dev_ctxt->cctxt_list_head;
+ struct vcd_clnt_ctxt *tmp_clnt = NULL;
+ VCD_MSG_LOW("vcd_handle_device_err_fatal:");
+ while (cctxt) {
+ tmp_clnt = cctxt;
+ cctxt = cctxt->next;
+ if (tmp_clnt != trig_clnt)
+ vcd_clnt_handle_device_err_fatal(tmp_clnt,
+ tmp_clnt->status.last_evt);
+ }
+ dev_ctxt->pending_cmd = VCD_CMD_DEVICE_RESET;
+ if (!dev_ctxt->cctxt_list_head)
+ vcd_do_device_state_transition(vcd_get_drv_context(),
+ VCD_DEVICE_STATE_NOT_INIT,
+ DEVICE_STATE_EVENT_NUMBER(timeout));
+ else
+ vcd_do_device_state_transition(vcd_get_drv_context(),
+ VCD_DEVICE_STATE_INVALID,
+ DEVICE_STATE_EVENT_NUMBER(dev_cb));
+}
+
+void vcd_handle_for_last_clnt_close(
+ struct vcd_dev_ctxt *dev_ctxt, u32 send_deinit)
+{
+ if (!dev_ctxt->cctxt_list_head) {
+ VCD_MSG_HIGH("All clients are closed");
+ if (send_deinit)
+ (void) vcd_deinit_device_context(
+ vcd_get_drv_context(),
+ DEVICE_STATE_EVENT_NUMBER(close));
+ else
+ dev_ctxt->pending_cmd =
+ VCD_CMD_DEVICE_TERM;
+ }
+}
+void vcd_continue(void)
+{
+ struct vcd_drv_ctxt *drv_ctxt;
+ struct vcd_dev_ctxt *dev_ctxt;
+ u32 command_continue;
+ struct vcd_transc *transc;
+ u32 rc;
+ VCD_MSG_LOW("vcd_continue:");
+
+ drv_ctxt = vcd_get_drv_context();
+ dev_ctxt = &drv_ctxt->dev_ctxt;
+
+ dev_ctxt->command_continue = false;
+
+ if (dev_ctxt->pending_cmd == VCD_CMD_DEVICE_INIT) {
+ VCD_MSG_HIGH("VCD_CMD_DEVICE_INIT is pending");
+
+ dev_ctxt->pending_cmd = VCD_CMD_NONE;
+
+ (void)vcd_init_device_context(drv_ctxt,
+ DEVICE_STATE_EVENT_NUMBER(open));
+ } else if (dev_ctxt->pending_cmd == VCD_CMD_DEVICE_TERM) {
+ VCD_MSG_HIGH("VCD_CMD_DEVICE_TERM is pending");
+
+ dev_ctxt->pending_cmd = VCD_CMD_NONE;
+
+ (void)vcd_deinit_device_context(drv_ctxt,
+ DEVICE_STATE_EVENT_NUMBER(close));
+ } else if (dev_ctxt->pending_cmd == VCD_CMD_DEVICE_RESET) {
+ VCD_MSG_HIGH("VCD_CMD_DEVICE_RESET is pending");
+ dev_ctxt->pending_cmd = VCD_CMD_NONE;
+ (void)vcd_reset_device_context(drv_ctxt,
+ DEVICE_STATE_EVENT_NUMBER(dev_cb));
+ } else {
+ if (dev_ctxt->set_perf_lvl_pending) {
+ rc = vcd_power_event(dev_ctxt, NULL,
+ VCD_EVT_PWR_DEV_SET_PERFLVL);
+
+ if (VCD_FAILED(rc)) {
+ VCD_MSG_ERROR
+ ("VCD_EVT_PWR_CLNT_SET_PERFLVL failed");
+ VCD_MSG_HIGH
+ ("Not running at desired perf level."
+ "curr=%d, reqd=%d",
+ dev_ctxt->curr_perf_lvl,
+ dev_ctxt->reqd_perf_lvl);
+ } else {
+ dev_ctxt->set_perf_lvl_pending = false;
+ }
+ }
+
+ do {
+ command_continue = false;
+
+ if (vcd_get_command_channel_in_loop
+ (dev_ctxt, &transc)) {
+ if (vcd_submit_command_in_continue(dev_ctxt,
+ transc))
+ command_continue = true;
+ else {
+ VCD_MSG_MED
+ ("No more commands to submit");
+
+ vcd_release_command_channel(dev_ctxt,
+ transc);
+
+ vcd_release_interim_command_channels
+ (dev_ctxt);
+ }
+ }
+ } while (command_continue);
+
+ do {
+ command_continue = false;
+
+ if (vcd_get_frame_channel_in_loop
+ (dev_ctxt, &transc)) {
+ if (vcd_try_submit_frame_in_continue(dev_ctxt,
+ transc)) {
+ command_continue = true;
+ } else {
+ VCD_MSG_MED("No more frames to submit");
+
+ vcd_release_frame_channel(dev_ctxt,
+ transc);
+
+ vcd_release_interim_frame_channels
+ (dev_ctxt);
+ }
+ }
+
+ } while (command_continue);
+
+ if (!vcd_core_is_busy(dev_ctxt)) {
+ rc = vcd_power_event(dev_ctxt, NULL,
+ VCD_EVT_PWR_CLNT_CMD_END);
+
+ if (VCD_FAILED(rc))
+ VCD_MSG_ERROR("Failed:"
+ "VCD_EVT_PWR_CLNT_CMD_END");
+ }
+ }
+}
+
+static void vcd_pause_all_sessions(struct vcd_dev_ctxt *dev_ctxt)
+{
+ struct vcd_clnt_ctxt *cctxt = dev_ctxt->cctxt_list_head;
+ u32 rc;
+
+ while (cctxt) {
+ if (cctxt->clnt_state.state_table->ev_hdlr.pause) {
+ rc = cctxt->clnt_state.state_table->ev_hdlr.
+ pause(cctxt);
+
+ if (VCD_FAILED(rc))
+ VCD_MSG_ERROR("Client pause failed");
+
+ }
+
+ cctxt = cctxt->next;
+ }
+}
+
+static void vcd_resume_all_sessions(struct vcd_dev_ctxt *dev_ctxt)
+{
+ struct vcd_clnt_ctxt *cctxt = dev_ctxt->cctxt_list_head;
+ u32 rc;
+
+ while (cctxt) {
+ if (cctxt->clnt_state.state_table->ev_hdlr.resume) {
+ rc = cctxt->clnt_state.state_table->ev_hdlr.
+ resume(cctxt);
+
+ if (VCD_FAILED(rc))
+ VCD_MSG_ERROR("Client resume failed");
+
+ }
+
+ cctxt = cctxt->next;
+ }
+}
+
+static u32 vcd_init_cmn
+ (struct vcd_drv_ctxt *drv_ctxt,
+ struct vcd_init_config *config, s32 *driver_handle)
+{
+ struct vcd_dev_ctxt *dev_ctxt = &drv_ctxt->dev_ctxt;
+ s32 driver_id;
+
+ if (dev_ctxt->config.interrupt_clr !=
+ config->interrupt_clr
+ || dev_ctxt->config.register_isr !=
+ config->register_isr
+ || dev_ctxt->config.deregister_isr !=
+ config->deregister_isr
+ || dev_ctxt->config.map_dev_base_addr !=
+ config->map_dev_base_addr
+ || dev_ctxt->config.un_map_dev_base_addr !=
+ config->un_map_dev_base_addr) {
+ VCD_MSG_ERROR("Device config mismatch");
+ VCD_MSG_HIGH("VCD will be using config from 1st vcd_init");
+ }
+
+ *driver_handle = 0;
+
+ driver_id = 0;
+ while (driver_id < VCD_DRIVER_INSTANCE_MAX &&
+ dev_ctxt->driver_ids[driver_id]) {
+ ++driver_id;
+ }
+
+ if (driver_id == VCD_DRIVER_INSTANCE_MAX) {
+ VCD_MSG_ERROR("Max driver instances reached");
+
+ return VCD_ERR_FAIL;
+ }
+
+ ++dev_ctxt->refs;
+ dev_ctxt->driver_ids[driver_id] = true;
+ *driver_handle = driver_id + 1;
+
+ VCD_MSG_HIGH("Driver_id = %d. No of driver instances = %d",
+ driver_id, dev_ctxt->refs);
+
+ return VCD_S_SUCCESS;
+
+}
+
+static u32 vcd_init_in_null
+ (struct vcd_drv_ctxt *drv_ctxt,
+ struct vcd_init_config *config, s32 *driver_handle) {
+ u32 rc = VCD_S_SUCCESS;
+ struct vcd_dev_ctxt *dev_ctxt = &drv_ctxt->dev_ctxt;
+ u32 done_create_timer = false;
+ VCD_MSG_LOW("vcd_init_in_dev_null:");
+
+
+ dev_ctxt->config = *config;
+
+ dev_ctxt->device_base_addr =
+ (u8 *)config->map_dev_base_addr(
+ dev_ctxt->config.device_name);
+
+ if (!dev_ctxt->device_base_addr) {
+ VCD_MSG_ERROR("NULL Device_base_addr");
+
+ return VCD_ERR_FAIL;
+ }
+
+ if (config->register_isr) {
+ config->register_isr(dev_ctxt->config.
+ device_name);
+ }
+
+ if (config->timer_create) {
+ if (config->timer_create(vcd_hw_timeout_handler,
+ NULL, &dev_ctxt->hw_timer_handle))
+ done_create_timer = true;
+ else {
+ VCD_MSG_ERROR("timercreate failed");
+ return VCD_ERR_FAIL;
+ }
+ }
+
+
+ rc = vcd_init_cmn(drv_ctxt, config, driver_handle);
+
+ if (!VCD_FAILED(rc)) {
+ vcd_do_device_state_transition(drv_ctxt,
+ VCD_DEVICE_STATE_NOT_INIT,
+ DEVICE_STATE_EVENT_NUMBER
+ (init));
+ } else {
+ if (dev_ctxt->config.un_map_dev_base_addr)
+ dev_ctxt->config.un_map_dev_base_addr();
+
+ if (dev_ctxt->config.deregister_isr)
+ dev_ctxt->config.deregister_isr();
+
+ if (done_create_timer && dev_ctxt->config.timer_release)
+ dev_ctxt->config.timer_release(dev_ctxt->
+ hw_timer_handle);
+
+ }
+
+ return rc;
+
+}
+
+static u32 vcd_init_in_not_init
+ (struct vcd_drv_ctxt *drv_ctxt,
+ struct vcd_init_config *config, s32 *driver_handle)
+{
+
+ VCD_MSG_LOW("vcd_init_in_dev_not_init:");
+
+ return vcd_init_cmn(drv_ctxt, config, driver_handle);
+
+}
+
+static u32 vcd_init_in_initing
+ (struct vcd_drv_ctxt *drv_ctxt,
+ struct vcd_init_config *config, s32 *driver_handle) {
+
+ VCD_MSG_LOW("vcd_init_in_dev_initing:");
+
+ return vcd_init_cmn(drv_ctxt, config, driver_handle);
+
+}
+
+static u32 vcd_init_in_ready
+ (struct vcd_drv_ctxt *drv_ctxt,
+ struct vcd_init_config *config, s32 *driver_handle)
+{
+ VCD_MSG_LOW("vcd_init_in_dev_ready:");
+
+ return vcd_init_cmn(drv_ctxt, config, driver_handle);
+}
+
+static u32 vcd_term_cmn
+ (struct vcd_drv_ctxt *drv_ctxt, s32 driver_handle)
+{
+ struct vcd_dev_ctxt *dev_ctxt = &drv_ctxt->dev_ctxt;
+
+ if (!vcd_validate_driver_handle(dev_ctxt, driver_handle)) {
+ VCD_MSG_ERROR("Invalid driver handle = %d", driver_handle);
+
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ if (vcd_check_for_client_context(dev_ctxt,
+ driver_handle - 1)) {
+ VCD_MSG_ERROR("Driver has active client");
+
+ return VCD_ERR_BAD_STATE;
+ }
+
+ --dev_ctxt->refs;
+ dev_ctxt->driver_ids[driver_handle - 1] = false;
+
+ VCD_MSG_HIGH("Driver_id %d terminated. No of driver instances = %d",
+ driver_handle - 1, dev_ctxt->refs);
+
+ return VCD_S_SUCCESS;
+}
+
+static u32 vcd_term_in_not_init
+ (struct vcd_drv_ctxt *drv_ctxt, s32 driver_handle)
+{
+ struct vcd_dev_ctxt *dev_ctxt = &drv_ctxt->dev_ctxt;
+ u32 rc;
+
+ VCD_MSG_LOW("vcd_term_in_dev_not_init:");
+
+ rc = vcd_term_cmn(drv_ctxt, driver_handle);
+
+ if (!VCD_FAILED(rc) && !dev_ctxt->refs)
+ vcd_term_driver_context(drv_ctxt);
+
+ return rc;
+}
+
+static u32 vcd_term_in_initing
+ (struct vcd_drv_ctxt *drv_ctxt, s32 driver_handle)
+{
+ VCD_MSG_LOW("vcd_term_in_dev_initing:");
+
+ return vcd_term_cmn(drv_ctxt, driver_handle);
+}
+
+static u32 vcd_term_in_ready
+ (struct vcd_drv_ctxt *drv_ctxt, s32 driver_handle)
+{
+ VCD_MSG_LOW("vcd_term_in_dev_ready:");
+
+ return vcd_term_cmn(drv_ctxt, driver_handle);
+}
+
+static u32 vcd_term_in_invalid(struct vcd_drv_ctxt *drv_ctxt,
+ s32 driver_handle)
+{
+ u32 rc;
+ VCD_MSG_LOW("vcd_term_in_invalid:");
+ rc = vcd_term_cmn(drv_ctxt, driver_handle);
+ if (!VCD_FAILED(rc) && !drv_ctxt->dev_ctxt.refs)
+ vcd_term_driver_context(drv_ctxt);
+
+ return rc;
+}
+
+static u32 vcd_open_cmn
+ (struct vcd_drv_ctxt *drv_ctxt,
+ s32 driver_handle,
+ u32 decoding,
+ void (*callback) (u32 event, u32 status, void *info, size_t sz,
+ void *handle, void *const client_data),
+ void *client_data, struct vcd_clnt_ctxt ** clnt_cctxt)
+{
+ struct vcd_dev_ctxt *dev_ctxt = &drv_ctxt->dev_ctxt;
+ struct vcd_clnt_ctxt *cctxt;
+ struct vcd_clnt_ctxt *client;
+
+ if (!vcd_validate_driver_handle(dev_ctxt, driver_handle)) {
+ VCD_MSG_ERROR("Invalid driver handle = %d", driver_handle);
+
+ return VCD_ERR_BAD_HANDLE;
+ }
+
+ cctxt = (struct vcd_clnt_ctxt *)
+ kmalloc(sizeof(struct vcd_clnt_ctxt), GFP_KERNEL);
+ if (!cctxt) {
+ VCD_MSG_ERROR("No memory for client ctxt");
+
+ return VCD_ERR_ALLOC_FAIL;
+ }
+
+ memset(cctxt, 0, sizeof(struct vcd_clnt_ctxt));
+ cctxt->dev_ctxt = dev_ctxt;
+ cctxt->driver_id = driver_handle - 1;
+ cctxt->decoding = decoding;
+ cctxt->callback = callback;
+ cctxt->client_data = client_data;
+ cctxt->status.last_evt = VCD_EVT_RESP_OPEN;
+ INIT_LIST_HEAD(&cctxt->in_buf_pool.queue);
+ INIT_LIST_HEAD(&cctxt->out_buf_pool.queue);
+ client = dev_ctxt->cctxt_list_head;
+ dev_ctxt->cctxt_list_head = cctxt;
+ cctxt->next = client;
+
+ *clnt_cctxt = cctxt;
+
+ return VCD_S_SUCCESS;
+
+}
+
+static u32 vcd_open_in_not_init
+ (struct vcd_drv_ctxt *drv_ctxt,
+ s32 driver_handle,
+ u32 decoding,
+ void (*callback) (u32 event, u32 status, void *info, size_t sz,
+ void *handle, void *const client_data),
+ void *client_data)
+{
+ struct vcd_clnt_ctxt *cctxt;
+ u32 rc;
+
+ VCD_MSG_LOW("vcd_open_in_dev_not_init:");
+
+ rc = vcd_open_cmn(drv_ctxt, driver_handle, decoding, callback,
+ client_data, &cctxt);
+
+ VCD_FAILED_RETURN(rc, "Failed: vcd_open_cmn");
+
+ rc = vcd_init_device_context(drv_ctxt,
+ DEVICE_STATE_EVENT_NUMBER(open));
+
+ if (VCD_FAILED(rc))
+ vcd_destroy_client_context(cctxt);
+
+ return rc;
+}
+
+static u32 vcd_open_in_initing(struct vcd_drv_ctxt *drv_ctxt,
+ s32 driver_handle, u32 decoding,
+ void (*callback) (u32 event, u32 status, void *info, size_t sz,
+ void *handle, void *const client_data),
+ void *client_data)
+{
+ struct vcd_clnt_ctxt *cctxt;
+
+ VCD_MSG_LOW("vcd_open_in_dev_initing:");
+
+ return vcd_open_cmn(drv_ctxt, driver_handle, decoding, callback,
+ client_data, &cctxt);
+}
+
+static u32 vcd_open_in_ready
+ (struct vcd_drv_ctxt *drv_ctxt,
+ s32 driver_handle,
+ u32 decoding,
+ void (*callback) (u32 event, u32 status, void *info, size_t sz,
+ void *handle, void *const client_data),
+ void *client_data)
+{
+ struct vcd_clnt_ctxt *cctxt;
+ struct vcd_handle_container container;
+ u32 rc;
+
+ VCD_MSG_LOW("vcd_open_in_dev_ready:");
+
+ rc = vcd_open_cmn(drv_ctxt, driver_handle, decoding, callback,
+ client_data, &cctxt);
+
+ VCD_FAILED_RETURN(rc, "Failed: vcd_open_cmn");
+
+ rc = vcd_init_client_context(cctxt);
+
+ if (!VCD_FAILED(rc)) {
+ container.handle = (void *)cctxt;
+
+ callback(VCD_EVT_RESP_OPEN,
+ VCD_S_SUCCESS,
+ &container,
+ sizeof(container), container.handle, client_data);
+ } else {
+ VCD_MSG_ERROR("rc = 0x%x. Failed: vcd_init_client_context", rc);
+
+ vcd_destroy_client_context(cctxt);
+ }
+
+ return rc;
+}
+
+static u32 vcd_close_in_ready
+ (struct vcd_drv_ctxt *drv_ctxt,
+ struct vcd_clnt_ctxt *cctxt) {
+ u32 rc;
+
+ VCD_MSG_LOW("vcd_close_in_dev_ready:");
+
+ if (cctxt->clnt_state.state_table->ev_hdlr.close) {
+ rc = cctxt->clnt_state.state_table->ev_hdlr.
+ close(cctxt);
+ } else {
+ VCD_MSG_ERROR("Unsupported API in client state %d",
+ cctxt->clnt_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+
+ if (!VCD_FAILED(rc))
+ vcd_handle_for_last_clnt_close(&drv_ctxt->dev_ctxt, true);
+
+ return rc;
+}
+
+static u32 vcd_close_in_dev_invalid(struct vcd_drv_ctxt *drv_ctxt,
+ struct vcd_clnt_ctxt *cctxt)
+{
+ u32 rc;
+ VCD_MSG_LOW("vcd_close_in_dev_invalid:");
+ if (cctxt->clnt_state.state_table->ev_hdlr.close) {
+ rc = cctxt->clnt_state.state_table->
+ ev_hdlr.close(cctxt);
+ } else {
+ VCD_MSG_ERROR("Unsupported API in client state %d",
+ cctxt->clnt_state.state);
+ rc = VCD_ERR_BAD_STATE;
+ }
+ if (!VCD_FAILED(rc) && !drv_ctxt->dev_ctxt.
+ cctxt_list_head) {
+ VCD_MSG_HIGH("All INVALID clients are closed");
+ vcd_do_device_state_transition(drv_ctxt,
+ VCD_DEVICE_STATE_NOT_INIT,
+ DEVICE_STATE_EVENT_NUMBER(close));
+ }
+ return rc;
+}
+
+static u32 vcd_resume_in_ready
+ (struct vcd_drv_ctxt *drv_ctxt,
+ struct vcd_clnt_ctxt *cctxt) {
+ u32 rc = VCD_S_SUCCESS;
+
+ VCD_MSG_LOW("vcd_resume_in_ready:");
+
+ if (cctxt->clnt_state.state_table->ev_hdlr.resume) {
+ rc = cctxt->clnt_state.state_table->ev_hdlr.
+ resume(cctxt);
+ } else {
+ VCD_MSG_ERROR("Unsupported API in client state %d",
+ cctxt->clnt_state.state);
+
+ rc = VCD_ERR_BAD_STATE;
+ }
+
+ return rc;
+}
+
+static u32 vcd_set_dev_pwr_in_ready
+ (struct vcd_drv_ctxt *drv_ctxt,
+ enum vcd_power_state pwr_state)
+{
+ u32 rc = VCD_S_SUCCESS;
+ struct vcd_dev_ctxt *dev_ctxt = &drv_ctxt->dev_ctxt;
+
+ VCD_MSG_LOW("vcd_set_dev_pwr_in_ready:");
+
+ switch (pwr_state) {
+ case VCD_PWR_STATE_SLEEP:
+ {
+ if (dev_ctxt->pwr_state == VCD_PWR_STATE_ON)
+ vcd_pause_all_sessions(dev_ctxt);
+ dev_ctxt->pwr_state = VCD_PWR_STATE_SLEEP;
+ break;
+ }
+
+ case VCD_PWR_STATE_ON:
+ {
+ if (dev_ctxt->pwr_state == VCD_PWR_STATE_SLEEP)
+ vcd_resume_all_sessions(dev_ctxt);
+ dev_ctxt->pwr_state = VCD_PWR_STATE_ON;
+ break;
+ }
+
+ default:
+ {
+ VCD_MSG_ERROR("Invalid power state requested %d",
+ pwr_state);
+ break;
+ }
+
+ }
+
+ return rc;
+}
+
+static void vcd_dev_cb_in_initing
+ (struct vcd_drv_ctxt *drv_ctxt,
+ u32 event,
+ u32 status,
+ void *payload, size_t sz, u32 *ddl_handle, void *const client_data)
+{
+ struct vcd_dev_ctxt *dev_ctxt;
+ struct vcd_clnt_ctxt *client;
+ struct vcd_clnt_ctxt *tmp_client;
+ struct vcd_handle_container container;
+ u32 rc = VCD_S_SUCCESS;
+ u32 client_inited = false;
+ u32 fail_all_open = false;
+
+ VCD_MSG_LOW("vcd_dev_cb_in_initing:");
+
+ if (event != VCD_EVT_RESP_DEVICE_INIT) {
+ VCD_MSG_ERROR("vcd_dev_cb_in_initing: Unexpected event %d",
+ (int)event);
+ return;
+ }
+
+ dev_ctxt = &drv_ctxt->dev_ctxt;
+
+ dev_ctxt->command_continue = false;
+
+ if (VCD_FAILED(status)) {
+ vcd_handle_device_init_failed(drv_ctxt, status);
+
+ return;
+ }
+
+ vcd_do_device_state_transition(drv_ctxt,
+ VCD_DEVICE_STATE_READY,
+ DEVICE_STATE_EVENT_NUMBER(open));
+
+ if (!dev_ctxt->cctxt_list_head) {
+ VCD_MSG_HIGH("All clients are closed");
+
+ dev_ctxt->pending_cmd = VCD_CMD_DEVICE_TERM;
+
+ return;
+ }
+
+ if (!dev_ctxt->ddl_cmd_ch_depth
+ || !dev_ctxt->trans_tbl)
+ rc = vcd_setup_with_ddl_capabilities(dev_ctxt);
+
+
+ if (VCD_FAILED(rc)) {
+ VCD_MSG_ERROR
+ ("rc = 0x%x: Failed vcd_setup_with_ddl_capabilities",
+ rc);
+
+ fail_all_open = true;
+ }
+
+ client = dev_ctxt->cctxt_list_head;
+ while (client) {
+ if (!fail_all_open)
+ rc = vcd_init_client_context(client);
+
+
+ if (!VCD_FAILED(rc)) {
+ container.handle = (void *)client;
+ client->callback(VCD_EVT_RESP_OPEN,
+ VCD_S_SUCCESS,
+ &container,
+ sizeof(container),
+ container.handle,
+ client->client_data);
+
+ client = client->next;
+
+ client_inited = true;
+ } else {
+ VCD_MSG_ERROR
+ ("rc = 0x%x, Failed: vcd_init_client_context",
+ rc);
+
+ client->callback(VCD_EVT_RESP_OPEN,
+ rc,
+ NULL, 0, 0, client->client_data);
+
+ tmp_client = client;
+ client = client->next;
+
+ vcd_destroy_client_context(tmp_client);
+ }
+ }
+
+ if (!client_inited || fail_all_open) {
+ VCD_MSG_ERROR("All client open requests failed");
+
+ dev_ctxt->pending_cmd = VCD_CMD_DEVICE_TERM;
+ } else {
+ if (vcd_power_event(dev_ctxt, NULL,
+ VCD_EVT_PWR_DEV_INIT_END)) {
+ VCD_MSG_ERROR("VCD_EVT_PWR_DEV_INIT_END failed");
+ }
+ }
+}
+
+static void vcd_hw_timeout_cmn(struct vcd_drv_ctxt *drv_ctxt,
+ void *user_data)
+{
+ struct vcd_dev_ctxt *dev_ctxt = &drv_ctxt->dev_ctxt;
+ VCD_MSG_LOW("vcd_hw_timeout_cmn:");
+ vcd_device_timer_stop(dev_ctxt);
+
+ vcd_handle_device_err_fatal(dev_ctxt, NULL);
+
+ /* Reset HW. */
+ (void) vcd_reset_device_context(drv_ctxt,
+ DEVICE_STATE_EVENT_NUMBER(timeout));
+}
+
+static void vcd_dev_enter_null
+ (struct vcd_drv_ctxt *drv_ctxt, s32 state_event) {
+ VCD_MSG_MED("Entering DEVICE_STATE_NULL on api %d", state_event);
+
+}
+
+static void vcd_dev_enter_not_init
+ (struct vcd_drv_ctxt *drv_ctxt, s32 state_event) {
+ VCD_MSG_MED("Entering DEVICE_STATE_NOT_INIT on api %d",
+ state_event);
+
+}
+
+static void vcd_dev_enter_initing
+ (struct vcd_drv_ctxt *drv_ctxt, s32 state_event) {
+ VCD_MSG_MED("Entering DEVICE_STATE_INITING on api %d",
+ state_event);
+
+}
+
+static void vcd_dev_enter_ready
+ (struct vcd_drv_ctxt *drv_ctxt, s32 state_event) {
+ VCD_MSG_MED("Entering DEVICE_STATE_READY on api %d",
+ state_event);
+}
+
+static void vcd_dev_enter_invalid(struct vcd_drv_ctxt *drv_ctxt,
+ s32 state_event)
+{
+ VCD_MSG_MED("Entering DEVICE_STATE_INVALID on api %d", state_event);
+}
+
+static void vcd_dev_exit_null
+ (struct vcd_drv_ctxt *drv_ctxt, s32 state_event) {
+ VCD_MSG_MED("Exiting DEVICE_STATE_NULL on api %d", state_event);
+}
+
+static void vcd_dev_exit_not_init
+ (struct vcd_drv_ctxt *drv_ctxt, s32 state_event) {
+ VCD_MSG_MED("Exiting DEVICE_STATE_NOT_INIT on api %d",
+ state_event);
+
+}
+
+static void vcd_dev_exit_initing
+ (struct vcd_drv_ctxt *drv_ctxt, s32 state_event) {
+ VCD_MSG_MED("Exiting DEVICE_STATE_INITING on api %d",
+ state_event);
+}
+
+static void vcd_dev_exit_ready
+ (struct vcd_drv_ctxt *drv_ctxt, s32 state_event) {
+ VCD_MSG_MED("Exiting DEVICE_STATE_READY on api %d", state_event);
+}
+
+static void vcd_dev_exit_invalid(struct vcd_drv_ctxt *drv_ctxt,
+ s32 state_event)
+{
+ VCD_MSG_MED("Exiting DEVICE_STATE_INVALID on api %d", state_event);
+}
+
+static const struct vcd_dev_state_table vcd_dev_table_null = {
+ {
+ vcd_init_in_null,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ },
+ vcd_dev_enter_null,
+ vcd_dev_exit_null
+};
+
+static const struct vcd_dev_state_table vcd_dev_table_not_init = {
+ {
+ vcd_init_in_not_init,
+ vcd_term_in_not_init,
+ vcd_open_in_not_init,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ },
+ vcd_dev_enter_not_init,
+ vcd_dev_exit_not_init
+};
+
+static const struct vcd_dev_state_table vcd_dev_table_initing = {
+ {
+ vcd_init_in_initing,
+ vcd_term_in_initing,
+ vcd_open_in_initing,
+ NULL,
+ NULL,
+ NULL,
+ vcd_dev_cb_in_initing,
+ vcd_hw_timeout_cmn,
+ },
+ vcd_dev_enter_initing,
+ vcd_dev_exit_initing
+};
+
+static const struct vcd_dev_state_table vcd_dev_table_ready = {
+ {
+ vcd_init_in_ready,
+ vcd_term_in_ready,
+ vcd_open_in_ready,
+ vcd_close_in_ready,
+ vcd_resume_in_ready,
+ vcd_set_dev_pwr_in_ready,
+ NULL,
+ vcd_hw_timeout_cmn,
+ },
+ vcd_dev_enter_ready,
+ vcd_dev_exit_ready
+};
+
+static const struct vcd_dev_state_table vcd_dev_table_in_invalid = {
+ {
+ NULL,
+ vcd_term_in_invalid,
+ NULL,
+ vcd_close_in_dev_invalid,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ },
+ vcd_dev_enter_invalid,
+ vcd_dev_exit_invalid
+};
+
+static const struct vcd_dev_state_table *vcd_dev_state_table[] = {
+ &vcd_dev_table_null,
+ &vcd_dev_table_not_init,
+ &vcd_dev_table_initing,
+ &vcd_dev_table_ready,
+ &vcd_dev_table_in_invalid
+};
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.h b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.h
new file mode 100644
index 0000000..8245966
--- /dev/null
+++ b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.h
@@ -0,0 +1,96 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _VCD_DEVICE_SM_H_
+#define _VCD_DEVICE_SM_H_
+
+#include "vcd_api.h"
+#include "vcd_ddl_api.h"
+#include "vcd_core.h"
+
+struct vcd_dev_state_table;
+struct vcd_dev_state_ctxt;
+struct vcd_drv_ctxt;
+
+enum vcd_dev_state_enum {
+ VCD_DEVICE_STATE_NULL = 0,
+ VCD_DEVICE_STATE_NOT_INIT,
+ VCD_DEVICE_STATE_INITING,
+ VCD_DEVICE_STATE_READY,
+ VCD_DEVICE_STATE_INVALID,
+ VCD_DEVICE_STATE_MAX,
+ VCD_DEVICE_STATE_32BIT = 0x7FFFFFFF
+};
+
+struct vcd_dev_state_table {
+ struct {
+ u32(*init) (struct vcd_drv_ctxt *drv_ctxt,
+ struct vcd_init_config *config,
+ s32 *driver_handle);
+
+ u32(*term) (struct vcd_drv_ctxt *drv_ctxt,
+ s32 driver_handle);
+
+ u32(*open) (struct vcd_drv_ctxt *drv_ctxt,
+ s32 driver_handle, u32 decoding,
+ void (*callback) (u32 event, u32 status,
+ void *info, size_t sz, void *handle,
+ void *const client_data),
+ void *client_data);
+
+ u32(*close) (struct vcd_drv_ctxt *drv_ctxt,
+ struct vcd_clnt_ctxt *cctxt);
+
+ u32(*resume) (struct vcd_drv_ctxt *drv_ctxt,
+ struct vcd_clnt_ctxt *cctxt);
+
+ u32(*set_dev_pwr) (struct vcd_drv_ctxt *drv_ctxt,
+ enum vcd_power_state pwr_state);
+
+ void (*dev_cb) (struct vcd_drv_ctxt *drv_ctxt,
+ u32 event, u32 status, void *payload,
+ size_t sz, u32 *ddl_handle,
+ void *const client_data);
+
+ void (*timeout) (struct vcd_drv_ctxt *drv_ctxt,
+ void *user_data);
+ } ev_hdlr;
+
+ void (*entry) (struct vcd_drv_ctxt *drv_ctxt,
+ s32 state_event);
+ void (*exit) (struct vcd_drv_ctxt *drv_ctxt,
+ s32 state_event);
+};
+
+#define DEVICE_STATE_EVENT_NUMBER(ppf) \
+ ((u32 *) (&(((struct vcd_dev_state_table*)0)->ev_hdlr.ppf)) - \
+ (u32 *) (&(((struct vcd_dev_state_table*)0)->ev_hdlr.init)) \
+ + 1)
+
+struct vcd_dev_state_ctxt {
+ const struct vcd_dev_state_table *state_table;
+
+ enum vcd_dev_state_enum state;
+};
+
+struct vcd_drv_ctxt {
+ struct vcd_dev_state_ctxt dev_state;
+ struct vcd_dev_ctxt dev_ctxt;
+ struct mutex dev_mutex;
+};
+
+
+extern struct vcd_drv_ctxt *vcd_get_drv_context(void);
+
+void vcd_continue(void);
+
+#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
new file mode 100644
index 0000000..fff6a3b
--- /dev/null
+++ b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
@@ -0,0 +1,351 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "vidc_type.h"
+#include "vcd_power_sm.h"
+#include "vcd_core.h"
+#include "vcd.h"
+
+u32 vcd_power_event(
+ struct vcd_dev_ctxt *dev_ctxt,
+ struct vcd_clnt_ctxt *cctxt, u32 event)
+{
+ u32 rc = VCD_S_SUCCESS;
+
+ VCD_MSG_MED("Device power state = %d", dev_ctxt->pwr_clk_state);
+ VCD_MSG_MED("event = 0x%x", event);
+ switch (event) {
+
+ case VCD_EVT_PWR_DEV_INIT_BEGIN:
+ case VCD_EVT_PWR_DEV_INIT_END:
+ case VCD_EVT_PWR_DEV_INIT_FAIL:
+ case VCD_EVT_PWR_DEV_TERM_BEGIN:
+ case VCD_EVT_PWR_DEV_TERM_END:
+ case VCD_EVT_PWR_DEV_TERM_FAIL:
+ case VCD_EVT_PWR_DEV_SLEEP_BEGIN:
+ case VCD_EVT_PWR_DEV_SLEEP_END:
+ case VCD_EVT_PWR_DEV_SET_PERFLVL:
+ case VCD_EVT_PWR_DEV_HWTIMEOUT:
+ {
+ rc = vcd_device_power_event(dev_ctxt, event,
+ cctxt);
+ break;
+ }
+
+ case VCD_EVT_PWR_CLNT_CMD_BEGIN:
+ case VCD_EVT_PWR_CLNT_CMD_END:
+ case VCD_EVT_PWR_CLNT_CMD_FAIL:
+ case VCD_EVT_PWR_CLNT_PAUSE:
+ case VCD_EVT_PWR_CLNT_RESUME:
+ case VCD_EVT_PWR_CLNT_FIRST_FRAME:
+ case VCD_EVT_PWR_CLNT_LAST_FRAME:
+ case VCD_EVT_PWR_CLNT_ERRFATAL:
+ {
+ rc = vcd_client_power_event(dev_ctxt, cctxt, event);
+ break;
+ }
+
+ }
+
+ if (VCD_FAILED(rc))
+ VCD_MSG_ERROR("vcd_power_event: event 0x%x failed", event);
+
+
+ return rc;
+
+}
+
+u32 vcd_device_power_event(struct vcd_dev_ctxt *dev_ctxt, u32 event,
+ struct vcd_clnt_ctxt *cctxt)
+{
+ u32 rc = VCD_ERR_FAIL;
+ u32 set_perf_lvl;
+
+ switch (event) {
+
+ case VCD_EVT_PWR_DEV_INIT_BEGIN:
+ {
+ if (dev_ctxt->pwr_clk_state ==
+ VCD_PWRCLK_STATE_OFF) {
+ if (res_trk_get_max_perf_level(&dev_ctxt->
+ max_perf_lvl)) {
+ if (res_trk_power_up()) {
+ dev_ctxt->pwr_clk_state =
+ VCD_PWRCLK_STATE_ON_NOTCLOCKED;
+ dev_ctxt->curr_perf_lvl = 0;
+ dev_ctxt->reqd_perf_lvl = 0;
+ dev_ctxt->active_clnts = 0;
+ dev_ctxt->
+ set_perf_lvl_pending = false;
+ rc = vcd_enable_clock(dev_ctxt,
+ cctxt);
+ if (VCD_FAILED(rc)) {
+ (void)res_trk_power_down();
+ dev_ctxt->pwr_clk_state =
+ VCD_PWRCLK_STATE_OFF;
+ }
+ }
+ }
+ }
+
+ break;
+ }
+
+ case VCD_EVT_PWR_DEV_INIT_END:
+ case VCD_EVT_PWR_DEV_TERM_FAIL:
+ case VCD_EVT_PWR_DEV_SLEEP_BEGIN:
+ case VCD_EVT_PWR_DEV_HWTIMEOUT:
+ {
+ rc = vcd_gate_clock(dev_ctxt);
+
+ break;
+ }
+
+ case VCD_EVT_PWR_DEV_INIT_FAIL:
+ case VCD_EVT_PWR_DEV_TERM_END:
+ {
+ if (dev_ctxt->pwr_clk_state !=
+ VCD_PWRCLK_STATE_OFF) {
+ (void)vcd_disable_clock(dev_ctxt);
+ (void)res_trk_power_down();
+
+ dev_ctxt->pwr_clk_state =
+ VCD_PWRCLK_STATE_OFF;
+ dev_ctxt->curr_perf_lvl = 0;
+ dev_ctxt->reqd_perf_lvl = 0;
+ dev_ctxt->active_clnts = 0;
+ dev_ctxt->set_perf_lvl_pending = false;
+ rc = VCD_S_SUCCESS;
+ }
+
+ break;
+ }
+
+ case VCD_EVT_PWR_DEV_TERM_BEGIN:
+ case VCD_EVT_PWR_DEV_SLEEP_END:
+ {
+ rc = vcd_un_gate_clock(dev_ctxt);
+
+ break;
+ }
+
+ case VCD_EVT_PWR_DEV_SET_PERFLVL:
+ {
+ set_perf_lvl =
+ dev_ctxt->reqd_perf_lvl >
+ 0 ? dev_ctxt->
+ reqd_perf_lvl : VCD_MIN_PERF_LEVEL;
+ rc = vcd_set_perf_level(dev_ctxt, set_perf_lvl);
+ break;
+ }
+ }
+ return rc;
+}
+
+u32 vcd_client_power_event(
+ struct vcd_dev_ctxt *dev_ctxt,
+ struct vcd_clnt_ctxt *cctxt, u32 event)
+{
+ u32 rc = VCD_ERR_FAIL;
+
+ switch (event) {
+
+ case VCD_EVT_PWR_CLNT_CMD_BEGIN:
+ {
+ rc = vcd_un_gate_clock(dev_ctxt);
+ break;
+ }
+
+ case VCD_EVT_PWR_CLNT_CMD_END:
+ {
+ rc = vcd_gate_clock(dev_ctxt);
+ break;
+ }
+
+ case VCD_EVT_PWR_CLNT_CMD_FAIL:
+ {
+ if (!vcd_core_is_busy(dev_ctxt))
+ rc = vcd_gate_clock(dev_ctxt);
+
+ break;
+ }
+
+ case VCD_EVT_PWR_CLNT_PAUSE:
+ case VCD_EVT_PWR_CLNT_LAST_FRAME:
+ case VCD_EVT_PWR_CLNT_ERRFATAL:
+ {
+ if (cctxt) {
+ rc = VCD_S_SUCCESS;
+ if (cctxt->status.req_perf_lvl) {
+ dev_ctxt->reqd_perf_lvl -=
+ cctxt->reqd_perf_lvl;
+ cctxt->status.req_perf_lvl = false;
+ rc = vcd_set_perf_level(dev_ctxt,
+ dev_ctxt->reqd_perf_lvl);
+ }
+ }
+
+ break;
+ }
+
+ case VCD_EVT_PWR_CLNT_RESUME:
+ case VCD_EVT_PWR_CLNT_FIRST_FRAME:
+ {
+ if (cctxt) {
+ rc = VCD_S_SUCCESS;
+ if (!cctxt->status.req_perf_lvl) {
+ dev_ctxt->reqd_perf_lvl +=
+ cctxt->reqd_perf_lvl;
+ cctxt->status.req_perf_lvl = true;
+
+ rc = vcd_set_perf_level(dev_ctxt,
+ dev_ctxt->reqd_perf_lvl);
+ }
+ }
+ break;
+ }
+ }
+
+ return rc;
+}
+
+u32 vcd_enable_clock(struct vcd_dev_ctxt *dev_ctxt,
+ struct vcd_clnt_ctxt *cctxt)
+{
+ u32 rc = VCD_S_SUCCESS;
+ u32 set_perf_lvl;
+
+ if (dev_ctxt->pwr_clk_state == VCD_PWRCLK_STATE_OFF) {
+ VCD_MSG_ERROR("vcd_enable_clock(): Already in state "
+ "VCD_PWRCLK_STATE_OFF\n");
+ rc = VCD_ERR_FAIL;
+ } else if (dev_ctxt->pwr_clk_state ==
+ VCD_PWRCLK_STATE_ON_NOTCLOCKED) {
+ set_perf_lvl =
+ dev_ctxt->reqd_perf_lvl >
+ 0 ? dev_ctxt->
+ reqd_perf_lvl : VCD_MIN_PERF_LEVEL;
+ rc = vcd_set_perf_level(dev_ctxt, set_perf_lvl);
+ if (!VCD_FAILED(rc)) {
+ if (res_trk_enable_clocks()) {
+ dev_ctxt->pwr_clk_state =
+ VCD_PWRCLK_STATE_ON_CLOCKED;
+ }
+ } else {
+ rc = VCD_ERR_FAIL;
+ }
+
+ }
+
+ if (!VCD_FAILED(rc))
+ dev_ctxt->active_clnts++;
+
+ return rc;
+}
+
+u32 vcd_disable_clock(struct vcd_dev_ctxt *dev_ctxt)
+{
+ u32 rc = VCD_S_SUCCESS;
+
+ if (dev_ctxt->pwr_clk_state == VCD_PWRCLK_STATE_OFF) {
+ VCD_MSG_ERROR("vcd_disable_clock(): Already in state "
+ "VCD_PWRCLK_STATE_OFF\n");
+ rc = VCD_ERR_FAIL;
+ } else if (dev_ctxt->pwr_clk_state == VCD_PWRCLK_STATE_ON_CLOCKED ||
+ dev_ctxt->pwr_clk_state == VCD_PWRCLK_STATE_ON_CLOCKGATED) {
+ dev_ctxt->active_clnts--;
+
+ if (!dev_ctxt->active_clnts) {
+ if (!res_trk_disable_clocks())
+ rc = VCD_ERR_FAIL;
+
+ dev_ctxt->pwr_clk_state =
+ VCD_PWRCLK_STATE_ON_NOTCLOCKED;
+ dev_ctxt->curr_perf_lvl = 0;
+ }
+ }
+
+ return rc;
+}
+
+u32 vcd_set_perf_level(struct vcd_dev_ctxt *dev_ctxt, u32 perf_lvl)
+{
+ u32 rc = VCD_S_SUCCESS;
+ if (!vcd_core_is_busy(dev_ctxt)) {
+ if (res_trk_set_perf_level(perf_lvl,
+ &dev_ctxt->curr_perf_lvl, dev_ctxt)) {
+ dev_ctxt->set_perf_lvl_pending = false;
+ } else {
+ rc = VCD_ERR_FAIL;
+ dev_ctxt->set_perf_lvl_pending = true;
+ }
+
+ } else {
+ dev_ctxt->set_perf_lvl_pending = true;
+ }
+
+ return rc;
+}
+
+u32 vcd_update_clnt_perf_lvl(
+ struct vcd_clnt_ctxt *cctxt,
+ struct vcd_property_frame_rate *fps, u32 frm_p_units)
+{
+ u32 rc = VCD_S_SUCCESS;
+ struct vcd_dev_ctxt *dev_ctxt = cctxt->dev_ctxt;
+ u32 new_perf_lvl;
+ new_perf_lvl =
+ frm_p_units * fps->fps_numerator / fps->fps_denominator;
+ if (cctxt->status.req_perf_lvl) {
+ dev_ctxt->reqd_perf_lvl =
+ dev_ctxt->reqd_perf_lvl - cctxt->reqd_perf_lvl +
+ new_perf_lvl;
+ rc = vcd_set_perf_level(cctxt->dev_ctxt,
+ dev_ctxt->reqd_perf_lvl);
+ }
+ cctxt->reqd_perf_lvl = new_perf_lvl;
+ return rc;
+}
+
+u32 vcd_gate_clock(struct vcd_dev_ctxt *dev_ctxt)
+{
+ u32 rc = VCD_S_SUCCESS;
+ if (dev_ctxt->pwr_clk_state == VCD_PWRCLK_STATE_OFF ||
+ dev_ctxt->pwr_clk_state == VCD_PWRCLK_STATE_ON_NOTCLOCKED) {
+ VCD_MSG_ERROR("%s(): Clk is Off or Not Clked yet\n", __func__);
+ rc = VCD_ERR_FAIL;
+ } else if (dev_ctxt->pwr_clk_state == VCD_PWRCLK_STATE_ON_CLOCKGATED)
+ rc = VCD_S_SUCCESS;
+ else if (res_trk_disable_clocks())
+ dev_ctxt->pwr_clk_state = VCD_PWRCLK_STATE_ON_CLOCKGATED;
+ else
+ rc = VCD_ERR_FAIL;
+ return rc;
+}
+
+u32 vcd_un_gate_clock(struct vcd_dev_ctxt *dev_ctxt)
+{
+ u32 rc = VCD_S_SUCCESS;
+ if (dev_ctxt->pwr_clk_state == VCD_PWRCLK_STATE_OFF ||
+ dev_ctxt->pwr_clk_state == VCD_PWRCLK_STATE_ON_NOTCLOCKED) {
+ VCD_MSG_ERROR("%s(): Clk is Off or Not Clked yet\n", __func__);
+ rc = VCD_ERR_FAIL;
+ } else if (dev_ctxt->pwr_clk_state == VCD_PWRCLK_STATE_ON_CLOCKED)
+ rc = VCD_S_SUCCESS;
+ else if (res_trk_enable_clocks())
+ dev_ctxt->pwr_clk_state = VCD_PWRCLK_STATE_ON_CLOCKED;
+ else
+ rc = VCD_ERR_FAIL;
+ return rc;
+}
+
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_power_sm.h b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.h
new file mode 100644
index 0000000..26ce019
--- /dev/null
+++ b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.h
@@ -0,0 +1,43 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _VCD_POWERSM_H_
+#define _VCD_POWERSM_H_
+
+#define VCD_EVT_PWR_BASE 0x5000
+#define VCD_EVT_PWR_DEV_INIT_BEGIN (VCD_EVT_PWR_BASE + 0x1)
+#define VCD_EVT_PWR_DEV_INIT_END (VCD_EVT_PWR_BASE + 0x2)
+#define VCD_EVT_PWR_DEV_INIT_FAIL (VCD_EVT_PWR_BASE + 0x3)
+#define VCD_EVT_PWR_DEV_TERM_BEGIN (VCD_EVT_PWR_BASE + 0x4)
+#define VCD_EVT_PWR_DEV_TERM_END (VCD_EVT_PWR_BASE + 0x5)
+#define VCD_EVT_PWR_DEV_TERM_FAIL (VCD_EVT_PWR_BASE + 0x6)
+#define VCD_EVT_PWR_DEV_SLEEP_BEGIN (VCD_EVT_PWR_BASE + 0x7)
+#define VCD_EVT_PWR_DEV_SLEEP_END (VCD_EVT_PWR_BASE + 0x8)
+#define VCD_EVT_PWR_DEV_SET_PERFLVL (VCD_EVT_PWR_BASE + 0x9)
+#define VCD_EVT_PWR_DEV_HWTIMEOUT (VCD_EVT_PWR_BASE + 0xa)
+#define VCD_EVT_PWR_CLNT_CMD_BEGIN (VCD_EVT_PWR_BASE + 0xb)
+#define VCD_EVT_PWR_CLNT_CMD_END (VCD_EVT_PWR_BASE + 0xc)
+#define VCD_EVT_PWR_CLNT_CMD_FAIL (VCD_EVT_PWR_BASE + 0xd)
+#define VCD_EVT_PWR_CLNT_PAUSE (VCD_EVT_PWR_BASE + 0xe)
+#define VCD_EVT_PWR_CLNT_RESUME (VCD_EVT_PWR_BASE + 0xf)
+#define VCD_EVT_PWR_CLNT_FIRST_FRAME (VCD_EVT_PWR_BASE + 0x10)
+#define VCD_EVT_PWR_CLNT_LAST_FRAME (VCD_EVT_PWR_BASE + 0x11)
+#define VCD_EVT_PWR_CLNT_ERRFATAL (VCD_EVT_PWR_BASE + 0x12)
+
+enum vcd_pwr_clk_state {
+ VCD_PWRCLK_STATE_OFF = 0,
+ VCD_PWRCLK_STATE_ON_NOTCLOCKED,
+ VCD_PWRCLK_STATE_ON_CLOCKED,
+ VCD_PWRCLK_STATE_ON_CLOCKGATED
+};
+
+#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_property.h b/drivers/video/msm/vidc/common/vcd/vcd_property.h
new file mode 100644
index 0000000..2cb894e
--- /dev/null
+++ b/drivers/video/msm/vidc/common/vcd/vcd_property.h
@@ -0,0 +1,342 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _VCD_DRIVER_PROPERTY_H_
+#define _VCD_DRIVER_PROPERTY_H_
+
+#define VCD_START_BASE 0x0
+#define VCD_I_LIVE (VCD_START_BASE + 0x1)
+#define VCD_I_CODEC (VCD_START_BASE + 0x2)
+#define VCD_I_FRAME_SIZE (VCD_START_BASE + 0x3)
+#define VCD_I_METADATA_ENABLE (VCD_START_BASE + 0x4)
+#define VCD_I_METADATA_HEADER (VCD_START_BASE + 0x5)
+#define VCD_I_PROFILE (VCD_START_BASE + 0x6)
+#define VCD_I_LEVEL (VCD_START_BASE + 0x7)
+#define VCD_I_BUFFER_FORMAT (VCD_START_BASE + 0x8)
+#define VCD_I_FRAME_RATE (VCD_START_BASE + 0x9)
+#define VCD_I_TARGET_BITRATE (VCD_START_BASE + 0xA)
+#define VCD_I_MULTI_SLICE (VCD_START_BASE + 0xB)
+#define VCD_I_ENTROPY_CTRL (VCD_START_BASE + 0xC)
+#define VCD_I_DEBLOCKING (VCD_START_BASE + 0xD)
+#define VCD_I_RATE_CONTROL (VCD_START_BASE + 0xE)
+#define VCD_I_QP_RANGE (VCD_START_BASE + 0xF)
+#define VCD_I_SESSION_QP (VCD_START_BASE + 0x10)
+#define VCD_I_INTRA_PERIOD (VCD_START_BASE + 0x11)
+#define VCD_I_VOP_TIMING (VCD_START_BASE + 0x12)
+#define VCD_I_SHORT_HEADER (VCD_START_BASE + 0x13)
+#define VCD_I_SEQ_HEADER (VCD_START_BASE + 0x14)
+#define VCD_I_HEADER_EXTENSION (VCD_START_BASE + 0x15)
+#define VCD_I_INTRA_REFRESH (VCD_START_BASE + 0x16)
+#define VCD_I_POST_FILTER (VCD_START_BASE + 0x17)
+#define VCD_I_PROGRESSIVE_ONLY (VCD_START_BASE + 0x18)
+#define VCD_I_OUTPUT_ORDER (VCD_START_BASE + 0x19)
+#define VCD_I_RECON_BUFFERS (VCD_START_BASE + 0x1A)
+#define VCD_I_FREE_RECON_BUFFERS (VCD_START_BASE + 0x1B)
+#define VCD_I_GET_RECON_BUFFER_SIZE (VCD_START_BASE + 0x1C)
+#define VCD_I_H264_MV_BUFFER (VCD_START_BASE + 0x1D)
+#define VCD_I_FREE_H264_MV_BUFFER (VCD_START_BASE + 0x1E)
+#define VCD_I_GET_H264_MV_SIZE (VCD_START_BASE + 0x1F)
+#define VCD_I_DEC_PICTYPE (VCD_START_BASE + 0x20)
+#define VCD_I_CONT_ON_RECONFIG (VCD_START_BASE + 0x21)
+
+#define VCD_START_REQ (VCD_START_BASE + 0x1000)
+#define VCD_I_REQ_IFRAME (VCD_START_REQ + 0x1)
+
+#define VCD_I_RESERVED_BASE (VCD_START_BASE + 0x10000)
+
+struct vcd_property_hdr {
+ u32 prop_id;
+ size_t sz;
+};
+
+struct vcd_property_live {
+ u32 live;
+};
+
+enum vcd_codec {
+ VCD_CODEC_H264 = 0x1,
+ VCD_CODEC_H263 = 0x2,
+ VCD_CODEC_MPEG1 = 0x3,
+ VCD_CODEC_MPEG2 = 0x4,
+ VCD_CODEC_MPEG4 = 0x5,
+ VCD_CODEC_DIVX_3 = 0x6,
+ VCD_CODEC_DIVX_4 = 0x7,
+ VCD_CODEC_DIVX_5 = 0x8,
+ VCD_CODEC_DIVX_6 = 0x9,
+ VCD_CODEC_XVID = 0xA,
+ VCD_CODEC_VC1 = 0xB,
+ VCD_CODEC_VC1_RCV = 0xC
+};
+
+struct vcd_property_codec {
+ enum vcd_codec codec;
+};
+
+struct vcd_property_frame_size {
+ u32 width;
+ u32 height;
+ u32 stride;
+ u32 scan_lines;
+};
+
+
+#define VCD_METADATA_DATANONE 0x001
+#define VCD_METADATA_QCOMFILLER 0x002
+#define VCD_METADATA_QPARRAY 0x004
+#define VCD_METADATA_CONCEALMB 0x008
+#define VCD_METADATA_SEI 0x010
+#define VCD_METADATA_VUI 0x020
+#define VCD_METADATA_VC1 0x040
+#define VCD_METADATA_PASSTHROUGH 0x080
+#define VCD_METADATA_ENC_SLICE 0x100
+
+struct vcd_property_meta_data_enable {
+ u32 meta_data_enable_flag;
+};
+
+struct vcd_property_metadata_hdr {
+ u32 meta_data_id;
+ u32 version;
+ u32 port_index;
+ u32 type;
+};
+
+struct vcd_property_frame_rate {
+ u32 fps_denominator;
+ u32 fps_numerator;
+};
+
+struct vcd_property_target_bitrate {
+ u32 target_bitrate;
+};
+
+enum vcd_yuv_buffer_format {
+ VCD_BUFFER_FORMAT_NV12 = 0x1,
+ VCD_BUFFER_FORMAT_TILE_4x2 = 0x2,
+ VCD_BUFFER_FORMAT_NV12_16M2KA = 0x3,
+ VCD_BUFFER_FORMAT_TILE_1x1 = 0x4
+};
+
+struct vcd_property_buffer_format {
+ enum vcd_yuv_buffer_format buffer_format;
+};
+
+struct vcd_property_post_filter {
+ u32 post_filter;
+};
+
+enum vcd_codec_profile {
+ VCD_PROFILE_UNKNOWN = 0x0,
+ VCD_PROFILE_MPEG4_SP = 0x1,
+ VCD_PROFILE_MPEG4_ASP = 0x2,
+ VCD_PROFILE_H264_BASELINE = 0x3,
+ VCD_PROFILE_H264_MAIN = 0x4,
+ VCD_PROFILE_H264_HIGH = 0x5,
+ VCD_PROFILE_H263_BASELINE = 0x6,
+ VCD_PROFILE_VC1_SIMPLE = 0x7,
+ VCD_PROFILE_VC1_MAIN = 0x8,
+ VCD_PROFILE_VC1_ADVANCE = 0x9,
+ VCD_PROFILE_MPEG2_MAIN = 0xA,
+ VCD_PROFILE_MPEG2_SIMPLE = 0xB
+};
+
+struct vcd_property_profile {
+ enum vcd_codec_profile profile;
+};
+
+enum vcd_codec_level {
+ VCD_LEVEL_UNKNOWN = 0x0,
+ VCD_LEVEL_MPEG4_0 = 0x1,
+ VCD_LEVEL_MPEG4_0b = 0x2,
+ VCD_LEVEL_MPEG4_1 = 0x3,
+ VCD_LEVEL_MPEG4_2 = 0x4,
+ VCD_LEVEL_MPEG4_3 = 0x5,
+ VCD_LEVEL_MPEG4_3b = 0x6,
+ VCD_LEVEL_MPEG4_4 = 0x7,
+ VCD_LEVEL_MPEG4_4a = 0x8,
+ VCD_LEVEL_MPEG4_5 = 0x9,
+ VCD_LEVEL_MPEG4_6 = 0xA,
+ VCD_LEVEL_MPEG4_7 = 0xB,
+ VCD_LEVEL_MPEG4_X = 0xC,
+ VCD_LEVEL_H264_1 = 0x10,
+ VCD_LEVEL_H264_1b = 0x11,
+ VCD_LEVEL_H264_1p1 = 0x12,
+ VCD_LEVEL_H264_1p2 = 0x13,
+ VCD_LEVEL_H264_1p3 = 0x14,
+ VCD_LEVEL_H264_2 = 0x15,
+ VCD_LEVEL_H264_2p1 = 0x16,
+ VCD_LEVEL_H264_2p2 = 0x17,
+ VCD_LEVEL_H264_3 = 0x18,
+ VCD_LEVEL_H264_3p1 = 0x19,
+ VCD_LEVEL_H264_3p2 = 0x1A,
+ VCD_LEVEL_H264_4 = 0x1B,
+ VCD_LEVEL_H264_4p1 = 0x1C,
+ VCD_LEVEL_H264_4p2 = 0x1D,
+ VCD_LEVEL_H264_5 = 0x1E,
+ VCD_LEVEL_H264_5p1 = 0x1F,
+ VCD_LEVEL_H263_10 = 0x20,
+ VCD_LEVEL_H263_20 = 0x21,
+ VCD_LEVEL_H263_30 = 0x22,
+ VCD_LEVEL_H263_40 = 0x23,
+ VCD_LEVEL_H263_45 = 0x24,
+ VCD_LEVEL_H263_50 = 0x25,
+ VCD_LEVEL_H263_60 = 0x26,
+ VCD_LEVEL_H263_70 = 0x27,
+ VCD_LEVEL_H263_X = 0x28,
+ VCD_LEVEL_MPEG2_LOW = 0x30,
+ VCD_LEVEL_MPEG2_MAIN = 0x31,
+ VCD_LEVEL_MPEG2_HIGH_14 = 0x32,
+ VCD_LEVEL_MPEG2_HIGH = 0x33,
+ VCD_LEVEL_MPEG2_X = 0x34,
+ VCD_LEVEL_VC1_S_LOW = 0x40,
+ VCD_LEVEL_VC1_S_MEDIUM = 0x41,
+ VCD_LEVEL_VC1_M_LOW = 0x42,
+ VCD_LEVEL_VC1_M_MEDIUM = 0x43,
+ VCD_LEVEL_VC1_M_HIGH = 0x44,
+ VCD_LEVEL_VC1_A_0 = 0x45,
+ VCD_LEVEL_VC1_A_1 = 0x46,
+ VCD_LEVEL_VC1_A_2 = 0x47,
+ VCD_LEVEL_VC1_A_3 = 0x48,
+ VCD_LEVEL_VC1_A_4 = 0x49,
+ VCD_LEVEL_VC1_X = 0x4A
+};
+
+struct vcd_property_level {
+ enum vcd_codec_level level;
+};
+
+enum vcd_m_slice_sel {
+ VCD_MSLICE_OFF = 0x1,
+ VCD_MSLICE_BY_MB_COUNT = 0x2,
+ VCD_MSLICE_BY_BYTE_COUNT = 0x3,
+ VCD_MSLICE_BY_GOB = 0x4
+};
+
+struct vcd_property_multi_slice {
+ enum vcd_m_slice_sel m_slice_sel;
+ u32 m_slice_size;
+};
+
+enum vcd_entropy_sel {
+ VCD_ENTROPY_SEL_CAVLC = 0x1,
+ VCD_ENTROPY_SEL_CABAC = 0x2
+};
+
+enum vcd_cabac_model {
+ VCD_CABAC_MODEL_NUMBER_0 = 0x1,
+ VCD_CABAC_MODEL_NUMBER_1 = 0x2,
+ VCD_CABAC_MODEL_NUMBER_2 = 0x3
+};
+
+struct vcd_property_entropy_control {
+ enum vcd_entropy_sel entropy_sel;
+ enum vcd_cabac_model cabac_model;
+};
+
+enum vcd_db_config {
+ VCD_DB_ALL_BLOCKING_BOUNDARY = 0x1,
+ VCD_DB_DISABLE = 0x2,
+ VCD_DB_SKIP_SLICE_BOUNDARY = 0x3
+};
+struct vcd_property_db_config {
+ enum vcd_db_config db_config;
+ u32 slice_alpha_offset;
+ u32 slice_beta_offset;
+};
+
+enum vcd_rate_control {
+ VCD_RATE_CONTROL_OFF = 0x1,
+ VCD_RATE_CONTROL_VBR_VFR = 0x2,
+ VCD_RATE_CONTROL_VBR_CFR = 0x3,
+ VCD_RATE_CONTROL_CBR_VFR = 0x4,
+ VCD_RATE_CONTROL_CBR_CFR = 0x5
+};
+
+struct vcd_property_rate_control {
+ enum vcd_rate_control rate_control;
+};
+
+struct vcd_property_qp_range {
+ u32 max_qp;
+ u32 min_qp;
+};
+
+struct vcd_property_session_qp {
+ u32 i_frame_qp;
+ u32 p_frame_qp;
+ u32 b_frame_qp;
+};
+
+struct vcd_property_i_period {
+ u32 p_frames;
+ u32 b_frames;
+};
+
+struct vcd_property_vop_timing {
+ u32 vop_time_resolution;
+};
+
+struct vcd_property_short_header {
+ u32 short_header;
+};
+
+struct vcd_property_intra_refresh_mb_number {
+ u32 cir_mb_number;
+};
+
+struct vcd_property_req_i_frame {
+ u32 req_i_frame;
+};
+
+struct vcd_frame_rect{
+ u32 left;
+ u32 top;
+ u32 right;
+ u32 bottom;
+};
+
+struct vcd_property_dec_output_buffer {
+ struct vcd_frame_rect disp_frm;
+ struct vcd_property_frame_size frm_size;
+};
+
+enum vcd_output_order {
+ VCD_DEC_ORDER_DISPLAY = 0x0,
+ VCD_DEC_ORDER_DECODE = 0x1
+};
+
+struct vcd_property_enc_recon_buffer{
+ u8 *kernel_virtual_addr;
+ u8 *physical_addr;
+ u32 buffer_size;
+ u32 ysize;
+ int pmem_fd;
+ u32 offset;
+};
+
+struct vcd_property_h264_mv_buffer{
+ u8 *kernel_virtual_addr;
+ u8 *physical_addr;
+ u32 size;
+ u32 count;
+ int pmem_fd;
+ u32 offset;
+};
+
+struct vcd_property_buffer_size{
+ int width;
+ int height;
+ int size;
+ int alignment;
+};
+
+#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c b/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c
new file mode 100644
index 0000000..34a3445
--- /dev/null
+++ b/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c
@@ -0,0 +1,286 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "vidc_type.h"
+#include "vcd.h"
+
+#define NORMALIZATION_FACTOR 3600
+#define ADJUST_CLIENT_ROUNDS(client, round_adjustment) \
+do {\
+ if ((client)->rounds < round_adjustment) {\
+ (client)->rounds = 0;\
+ VCD_MSG_HIGH("%s(): WARNING: Scheduler list unsorted",\
+ __func__);\
+ } else\
+ (client)->rounds -= round_adjustment;\
+} while (0)
+
+u32 vcd_sched_create(struct list_head *sched_list)
+{
+ u32 rc = VCD_S_SUCCESS;
+ if (!sched_list) {
+ VCD_MSG_ERROR("%s(): Invalid parameter", __func__);
+ rc = VCD_ERR_ILLEGAL_PARM;
+ } else
+ INIT_LIST_HEAD(sched_list);
+ return rc;
+}
+
+void vcd_sched_destroy(struct list_head *sched_clnt_list)
+{
+ struct vcd_sched_clnt_ctx *sched_clnt, *sched_clnt_next;
+ if (sched_clnt_list)
+ list_for_each_entry_safe(sched_clnt,
+ sched_clnt_next, sched_clnt_list, list) {
+ list_del_init(&sched_clnt->list);
+ sched_clnt->clnt_active = false;
+ }
+}
+
+void insert_client_in_list(struct list_head *sched_clnt_list,
+ struct vcd_sched_clnt_ctx *sched_new_clnt, bool tail)
+{
+ struct vcd_sched_clnt_ctx *sched_clnt;
+ if (!list_empty(sched_clnt_list)) {
+ if (tail)
+ sched_clnt = list_entry(sched_clnt_list->prev,
+ struct vcd_sched_clnt_ctx, list);
+ else
+ sched_clnt = list_first_entry(sched_clnt_list,
+ struct vcd_sched_clnt_ctx, list);
+ sched_new_clnt->rounds = sched_clnt->rounds;
+ } else
+ sched_new_clnt->rounds = 0;
+ if (tail)
+ list_add_tail(&sched_new_clnt->list, sched_clnt_list);
+ else
+ list_add(&sched_new_clnt->list, sched_clnt_list);
+}
+
+u32 vcd_sched_add_client(struct vcd_clnt_ctxt *cctxt)
+{
+ struct vcd_property_hdr prop_hdr;
+ struct vcd_sched_clnt_ctx *sched_cctxt;
+ u32 rc = VCD_S_SUCCESS;
+ if (!cctxt) {
+ VCD_MSG_ERROR("%s(): Invalid parameter", __func__);
+ rc = VCD_ERR_ILLEGAL_PARM;
+ } else if (cctxt->sched_clnt_hdl)
+ VCD_MSG_HIGH(
+ "%s(): Scheduler client already exists!", __func__);
+ else {
+ sched_cctxt = (struct vcd_sched_clnt_ctx *)
+ kmalloc(sizeof(struct vcd_sched_clnt_ctx),
+ GFP_KERNEL);
+ if (sched_cctxt) {
+
+ prop_hdr.prop_id = DDL_I_FRAME_PROC_UNITS;
+ prop_hdr.sz = sizeof(cctxt->frm_p_units);
+ rc = ddl_get_property(cctxt->ddl_handle, &prop_hdr,
+ &cctxt->frm_p_units);
+ VCD_FAILED_RETURN(rc,
+ "Failed: Get DDL_I_FRAME_PROC_UNITS");
+ if (cctxt->decoding) {
+ cctxt->frm_rate.fps_numerator =
+ VCD_DEC_INITIAL_FRAME_RATE;
+ cctxt->frm_rate.fps_denominator = 1;
+ } else {
+ prop_hdr.prop_id = VCD_I_FRAME_RATE;
+ prop_hdr.sz = sizeof(cctxt->frm_rate);
+ rc = ddl_get_property(cctxt->ddl_handle,
+ &prop_hdr, &cctxt->frm_rate);
+ VCD_FAILED_RETURN(rc,
+ "Failed: Get VCD_I_FRAME_RATE");
+ }
+ cctxt->reqd_perf_lvl = cctxt->frm_p_units *
+ cctxt->frm_rate.fps_numerator /
+ cctxt->frm_rate.fps_denominator;
+
+ cctxt->sched_clnt_hdl = sched_cctxt;
+ memset(sched_cctxt, 0,
+ sizeof(struct vcd_sched_clnt_ctx));
+ sched_cctxt->tkns = 0;
+ sched_cctxt->round_perfrm = NORMALIZATION_FACTOR *
+ cctxt->frm_rate.fps_denominator /
+ cctxt->frm_rate.fps_numerator;
+ sched_cctxt->clnt_active = true;
+ sched_cctxt->clnt_data = cctxt;
+ INIT_LIST_HEAD(&sched_cctxt->ip_frm_list);
+
+ insert_client_in_list(
+ &cctxt->dev_ctxt->sched_clnt_list,
+ sched_cctxt, false);
+ }
+ }
+ return rc;
+}
+
+u32 vcd_sched_remove_client(struct vcd_sched_clnt_ctx *sched_cctxt)
+{
+ u32 rc = VCD_S_SUCCESS;
+ struct vcd_clnt_ctxt *cctxt;
+ if (!sched_cctxt) {
+ VCD_MSG_ERROR("%s(): Invalid handle ptr", __func__);
+ rc = VCD_ERR_ILLEGAL_PARM;
+ } else if (!list_empty(&sched_cctxt->ip_frm_list)) {
+ VCD_MSG_ERROR(
+ "%s(): Cannot remove client, queue no empty", __func__);
+ rc = VCD_ERR_ILLEGAL_OP;
+ } else {
+ cctxt = sched_cctxt->clnt_data;
+ list_del(&sched_cctxt->list);
+ memset(sched_cctxt, 0,
+ sizeof(struct vcd_sched_clnt_ctx));
+ kfree(sched_cctxt);
+ }
+ return rc;
+}
+
+u32 vcd_sched_update_config(struct vcd_clnt_ctxt *cctxt)
+{
+ u32 rc = VCD_S_SUCCESS;
+ if (!cctxt || !cctxt->sched_clnt_hdl) {
+ VCD_MSG_ERROR("%s(): Invalid parameter", __func__);
+ rc = VCD_ERR_ILLEGAL_PARM;
+ } else {
+ cctxt->sched_clnt_hdl->rounds /=
+ cctxt->sched_clnt_hdl->round_perfrm;
+ cctxt->sched_clnt_hdl->round_perfrm =
+ NORMALIZATION_FACTOR *
+ cctxt->frm_rate.fps_denominator /
+ cctxt->frm_rate.fps_numerator;
+ cctxt->sched_clnt_hdl->rounds *=
+ cctxt->sched_clnt_hdl->round_perfrm;
+ }
+ return rc;
+}
+
+u32 vcd_sched_queue_buffer(
+ struct vcd_sched_clnt_ctx *sched_cctxt,
+ struct vcd_buffer_entry *buffer, u32 tail)
+{
+ u32 rc = VCD_S_SUCCESS;
+ if (!sched_cctxt || !buffer) {
+ VCD_MSG_ERROR("%s(): Invalid parameter", __func__);
+ rc = VCD_ERR_ILLEGAL_PARM;
+ } else if (tail)
+ list_add_tail(&buffer->sched_list,
+ &sched_cctxt->ip_frm_list);
+ else
+ list_add(&buffer->sched_list, &sched_cctxt->ip_frm_list);
+ return rc;
+}
+
+u32 vcd_sched_dequeue_buffer(
+ struct vcd_sched_clnt_ctx *sched_cctxt,
+ struct vcd_buffer_entry **buffer)
+{
+ u32 rc = VCD_ERR_QEMPTY;
+ if (!sched_cctxt || !buffer) {
+ VCD_MSG_ERROR("%s(): Invalid parameter", __func__);
+ rc = VCD_ERR_ILLEGAL_PARM;
+ } else {
+ *buffer = NULL;
+ if (!list_empty(&sched_cctxt->ip_frm_list)) {
+ *buffer = list_first_entry(
+ &sched_cctxt->ip_frm_list,
+ struct vcd_buffer_entry,
+ sched_list);
+ list_del(&(*buffer)->sched_list);
+ rc = VCD_S_SUCCESS;
+ }
+ }
+ return rc;
+}
+
+u32 vcd_sched_mark_client_eof(struct vcd_sched_clnt_ctx *sched_cctxt)
+{
+ u32 rc = VCD_S_SUCCESS;
+ struct vcd_buffer_entry *buffer = NULL;
+ if (!sched_cctxt) {
+ VCD_MSG_ERROR("%s(): Invalid parameter", __func__);
+ rc = VCD_ERR_ILLEGAL_PARM;
+ } else if (!list_empty(&sched_cctxt->ip_frm_list)) {
+ buffer = list_entry(sched_cctxt->ip_frm_list.prev,
+ struct vcd_buffer_entry, sched_list);
+ buffer->frame.flags |= VCD_FRAME_FLAG_EOS;
+ } else
+ rc = VCD_ERR_QEMPTY;
+ return rc;
+}
+
+u32 vcd_sched_suspend_resume_clnt(
+ struct vcd_clnt_ctxt *cctxt, u32 state)
+{
+ u32 rc = VCD_S_SUCCESS;
+ struct vcd_sched_clnt_ctx *sched_cctxt;
+ if (!cctxt || !cctxt->sched_clnt_hdl) {
+ VCD_MSG_ERROR("%s(): Invalid parameter", __func__);
+ rc = VCD_ERR_ILLEGAL_PARM;
+ } else {
+ sched_cctxt = cctxt->sched_clnt_hdl;
+ if (state != sched_cctxt->clnt_active) {
+ sched_cctxt->clnt_active = state;
+ if (state)
+ insert_client_in_list(&cctxt->dev_ctxt->\
+ sched_clnt_list, sched_cctxt, false);
+ else
+ list_del_init(&sched_cctxt->list);
+ }
+ }
+ return rc;
+}
+
+u32 vcd_sched_get_client_frame(struct list_head *sched_clnt_list,
+ struct vcd_clnt_ctxt **cctxt,
+ struct vcd_buffer_entry **buffer)
+{
+ u32 rc = VCD_ERR_QEMPTY, round_adjustment = 0;
+ struct vcd_sched_clnt_ctx *sched_clnt, *clnt_nxt;
+ if (!sched_clnt_list || !cctxt || !buffer) {
+ VCD_MSG_ERROR("%s(): Invalid parameter", __func__);
+ rc = VCD_ERR_ILLEGAL_PARM;
+ } else if (!list_empty(sched_clnt_list)) {
+ *cctxt = NULL;
+ *buffer = NULL;
+ list_for_each_entry_safe(sched_clnt,
+ clnt_nxt, sched_clnt_list, list) {
+ if (&sched_clnt->list == sched_clnt_list->next)
+ round_adjustment = sched_clnt->rounds;
+ if (*cctxt) {
+ if ((*cctxt)->sched_clnt_hdl->rounds >=
+ sched_clnt->rounds)
+ list_move(&(*cctxt)->sched_clnt_hdl\
+ ->list, &sched_clnt->list);
+ ADJUST_CLIENT_ROUNDS(sched_clnt,
+ round_adjustment);
+ } else if (sched_clnt->tkns &&
+ !list_empty(&sched_clnt->ip_frm_list)) {
+ *cctxt = sched_clnt->clnt_data;
+ sched_clnt->rounds += sched_clnt->round_perfrm;
+ } else
+ ADJUST_CLIENT_ROUNDS(sched_clnt,
+ round_adjustment);
+ }
+ if (*cctxt) {
+ rc = vcd_sched_dequeue_buffer(
+ (*cctxt)->sched_clnt_hdl, buffer);
+ if (rc == VCD_S_SUCCESS) {
+ (*cctxt)->sched_clnt_hdl->tkns--;
+ ADJUST_CLIENT_ROUNDS((*cctxt)->\
+ sched_clnt_hdl, round_adjustment);
+ }
+ }
+ }
+ return rc;
+}
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_status.h b/drivers/video/msm/vidc/common/vcd/vcd_status.h
new file mode 100644
index 0000000..807718f
--- /dev/null
+++ b/drivers/video/msm/vidc/common/vcd/vcd_status.h
@@ -0,0 +1,60 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _VCD_ERR_STATUS_H_
+#define _VCD_ERR_STATUS_H_
+
+#define VCD_EVT_RESP_BASE 0x1000
+#define VCD_EVT_RESP_OPEN (VCD_EVT_RESP_BASE + 0x1)
+#define VCD_EVT_RESP_START (VCD_EVT_RESP_BASE + 0x2)
+#define VCD_EVT_RESP_STOP (VCD_EVT_RESP_BASE + 0x3)
+#define VCD_EVT_RESP_PAUSE (VCD_EVT_RESP_BASE + 0x4)
+#define VCD_EVT_RESP_FLUSH_INPUT_DONE (VCD_EVT_RESP_BASE + 0x5)
+#define VCD_EVT_RESP_FLUSH_OUTPUT_DONE (VCD_EVT_RESP_BASE + 0x6)
+#define VCD_EVT_RESP_INPUT_FLUSHED (VCD_EVT_RESP_BASE + 0x7)
+#define VCD_EVT_RESP_OUTPUT_FLUSHED (VCD_EVT_RESP_BASE + 0x8)
+#define VCD_EVT_RESP_INPUT_DONE (VCD_EVT_RESP_BASE + 0x9)
+#define VCD_EVT_RESP_OUTPUT_DONE (VCD_EVT_RESP_BASE + 0xa)
+
+#define VCD_EVT_IND_BASE 0x2000
+#define VCD_EVT_IND_INPUT_RECONFIG (VCD_EVT_IND_BASE + 0x1)
+#define VCD_EVT_IND_OUTPUT_RECONFIG (VCD_EVT_IND_BASE + 0x2)
+#define VCD_EVT_IND_HWERRFATAL (VCD_EVT_IND_BASE + 0x3)
+#define VCD_EVT_IND_RESOURCES_LOST (VCD_EVT_IND_BASE + 0x4)
+#define VCD_EVT_IND_INFO_OUTPUT_RECONFIG (VCD_EVT_IND_BASE + 0x5)
+
+#define VCD_S_SUCCESS 0x0
+
+#define VCD_S_ERR_BASE 0x80000000
+#define VCD_ERR_FAIL (VCD_S_ERR_BASE + 0x01)
+#define VCD_ERR_ALLOC_FAIL (VCD_S_ERR_BASE + 0x02)
+#define VCD_ERR_ILLEGAL_OP (VCD_S_ERR_BASE + 0x03)
+#define VCD_ERR_ILLEGAL_PARM (VCD_S_ERR_BASE + 0x04)
+#define VCD_ERR_BAD_POINTER (VCD_S_ERR_BASE + 0x05)
+#define VCD_ERR_BAD_HANDLE (VCD_S_ERR_BASE + 0x06)
+#define VCD_ERR_NOT_SUPPORTED (VCD_S_ERR_BASE + 0x07)
+#define VCD_ERR_BAD_STATE (VCD_S_ERR_BASE + 0x08)
+#define VCD_ERR_BUSY (VCD_S_ERR_BASE + 0x09)
+#define VCD_ERR_MAX_CLIENT (VCD_S_ERR_BASE + 0x0a)
+#define VCD_ERR_IFRAME_EXPECTED (VCD_S_ERR_BASE + 0x0b)
+#define VCD_ERR_INTRLCD_FIELD_DROP (VCD_S_ERR_BASE + 0x0c)
+#define VCD_ERR_HW_FATAL (VCD_S_ERR_BASE + 0x0d)
+#define VCD_ERR_BITSTREAM_ERR (VCD_S_ERR_BASE + 0x0e)
+#define VCD_ERR_QEMPTY (VCD_S_ERR_BASE + 0x0f)
+#define VCD_ERR_SEQHDR_PARSE_FAIL (VCD_S_ERR_BASE + 0x10)
+#define VCD_ERR_INPUT_NOT_PROCESSED (VCD_S_ERR_BASE + 0x11)
+#define VCD_ERR_INDEX_NOMORE (VCD_S_ERR_BASE + 0x12)
+
+#define VCD_FAILED(rc) ((rc > VCD_S_ERR_BASE) ? true : false)
+
+#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
new file mode 100644
index 0000000..6bc591b
--- /dev/null
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -0,0 +1,3057 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <asm/div64.h>
+
+#include "vidc_type.h"
+#include "vcd.h"
+#include "vdec_internal.h"
+#include <linux/memory_alloc.h>
+
+#define MAX(x, y) (((x) > (y)) ? (x) : (y))
+
+static int vcd_pmem_alloc(size_t sz, u8 **kernel_vaddr, u8 **phy_addr)
+{
+ u32 memtype;
+
+ if (!kernel_vaddr || !phy_addr) {
+ pr_err("\n%s: Invalid parameters", __func__);
+ return -ENOMEM;
+ }
+ memtype = res_trk_get_mem_type();
+ *phy_addr = (u8 *) allocate_contiguous_memory_nomap(sz,
+ memtype, SZ_4K);
+ if (!*phy_addr) {
+ *kernel_vaddr = ioremap((unsigned long)*phy_addr, sz);
+
+ if (!*kernel_vaddr) {
+ pr_err("%s: could not ioremap in kernel pmem buffers\n",
+ __func__);
+ free_contiguous_memory_by_paddr(
+ (unsigned long) *phy_addr);
+ *phy_addr = NULL;
+ return -ENOMEM;
+ }
+ pr_debug("write buf: phy addr 0x%08x kernel addr 0x%08x\n",
+ (u32) *phy_addr, (u32) *kernel_vaddr);
+ return 0;
+ } else {
+ pr_err("%s: could not allocte in kernel pmem buffers\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+}
+
+static int vcd_pmem_free(u8 *kernel_vaddr, u8 *phy_addr)
+{
+ if (kernel_vaddr)
+ iounmap((void *)kernel_vaddr);
+ if (phy_addr)
+ free_contiguous_memory_by_paddr((unsigned long)phy_addr);
+ kernel_vaddr = NULL;
+ phy_addr = NULL;
+ return 0;
+}
+
+u8 *vcd_pmem_get_physical(struct video_client_ctx *client_ctx,
+ unsigned long kernel_vaddr)
+{
+ unsigned long phy_addr, user_vaddr;
+ int pmem_fd;
+ struct file *file;
+ s32 buffer_index = -1;
+
+ if (vidc_lookup_addr_table(client_ctx, BUFFER_TYPE_INPUT,
+ false, &user_vaddr, &kernel_vaddr,
+ &phy_addr, &pmem_fd, &file,
+ &buffer_index)) {
+
+ return (u8 *) phy_addr;
+ } else if (vidc_lookup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT,
+ false, &user_vaddr, &kernel_vaddr, &phy_addr, &pmem_fd, &file,
+ &buffer_index)) {
+ return (u8 *) phy_addr;
+ } else {
+ VCD_MSG_ERROR("Couldn't get physical address");
+
+ return NULL;
+ }
+
+}
+
+void vcd_reset_device_channels(struct vcd_dev_ctxt *dev_ctxt)
+{
+ dev_ctxt->ddl_frame_ch_free = dev_ctxt->ddl_frame_ch_depth;
+ dev_ctxt->ddl_cmd_ch_free = dev_ctxt->ddl_cmd_ch_depth;
+ dev_ctxt->ddl_frame_ch_interim = 0;
+ dev_ctxt->ddl_cmd_ch_interim = 0;
+}
+
+u32 vcd_get_command_channel(
+ struct vcd_dev_ctxt *dev_ctxt,
+ struct vcd_transc **transc)
+{
+ u32 result = false;
+
+ *transc = NULL;
+
+ if (dev_ctxt->ddl_cmd_ch_free > 0) {
+ if (dev_ctxt->ddl_cmd_concurrency) {
+ --dev_ctxt->ddl_cmd_ch_free;
+ result = true;
+ } else if ((dev_ctxt->ddl_frame_ch_free +
+ dev_ctxt->ddl_frame_ch_interim)
+ == dev_ctxt->ddl_frame_ch_depth) {
+ --dev_ctxt->ddl_cmd_ch_free;
+ result = true;
+ }
+ }
+
+ if (result) {
+ *transc = vcd_get_free_trans_tbl_entry(dev_ctxt);
+
+ if (!*transc) {
+ result = false;
+
+ vcd_release_command_channel(dev_ctxt, *transc);
+ }
+
+ }
+ return result;
+}
+
+u32 vcd_get_command_channel_in_loop(
+ struct vcd_dev_ctxt *dev_ctxt,
+ struct vcd_transc **transc)
+{
+ u32 result = false;
+
+ *transc = NULL;
+
+ if (dev_ctxt->ddl_cmd_ch_interim > 0) {
+ if (dev_ctxt->ddl_cmd_concurrency) {
+ --dev_ctxt->ddl_cmd_ch_interim;
+ result = true;
+ } else if ((dev_ctxt->ddl_frame_ch_free +
+ dev_ctxt->ddl_frame_ch_interim)
+ == dev_ctxt->ddl_frame_ch_depth) {
+ --dev_ctxt->ddl_cmd_ch_interim;
+ result = true;
+ }
+ } else {
+ result = vcd_get_command_channel(dev_ctxt, transc);
+ }
+
+ if (result && !*transc) {
+ *transc = vcd_get_free_trans_tbl_entry(dev_ctxt);
+
+ if (!*transc) {
+ result = false;
+
+ ++dev_ctxt->ddl_cmd_ch_interim;
+ }
+
+ }
+
+ return result;
+}
+
+void vcd_mark_command_channel(struct vcd_dev_ctxt *dev_ctxt,
+ struct vcd_transc *transc)
+{
+ ++dev_ctxt->ddl_cmd_ch_interim;
+
+ vcd_release_trans_tbl_entry(transc);
+ if (dev_ctxt->ddl_cmd_ch_interim +
+ dev_ctxt->ddl_cmd_ch_free >
+ dev_ctxt->ddl_cmd_ch_depth) {
+ VCD_MSG_ERROR("\n Command channel access counters messed up");
+ }
+}
+
+void vcd_release_command_channel(
+ struct vcd_dev_ctxt *dev_ctxt, struct vcd_transc *transc)
+{
+ ++dev_ctxt->ddl_cmd_ch_free;
+
+ vcd_release_trans_tbl_entry(transc);
+ if (dev_ctxt->ddl_cmd_ch_interim + dev_ctxt->ddl_cmd_ch_free >
+ dev_ctxt->ddl_cmd_ch_depth) {
+ VCD_MSG_ERROR("\n Command channel access counters messed up");
+ }
+}
+
+void vcd_release_multiple_command_channels(struct vcd_dev_ctxt
+ *dev_ctxt, u32 channels)
+{
+ dev_ctxt->ddl_cmd_ch_free += channels;
+
+ if (dev_ctxt->ddl_cmd_ch_interim +
+ dev_ctxt->ddl_cmd_ch_free >
+ dev_ctxt->ddl_cmd_ch_depth) {
+ VCD_MSG_ERROR("\n Command channel access counters messed up");
+ }
+}
+
+void vcd_release_interim_command_channels(struct vcd_dev_ctxt *dev_ctxt)
+{
+ dev_ctxt->ddl_cmd_ch_free += dev_ctxt->ddl_cmd_ch_interim;
+ dev_ctxt->ddl_cmd_ch_interim = 0;
+
+ if (dev_ctxt->ddl_cmd_ch_interim + dev_ctxt->ddl_cmd_ch_free >
+ dev_ctxt->ddl_cmd_ch_depth) {
+ VCD_MSG_ERROR("\n Command channel access counters messed up");
+ }
+}
+
+u32 vcd_get_frame_channel(struct vcd_dev_ctxt *dev_ctxt,
+ struct vcd_transc **transc)
+{
+ u32 result = false;
+
+ if (dev_ctxt->ddl_frame_ch_free > 0) {
+ if (dev_ctxt->ddl_cmd_concurrency) {
+ --dev_ctxt->ddl_frame_ch_free;
+ result = true;
+ } else if ((dev_ctxt->ddl_cmd_ch_free +
+ dev_ctxt->ddl_cmd_ch_interim)
+ == dev_ctxt->ddl_cmd_ch_depth) {
+ --dev_ctxt->ddl_frame_ch_free;
+ result = true;
+ }
+ }
+
+ if (result) {
+ *transc = vcd_get_free_trans_tbl_entry(dev_ctxt);
+
+ if (!*transc) {
+ result = false;
+
+ vcd_release_frame_channel(dev_ctxt, *transc);
+ } else {
+ (*transc)->type = VCD_CMD_CODE_FRAME;
+ }
+
+ }
+
+ return result;
+}
+
+u32 vcd_get_frame_channel_in_loop(
+ struct vcd_dev_ctxt *dev_ctxt,
+ struct vcd_transc **transc)
+{
+ u32 result = false;
+
+ *transc = NULL;
+
+ if (dev_ctxt->ddl_frame_ch_interim > 0) {
+ if (dev_ctxt->ddl_cmd_concurrency) {
+ --dev_ctxt->ddl_frame_ch_interim;
+ result = true;
+ } else if ((dev_ctxt->ddl_cmd_ch_free +
+ dev_ctxt->ddl_cmd_ch_interim)
+ == dev_ctxt->ddl_cmd_ch_depth) {
+ --dev_ctxt->ddl_frame_ch_interim;
+ result = true;
+ }
+ } else {
+ result = vcd_get_frame_channel(dev_ctxt, transc);
+ }
+
+ if (result && !*transc) {
+ *transc = vcd_get_free_trans_tbl_entry(dev_ctxt);
+
+ if (!*transc) {
+ result = false;
+ VCD_MSG_FATAL("\n%s: All transactions are busy;"
+ "Couldnt find free one\n", __func__);
+ ++dev_ctxt->ddl_frame_ch_interim;
+ } else
+ (*transc)->type = VCD_CMD_CODE_FRAME;
+ }
+
+ return result;
+}
+
+void vcd_mark_frame_channel(struct vcd_dev_ctxt *dev_ctxt)
+{
+ ++dev_ctxt->ddl_frame_ch_interim;
+
+ if (dev_ctxt->ddl_frame_ch_interim +
+ dev_ctxt->ddl_frame_ch_free >
+ dev_ctxt->ddl_cmd_ch_depth) {
+ VCD_MSG_FATAL("Frame channel access counters messed up");
+ }
+}
+
+void vcd_release_frame_channel(struct vcd_dev_ctxt *dev_ctxt,
+ struct vcd_transc *transc)
+{
+ ++dev_ctxt->ddl_frame_ch_free;
+
+ vcd_release_trans_tbl_entry(transc);
+
+ if (dev_ctxt->ddl_frame_ch_interim +
+ dev_ctxt->ddl_frame_ch_free >
+ dev_ctxt->ddl_cmd_ch_depth) {
+ VCD_MSG_FATAL("Frame channel access counters messed up");
+ }
+}
+
+void vcd_release_multiple_frame_channels(struct vcd_dev_ctxt
+ *dev_ctxt, u32 channels)
+{
+ dev_ctxt->ddl_frame_ch_free += channels;
+
+ if (dev_ctxt->ddl_frame_ch_interim +
+ dev_ctxt->ddl_frame_ch_free >
+ dev_ctxt->ddl_frame_ch_depth) {
+ VCD_MSG_FATAL("Frame channel access counters messed up");
+ }
+}
+
+void vcd_release_interim_frame_channels(struct vcd_dev_ctxt
+ *dev_ctxt)
+{
+ dev_ctxt->ddl_frame_ch_free +=
+ dev_ctxt->ddl_frame_ch_interim;
+ dev_ctxt->ddl_frame_ch_interim = 0;
+
+ if (dev_ctxt->ddl_frame_ch_free >
+ dev_ctxt->ddl_cmd_ch_depth) {
+ VCD_MSG_FATAL("Frame channel access counters messed up");
+ }
+}
+
+u32 vcd_core_is_busy(struct vcd_dev_ctxt *dev_ctxt)
+{
+ if (((dev_ctxt->ddl_cmd_ch_free +
+ dev_ctxt->ddl_cmd_ch_interim) !=
+ dev_ctxt->ddl_cmd_ch_depth)
+ ||
+ ((dev_ctxt->ddl_frame_ch_free +
+ dev_ctxt->ddl_frame_ch_interim) !=
+ dev_ctxt->ddl_frame_ch_depth)
+ ) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void vcd_device_timer_start(struct vcd_dev_ctxt *dev_ctxt)
+{
+ if (dev_ctxt->config.timer_start)
+ dev_ctxt->config.timer_start(dev_ctxt->hw_timer_handle,
+ dev_ctxt->hw_time_out);
+}
+
+void vcd_device_timer_stop(struct vcd_dev_ctxt *dev_ctxt)
+{
+ if (dev_ctxt->config.timer_stop)
+ dev_ctxt->config.timer_stop(dev_ctxt->hw_timer_handle);
+}
+
+
+u32 vcd_common_allocate_set_buffer(
+ struct vcd_clnt_ctxt *cctxt,
+ enum vcd_buffer_type buffer,
+ u32 buf_size, struct vcd_buffer_pool **buffer_pool)
+{
+ u32 rc = VCD_S_SUCCESS;
+ struct vcd_buffer_requirement Buf_req;
+ struct vcd_property_hdr Prop_hdr;
+ struct vcd_buffer_pool *buf_pool;
+
+ if (buffer == VCD_BUFFER_INPUT) {
+ Prop_hdr.prop_id = DDL_I_INPUT_BUF_REQ;
+ buf_pool = &cctxt->in_buf_pool;
+ } else if (buffer == VCD_BUFFER_OUTPUT) {
+ Prop_hdr.prop_id = DDL_I_OUTPUT_BUF_REQ;
+ buf_pool = &cctxt->out_buf_pool;
+ } else {
+ rc = VCD_ERR_ILLEGAL_PARM;
+ }
+ VCD_FAILED_RETURN(rc, "Invalid buffer type provided");
+
+ *buffer_pool = buf_pool;
+
+ if (buf_pool->count > 0 &&
+ buf_pool->validated == buf_pool->count) {
+ VCD_MSG_ERROR("Buffer pool is full");
+ return VCD_ERR_FAIL;
+ }
+
+ if (!buf_pool->entries) {
+ Prop_hdr.sz = sizeof(Buf_req);
+ rc = ddl_get_property(cctxt->ddl_handle, &Prop_hdr, &Buf_req);
+ if (!VCD_FAILED(rc)) {
+ rc = vcd_alloc_buffer_pool_entries(buf_pool,
+ &Buf_req);
+ } else {
+ VCD_MSG_ERROR("rc = 0x%x. Failed: ddl_get_property",
+ rc);
+ }
+ }
+
+ if (!VCD_FAILED(rc)) {
+ if (buf_pool->buf_req.sz > buf_size) {
+ VCD_MSG_ERROR("\n required buffer sz %u "
+ "allocated sz %u", buf_pool->buf_req.
+ sz, buf_size);
+
+ rc = VCD_ERR_ILLEGAL_PARM;
+ }
+ }
+
+ return rc;
+}
+
+u32 vcd_set_buffer_internal(
+ struct vcd_clnt_ctxt *cctxt,
+ struct vcd_buffer_pool *buf_pool, u8 *buffer, u32 buf_size)
+{
+ struct vcd_buffer_entry *buf_entry;
+ u8 *physical;
+
+ buf_entry = vcd_find_buffer_pool_entry(buf_pool, buffer);
+ if (buf_entry) {
+ VCD_MSG_ERROR("This buffer address already exists");
+
+ return VCD_ERR_ILLEGAL_OP;
+ }
+
+ physical = (u8 *) vcd_pmem_get_physical(
+ cctxt->client_data, (unsigned long)buffer);
+
+ if (!physical) {
+ VCD_MSG_ERROR("Couldn't get physical address");
+ return VCD_ERR_BAD_POINTER;
+ }
+ if (((u32) physical % buf_pool->buf_req.align)) {
+ VCD_MSG_ERROR("Physical addr is not aligned");
+ return VCD_ERR_BAD_POINTER;
+ }
+
+ buf_entry = vcd_get_free_buffer_pool_entry(buf_pool);
+ if (!buf_entry) {
+ VCD_MSG_ERROR("Can't allocate buffer pool is full");
+ return VCD_ERR_FAIL;
+ }
+
+ buf_entry->virtual = buffer;
+ buf_entry->physical = physical;
+ buf_entry->sz = buf_size;
+ buf_entry->frame.alloc_len = buf_size;
+ buf_entry->allocated = false;
+
+ buf_entry->frame.virtual = buf_entry->virtual;
+ buf_entry->frame.physical = buf_entry->physical;
+
+ buf_pool->validated++;
+
+ return VCD_S_SUCCESS;
+
+}
+
+u32 vcd_allocate_buffer_internal(
+ struct vcd_clnt_ctxt *cctxt,
+ struct vcd_buffer_pool *buf_pool,
+ u32 buf_size, u8 **vir_buf_addr, u8 **phy_buf_addr)
+{
+ struct vcd_buffer_entry *buf_entry;
+ struct vcd_buffer_requirement *buf_req;
+ u32 addr;
+ int rc = 0;
+
+ buf_entry = vcd_get_free_buffer_pool_entry(buf_pool);
+ if (!buf_entry) {
+ VCD_MSG_ERROR("Can't allocate buffer pool is full");
+
+ return VCD_ERR_FAIL;
+ }
+
+ buf_req = &buf_pool->buf_req;
+
+ buf_size += buf_req->align;
+
+ rc = vcd_pmem_alloc(buf_size, &buf_entry->alloc,
+ &buf_entry->physical);
+
+ if (rc < 0) {
+ VCD_MSG_ERROR("Buffer allocation failed");
+
+ return VCD_ERR_ALLOC_FAIL;
+ }
+
+ buf_entry->sz = buf_size;
+ buf_entry->frame.alloc_len = buf_size;
+
+ if (!buf_entry->physical) {
+ VCD_MSG_ERROR("Couldn't get physical address");
+
+ return VCD_ERR_BAD_POINTER;
+ }
+
+ buf_entry->allocated = true;
+
+ if (buf_req->align > 0) {
+
+ addr = (u32) buf_entry->physical;
+ addr += buf_req->align;
+ addr -= (addr % buf_req->align);
+ buf_entry->virtual = buf_entry->alloc;
+ buf_entry->virtual += (u32) (addr - (u32)
+ buf_entry->physical);
+ buf_entry->physical = (u8 *) addr;
+ } else {
+ VCD_MSG_LOW("No buffer alignment required");
+
+ buf_entry->virtual = buf_entry->alloc;
+
+ }
+
+ buf_entry->frame.virtual = buf_entry->virtual;
+ buf_entry->frame.physical = buf_entry->physical;
+
+ *vir_buf_addr = buf_entry->virtual;
+ *phy_buf_addr = buf_entry->physical;
+
+ buf_pool->allocated++;
+ buf_pool->validated++;
+
+ return VCD_S_SUCCESS;
+}
+
+u32 vcd_free_one_buffer_internal(
+ struct vcd_clnt_ctxt *cctxt,
+ enum vcd_buffer_type buffer_type, u8 *buffer)
+{
+ struct vcd_buffer_pool *buf_pool;
+ u32 rc = VCD_S_SUCCESS;
+ struct vcd_buffer_entry *buf_entry;
+ u32 first_frm_recvd = 0;
+
+ if (buffer_type == VCD_BUFFER_INPUT) {
+ buf_pool = &cctxt->in_buf_pool;
+ first_frm_recvd = VCD_FIRST_IP_RCVD;
+ } else if (buffer_type == VCD_BUFFER_OUTPUT) {
+ buf_pool = &cctxt->out_buf_pool;
+ first_frm_recvd = VCD_FIRST_OP_RCVD;
+ } else
+ rc = VCD_ERR_ILLEGAL_PARM;
+
+ VCD_FAILED_RETURN(rc, "Invalid buffer type provided");
+
+ first_frm_recvd &= cctxt->status.mask;
+ if (first_frm_recvd) {
+ VCD_MSG_ERROR(
+ "VCD free buffer called when data path is active");
+ return VCD_ERR_BAD_STATE;
+ }
+
+ buf_entry = vcd_find_buffer_pool_entry(buf_pool, buffer);
+ if (!buf_entry) {
+ VCD_MSG_ERROR("Buffer addr %p not found. Can't free buffer",
+ buffer);
+
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+ if (buf_entry->in_use) {
+ VCD_MSG_ERROR("\n Buffer is in use and is not flushed");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+
+ VCD_MSG_LOW("Freeing buffer %p. Allocated %d",
+ buf_entry->virtual, buf_entry->allocated);
+
+ if (buf_entry->allocated) {
+ vcd_pmem_free(buf_entry->alloc, buf_entry->physical);
+ buf_pool->allocated--;
+ }
+
+ memset(buf_entry, 0, sizeof(struct vcd_buffer_entry));
+ buf_pool->validated--;
+ if (buf_pool->validated == 0)
+ vcd_free_buffer_pool_entries(buf_pool);
+
+ return VCD_S_SUCCESS;
+}
+
+u32 vcd_free_buffers_internal(
+ struct vcd_clnt_ctxt *cctxt,
+ struct vcd_buffer_pool *buf_pool)
+{
+ u32 rc = VCD_S_SUCCESS;
+ u32 i;
+
+ VCD_MSG_LOW("vcd_free_buffers_internal:");
+
+ if (buf_pool->entries) {
+ for (i = 1; i <= buf_pool->count; i++) {
+ if (buf_pool->entries[i].valid &&
+ buf_pool->entries[i].allocated) {
+ vcd_pmem_free(buf_pool->entries[i].alloc,
+ buf_pool->entries[i].
+ physical);
+ }
+ }
+
+ }
+
+ vcd_reset_buffer_pool_for_reuse(buf_pool);
+
+ return rc;
+}
+
+u32 vcd_alloc_buffer_pool_entries(
+ struct vcd_buffer_pool *buf_pool,
+ struct vcd_buffer_requirement *buf_req)
+{
+
+ VCD_MSG_LOW("vcd_alloc_buffer_pool_entries:");
+
+ buf_pool->buf_req = *buf_req;
+
+ buf_pool->count = buf_req->actual_count;
+ buf_pool->entries = (struct vcd_buffer_entry *)
+ kzalloc((sizeof(struct vcd_buffer_entry) *
+ (VCD_MAX_BUFFER_ENTRIES + 1)), GFP_KERNEL);
+
+ if (!buf_pool->entries) {
+ VCD_MSG_ERROR("Buf_pool entries alloc failed");
+ return VCD_ERR_ALLOC_FAIL;
+ }
+
+ INIT_LIST_HEAD(&buf_pool->queue);
+ buf_pool->entries[0].valid = true;
+ buf_pool->q_len = 0;
+
+ buf_pool->validated = 0;
+ buf_pool->allocated = 0;
+ buf_pool->in_use = 0;
+
+ return VCD_S_SUCCESS;
+}
+
+void vcd_free_buffer_pool_entries(struct vcd_buffer_pool *buf_pool)
+{
+ VCD_MSG_LOW("vcd_free_buffer_pool_entries:");
+ kfree(buf_pool->entries);
+ memset(buf_pool, 0, sizeof(struct vcd_buffer_pool));
+ INIT_LIST_HEAD(&buf_pool->queue);
+}
+
+void vcd_flush_in_use_buffer_pool_entries(struct vcd_clnt_ctxt *cctxt,
+ struct vcd_buffer_pool *buf_pool, u32 event)
+{
+ u32 i;
+ VCD_MSG_LOW("vcd_flush_buffer_pool_entries: event=0x%x", event);
+
+ if (buf_pool->entries) {
+ for (i = 0; i <= buf_pool->count; i++) {
+ if (buf_pool->entries[i].virtual &&
+ buf_pool->entries[i].in_use) {
+ cctxt->callback(event, VCD_S_SUCCESS,
+ &buf_pool->entries[i].frame,
+ sizeof(struct vcd_frame_data),
+ cctxt, cctxt->client_data);
+ buf_pool->entries[i].in_use = false;
+ VCD_BUFFERPOOL_INUSE_DECREMENT(
+ buf_pool->in_use);
+ }
+ }
+ }
+}
+
+
+void vcd_reset_buffer_pool_for_reuse(struct vcd_buffer_pool *buf_pool)
+{
+ VCD_MSG_LOW("vcd_reset_buffer_pool_for_reuse:");
+
+ if (buf_pool->entries) {
+ memset(&buf_pool->entries[1], 0,
+ sizeof(struct vcd_buffer_entry) *
+ VCD_MAX_BUFFER_ENTRIES);
+ }
+ buf_pool->q_len = 0;
+
+ buf_pool->validated = 0;
+ buf_pool->allocated = 0;
+ buf_pool->in_use = 0;
+ INIT_LIST_HEAD(&buf_pool->queue);
+}
+
+struct vcd_buffer_entry *vcd_get_free_buffer_pool_entry
+ (struct vcd_buffer_pool *pool) {
+ u32 i;
+
+ i = 1;
+ while (i <= pool->count && pool->entries[i].valid)
+ i++;
+
+
+ if (i <= pool->count) {
+ pool->entries[i].valid = true;
+
+ return &pool->entries[i];
+ } else {
+ return NULL;
+ }
+}
+
+struct vcd_buffer_entry *vcd_find_buffer_pool_entry
+ (struct vcd_buffer_pool *pool, u8 *addr)
+{
+ u32 i;
+ u32 found = false;
+
+ for (i = 0; i <= pool->count && !found; i++) {
+ if (pool->entries[i].virtual == addr)
+ found = true;
+
+ }
+
+ if (found)
+ return &pool->entries[i - 1];
+ else
+ return NULL;
+
+}
+
+u32 vcd_buffer_pool_entry_en_q(
+ struct vcd_buffer_pool *pool,
+ struct vcd_buffer_entry *entry)
+{
+ struct vcd_buffer_entry *list_itr;
+
+ if (pool->q_len == pool->count)
+ return false;
+
+ list_for_each_entry(list_itr, &pool->queue, list)
+ if (list_itr == entry) {
+ VCD_MSG_HIGH("\n this output buffer is already present"
+ " in queue");
+ VCD_MSG_HIGH("\n Vir Addr %p Phys Addr %p",
+ entry->virtual, entry->physical);
+ return false;
+ }
+
+ list_add_tail(&entry->list, &pool->queue);
+ pool->q_len++;
+
+ return true;
+}
+
+struct vcd_buffer_entry *vcd_buffer_pool_entry_de_q
+ (struct vcd_buffer_pool *pool) {
+ struct vcd_buffer_entry *entry;
+
+ if (!pool || !pool->q_len)
+ return NULL;
+
+ entry = list_first_entry(&pool->queue,
+ struct vcd_buffer_entry, list);
+
+ if (entry) {
+ list_del(&entry->list);
+ pool->q_len--;
+ }
+
+ return entry;
+}
+
+void vcd_flush_bframe_buffers(struct vcd_clnt_ctxt *cctxt, u32 mode)
+{
+ int i;
+ struct vcd_buffer_pool *buf_pool;
+
+ if (!cctxt->decoding && cctxt->bframe) {
+ buf_pool = (mode == VCD_FLUSH_INPUT) ?
+ &cctxt->in_buf_pool : &cctxt->out_buf_pool;
+ if (buf_pool->entries != NULL) {
+ for (i = 1; i <= buf_pool->count; i++) {
+ if ((buf_pool->entries[i].in_use) &&
+ (buf_pool->entries[i].frame.virtual
+ != NULL)) {
+ if (mode == VCD_FLUSH_INPUT) {
+ cctxt->callback(
+ VCD_EVT_RESP_INPUT_FLUSHED,
+ VCD_S_SUCCESS,
+ &(buf_pool->entries[i].frame),
+ sizeof(struct vcd_frame_data),
+ cctxt, cctxt->client_data);
+ } else {
+ buf_pool->entries[i].
+ frame.data_len = 0;
+ cctxt->callback(
+ VCD_EVT_RESP_OUTPUT_FLUSHED,
+ VCD_S_SUCCESS,
+ &(buf_pool->entries[i].frame),
+ sizeof(struct vcd_frame_data),
+ cctxt,
+ cctxt->client_data);
+ }
+ VCD_BUFFERPOOL_INUSE_DECREMENT(
+ buf_pool->in_use);
+ buf_pool->entries[i].in_use = false;
+ }
+ }
+ }
+ }
+}
+
+void vcd_flush_output_buffers(struct vcd_clnt_ctxt *cctxt)
+{
+ struct vcd_buffer_pool *buf_pool;
+ struct vcd_buffer_entry *buf_entry;
+ u32 count = 0;
+ struct vcd_property_hdr prop_hdr;
+
+ VCD_MSG_LOW("vcd_flush_output_buffers:");
+ buf_pool = &cctxt->out_buf_pool;
+ buf_entry = vcd_buffer_pool_entry_de_q(buf_pool);
+ while (buf_entry) {
+ if (!cctxt->decoding || buf_entry->in_use) {
+ buf_entry->frame.data_len = 0;
+ cctxt->callback(VCD_EVT_RESP_OUTPUT_FLUSHED,
+ VCD_S_SUCCESS,
+ &buf_entry->frame,
+ sizeof(struct vcd_frame_data),
+ cctxt, cctxt->client_data);
+ if (buf_entry->in_use) {
+ VCD_BUFFERPOOL_INUSE_DECREMENT(
+ buf_pool->in_use);
+ buf_entry->in_use = false;
+ }
+ count++;
+ }
+ buf_entry = vcd_buffer_pool_entry_de_q(buf_pool);
+ }
+ vcd_flush_bframe_buffers(cctxt, VCD_FLUSH_OUTPUT);
+ if (buf_pool->in_use || buf_pool->q_len) {
+ VCD_MSG_ERROR("%s(): WARNING in_use(%u) or q_len(%u) not zero!",
+ __func__, buf_pool->in_use, buf_pool->q_len);
+ buf_pool->in_use = buf_pool->q_len = 0;
+ }
+ if (cctxt->sched_clnt_hdl) {
+ if (count > cctxt->sched_clnt_hdl->tkns)
+ cctxt->sched_clnt_hdl->tkns = 0;
+ else
+ cctxt->sched_clnt_hdl->tkns -= count;
+ }
+
+ if (cctxt->ddl_hdl_valid && cctxt->decoding) {
+ prop_hdr.prop_id = DDL_I_REQ_OUTPUT_FLUSH;
+ prop_hdr.sz = sizeof(u32);
+ count = 0x1;
+
+ (void)ddl_set_property(cctxt->ddl_handle, &prop_hdr,
+ &count);
+ }
+ vcd_release_all_clnt_frm_transc(cctxt);
+ cctxt->status.mask &= ~VCD_IN_RECONFIG;
+}
+
+u32 vcd_flush_buffers(struct vcd_clnt_ctxt *cctxt, u32 mode)
+{
+ u32 rc = VCD_S_SUCCESS;
+ struct vcd_buffer_entry *buf_entry;
+
+ VCD_MSG_LOW("vcd_flush_buffers:");
+
+ if (mode > VCD_FLUSH_ALL || !(mode & VCD_FLUSH_ALL)) {
+ VCD_MSG_ERROR("Invalid flush mode %d", mode);
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+
+ VCD_MSG_MED("Flush mode %d requested", mode);
+ if ((mode & VCD_FLUSH_INPUT) &&
+ cctxt->sched_clnt_hdl) {
+
+ rc = vcd_sched_dequeue_buffer(
+ cctxt->sched_clnt_hdl, &buf_entry);
+ while (!VCD_FAILED(rc) && buf_entry) {
+ if (buf_entry->virtual) {
+ cctxt->callback(VCD_EVT_RESP_INPUT_FLUSHED,
+ VCD_S_SUCCESS,
+ &buf_entry->frame,
+ sizeof(struct
+ vcd_frame_data),
+ cctxt,
+ cctxt->client_data);
+ }
+
+ buf_entry->in_use = false;
+ VCD_BUFFERPOOL_INUSE_DECREMENT(
+ cctxt->in_buf_pool.in_use);
+ buf_entry = NULL;
+ rc = vcd_sched_dequeue_buffer(
+ cctxt->sched_clnt_hdl, &buf_entry);
+ }
+ }
+ if (rc != VCD_ERR_QEMPTY)
+ VCD_FAILED_RETURN(rc, "Failed: vcd_sched_dequeue_buffer");
+ if (cctxt->status.frame_submitted > 0)
+ cctxt->status.mask |= mode;
+ else {
+ if (mode & VCD_FLUSH_INPUT)
+ vcd_flush_bframe_buffers(cctxt, VCD_FLUSH_INPUT);
+ if (mode & VCD_FLUSH_OUTPUT)
+ vcd_flush_output_buffers(cctxt);
+ }
+ return VCD_S_SUCCESS;
+}
+
+void vcd_flush_buffers_in_err_fatal(struct vcd_clnt_ctxt *cctxt)
+{
+ VCD_MSG_LOW("\n vcd_flush_buffers_in_err_fatal:");
+ (void) vcd_flush_buffers(cctxt, VCD_FLUSH_ALL);
+ vcd_flush_in_use_buffer_pool_entries(cctxt,
+ &cctxt->in_buf_pool, VCD_EVT_RESP_INPUT_FLUSHED);
+ vcd_flush_in_use_buffer_pool_entries(cctxt,
+ &cctxt->out_buf_pool, VCD_EVT_RESP_OUTPUT_FLUSHED);
+ vcd_send_flush_done(cctxt, VCD_S_SUCCESS);
+}
+
+u32 vcd_init_client_context(struct vcd_clnt_ctxt *cctxt)
+{
+ u32 rc;
+ VCD_MSG_LOW("vcd_init_client_context:");
+ rc = ddl_open(&cctxt->ddl_handle, cctxt->decoding);
+ VCD_FAILED_RETURN(rc, "Failed: ddl_open");
+ cctxt->ddl_hdl_valid = true;
+ cctxt->clnt_state.state = VCD_CLIENT_STATE_OPEN;
+ cctxt->clnt_state.state_table =
+ vcd_get_client_state_table(VCD_CLIENT_STATE_OPEN);
+ cctxt->signature = VCD_SIGNATURE;
+ cctxt->live = true;
+ cctxt->bframe = 0;
+ cctxt->cmd_q.pending_cmd = VCD_CMD_NONE;
+ cctxt->status.last_evt = VCD_EVT_RESP_BASE;
+ return rc;
+}
+
+void vcd_destroy_client_context(struct vcd_clnt_ctxt *cctxt)
+{
+ struct vcd_dev_ctxt *dev_ctxt;
+ struct vcd_clnt_ctxt *client;
+ struct vcd_buffer_entry *buf_entry;
+ u32 rc = VCD_S_SUCCESS;
+ VCD_MSG_LOW("vcd_destroy_client_context:");
+
+ dev_ctxt = cctxt->dev_ctxt;
+
+ if (cctxt == dev_ctxt->cctxt_list_head) {
+ VCD_MSG_MED("Clnt list head clnt being removed");
+
+ dev_ctxt->cctxt_list_head = cctxt->next;
+ } else {
+ client = dev_ctxt->cctxt_list_head;
+ while (client && cctxt != client->next)
+ client = client->next;
+ if (client)
+ client->next = cctxt->next;
+ if (!client) {
+ rc = VCD_ERR_FAIL;
+ VCD_MSG_ERROR("Client not found in client list");
+ }
+ }
+
+ if (VCD_FAILED(rc))
+ return;
+
+ if (cctxt->sched_clnt_hdl) {
+ rc = VCD_S_SUCCESS;
+ while (!VCD_FAILED(rc)) {
+ rc = vcd_sched_dequeue_buffer(
+ cctxt->sched_clnt_hdl, &buf_entry);
+ if (rc != VCD_ERR_QEMPTY && VCD_FAILED(rc))
+ VCD_MSG_ERROR("\n Failed: "
+ "vcd_sched_de_queue_buffer");
+ }
+ rc = vcd_sched_remove_client(cctxt->sched_clnt_hdl);
+ if (VCD_FAILED(rc))
+ VCD_MSG_ERROR("\n Failed: sched_remove_client");
+ cctxt->sched_clnt_hdl = NULL;
+ }
+
+ if (cctxt->seq_hdr.sequence_header) {
+ vcd_pmem_free(cctxt->seq_hdr.sequence_header,
+ cctxt->seq_hdr_phy_addr);
+ cctxt->seq_hdr.sequence_header = NULL;
+ }
+
+ vcd_free_buffers_internal(cctxt, &cctxt->in_buf_pool);
+ vcd_free_buffers_internal(cctxt, &cctxt->out_buf_pool);
+ vcd_free_buffer_pool_entries(&cctxt->in_buf_pool);
+ vcd_free_buffer_pool_entries(&cctxt->out_buf_pool);
+ vcd_release_all_clnt_transc(cctxt);
+
+ if (cctxt->ddl_hdl_valid) {
+ (void)ddl_close(&cctxt->ddl_handle);
+ cctxt->ddl_hdl_valid = false;
+ }
+
+ cctxt->signature = 0;
+ cctxt->clnt_state.state = VCD_CLIENT_STATE_NULL;
+ cctxt->clnt_state.state_table = NULL;
+
+ kfree(cctxt);
+}
+
+u32 vcd_check_for_client_context(
+ struct vcd_dev_ctxt *dev_ctxt, s32 driver_id)
+{
+ struct vcd_clnt_ctxt *client;
+
+ client = dev_ctxt->cctxt_list_head;
+ while (client && client->driver_id != driver_id)
+ client = client->next;
+
+ if (!client)
+ return false;
+ else
+ return true;
+}
+
+u32 vcd_validate_driver_handle(
+ struct vcd_dev_ctxt *dev_ctxt, s32 driver_handle)
+{
+ driver_handle--;
+
+ if (driver_handle < 0 ||
+ driver_handle >= VCD_DRIVER_INSTANCE_MAX ||
+ !dev_ctxt->driver_ids[driver_handle]) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+u32 vcd_client_cmd_en_q(
+ struct vcd_clnt_ctxt *cctxt, enum vcd_command command)
+{
+ u32 result;
+
+ if (cctxt->cmd_q.pending_cmd == VCD_CMD_NONE) {
+ cctxt->cmd_q.pending_cmd = command;
+ result = true;
+ } else {
+ result = false;
+ }
+
+ return result;
+}
+
+void vcd_client_cmd_flush_and_en_q(
+ struct vcd_clnt_ctxt *cctxt, enum vcd_command command)
+{
+ cctxt->cmd_q.pending_cmd = command;
+}
+
+u32 vcd_client_cmd_de_q(struct vcd_clnt_ctxt *cctxt,
+ enum vcd_command *command)
+{
+ if (cctxt->cmd_q.pending_cmd == VCD_CMD_NONE)
+ return false;
+
+ *command = cctxt->cmd_q.pending_cmd;
+ cctxt->cmd_q.pending_cmd = VCD_CMD_NONE;
+
+ return true;
+}
+
+u32 vcd_get_next_queued_client_cmd(struct vcd_dev_ctxt *dev_ctxt,
+ struct vcd_clnt_ctxt **cctxt, enum vcd_command *command)
+{
+ struct vcd_clnt_ctxt *client = dev_ctxt->cctxt_list_head;
+ u32 result = false;
+
+ while (client && !result) {
+ *cctxt = client;
+ result = vcd_client_cmd_de_q(client, command);
+ client = client->next;
+ }
+ return result;
+}
+
+u32 vcd_submit_cmd_sess_start(struct vcd_transc *transc)
+{
+ u32 rc;
+ struct vcd_sequence_hdr Seq_hdr;
+
+ VCD_MSG_LOW("vcd_submit_cmd_sess_start:");
+
+ if (transc->cctxt->decoding) {
+
+ if (transc->cctxt->seq_hdr.sequence_header) {
+ Seq_hdr.sequence_header_len =
+ transc->cctxt->seq_hdr.
+ sequence_header_len;
+ Seq_hdr.sequence_header =
+ transc->cctxt->seq_hdr_phy_addr;
+
+ rc = ddl_decode_start(transc->cctxt->ddl_handle,
+ &Seq_hdr, (void *)transc);
+ } else {
+ rc = ddl_decode_start(transc->cctxt->ddl_handle,
+ NULL, (void *)transc);
+ }
+
+ } else {
+ rc = ddl_encode_start(transc->cctxt->ddl_handle,
+ (void *)transc);
+ }
+ if (!VCD_FAILED(rc)) {
+ transc->cctxt->status.cmd_submitted++;
+ vcd_device_timer_start(transc->cctxt->dev_ctxt);
+ } else
+ VCD_MSG_ERROR("rc = 0x%x. Failed: ddl start", rc);
+
+ return rc;
+}
+
+u32 vcd_submit_cmd_sess_end(struct vcd_transc *transc)
+{
+ u32 rc;
+
+ VCD_MSG_LOW("vcd_submit_cmd_sess_end:");
+
+ if (transc->cctxt->decoding) {
+ rc = ddl_decode_end(transc->cctxt->ddl_handle,
+ (void *)transc);
+ } else {
+ rc = ddl_encode_end(transc->cctxt->ddl_handle,
+ (void *)transc);
+ }
+ if (!VCD_FAILED(rc)) {
+ transc->cctxt->status.cmd_submitted++;
+ vcd_device_timer_start(transc->cctxt->dev_ctxt);
+ } else
+ VCD_MSG_ERROR("rc = 0x%x. Failed: ddl end", rc);
+
+ return rc;
+}
+
+void vcd_submit_cmd_client_close(struct vcd_clnt_ctxt *cctxt)
+{
+ (void) ddl_close(&cctxt->ddl_handle);
+ cctxt->ddl_hdl_valid = false;
+ cctxt->status.mask &= ~VCD_CLEANING_UP;
+ if (cctxt->status.mask & VCD_CLOSE_PENDING) {
+ vcd_destroy_client_context(cctxt);
+ vcd_handle_for_last_clnt_close(cctxt->dev_ctxt, true);
+ }
+}
+
+u32 vcd_submit_command_in_continue(struct vcd_dev_ctxt
+ *dev_ctxt, struct vcd_transc *transc)
+{
+ struct vcd_property_hdr prop_hdr;
+ struct vcd_clnt_ctxt *client = NULL;
+ enum vcd_command cmd = VCD_CMD_NONE;
+ u32 rc = VCD_ERR_FAIL;
+ u32 result = false, flush = 0, event = 0;
+ u32 command_break = false;
+
+ VCD_MSG_LOW("\n vcd_submit_command_in_continue:");
+
+ while (!command_break) {
+ result = vcd_get_next_queued_client_cmd(dev_ctxt,
+ &client, &cmd);
+
+ if (!result)
+ command_break = true;
+ else {
+ transc->type = cmd;
+ transc->cctxt = client;
+
+ switch (cmd) {
+ case VCD_CMD_CODEC_START:
+ {
+ rc = vcd_submit_cmd_sess_start(transc);
+ event = VCD_EVT_RESP_START;
+ break;
+ }
+ case VCD_CMD_CODEC_STOP:
+ {
+ rc = vcd_submit_cmd_sess_end(transc);
+ event = VCD_EVT_RESP_STOP;
+ break;
+ }
+ case VCD_CMD_OUTPUT_FLUSH:
+ {
+ prop_hdr.prop_id = DDL_I_REQ_OUTPUT_FLUSH;
+ prop_hdr.sz = sizeof(u32);
+ flush = 0x1;
+ (void) ddl_set_property(client->ddl_handle,
+ &prop_hdr, &flush);
+ vcd_release_command_channel(dev_ctxt,
+ transc);
+ rc = VCD_S_SUCCESS;
+ break;
+ }
+ case VCD_CMD_CLIENT_CLOSE:
+ {
+ vcd_submit_cmd_client_close(client);
+ vcd_release_command_channel(dev_ctxt,
+ transc);
+ rc = VCD_S_SUCCESS;
+ break;
+ }
+ default:
+ {
+ VCD_MSG_ERROR("\n vcd_submit_command: Unknown"
+ "command %d", (int)cmd);
+ break;
+ }
+ }
+
+ if (!VCD_FAILED(rc)) {
+ command_break = true;
+ } else {
+ VCD_MSG_ERROR("vcd_submit_command %d: failed 0x%x",
+ cmd, rc);
+ client->callback(event, rc, NULL, 0, client,
+ client->client_data);
+ }
+ }
+ }
+ return result;
+}
+
+u32 vcd_schedule_frame(struct vcd_dev_ctxt *dev_ctxt,
+ struct vcd_clnt_ctxt **cctxt, struct vcd_buffer_entry
+ **ip_buf_entry)
+{
+ u32 rc = VCD_S_SUCCESS;
+ VCD_MSG_LOW("vcd_schedule_frame:");
+
+ if (!dev_ctxt->cctxt_list_head) {
+ VCD_MSG_HIGH("Client list empty");
+ return false;
+ }
+ rc = vcd_sched_get_client_frame(&dev_ctxt->sched_clnt_list,
+ cctxt, ip_buf_entry);
+ if (rc == VCD_ERR_QEMPTY) {
+ VCD_MSG_HIGH("No frame available. Sched queues are empty");
+ return false;
+ }
+ if (VCD_FAILED(rc)) {
+ VCD_MSG_FATAL("vcd_submit_frame: sched_de_queue_frame"
+ "failed 0x%x", rc);
+ return false;
+ }
+ if (!*cctxt || !*ip_buf_entry) {
+ VCD_MSG_FATAL("Sched returned invalid values. ctxt=%p,"
+ "ipbuf=%p", *cctxt, *ip_buf_entry);
+ return false;
+ }
+ return true;
+}
+
+void vcd_try_submit_frame(struct vcd_dev_ctxt *dev_ctxt)
+{
+ struct vcd_transc *transc;
+ u32 rc = VCD_S_SUCCESS;
+ struct vcd_clnt_ctxt *cctxt = NULL;
+ struct vcd_buffer_entry *ip_buf_entry = NULL;
+ u32 result = false;
+
+ VCD_MSG_LOW("vcd_try_submit_frame:");
+
+ if (!vcd_get_frame_channel(dev_ctxt, &transc))
+ return;
+
+ if (!vcd_schedule_frame(dev_ctxt, &cctxt, &ip_buf_entry)) {
+ vcd_release_frame_channel(dev_ctxt, transc);
+ return;
+ }
+
+ rc = vcd_power_event(dev_ctxt, cctxt, VCD_EVT_PWR_CLNT_CMD_BEGIN);
+
+ if (!VCD_FAILED(rc)) {
+ transc->cctxt = cctxt;
+ transc->ip_buf_entry = ip_buf_entry;
+
+ result = vcd_submit_frame(dev_ctxt, transc);
+ } else {
+ VCD_MSG_ERROR("Failed: VCD_EVT_PWR_CLNT_CMD_BEGIN");
+ (void) vcd_sched_queue_buffer(
+ cctxt->sched_clnt_hdl, ip_buf_entry, false);
+ cctxt->sched_clnt_hdl->tkns++;
+ }
+
+ if (!result) {
+ vcd_release_frame_channel(dev_ctxt, transc);
+ (void) vcd_power_event(dev_ctxt, cctxt,
+ VCD_EVT_PWR_CLNT_CMD_FAIL);
+ }
+}
+
+u32 vcd_submit_frame(struct vcd_dev_ctxt *dev_ctxt,
+ struct vcd_transc *transc)
+{
+ struct vcd_clnt_ctxt *cctxt = NULL;
+ struct vcd_frame_data *ip_frm_entry;
+ struct vcd_buffer_entry *op_buf_entry = NULL;
+ u32 rc = VCD_S_SUCCESS;
+ u32 evcode = 0;
+ struct ddl_frame_data_tag ddl_ip_frm;
+ struct ddl_frame_data_tag ddl_op_frm;
+
+ VCD_MSG_LOW("vcd_submit_frame:");
+ cctxt = transc->cctxt;
+ ip_frm_entry = &transc->ip_buf_entry->frame;
+
+ transc->op_buf_entry = op_buf_entry;
+ transc->ip_frm_tag = ip_frm_entry->ip_frm_tag;
+ transc->time_stamp = ip_frm_entry->time_stamp;
+ ip_frm_entry->ip_frm_tag = (u32) transc;
+ memset(&ddl_ip_frm, 0, sizeof(ddl_ip_frm));
+ memset(&ddl_op_frm, 0, sizeof(ddl_op_frm));
+ if (cctxt->decoding) {
+ evcode = CLIENT_STATE_EVENT_NUMBER(decode_frame);
+ ddl_ip_frm.vcd_frm = *ip_frm_entry;
+ rc = ddl_decode_frame(cctxt->ddl_handle, &ddl_ip_frm,
+ (void *) transc);
+ } else {
+ op_buf_entry = vcd_buffer_pool_entry_de_q(
+ &cctxt->out_buf_pool);
+ if (!op_buf_entry) {
+ VCD_MSG_ERROR("Sched provided frame when no"
+ "op buffer was present");
+ rc = VCD_ERR_FAIL;
+ } else {
+ op_buf_entry->in_use = true;
+ cctxt->out_buf_pool.in_use++;
+ ddl_ip_frm.vcd_frm = *ip_frm_entry;
+ ddl_ip_frm.frm_delta =
+ vcd_calculate_frame_delta(cctxt,
+ ip_frm_entry);
+
+ ddl_op_frm.vcd_frm = op_buf_entry->frame;
+
+ evcode = CLIENT_STATE_EVENT_NUMBER(encode_frame);
+
+ rc = ddl_encode_frame(cctxt->ddl_handle,
+ &ddl_ip_frm, &ddl_op_frm, (void *) transc);
+ }
+ }
+ ip_frm_entry->ip_frm_tag = transc->ip_frm_tag;
+ if (!VCD_FAILED(rc)) {
+ vcd_device_timer_start(dev_ctxt);
+ cctxt->status.frame_submitted++;
+ if (ip_frm_entry->flags & VCD_FRAME_FLAG_EOS)
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_EOS, evcode);
+ } else {
+ VCD_MSG_ERROR("Frame submission failed. rc = 0x%x", rc);
+ vcd_handle_submit_frame_failed(dev_ctxt, transc);
+ }
+ return true;
+}
+
+u32 vcd_try_submit_frame_in_continue(struct vcd_dev_ctxt *dev_ctxt,
+ struct vcd_transc *transc)
+{
+ struct vcd_clnt_ctxt *cctxt = NULL;
+ struct vcd_buffer_entry *ip_buf_entry = NULL;
+
+ VCD_MSG_LOW("vcd_try_submit_frame_in_continue:");
+
+ if (!vcd_schedule_frame(dev_ctxt, &cctxt, &ip_buf_entry))
+ return false;
+
+ transc->cctxt = cctxt;
+ transc->ip_buf_entry = ip_buf_entry;
+
+ return vcd_submit_frame(dev_ctxt, transc);
+}
+
+u32 vcd_process_cmd_sess_start(struct vcd_clnt_ctxt *cctxt)
+{
+ struct vcd_transc *transc;
+ u32 rc = VCD_S_SUCCESS;
+
+ VCD_MSG_LOW("vcd_process_cmd_sess_start:");
+ if (vcd_get_command_channel(cctxt->dev_ctxt, &transc)) {
+ rc = vcd_power_event(cctxt->dev_ctxt,
+ cctxt, VCD_EVT_PWR_CLNT_CMD_BEGIN);
+
+ if (!VCD_FAILED(rc)) {
+ transc->type = VCD_CMD_CODEC_START;
+ transc->cctxt = cctxt;
+ rc = vcd_submit_cmd_sess_start(transc);
+ } else {
+ VCD_MSG_ERROR("Failed: VCD_EVT_PWR_CLNT_CMD_BEGIN");
+ }
+
+ if (VCD_FAILED(rc)) {
+ vcd_release_command_channel(cctxt->dev_ctxt,
+ transc);
+ }
+ } else {
+ u32 result;
+
+ result = vcd_client_cmd_en_q(cctxt, VCD_CMD_CODEC_START);
+ if (!result) {
+ rc = VCD_ERR_BUSY;
+ VCD_MSG_ERROR("%s(): vcd_client_cmd_en_q() "
+ "failed\n", __func__);
+ }
+ }
+
+ if (VCD_FAILED(rc)) {
+ (void)vcd_power_event(cctxt->dev_ctxt,
+ cctxt, VCD_EVT_PWR_CLNT_CMD_FAIL);
+ }
+
+ return rc;
+}
+
+void vcd_send_frame_done_in_eos(struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *input_frame, u32 valid_opbuf)
+{
+ VCD_MSG_LOW("vcd_send_frame_done_in_eos:");
+
+ if (!input_frame->virtual && !valid_opbuf) {
+ VCD_MSG_MED("Sending NULL output with EOS");
+
+ cctxt->out_buf_pool.entries[0].frame.flags =
+ VCD_FRAME_FLAG_EOS;
+ cctxt->out_buf_pool.entries[0].frame.data_len = 0;
+ cctxt->out_buf_pool.entries[0].frame.time_stamp =
+ input_frame->time_stamp;
+ cctxt->out_buf_pool.entries[0].frame.ip_frm_tag =
+ input_frame->ip_frm_tag;
+
+ cctxt->callback(VCD_EVT_RESP_OUTPUT_DONE,
+ VCD_S_SUCCESS,
+ &cctxt->out_buf_pool.entries[0].frame,
+ sizeof(struct vcd_frame_data),
+ cctxt, cctxt->client_data);
+
+ memset(&cctxt->out_buf_pool.entries[0].frame,
+ 0, sizeof(struct vcd_frame_data));
+ } else if (!input_frame->data_len) {
+ if (cctxt->decoding) {
+ vcd_send_frame_done_in_eos_for_dec(cctxt,
+ input_frame);
+ } else {
+ vcd_send_frame_done_in_eos_for_enc(cctxt,
+ input_frame);
+ }
+
+ }
+}
+
+void vcd_send_frame_done_in_eos_for_dec(
+ struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *input_frame)
+{
+ struct vcd_buffer_entry *buf_entry;
+ struct vcd_property_hdr prop_hdr;
+ u32 rc;
+ struct ddl_frame_data_tag ddl_frm;
+
+ prop_hdr.prop_id = DDL_I_DPB_RETRIEVE;
+ prop_hdr.sz = sizeof(struct ddl_frame_data_tag);
+ memset(&ddl_frm, 0, sizeof(ddl_frm));
+ rc = ddl_get_property(cctxt->ddl_handle, &prop_hdr, &ddl_frm);
+
+ if (VCD_FAILED(rc) || !ddl_frm.vcd_frm.virtual) {
+ cctxt->status.eos_trig_ip_frm = *input_frame;
+ cctxt->status.mask |= VCD_EOS_WAIT_OP_BUF;
+ return;
+ }
+
+ buf_entry = vcd_find_buffer_pool_entry(&cctxt->out_buf_pool,
+ ddl_frm.vcd_frm.virtual);
+ if (!buf_entry) {
+ VCD_MSG_ERROR("Unrecognized buffer address provided = %p",
+ ddl_frm.vcd_frm.virtual);
+ return;
+ } else {
+ if (cctxt->sched_clnt_hdl->tkns)
+ cctxt->sched_clnt_hdl->tkns--;
+
+ VCD_MSG_MED("Sending non-NULL output with EOS");
+
+ buf_entry->frame.data_len = 0;
+ buf_entry->frame.offset = 0;
+ buf_entry->frame.flags |= VCD_FRAME_FLAG_EOS;
+ buf_entry->frame.ip_frm_tag = input_frame->ip_frm_tag;
+ buf_entry->frame.time_stamp = input_frame->time_stamp;
+
+ cctxt->callback(VCD_EVT_RESP_OUTPUT_DONE,
+ VCD_S_SUCCESS,
+ &buf_entry->frame,
+ sizeof(struct vcd_frame_data),
+ cctxt, cctxt->client_data);
+
+ buf_entry->in_use = false;
+ VCD_BUFFERPOOL_INUSE_DECREMENT(cctxt->out_buf_pool.in_use);
+ }
+}
+
+void vcd_send_frame_done_in_eos_for_enc(
+ struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *input_frame)
+{
+ struct vcd_buffer_entry *op_buf_entry;
+
+ if (!cctxt->out_buf_pool.q_len) {
+ cctxt->status.eos_trig_ip_frm = *input_frame;
+
+ cctxt->status.mask |= VCD_EOS_WAIT_OP_BUF;
+
+ return;
+ }
+
+ op_buf_entry = vcd_buffer_pool_entry_de_q(&cctxt->out_buf_pool);
+ if (!op_buf_entry) {
+ VCD_MSG_ERROR("%s(): vcd_buffer_pool_entry_de_q() "
+ "failed\n", __func__);
+ } else {
+ if (cctxt->sched_clnt_hdl->tkns)
+ cctxt->sched_clnt_hdl->tkns--;
+
+ VCD_MSG_MED("Sending non-NULL output with EOS");
+
+ op_buf_entry->frame.data_len = 0;
+ op_buf_entry->frame.flags |= VCD_FRAME_FLAG_EOS;
+ op_buf_entry->frame.ip_frm_tag =
+ input_frame->ip_frm_tag;
+ op_buf_entry->frame.time_stamp = input_frame->time_stamp;
+
+ cctxt->callback(VCD_EVT_RESP_OUTPUT_DONE,
+ VCD_S_SUCCESS,
+ &op_buf_entry->frame,
+ sizeof(struct vcd_frame_data),
+ cctxt, cctxt->client_data);
+ }
+}
+
+u32 vcd_handle_recvd_eos(
+ struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *input_frame, u32 *pb_eos_handled)
+{
+ u32 rc;
+
+ VCD_MSG_LOW("vcd_handle_recvd_eos:");
+
+ *pb_eos_handled = false;
+
+ if (input_frame->virtual &&
+ input_frame->data_len)
+ return VCD_S_SUCCESS;
+
+ input_frame->data_len = 0;
+ rc = vcd_sched_mark_client_eof(cctxt->sched_clnt_hdl);
+ if (VCD_FAILED(rc) && rc != VCD_ERR_QEMPTY)
+ return rc;
+
+ if (rc == VCD_S_SUCCESS)
+ *pb_eos_handled = true;
+ else if (cctxt->decoding && !input_frame->virtual)
+ cctxt->sched_clnt_hdl->tkns++;
+ else if (!cctxt->decoding) {
+ vcd_send_frame_done_in_eos(cctxt, input_frame, false);
+ if (cctxt->status.mask & VCD_EOS_WAIT_OP_BUF) {
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_EOS,
+ CLIENT_STATE_EVENT_NUMBER
+ (encode_frame));
+ }
+ *pb_eos_handled = true;
+ }
+
+ if (*pb_eos_handled &&
+ input_frame->virtual &&
+ !input_frame->data_len) {
+ cctxt->callback(VCD_EVT_RESP_INPUT_DONE,
+ VCD_S_SUCCESS,
+ input_frame,
+ sizeof(struct vcd_frame_data),
+ cctxt, cctxt->client_data);
+ }
+ return VCD_S_SUCCESS;
+}
+
+u32 vcd_handle_first_decode_frame(struct vcd_clnt_ctxt *cctxt)
+{
+ u32 rc = VCD_ERR_BAD_STATE;
+
+ VCD_MSG_LOW("vcd_handle_first_decode_frame:");
+ if (!cctxt->in_buf_pool.entries ||
+ !cctxt->out_buf_pool.entries ||
+ cctxt->in_buf_pool.validated !=
+ cctxt->in_buf_pool.count ||
+ cctxt->out_buf_pool.validated !=
+ cctxt->out_buf_pool.count)
+ VCD_MSG_ERROR("Buffer pool is not completely setup yet");
+ else if (!cctxt->sched_clnt_hdl) {
+ rc = vcd_sched_add_client(cctxt);
+ VCD_FAILED_RETURN(rc, "Failed: vcd_add_client_to_sched");
+ cctxt->sched_clnt_hdl->tkns =
+ cctxt->out_buf_pool.q_len;
+ } else
+ rc = vcd_sched_suspend_resume_clnt(cctxt, true);
+ return rc;
+}
+
+u32 vcd_setup_with_ddl_capabilities(struct vcd_dev_ctxt *dev_ctxt)
+{
+ struct vcd_property_hdr Prop_hdr;
+ struct ddl_property_capability capability;
+ u32 rc = VCD_S_SUCCESS;
+
+ VCD_MSG_LOW("vcd_setup_with_ddl_capabilities:");
+
+ if (!dev_ctxt->ddl_cmd_ch_depth) {
+ Prop_hdr.prop_id = DDL_I_CAPABILITY;
+ Prop_hdr.sz = sizeof(capability);
+
+ /*
+ ** Since this is underlying core's property we don't need a
+ ** ddl client handle.
+ */
+ rc = ddl_get_property(NULL, &Prop_hdr, &capability);
+
+ if (!VCD_FAILED(rc)) {
+ /*
+ ** Allocate the transaction table.
+ */
+ dev_ctxt->trans_tbl_size =
+ (VCD_MAX_CLIENT_TRANSACTIONS *
+ capability.max_num_client) +
+ capability.general_command_depth;
+
+ dev_ctxt->trans_tbl = (struct vcd_transc *)
+ kzalloc((sizeof(struct vcd_transc) *
+ dev_ctxt->trans_tbl_size), GFP_KERNEL);
+
+ if (!dev_ctxt->trans_tbl) {
+ VCD_MSG_ERROR("Transaction table alloc failed");
+ rc = VCD_ERR_ALLOC_FAIL;
+ } else {
+ dev_ctxt->ddl_cmd_concurrency =
+ !capability.exclusive;
+ dev_ctxt->ddl_frame_ch_depth =
+ capability.frame_command_depth;
+ dev_ctxt->ddl_cmd_ch_depth =
+ capability.general_command_depth;
+
+ vcd_reset_device_channels(dev_ctxt);
+
+ dev_ctxt->hw_time_out =
+ capability.ddl_time_out_in_ms;
+
+ }
+ }
+ }
+ return rc;
+}
+
+struct vcd_transc *vcd_get_free_trans_tbl_entry
+ (struct vcd_dev_ctxt *dev_ctxt) {
+ u32 i;
+
+ if (!dev_ctxt->trans_tbl)
+ return NULL;
+
+ i = 0;
+ while (i < dev_ctxt->trans_tbl_size &&
+ dev_ctxt->trans_tbl[i].in_use)
+ i++;
+
+ if (i == dev_ctxt->trans_tbl_size) {
+ return NULL;
+ } else {
+ memset(&dev_ctxt->trans_tbl[i], 0,
+ sizeof(struct vcd_transc));
+
+ dev_ctxt->trans_tbl[i].in_use = true;
+
+ return &dev_ctxt->trans_tbl[i];
+ }
+}
+
+void vcd_release_trans_tbl_entry(struct vcd_transc *trans_entry)
+{
+ if (trans_entry)
+ trans_entry->in_use = false;
+}
+
+u32 vcd_handle_input_done(
+ struct vcd_clnt_ctxt *cctxt,
+ void *payload, u32 event, u32 status)
+{
+ struct vcd_transc *transc;
+ struct ddl_frame_data_tag *frame =
+ (struct ddl_frame_data_tag *) payload;
+ u32 rc;
+
+ if (!cctxt->status.frame_submitted &&
+ !cctxt->status.frame_delayed) {
+ VCD_MSG_ERROR("Input done was not expected");
+ return VCD_ERR_BAD_STATE;
+ }
+
+ rc = vcd_validate_io_done_pyld(cctxt, payload, status);
+ if (rc == VCD_ERR_CLIENT_FATAL)
+ vcd_handle_clnt_fatal_input_done(cctxt, frame->frm_trans_end);
+ VCD_FAILED_RETURN(rc, "Bad input done payload");
+
+ transc = (struct vcd_transc *)frame->vcd_frm.ip_frm_tag;
+
+ if ((transc->ip_buf_entry->frame.virtual !=
+ frame->vcd_frm.virtual)
+ || !transc->ip_buf_entry->in_use) {
+ VCD_MSG_ERROR("Bad frm transaction state");
+ vcd_handle_clnt_fatal_input_done(cctxt, frame->frm_trans_end);
+ return VCD_ERR_BAD_POINTER;
+ }
+
+ frame->vcd_frm.ip_frm_tag = transc->ip_frm_tag;
+ transc->frame = frame->vcd_frm.frame;
+
+ cctxt->callback(event,
+ status,
+ &frame->vcd_frm,
+ sizeof(struct vcd_frame_data),
+ cctxt, cctxt->client_data);
+
+ transc->ip_buf_entry->in_use = false;
+ VCD_BUFFERPOOL_INUSE_DECREMENT(cctxt->in_buf_pool.in_use);
+ transc->ip_buf_entry = NULL;
+ transc->input_done = true;
+
+ if (transc->input_done && transc->frame_done)
+ vcd_release_trans_tbl_entry(transc);
+
+ if (VCD_FAILED(status)) {
+ VCD_MSG_ERROR("INPUT_DONE returned err = 0x%x", status);
+ vcd_handle_input_done_failed(cctxt, transc);
+ } else
+ cctxt->status.mask |= VCD_FIRST_IP_DONE;
+
+ if (cctxt->status.frame_submitted > 0)
+ cctxt->status.frame_submitted--;
+ else
+ cctxt->status.frame_delayed--;
+
+ if (!VCD_FAILED(status) &&
+ cctxt->decoding) {
+ if (frame->vcd_frm.flags & VCD_FRAME_FLAG_CODECCONFIG) {
+ VCD_MSG_HIGH(
+ "INPUT_DONE with VCD_FRAME_FLAG_CODECCONFIG");
+ vcd_handle_input_done_with_codec_config(cctxt,
+ transc, frame);
+ frame->vcd_frm.flags &= ~VCD_FRAME_FLAG_CODECCONFIG;
+ }
+ if (frame->vcd_frm.interlaced)
+ vcd_handle_input_done_for_interlacing(cctxt);
+ if (frame->frm_trans_end)
+ vcd_handle_input_done_with_trans_end(cctxt);
+ }
+
+ return VCD_S_SUCCESS;
+}
+
+u32 vcd_handle_input_done_in_eos(
+ struct vcd_clnt_ctxt *cctxt, void *payload, u32 status)
+{
+ struct vcd_transc *transc;
+ struct ddl_frame_data_tag *frame =
+ (struct ddl_frame_data_tag *) payload;
+ u32 rc = VCD_ERR_FAIL, codec_config = false;
+ u32 core_type = res_trk_get_core_type();
+ rc = vcd_validate_io_done_pyld(cctxt, payload, status);
+ if (rc == VCD_ERR_CLIENT_FATAL)
+ vcd_handle_clnt_fatal_input_done(cctxt, frame->frm_trans_end);
+ VCD_FAILED_RETURN(rc, "Failed: vcd_validate_io_done_pyld");
+ transc = (struct vcd_transc *)frame->vcd_frm.ip_frm_tag;
+ codec_config = frame->vcd_frm.flags & VCD_FRAME_FLAG_CODECCONFIG;
+ rc = vcd_handle_input_done(cctxt,
+ payload, VCD_EVT_RESP_INPUT_DONE, status);
+ VCD_FAILED_RETURN(rc, "Failed: vcd_handle_input_done");
+ if (frame->vcd_frm.flags & VCD_FRAME_FLAG_EOS) {
+ VCD_MSG_HIGH("Got input done for EOS initiator");
+ transc->input_done = false;
+ transc->in_use = true;
+ if (codec_config ||
+ ((status == VCD_ERR_BITSTREAM_ERR) &&
+ !(cctxt->status.mask & VCD_FIRST_IP_DONE) &&
+ (core_type == VCD_CORE_720P)))
+ vcd_handle_eos_done(cctxt, transc, VCD_S_SUCCESS);
+ }
+ return rc;
+}
+
+u32 vcd_validate_io_done_pyld(
+ struct vcd_clnt_ctxt *cctxt, void *payload, u32 status)
+{
+ struct ddl_frame_data_tag *frame =
+ (struct ddl_frame_data_tag *) payload;
+ struct vcd_dev_ctxt *dev_ctxt = cctxt->dev_ctxt;
+ struct vcd_transc *transc = NULL;
+ u32 rc = VCD_S_SUCCESS, i = 0;
+
+ if (!frame) {
+ VCD_MSG_ERROR("Bad payload from DDL");
+ return VCD_ERR_BAD_POINTER;
+ }
+
+ transc = (struct vcd_transc *)frame->vcd_frm.ip_frm_tag;
+ if (dev_ctxt->trans_tbl) {
+ while (i < dev_ctxt->trans_tbl_size &&
+ transc != &dev_ctxt->trans_tbl[i])
+ i++;
+ if (i == dev_ctxt->trans_tbl_size ||
+ !dev_ctxt->trans_tbl[i].in_use)
+ rc = VCD_ERR_CLIENT_FATAL;
+ } else
+ rc = VCD_ERR_CLIENT_FATAL;
+
+ if (VCD_FAILED(rc)) {
+ VCD_MSG_FATAL(
+ "vcd_validate_io_done_pyld: invalid transaction");
+ } else if (!frame->vcd_frm.virtual &&
+ status != VCD_ERR_INTRLCD_FIELD_DROP)
+ rc = VCD_ERR_BAD_POINTER;
+
+ return rc;
+}
+
+void vcd_handle_input_done_failed(
+ struct vcd_clnt_ctxt *cctxt, struct vcd_transc *transc)
+{
+ if (cctxt->decoding) {
+ cctxt->sched_clnt_hdl->tkns++;
+ vcd_release_trans_tbl_entry(transc);
+ }
+}
+
+void vcd_handle_input_done_with_codec_config(
+ struct vcd_clnt_ctxt *cctxt, struct vcd_transc *transc,
+ struct ddl_frame_data_tag *frm)
+{
+ cctxt->sched_clnt_hdl->tkns++;
+ if (frm->frm_trans_end)
+ vcd_release_trans_tbl_entry(transc);
+}
+
+void vcd_handle_input_done_for_interlacing(struct vcd_clnt_ctxt *cctxt)
+{
+ cctxt->status.int_field_cnt++;
+ if (cctxt->status.int_field_cnt == 1)
+ cctxt->sched_clnt_hdl->tkns++;
+ else if (cctxt->status.int_field_cnt ==
+ VCD_DEC_NUM_INTERLACED_FIELDS)
+ cctxt->status.int_field_cnt = 0;
+}
+
+void vcd_handle_input_done_with_trans_end(
+ struct vcd_clnt_ctxt *cctxt)
+{
+ if (!cctxt->decoding)
+ return;
+ if (cctxt->out_buf_pool.in_use <
+ cctxt->out_buf_pool.buf_req.min_count)
+ return;
+ if (!cctxt->sched_clnt_hdl->tkns)
+ cctxt->sched_clnt_hdl->tkns++;
+}
+
+u32 vcd_handle_output_required(struct vcd_clnt_ctxt
+ *cctxt, void *payload, u32 status)
+{
+ struct vcd_transc *transc;
+ struct ddl_frame_data_tag *frame =
+ (struct ddl_frame_data_tag *)payload;
+ u32 rc = VCD_S_SUCCESS;
+
+ if (!cctxt->status.frame_submitted &&
+ !cctxt->status.frame_delayed) {
+ VCD_MSG_ERROR("\n Input done was not expected");
+ return VCD_ERR_BAD_STATE;
+ }
+
+ rc = vcd_validate_io_done_pyld(cctxt, payload, status);
+ if (rc == VCD_ERR_CLIENT_FATAL)
+ vcd_handle_clnt_fatal_input_done(cctxt, frame->frm_trans_end);
+ VCD_FAILED_RETURN(rc, "\n Bad input done payload");
+
+ transc = (struct vcd_transc *)frame->
+ vcd_frm.ip_frm_tag;
+
+ if ((transc->ip_buf_entry->frame.virtual !=
+ frame->vcd_frm.virtual) ||
+ !transc->ip_buf_entry->in_use) {
+ VCD_MSG_ERROR("\n Bad frm transaction state");
+ vcd_handle_clnt_fatal_input_done(cctxt, frame->frm_trans_end);
+ return VCD_ERR_BAD_STATE;
+ }
+ rc = vcd_sched_queue_buffer(cctxt->sched_clnt_hdl,
+ transc->ip_buf_entry, false);
+ VCD_FAILED_RETURN(rc, "Failed: vcd_sched_queue_buffer");
+
+ transc->ip_buf_entry = NULL;
+ vcd_release_trans_tbl_entry(transc);
+ frame->frm_trans_end = true;
+
+ if (VCD_FAILED(status))
+ VCD_MSG_ERROR("\n OUTPUT_REQ returned err = 0x%x",
+ status);
+
+ if (cctxt->status.frame_submitted > 0)
+ cctxt->status.frame_submitted--;
+ else
+ cctxt->status.frame_delayed--;
+
+
+ if (!VCD_FAILED(status) &&
+ cctxt->decoding &&
+ frame->vcd_frm.interlaced) {
+ if (cctxt->status.int_field_cnt > 0) {
+ VCD_MSG_ERROR("\n Not expected: OUTPUT_REQ"
+ "for 2nd interlace field");
+ rc = VCD_ERR_FAIL;
+ }
+ }
+
+ return rc;
+}
+
+u32 vcd_handle_output_required_in_flushing(
+struct vcd_clnt_ctxt *cctxt, void *payload)
+{
+ u32 rc;
+ struct vcd_transc *transc;
+ struct ddl_frame_data_tag *frame =
+ (struct ddl_frame_data_tag *)payload;
+
+ rc = vcd_validate_io_done_pyld(cctxt, payload, VCD_S_SUCCESS);
+ if (rc == VCD_ERR_CLIENT_FATAL)
+ vcd_handle_clnt_fatal_input_done(cctxt, frame->frm_trans_end);
+ VCD_FAILED_RETURN(rc, "Bad input done payload");
+
+ transc = (struct vcd_transc *)
+ (((struct ddl_frame_data_tag *)payload)->
+ vcd_frm.ip_frm_tag);
+
+ ((struct ddl_frame_data_tag *)payload)->
+ vcd_frm.interlaced = false;
+
+ rc = vcd_handle_input_done(cctxt, payload,
+ VCD_EVT_RESP_INPUT_FLUSHED, VCD_S_SUCCESS);
+ VCD_FAILED_RETURN(rc, "Failed: vcd_handle_input_done");
+
+ vcd_release_trans_tbl_entry(transc);
+ ((struct ddl_frame_data_tag *)payload)->frm_trans_end = true;
+
+ return rc;
+}
+
+u32 vcd_handle_frame_done(
+ struct vcd_clnt_ctxt *cctxt,
+ void *payload, u32 event, u32 status)
+{
+ struct vcd_buffer_entry *op_buf_entry = NULL;
+ struct ddl_frame_data_tag *op_frm =
+ (struct ddl_frame_data_tag *) payload;
+ struct vcd_transc *transc;
+ u32 rc;
+
+ rc = vcd_validate_io_done_pyld(cctxt, payload, status);
+ if (rc == VCD_ERR_CLIENT_FATAL)
+ vcd_handle_clnt_fatal(cctxt, op_frm->frm_trans_end);
+ VCD_FAILED_RETURN(rc, "Bad payload recvd");
+
+ transc = (struct vcd_transc *)op_frm->vcd_frm.ip_frm_tag;
+
+ if (op_frm->vcd_frm.virtual) {
+
+ if (!transc->op_buf_entry) {
+ op_buf_entry =
+ vcd_find_buffer_pool_entry(
+ &cctxt->out_buf_pool,
+ op_frm->vcd_frm.
+ virtual);
+ } else {
+ op_buf_entry = transc->op_buf_entry;
+ }
+
+ if (!op_buf_entry) {
+ VCD_MSG_ERROR("Invalid output buffer returned"
+ "from DDL");
+ vcd_handle_clnt_fatal(cctxt, op_frm->frm_trans_end);
+ rc = VCD_ERR_BAD_POINTER;
+ } else if (!op_buf_entry->in_use) {
+ VCD_MSG_ERROR("Bad output buffer 0x%p recvd from DDL",
+ op_buf_entry->frame.virtual);
+ vcd_handle_clnt_fatal(cctxt, op_frm->frm_trans_end);
+ rc = VCD_ERR_BAD_POINTER;
+ } else {
+ op_buf_entry->in_use = false;
+ VCD_BUFFERPOOL_INUSE_DECREMENT(
+ cctxt->out_buf_pool.in_use);
+ VCD_MSG_LOW("outBufPool.InUse = %d",
+ cctxt->out_buf_pool.in_use);
+ }
+ }
+ VCD_FAILED_RETURN(rc, "Bad output buffer pointer");
+ op_frm->vcd_frm.time_stamp = transc->time_stamp;
+ op_frm->vcd_frm.ip_frm_tag = transc->ip_frm_tag;
+ if (cctxt->decoding)
+ op_frm->vcd_frm.frame = transc->frame;
+ else
+ transc->frame = op_frm->vcd_frm.frame;
+ transc->frame_done = true;
+
+ if (transc->input_done && transc->frame_done)
+ vcd_release_trans_tbl_entry(transc);
+
+ if (status == VCD_ERR_INTRLCD_FIELD_DROP ||
+ (op_frm->vcd_frm.intrlcd_ip_frm_tag !=
+ VCD_FRAMETAG_INVALID &&
+ op_frm->vcd_frm.intrlcd_ip_frm_tag)) {
+ vcd_handle_frame_done_for_interlacing(cctxt, transc,
+ op_frm, status);
+ }
+
+ if (status != VCD_ERR_INTRLCD_FIELD_DROP) {
+ cctxt->callback(event,
+ status,
+ &op_frm->vcd_frm,
+ sizeof(struct vcd_frame_data),
+ cctxt, cctxt->client_data);
+ }
+ return rc;
+}
+
+u32 vcd_handle_frame_done_in_eos(
+ struct vcd_clnt_ctxt *cctxt, void *payload, u32 status)
+{
+ struct ddl_frame_data_tag *frame =
+ (struct ddl_frame_data_tag *) payload;
+ u32 rc = VCD_S_SUCCESS;
+ VCD_MSG_LOW("vcd_handle_frame_done_in_eos:");
+ rc = vcd_validate_io_done_pyld(cctxt, payload, status);
+ if (rc == VCD_ERR_CLIENT_FATAL)
+ vcd_handle_clnt_fatal(cctxt, frame->frm_trans_end);
+ VCD_FAILED_RETURN(rc, "Bad payload received");
+
+ if (cctxt->status.mask & VCD_EOS_PREV_VALID) {
+ rc = vcd_handle_frame_done(cctxt,
+ (void *)&cctxt->status.
+ eos_prev_op_frm,
+ VCD_EVT_RESP_OUTPUT_DONE,
+ cctxt->status.eos_prev_op_frm_status);
+ VCD_FAILED_RETURN(rc, "Failed: vcd_handle_frame_done");
+ }
+
+ cctxt->status.eos_prev_op_frm = *frame;
+ cctxt->status.eos_prev_op_frm_status = status;
+ cctxt->status.mask |= VCD_EOS_PREV_VALID;
+ return rc;
+}
+
+void vcd_handle_frame_done_for_interlacing(
+ struct vcd_clnt_ctxt *cctxt,
+ struct vcd_transc *transc_ip1,
+ struct ddl_frame_data_tag *op_frm, u32 status)
+{
+ struct vcd_transc *transc_ip2 =
+ (struct vcd_transc *)op_frm->\
+ vcd_frm.intrlcd_ip_frm_tag;
+
+ if (status == VCD_ERR_INTRLCD_FIELD_DROP) {
+ cctxt->status.int_field_cnt = 0;
+ return;
+ }
+
+ op_frm->vcd_frm.intrlcd_ip_frm_tag = transc_ip2->ip_frm_tag;
+
+ transc_ip2->frame_done = true;
+
+ if (transc_ip2->input_done && transc_ip2->frame_done)
+ vcd_release_trans_tbl_entry(transc_ip2);
+
+ if (!transc_ip1->frame || !transc_ip2->frame) {
+ VCD_MSG_ERROR("DDL didn't provided frame type");
+ return;
+ }
+}
+
+u32 vcd_handle_first_fill_output_buffer(
+ struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *buffer,
+ u32 *handled)
+{
+ u32 rc = VCD_S_SUCCESS;
+ rc = vcd_check_if_buffer_req_met(cctxt, VCD_BUFFER_OUTPUT);
+ VCD_FAILED_RETURN(rc, "Output buffer requirements not met");
+ if (cctxt->out_buf_pool.q_len > 0) {
+ VCD_MSG_ERROR("Old output buffers were not flushed out");
+ return VCD_ERR_BAD_STATE;
+ }
+ cctxt->status.mask |= VCD_FIRST_OP_RCVD;
+ if (cctxt->sched_clnt_hdl)
+ rc = vcd_sched_suspend_resume_clnt(cctxt, true);
+ VCD_FAILED_RETURN(rc, "Failed: vcd_sched_suspend_resume_clnt");
+ if (cctxt->decoding)
+ rc = vcd_handle_first_fill_output_buffer_for_dec(
+ cctxt, buffer, handled);
+ else
+ rc = vcd_handle_first_fill_output_buffer_for_enc(
+ cctxt, buffer, handled);
+ return rc;
+}
+
+u32 vcd_handle_first_fill_output_buffer_for_enc(
+ struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *frm_entry,
+ u32 *handled)
+{
+ u32 rc, seqhdr_present = 0;
+ struct vcd_property_hdr prop_hdr;
+ struct vcd_sequence_hdr seq_hdr;
+ struct vcd_property_codec codec;
+ *handled = true;
+ prop_hdr.prop_id = DDL_I_SEQHDR_PRESENT;
+ prop_hdr.sz = sizeof(seqhdr_present);
+ rc = ddl_get_property(cctxt->ddl_handle, &prop_hdr, &seqhdr_present);
+ VCD_FAILED_RETURN(rc, "Failed: DDL_I_SEQHDR_PRESENT");
+ if (!seqhdr_present) {
+ *handled = false;
+ return VCD_S_SUCCESS;
+ }
+
+ prop_hdr.prop_id = VCD_I_CODEC;
+ prop_hdr.sz = sizeof(struct vcd_property_codec);
+ rc = ddl_get_property(cctxt->ddl_handle, &prop_hdr, &codec);
+ if (!VCD_FAILED(rc)) {
+ if (codec.codec != VCD_CODEC_H263) {
+ prop_hdr.prop_id = VCD_I_SEQ_HEADER;
+ prop_hdr.sz = sizeof(struct vcd_sequence_hdr);
+ seq_hdr.sequence_header = frm_entry->virtual;
+ seq_hdr.sequence_header_len =
+ frm_entry->alloc_len;
+ rc = ddl_get_property(cctxt->ddl_handle,
+ &prop_hdr, &seq_hdr);
+ if (!VCD_FAILED(rc)) {
+ frm_entry->data_len =
+ seq_hdr.sequence_header_len;
+ frm_entry->time_stamp = 0;
+ frm_entry->flags |=
+ VCD_FRAME_FLAG_CODECCONFIG;
+ cctxt->callback(VCD_EVT_RESP_OUTPUT_DONE,
+ VCD_S_SUCCESS, frm_entry,
+ sizeof(struct vcd_frame_data),
+ cctxt,
+ cctxt->client_data);
+ } else
+ VCD_MSG_ERROR(
+ "rc = 0x%x. Failed:\
+ ddl_get_property: VCD_I_SEQ_HEADER",
+ rc);
+ } else
+ VCD_MSG_LOW("Codec Type is H.263\n");
+ } else
+ VCD_MSG_ERROR(
+ "rc = 0x%x. Failed: ddl_get_property:VCD_I_CODEC",
+ rc);
+ return rc;
+}
+
+u32 vcd_handle_first_fill_output_buffer_for_dec(
+ struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *frm_entry,
+ u32 *handled)
+{
+ u32 rc;
+ struct vcd_property_hdr prop_hdr;
+ struct vcd_buffer_pool *out_buf_pool;
+ struct ddl_property_dec_pic_buffers dpb;
+ struct ddl_frame_data_tag *dpb_list;
+ u8 i;
+
+ (void)frm_entry;
+ *handled = true;
+ prop_hdr.prop_id = DDL_I_DPB;
+ prop_hdr.sz = sizeof(dpb);
+ out_buf_pool = &cctxt->out_buf_pool;
+
+ dpb_list = (struct ddl_frame_data_tag *)
+ kmalloc((sizeof(struct ddl_frame_data_tag) *
+ out_buf_pool->count), GFP_KERNEL);
+
+ if (!dpb_list) {
+ VCD_MSG_ERROR("Memory allocation failure");
+ return VCD_ERR_ALLOC_FAIL;
+ }
+
+ for (i = 1; i <= out_buf_pool->count; i++)
+ dpb_list[i - 1].vcd_frm = out_buf_pool->entries[i].frame;
+
+ dpb.dec_pic_buffers = dpb_list;
+ dpb.no_of_dec_pic_buf = out_buf_pool->count;
+ rc = ddl_set_property(cctxt->ddl_handle, &prop_hdr, &dpb);
+
+ kfree(dpb_list);
+ *handled = false;
+
+ return VCD_S_SUCCESS;
+}
+
+void vcd_handle_eos_trans_end(struct vcd_clnt_ctxt *cctxt)
+{
+ u32 rc = VCD_S_SUCCESS;
+ if (cctxt->status.mask & VCD_EOS_PREV_VALID) {
+ rc = vcd_handle_frame_done(cctxt,
+ (void *)&cctxt->status.eos_prev_op_frm,
+ VCD_EVT_RESP_OUTPUT_DONE,
+ cctxt->status.eos_prev_op_frm_status);
+ cctxt->status.mask &= ~VCD_EOS_PREV_VALID;
+ }
+ if (VCD_FAILED(rc))
+ return;
+
+ if (cctxt->status.mask & VCD_FLUSH_ALL)
+ vcd_process_pending_flush_in_eos(cctxt);
+
+ if (cctxt->status.mask & VCD_STOP_PENDING)
+ vcd_process_pending_stop_in_eos(cctxt);
+ else {
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_RUN,
+ CLIENT_STATE_EVENT_NUMBER(clnt_cb));
+ }
+}
+
+void vcd_handle_eos_done(struct vcd_clnt_ctxt *cctxt,
+ struct vcd_transc *transc, u32 status)
+{
+ struct vcd_frame_data vcd_frm;
+ u32 rc = VCD_S_SUCCESS, sent_eos_frm = false;
+ VCD_MSG_LOW("vcd_handle_eos_done:");
+
+ if (VCD_FAILED(status))
+ VCD_MSG_ERROR("EOS DONE returned error = 0x%x", status);
+
+ if (cctxt->status.mask & VCD_EOS_PREV_VALID) {
+ cctxt->status.eos_prev_op_frm.vcd_frm.flags |=
+ VCD_FRAME_FLAG_EOS;
+
+ rc = vcd_handle_frame_done(cctxt,
+ (void *)&cctxt->status.
+ eos_prev_op_frm,
+ VCD_EVT_RESP_OUTPUT_DONE,
+ cctxt->status.
+ eos_prev_op_frm_status);
+ cctxt->status.mask &= ~VCD_EOS_PREV_VALID;
+ if (!VCD_FAILED(rc) &&
+ cctxt->status.eos_prev_op_frm_status !=
+ VCD_ERR_INTRLCD_FIELD_DROP)
+ sent_eos_frm = true;
+ }
+ if (!sent_eos_frm) {
+ if (transc->ip_buf_entry) {
+ transc->ip_buf_entry->frame.ip_frm_tag =
+ transc->ip_frm_tag;
+
+ vcd_send_frame_done_in_eos(cctxt,
+ &transc->ip_buf_entry->frame, false);
+ } else {
+ memset(&vcd_frm, 0, sizeof(struct vcd_frame_data));
+ vcd_frm.ip_frm_tag = transc->ip_frm_tag;
+ vcd_frm.time_stamp = transc->time_stamp;
+ vcd_frm.flags = VCD_FRAME_FLAG_EOS;
+ vcd_send_frame_done_in_eos(cctxt, &vcd_frm, true);
+ }
+ }
+ if (VCD_FAILED(rc))
+ return;
+ if (transc->ip_buf_entry) {
+ if (transc->ip_buf_entry->frame.virtual) {
+ transc->ip_buf_entry->frame.ip_frm_tag =
+ transc->ip_frm_tag;
+ cctxt->callback(VCD_EVT_RESP_INPUT_DONE,
+ VCD_S_SUCCESS,
+ &transc->ip_buf_entry->frame,
+ sizeof(struct vcd_frame_data),
+ cctxt, cctxt->client_data);
+ }
+ transc->ip_buf_entry->in_use = false;
+ VCD_BUFFERPOOL_INUSE_DECREMENT(cctxt->in_buf_pool.in_use);
+ transc->ip_buf_entry = NULL;
+ if (cctxt->status.frame_submitted)
+ cctxt->status.frame_submitted--;
+ else
+ cctxt->status.frame_delayed--;
+ }
+
+ vcd_release_trans_tbl_entry(transc);
+ if (cctxt->status.mask & VCD_FLUSH_ALL)
+ vcd_process_pending_flush_in_eos(cctxt);
+
+ if (cctxt->status.mask & VCD_STOP_PENDING) {
+ vcd_process_pending_stop_in_eos(cctxt);
+ } else if (!(cctxt->status.mask & VCD_EOS_WAIT_OP_BUF)) {
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_RUN,
+ CLIENT_STATE_EVENT_NUMBER
+ (clnt_cb));
+ }
+}
+
+void vcd_handle_start_done(struct vcd_clnt_ctxt *cctxt,
+ struct vcd_transc *transc, u32 status)
+{
+ cctxt->status.cmd_submitted--;
+ vcd_mark_command_channel(cctxt->dev_ctxt, transc);
+
+ if (!VCD_FAILED(status)) {
+ cctxt->callback(VCD_EVT_RESP_START, status, NULL,
+ 0, cctxt, cctxt->client_data);
+
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_RUN,
+ CLIENT_STATE_EVENT_NUMBER(clnt_cb));
+ } else {
+ VCD_MSG_ERROR("ddl callback returned failure."
+ "status = 0x%x", status);
+ vcd_handle_err_in_starting(cctxt, status);
+ }
+}
+
+void vcd_handle_stop_done(struct vcd_clnt_ctxt *cctxt,
+ struct vcd_transc *transc, u32 status)
+{
+
+ VCD_MSG_LOW("vcd_handle_stop_done:");
+ cctxt->status.cmd_submitted--;
+ vcd_mark_command_channel(cctxt->dev_ctxt, transc);
+
+ if (!VCD_FAILED(status)) {
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_OPEN,
+ CLIENT_STATE_EVENT_NUMBER(clnt_cb));
+ } else {
+ VCD_MSG_FATAL("STOP_DONE returned error = 0x%x", status);
+ status = VCD_ERR_HW_FATAL;
+ vcd_handle_device_err_fatal(cctxt->dev_ctxt, cctxt);
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_INVALID,
+ CLIENT_STATE_EVENT_NUMBER(clnt_cb));
+ }
+
+ cctxt->callback(VCD_EVT_RESP_STOP, status, NULL, 0, cctxt,
+ cctxt->client_data);
+
+ memset(&cctxt->status, 0, sizeof(struct vcd_clnt_status));
+}
+
+void vcd_handle_stop_done_in_starting(struct vcd_clnt_ctxt
+ *cctxt, struct vcd_transc *transc, u32 status)
+{
+ VCD_MSG_LOW("vcd_handle_stop_done_in_starting:");
+ cctxt->status.cmd_submitted--;
+ vcd_mark_command_channel(cctxt->dev_ctxt, transc);
+ if (!VCD_FAILED(status)) {
+ cctxt->callback(VCD_EVT_RESP_START, cctxt->status.
+ last_err, NULL, 0, cctxt, cctxt->client_data);
+ vcd_do_client_state_transition(cctxt, VCD_CLIENT_STATE_OPEN,
+ CLIENT_STATE_EVENT_NUMBER(clnt_cb));
+ } else {
+ VCD_MSG_FATAL("VCD Cleanup: STOP_DONE returned error "
+ "= 0x%x", status);
+ vcd_handle_err_fatal(cctxt, VCD_EVT_RESP_START,
+ VCD_ERR_HW_FATAL);
+ }
+}
+
+void vcd_handle_stop_done_in_invalid(struct vcd_clnt_ctxt *cctxt,
+ struct vcd_transc *transc, u32 status)
+{
+ u32 rc;
+ VCD_MSG_LOW("vcd_handle_stop_done_in_invalid:");
+
+ cctxt->status.cmd_submitted--;
+ vcd_mark_command_channel(cctxt->dev_ctxt, transc);
+
+ if (!VCD_FAILED(status)) {
+ vcd_client_cmd_flush_and_en_q(cctxt, VCD_CMD_CLIENT_CLOSE);
+ if (cctxt->status.frame_submitted) {
+ vcd_release_multiple_frame_channels(cctxt->dev_ctxt,
+ cctxt->status.frame_submitted);
+
+ cctxt->status.frame_submitted = 0;
+ cctxt->status.frame_delayed = 0;
+ }
+ if (cctxt->status.cmd_submitted) {
+ vcd_release_multiple_command_channels(
+ cctxt->dev_ctxt,
+ cctxt->status.cmd_submitted);
+ cctxt->status.cmd_submitted = 0;
+ }
+ } else {
+ VCD_MSG_FATAL("VCD Cleanup: STOP_DONE returned error "
+ "= 0x%x", status);
+ vcd_handle_device_err_fatal(cctxt->dev_ctxt, cctxt);
+ cctxt->status.mask &= ~VCD_CLEANING_UP;
+ }
+ vcd_flush_buffers_in_err_fatal(cctxt);
+ VCD_MSG_HIGH("VCD cleanup: All buffers are returned");
+ if (cctxt->status.mask & VCD_STOP_PENDING) {
+ cctxt->callback(VCD_EVT_RESP_STOP, VCD_S_SUCCESS, NULL, 0,
+ cctxt, cctxt->client_data);
+ cctxt->status.mask &= ~VCD_STOP_PENDING;
+ }
+ rc = vcd_power_event(cctxt->dev_ctxt, cctxt,
+ VCD_EVT_PWR_CLNT_ERRFATAL);
+ if (VCD_FAILED(rc))
+ VCD_MSG_ERROR("VCD_EVT_PWR_CLNT_ERRFATAL failed");
+ if (!(cctxt->status.mask & VCD_CLEANING_UP) &&
+ cctxt->status.mask & VCD_CLOSE_PENDING) {
+ vcd_destroy_client_context(cctxt);
+ vcd_handle_for_last_clnt_close(cctxt->dev_ctxt, false);
+ }
+}
+
+u32 vcd_handle_input_frame(
+ struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *input_frame)
+{
+ struct vcd_dev_ctxt *dev_ctxt = cctxt->dev_ctxt;
+ struct vcd_buffer_entry *buf_entry;
+ struct vcd_frame_data *frm_entry;
+ u32 rc = VCD_S_SUCCESS;
+ u32 eos_handled = false;
+
+ VCD_MSG_LOW("vcd_handle_input_frame:");
+
+ VCD_MSG_LOW("input buffer: addr=(0x%p), sz=(%d), len=(%d)",
+ input_frame->virtual, input_frame->alloc_len,
+ input_frame->data_len);
+
+ if (!input_frame->virtual &&
+ !(input_frame->flags & VCD_FRAME_FLAG_EOS)) {
+ VCD_MSG_ERROR("Bad frame ptr/len/EOS combination");
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+
+
+ if (!input_frame->data_len &&
+ !(input_frame->flags & VCD_FRAME_FLAG_EOS)) {
+ VCD_MSG_MED("data_len = 0, returning INPUT DONE");
+ cctxt->callback(VCD_EVT_RESP_INPUT_DONE,
+ VCD_ERR_INPUT_NOT_PROCESSED,
+ input_frame,
+ sizeof(struct vcd_frame_data),
+ cctxt, cctxt->client_data);
+ return VCD_S_SUCCESS;
+ }
+
+ if (!(cctxt->status.mask & VCD_FIRST_IP_RCVD)) {
+ if (cctxt->decoding)
+ rc = vcd_handle_first_decode_frame(cctxt);
+
+ if (!VCD_FAILED(rc)) {
+ cctxt->status.first_ts = input_frame->time_stamp;
+ cctxt->status.prev_ts = cctxt->status.first_ts;
+
+ cctxt->status.mask |= VCD_FIRST_IP_RCVD;
+
+ (void)vcd_power_event(cctxt->dev_ctxt,
+ cctxt,
+ VCD_EVT_PWR_CLNT_FIRST_FRAME);
+ }
+ }
+ VCD_FAILED_RETURN(rc, "Failed: First frame handling");
+
+ buf_entry = vcd_find_buffer_pool_entry(&cctxt->in_buf_pool,
+ input_frame->virtual);
+ if (!buf_entry) {
+ VCD_MSG_ERROR("Bad buffer addr: %p", input_frame->virtual);
+ return VCD_ERR_FAIL;
+ }
+
+ if (buf_entry->in_use) {
+ VCD_MSG_ERROR("An inuse input frame is being"
+ "re-queued to scheduler");
+ return VCD_ERR_FAIL;
+ }
+
+ if (input_frame->alloc_len > buf_entry->sz) {
+ VCD_MSG_ERROR("Bad buffer Alloc_len %d, Actual sz=%d",
+ input_frame->alloc_len, buf_entry->sz);
+
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+
+ frm_entry = &buf_entry->frame;
+
+ *frm_entry = *input_frame;
+ frm_entry->physical = buf_entry->physical;
+
+ if (input_frame->flags & VCD_FRAME_FLAG_EOS) {
+ rc = vcd_handle_recvd_eos(cctxt, input_frame,
+ &eos_handled);
+ }
+
+ if (VCD_FAILED(rc) || eos_handled) {
+ VCD_MSG_HIGH("rc = 0x%x, eos_handled = %d", rc,
+ eos_handled);
+
+ return rc;
+ }
+ rc = vcd_sched_queue_buffer(
+ cctxt->sched_clnt_hdl, buf_entry, true);
+ VCD_FAILED_RETURN(rc, "Failed: vcd_sched_queue_buffer");
+
+ buf_entry->in_use = true;
+ cctxt->in_buf_pool.in_use++;
+ vcd_try_submit_frame(dev_ctxt);
+ return rc;
+}
+
+void vcd_release_all_clnt_frm_transc(struct vcd_clnt_ctxt *cctxt)
+{
+ struct vcd_dev_ctxt *dev_ctxt = cctxt->dev_ctxt;
+ u32 i, cntr = 0;
+ VCD_MSG_LOW("vcd_release_all_clnt_frm_transc:");
+ for (i = 0; i < dev_ctxt->trans_tbl_size; i++) {
+ if (dev_ctxt->trans_tbl[i].in_use &&
+ cctxt == dev_ctxt->trans_tbl[i].cctxt) {
+ if (dev_ctxt->trans_tbl[i].
+ type == VCD_CMD_CODE_FRAME ||
+ dev_ctxt->trans_tbl[i].
+ type == VCD_CMD_NONE) {
+ vcd_release_trans_tbl_entry(&dev_ctxt->
+ trans_tbl[i]);
+ } else {
+ VCD_MSG_LOW("vcd_transaction in use type(%u)",
+ dev_ctxt->trans_tbl[i].type);
+ cntr++;
+ }
+ }
+ }
+ if (cntr)
+ VCD_MSG_ERROR("vcd_transactions still in use: (%d)", cntr);
+}
+
+void vcd_release_all_clnt_transc(struct vcd_clnt_ctxt *cctxt)
+{
+ struct vcd_dev_ctxt *dev_ctxt = cctxt->dev_ctxt;
+ u32 i;
+
+ VCD_MSG_LOW("vcd_release_all_clnt_transc:");
+
+ for (i = 0; i < dev_ctxt->trans_tbl_size; i++) {
+ if (dev_ctxt->trans_tbl[i].in_use &&
+ cctxt == dev_ctxt->trans_tbl[i].cctxt) {
+ vcd_release_trans_tbl_entry(
+ &dev_ctxt->trans_tbl[i]);
+ }
+ }
+}
+
+void vcd_send_flush_done(struct vcd_clnt_ctxt *cctxt, u32 status)
+{
+ VCD_MSG_LOW("vcd_send_flush_done:");
+
+ if (cctxt->status.mask & VCD_FLUSH_INPUT) {
+ cctxt->callback(VCD_EVT_RESP_FLUSH_INPUT_DONE,
+ status, NULL, 0, cctxt, cctxt->client_data);
+ cctxt->status.mask &= ~VCD_FLUSH_INPUT;
+ }
+
+ if (cctxt->status.mask & VCD_FLUSH_OUTPUT) {
+ cctxt->callback(VCD_EVT_RESP_FLUSH_OUTPUT_DONE,
+ status, NULL, 0, cctxt, cctxt->client_data);
+ cctxt->status.mask &= ~VCD_FLUSH_OUTPUT;
+ }
+}
+
+u32 vcd_store_seq_hdr(
+ struct vcd_clnt_ctxt *cctxt,
+ struct vcd_sequence_hdr *seq_hdr)
+{
+ u32 rc;
+ struct vcd_property_hdr prop_hdr;
+ u32 align;
+ u8 *virtual_aligned;
+ u32 addr;
+ int ret = 0;
+
+ if (!seq_hdr->sequence_header_len
+ || !seq_hdr->sequence_header) {
+ VCD_MSG_ERROR("Bad seq hdr");
+
+ return VCD_ERR_BAD_POINTER;
+ }
+
+ if (cctxt->seq_hdr.sequence_header) {
+ VCD_MSG_HIGH("Old seq hdr detected");
+
+ vcd_pmem_free(cctxt->seq_hdr.sequence_header,
+ cctxt->seq_hdr_phy_addr);
+ cctxt->seq_hdr.sequence_header = NULL;
+ }
+
+ cctxt->seq_hdr.sequence_header_len =
+ seq_hdr->sequence_header_len;
+
+ prop_hdr.prop_id = DDL_I_SEQHDR_ALIGN_BYTES;
+ prop_hdr.sz = sizeof(u32);
+
+ rc = ddl_get_property(cctxt->ddl_handle, &prop_hdr, &align);
+
+ VCD_FAILED_RETURN(rc,
+ "Failed: ddl_get_property DDL_I_SEQHDR_ALIGN_BYTES");
+
+ VCD_MSG_MED("Seq hdr alignment bytes = %d", align);
+
+ ret = vcd_pmem_alloc(cctxt->seq_hdr.sequence_header_len + align +
+ VCD_SEQ_HDR_PADDING_BYTES,
+ &(cctxt->seq_hdr.sequence_header),
+ &(cctxt->seq_hdr_phy_addr));
+
+ if (ret < 0) {
+ VCD_MSG_ERROR("Seq hdr allocation failed");
+
+ return VCD_ERR_ALLOC_FAIL;
+ }
+
+ if (!cctxt->seq_hdr_phy_addr) {
+ VCD_MSG_ERROR("Couldn't get physical address");
+
+ return VCD_ERR_BAD_POINTER;
+ }
+
+ if (align > 0) {
+ addr = (u32) cctxt->seq_hdr_phy_addr;
+ addr += align;
+ addr -= (addr % align);
+ virtual_aligned = cctxt->seq_hdr.sequence_header;
+ virtual_aligned += (u32) (addr -
+ (u32) cctxt->seq_hdr_phy_addr);
+ cctxt->seq_hdr_phy_addr = (u8 *) addr;
+ } else {
+ virtual_aligned = cctxt->seq_hdr.sequence_header;
+ }
+
+ memcpy(virtual_aligned, seq_hdr->sequence_header,
+ seq_hdr->sequence_header_len);
+
+ return VCD_S_SUCCESS;
+}
+
+u32 vcd_set_frame_rate(
+ struct vcd_clnt_ctxt *cctxt,
+ struct vcd_property_frame_rate *fps)
+{
+ u32 rc;
+ cctxt->frm_rate = *fps;
+ rc = vcd_update_clnt_perf_lvl(cctxt, &cctxt->frm_rate,
+ cctxt->frm_p_units);
+ if (VCD_FAILED(rc)) {
+ VCD_MSG_ERROR("rc = 0x%x. Failed: vcd_update_clnt_perf_lvl",
+ rc);
+ }
+ rc = vcd_sched_update_config(cctxt);
+ return rc;
+}
+
+u32 vcd_set_frame_size(
+ struct vcd_clnt_ctxt *cctxt,
+ struct vcd_property_frame_size *frm_size)
+{
+ struct vcd_property_hdr prop_hdr;
+ u32 rc;
+ u32 frm_p_units;
+ (void)frm_size;
+
+ prop_hdr.prop_id = DDL_I_FRAME_PROC_UNITS;
+ prop_hdr.sz = sizeof(frm_p_units);
+ rc = ddl_get_property(cctxt->ddl_handle, &prop_hdr, &frm_p_units);
+ VCD_FAILED_RETURN(rc, "Failed: Get DDL_I_FRAME_PROC_UNITS");
+
+ cctxt->frm_p_units = frm_p_units;
+
+ rc = vcd_update_clnt_perf_lvl(cctxt, &cctxt->frm_rate,
+ frm_p_units);
+ if (VCD_FAILED(rc)) {
+ VCD_MSG_ERROR("rc = 0x%x. Failed: vcd_update_clnt_perf_lvl",
+ rc);
+ }
+ return rc;
+}
+
+void vcd_process_pending_flush_in_eos(struct vcd_clnt_ctxt *cctxt)
+{
+ u32 rc = VCD_S_SUCCESS;
+ VCD_MSG_HIGH("Buffer flush is pending");
+ rc = vcd_flush_buffers(cctxt, cctxt->status.mask & VCD_FLUSH_ALL);
+ if (VCD_FAILED(rc))
+ VCD_MSG_ERROR("rc = 0x%x. Failed: vcd_flush_buffers", rc);
+ cctxt->status.mask &= ~VCD_EOS_WAIT_OP_BUF;
+ vcd_send_flush_done(cctxt, VCD_S_SUCCESS);
+}
+
+void vcd_process_pending_stop_in_eos(struct vcd_clnt_ctxt *cctxt)
+{
+ u32 rc = VCD_S_SUCCESS;
+ rc = vcd_flush_buffers(cctxt, VCD_FLUSH_ALL);
+ if (VCD_FAILED(rc))
+ VCD_MSG_ERROR("rc = 0x%x. Failed: vcd_flush_buffers", rc);
+ VCD_MSG_HIGH("All buffers are returned. Enqueuing stop cmd");
+ vcd_client_cmd_flush_and_en_q(cctxt, VCD_CMD_CODEC_STOP);
+ cctxt->status.mask &= ~VCD_STOP_PENDING;
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_STOPPING,
+ CLIENT_STATE_EVENT_NUMBER(stop));
+}
+
+u32 vcd_calculate_frame_delta(
+ struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *frame)
+{
+ u32 frm_delta;
+ u64 temp, max = ~((u64)0);
+
+ if (frame->time_stamp >= cctxt->status.prev_ts)
+ temp = frame->time_stamp - cctxt->status.prev_ts;
+ else
+ temp = (max - cctxt->status.prev_ts) +
+ frame->time_stamp;
+
+ VCD_MSG_LOW("Curr_ts=%lld Prev_ts=%lld Diff=%llu",
+ frame->time_stamp, cctxt->status.prev_ts, temp);
+
+ temp *= cctxt->time_resoln;
+ (void)do_div(temp, VCD_TIMESTAMP_RESOLUTION);
+ frm_delta = temp;
+ cctxt->status.time_elapsed += frm_delta;
+
+ temp = (cctxt->status.time_elapsed * VCD_TIMESTAMP_RESOLUTION);
+ (void)do_div(temp, cctxt->time_resoln);
+ cctxt->status.prev_ts = cctxt->status.first_ts + temp;
+
+ VCD_MSG_LOW("Time_elapsed=%llu, Drift=%llu, new Prev_ts=%lld",
+ cctxt->status.time_elapsed, temp,
+ cctxt->status.prev_ts);
+
+ return frm_delta;
+}
+
+struct vcd_buffer_entry *vcd_check_fill_output_buffer
+ (struct vcd_clnt_ctxt *cctxt,
+ struct vcd_frame_data *buffer) {
+ struct vcd_buffer_pool *buf_pool = &cctxt->out_buf_pool;
+ struct vcd_buffer_entry *buf_entry;
+
+ if (!buf_pool->entries) {
+ VCD_MSG_ERROR("Buffers not set or allocated yet");
+
+ return NULL;
+ }
+
+ if (!buffer->virtual) {
+ VCD_MSG_ERROR("NULL buffer address provided");
+ return NULL;
+ }
+
+ buf_entry =
+ vcd_find_buffer_pool_entry(buf_pool, buffer->virtual);
+ if (!buf_entry) {
+ VCD_MSG_ERROR("Unrecognized buffer address provided = %p",
+ buffer->virtual);
+ return NULL;
+ }
+
+ if (buf_entry->in_use) {
+ VCD_MSG_ERROR
+ ("An inuse output frame is being provided for reuse");
+ return NULL;
+ }
+
+ if ((buffer->alloc_len < buf_pool->buf_req.sz ||
+ buffer->alloc_len > buf_entry->sz) &&
+ !(cctxt->status.mask & VCD_IN_RECONFIG)) {
+ VCD_MSG_ERROR
+ ("Bad buffer Alloc_len = %d, Actual sz = %d, "
+ " Min sz = %u",
+ buffer->alloc_len, buf_entry->sz,
+ buf_pool->buf_req.sz);
+ return NULL;
+ }
+
+ return buf_entry;
+}
+
+void vcd_handle_ind_hw_err_fatal(struct vcd_clnt_ctxt *cctxt,
+ u32 event, u32 status)
+{
+ if (cctxt->status.frame_submitted) {
+ cctxt->status.frame_submitted--;
+ vcd_mark_frame_channel(cctxt->dev_ctxt);
+ }
+ vcd_handle_err_fatal(cctxt, event, status);
+}
+
+void vcd_handle_err_fatal(struct vcd_clnt_ctxt *cctxt, u32 event,
+ u32 status)
+{
+ VCD_MSG_LOW("vcd_handle_err_fatal: event=%x, err=%x", event, status);
+ if (!VCD_FAILED_FATAL(status))
+ return;
+
+ if (VCD_FAILED_DEVICE_FATAL(status)) {
+ vcd_clnt_handle_device_err_fatal(cctxt, event);
+ vcd_handle_device_err_fatal(cctxt->dev_ctxt, cctxt);
+ } else if (VCD_FAILED_CLIENT_FATAL(status)) {
+ cctxt->status.last_evt = event;
+ cctxt->callback(event, VCD_ERR_HW_FATAL, NULL, 0, cctxt,
+ cctxt->client_data);
+ cctxt->status.mask |= VCD_CLEANING_UP;
+ vcd_client_cmd_flush_and_en_q(cctxt, VCD_CMD_CODEC_STOP);
+ vcd_do_client_state_transition(cctxt,
+ VCD_CLIENT_STATE_INVALID,
+ CLIENT_STATE_EVENT_NUMBER(clnt_cb));
+ }
+}
+
+void vcd_handle_err_in_starting(struct vcd_clnt_ctxt *cctxt,
+ u32 status)
+{
+ VCD_MSG_LOW("\n vcd_handle_err_in_starting:");
+ if (VCD_FAILED_FATAL(status)) {
+ vcd_handle_err_fatal(cctxt, VCD_EVT_RESP_START, status);
+ } else {
+ cctxt->status.last_err = status;
+ VCD_MSG_HIGH("\n VCD cleanup: Enqueuing stop cmd");
+ vcd_client_cmd_flush_and_en_q(cctxt, VCD_CMD_CODEC_STOP);
+ }
+}
+
+void vcd_handle_trans_pending(struct vcd_clnt_ctxt *cctxt)
+{
+ if (!cctxt->status.frame_submitted) {
+ VCD_MSG_ERROR("Transaction pending response was not expected");
+ return;
+ }
+ cctxt->status.frame_submitted--;
+ cctxt->status.frame_delayed++;
+ vcd_mark_frame_channel(cctxt->dev_ctxt);
+}
+void vcd_handle_submit_frame_failed(struct vcd_dev_ctxt
+ *dev_ctxt, struct vcd_transc *transc)
+{
+ struct vcd_clnt_ctxt *cctxt = transc->cctxt;
+ u32 rc;
+
+ vcd_mark_frame_channel(dev_ctxt);
+ vcd_release_trans_tbl_entry(transc);
+
+ vcd_handle_err_fatal(cctxt, VCD_EVT_IND_HWERRFATAL,
+ VCD_ERR_CLIENT_FATAL);
+
+ if (vcd_get_command_channel(dev_ctxt, &transc)) {
+ transc->type = VCD_CMD_CODEC_STOP;
+ transc->cctxt = cctxt;
+ rc = vcd_submit_cmd_sess_end(transc);
+ if (VCD_FAILED(rc)) {
+ vcd_release_command_channel(dev_ctxt, transc);
+ VCD_MSG_ERROR("rc = 0x%x. Failed: VCD_SubmitCmdSessEnd",
+ rc);
+ }
+ }
+}
+
+u32 vcd_check_if_buffer_req_met(struct vcd_clnt_ctxt *cctxt,
+ enum vcd_buffer_type buffer)
+{
+ struct vcd_property_hdr prop_hdr;
+ struct vcd_buffer_pool *buf_pool;
+ struct vcd_buffer_requirement buf_req;
+ u32 rc;
+ u8 i;
+
+ if (buffer == VCD_BUFFER_INPUT) {
+ prop_hdr.prop_id = DDL_I_INPUT_BUF_REQ;
+ buf_pool = &cctxt->in_buf_pool;
+ } else {
+ prop_hdr.prop_id = DDL_I_OUTPUT_BUF_REQ;
+ buf_pool = &cctxt->out_buf_pool;
+ }
+
+ prop_hdr.sz = sizeof(buf_req);
+ rc = ddl_get_property(cctxt->ddl_handle, &prop_hdr, &buf_req);
+ VCD_FAILED_RETURN(rc, "Failed: ddl_GetProperty");
+
+ buf_pool->buf_req = buf_req;
+ if (buf_pool->count < buf_req.actual_count) {
+ VCD_MSG_ERROR("Buf requirement count not met");
+ return VCD_ERR_FAIL;
+ }
+
+ if (buf_pool->count > buf_req.actual_count)
+ buf_pool->count = buf_req.actual_count;
+
+ if (!buf_pool->entries ||
+ buf_pool->validated != buf_pool->count) {
+ VCD_MSG_ERROR("Buffer pool is not completely setup yet");
+ return VCD_ERR_BAD_STATE;
+ }
+ for (i = 1; (rc == VCD_S_SUCCESS && i <= buf_pool->count); i++) {
+ if (buf_pool->entries[i].sz <
+ buf_pool->buf_req.sz) {
+ VCD_MSG_ERROR(
+ "BufReq sz not met:\
+ addr=(0x%p) sz=%d ReqSize=%d",
+ buf_pool->entries[i].virtual,
+ buf_pool->entries[i].sz,
+ buf_pool->buf_req.sz);
+ rc = VCD_ERR_FAIL;
+ }
+ }
+ return rc;
+}
+
+u32 vcd_handle_ind_output_reconfig(
+ struct vcd_clnt_ctxt *cctxt, void* payload, u32 status)
+{
+ struct ddl_frame_data_tag *frame =
+ (struct ddl_frame_data_tag *)payload;
+ struct vcd_property_hdr prop_hdr;
+ u32 rc = VCD_S_SUCCESS;
+ struct vcd_buffer_pool *out_buf_pool;
+ struct vcd_buffer_requirement buf_req;
+
+ if (frame)
+ rc = vcd_handle_output_required(cctxt, payload, status);
+ VCD_FAILED_RETURN(rc, "Failed: vcd_handle_output_required in reconfig");
+ vcd_mark_frame_channel(cctxt->dev_ctxt);
+
+ rc = vcd_sched_suspend_resume_clnt(cctxt, false);
+ VCD_FAILED_RETURN(rc, "Failed: vcd_sched_suspend_resume_clnt");
+ out_buf_pool = &cctxt->out_buf_pool;
+ prop_hdr.prop_id = DDL_I_OUTPUT_BUF_REQ;
+ prop_hdr.sz = sizeof(buf_req);
+ rc = ddl_get_property(cctxt->ddl_handle, &prop_hdr, &buf_req);
+ VCD_FAILED_RETURN(rc, "Failed: ddl_GetProperty");
+
+ out_buf_pool->buf_req = buf_req;
+
+ if (out_buf_pool->count < buf_req.actual_count) {
+ VCD_MSG_HIGH("Output buf requirement count increased");
+ out_buf_pool->count = buf_req.actual_count;
+ }
+
+ if (buf_req.actual_count > VCD_MAX_BUFFER_ENTRIES) {
+ VCD_MSG_ERROR("\n New act count exceeds Max count(32)");
+ return VCD_ERR_FAIL;
+ }
+
+ if (!VCD_FAILED(rc)) {
+ rc = vcd_set_frame_size(cctxt, NULL);
+ VCD_FAILED_RETURN(rc, "Failed: set_frame_size in reconfig");
+ cctxt->status.mask &= ~VCD_FIRST_OP_RCVD;
+ cctxt->status.mask |= VCD_IN_RECONFIG;
+ cctxt->callback(VCD_EVT_IND_OUTPUT_RECONFIG,
+ status, NULL, 0, cctxt,
+ cctxt->client_data);
+ }
+ return rc;
+}
+
+u32 vcd_handle_ind_output_reconfig_in_flushing(
+ struct vcd_clnt_ctxt *cctxt, void* payload, u32 status)
+{
+ u32 rc = VCD_S_SUCCESS;
+ if (cctxt->status.mask & VCD_FLUSH_INPUT && payload) {
+ (void)vcd_handle_input_done(cctxt, payload,
+ VCD_EVT_RESP_INPUT_FLUSHED, status);
+ payload = NULL;
+ }
+ rc = vcd_handle_ind_output_reconfig(cctxt, payload, status);
+ return rc;
+}
+
+u32 vcd_return_op_buffer_to_hw(struct vcd_clnt_ctxt *cctxt,
+ struct vcd_buffer_entry *buf_entry)
+{
+ u32 rc = VCD_S_SUCCESS;
+ struct vcd_frame_data *frm_entry = &buf_entry->frame;
+
+ VCD_MSG_LOW("vcd_return_op_buffer_to_hw in %d:",
+ cctxt->clnt_state.state);
+ frm_entry->physical = buf_entry->physical;
+ frm_entry->ip_frm_tag = VCD_FRAMETAG_INVALID;
+ frm_entry->intrlcd_ip_frm_tag = VCD_FRAMETAG_INVALID;
+ frm_entry->data_len = 0;
+
+ if (cctxt->decoding) {
+ struct vcd_property_hdr Prop_hdr;
+ struct ddl_frame_data_tag ddl_frm;
+ Prop_hdr.prop_id = DDL_I_DPB_RELEASE;
+ Prop_hdr.sz =
+ sizeof(struct ddl_frame_data_tag);
+ memset(&ddl_frm, 0, sizeof(ddl_frm));
+ ddl_frm.vcd_frm = *frm_entry;
+ rc = ddl_set_property(cctxt->ddl_handle, &Prop_hdr,
+ &ddl_frm);
+ if (VCD_FAILED(rc)) {
+ VCD_MSG_ERROR("Error returning output buffer to"
+ " HW. rc = 0x%x", rc);
+ buf_entry->in_use = false;
+ } else {
+ cctxt->out_buf_pool.in_use++;
+ buf_entry->in_use = true;
+ }
+ }
+ return rc;
+}
+
+void vcd_handle_clnt_fatal(struct vcd_clnt_ctxt *cctxt, u32 trans_end)
+{
+ if (trans_end)
+ vcd_mark_frame_channel(cctxt->dev_ctxt);
+ vcd_handle_err_fatal(cctxt,
+ VCD_EVT_IND_HWERRFATAL, VCD_ERR_CLIENT_FATAL);
+}
+
+void vcd_handle_clnt_fatal_input_done(struct vcd_clnt_ctxt *cctxt,
+ u32 trans_end)
+{
+ if (cctxt->status.frame_submitted > 0)
+ cctxt->status.frame_submitted--;
+ vcd_handle_clnt_fatal(cctxt, trans_end);
+}
+
+void vcd_handle_ind_info_output_reconfig(
+ struct vcd_clnt_ctxt *cctxt, u32 status)
+{
+ if (cctxt) {
+ cctxt->callback(VCD_EVT_IND_INFO_OUTPUT_RECONFIG, status, NULL,
+ 0, cctxt, cctxt->client_data);
+ }
+}
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_util.c b/drivers/video/msm/vidc/common/vcd/vcd_util.c
new file mode 100644
index 0000000..ba991f1
--- /dev/null
+++ b/drivers/video/msm/vidc/common/vcd/vcd_util.c
@@ -0,0 +1,106 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "vidc_type.h"
+#include "vcd_util.h"
+
+u32 vcd_critical_section_create(u32 **p_cs)
+{
+ struct mutex *lock;
+ if (!p_cs) {
+ VCD_MSG_ERROR("Bad critical section ptr");
+ return VCD_ERR_BAD_POINTER;
+ } else {
+ lock = kmalloc(sizeof(struct mutex), GFP_KERNEL);
+ if (!lock) {
+ VCD_MSG_ERROR("Failed: vcd_critical_section_create");
+ return VCD_ERR_ALLOC_FAIL;
+ }
+ mutex_init(lock);
+ *p_cs = (u32 *) lock;
+ return VCD_S_SUCCESS;
+ }
+}
+
+u32 vcd_critical_section_release(u32 *cs)
+{
+ struct mutex *lock = (struct mutex *)cs;
+ if (!lock) {
+ VCD_MSG_ERROR("Bad critical section object");
+ return VCD_ERR_BAD_POINTER;
+ }
+
+ mutex_destroy(lock);
+ kfree(cs);
+ return VCD_S_SUCCESS;
+}
+
+u32 vcd_critical_section_enter(u32 *cs)
+{
+ struct mutex *lock = (struct mutex *)cs;
+ if (!lock) {
+ VCD_MSG_ERROR("Bad critical section object");
+ return VCD_ERR_BAD_POINTER;
+ } else
+ mutex_lock(lock);
+
+ return VCD_S_SUCCESS;
+}
+
+u32 vcd_critical_section_leave(u32 *cs)
+{
+ struct mutex *lock = (struct mutex *)cs;
+
+ if (!lock) {
+ VCD_MSG_ERROR("Bad critical section object");
+
+ return VCD_ERR_BAD_POINTER;
+ } else
+ mutex_unlock(lock);
+
+ return VCD_S_SUCCESS;
+}
+
+int vcd_pmem_alloc(u32 size, u8 **kernel_vaddr, u8 **phy_addr)
+{
+ *phy_addr =
+ (u8 *) pmem_kalloc(size, PMEM_MEMTYPE | PMEM_ALIGNMENT_4K);
+
+ if (!IS_ERR((void *)*phy_addr)) {
+
+ *kernel_vaddr = ioremap((unsigned long)*phy_addr, size);
+
+ if (!*kernel_vaddr) {
+ pr_err("%s: could not ioremap in kernel pmem buffers\n",
+ __func__);
+ pmem_kfree((s32) *phy_addr);
+ return -ENOMEM;
+ }
+ pr_debug("write buf: phy addr 0x%08x kernel addr 0x%08x\n",
+ (u32) *phy_addr, (u32) *kernel_vaddr);
+ return 0;
+ } else {
+ pr_err("%s: could not allocte in kernel pmem buffers\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+}
+
+int vcd_pmem_free(u8 *kernel_vaddr, u8 *phy_addr)
+{
+ iounmap((void *)kernel_vaddr);
+ pmem_kfree((s32) phy_addr);
+
+ return 0;
+}
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_util.h b/drivers/video/msm/vidc/common/vcd/vcd_util.h
new file mode 100644
index 0000000..07ad651
--- /dev/null
+++ b/drivers/video/msm/vidc/common/vcd/vcd_util.h
@@ -0,0 +1,52 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _VCD_UTIL_H_
+#define _VCD_UTIL_H_
+#include "vidc_type.h"
+#include "vcd_api.h"
+
+#if DEBUG
+
+#define VCD_MSG_LOW(xx_fmt...) printk(KERN_INFO "\n\t* " xx_fmt)
+#define VCD_MSG_MED(xx_fmt...) printk(KERN_INFO "\n * " xx_fmt)
+#define VCD_MSG_HIGH(xx_fmt...) printk(KERN_WARNING "\n" xx_fmt)
+
+#else
+
+#define VCD_MSG_LOW(xx_fmt...)
+#define VCD_MSG_MED(xx_fmt...)
+#define VCD_MSG_HIGH(xx_fmt...)
+
+#endif
+
+#define VCD_MSG_ERROR(xx_fmt...) printk(KERN_ERR "\n err: " xx_fmt)
+#define VCD_MSG_FATAL(xx_fmt...) printk(KERN_ERR "\n<FATAL> " xx_fmt)
+
+#define VCD_FAILED_RETURN(rc, xx_fmt...) \
+ do { \
+ if (VCD_FAILED(rc)) { \
+ printk(KERN_ERR xx_fmt); \
+ return rc; \
+ } \
+ } while (0)
+
+#define VCD_FAILED_DEVICE_FATAL(rc) \
+ (rc == VCD_ERR_HW_FATAL ? true : false)
+#define VCD_FAILED_CLIENT_FATAL(rc) \
+ (rc == VCD_ERR_CLIENT_FATAL ? true : false)
+
+#define VCD_FAILED_FATAL(rc) \
+ ((VCD_FAILED_DEVICE_FATAL(rc) || VCD_FAILED_CLIENT_FATAL(rc)) \
+ ? true : false)
+
+#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vidc_type.h b/drivers/video/msm/vidc/common/vcd/vidc_type.h
new file mode 100644
index 0000000..bd87c0d
--- /dev/null
+++ b/drivers/video/msm/vidc/common/vcd/vidc_type.h
@@ -0,0 +1,30 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef VIDC_TYPE_H
+#define VIDC_TYPE_H
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/time.h>
+#include <linux/dma-mapping.h>
+#include <linux/android_pmem.h>
+
+#define DEBUG 0
+#define VIDC_ENABLE_DBGFS
+
+#define USE_RES_TRACKER
+#endif