Update kgsl and msm_fb from caf jb_chocolate
Current as of 9f50d27978515e62323231539cdb44f897386b29
msm_fb: hdmi: Correct checksum value
Signed-off-by: Evan McClain <aeroevan@gmail.com>
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 3bfe31c..376d68c 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -11,7 +11,7 @@
endif
obj-$(CONFIG_ARCH_QSD8X50) += sirc.o
-obj-y += proc_comm.o
+obj-y += proc_comm.o subsystem_map.o
obj-$(CONFIG_ARCH_MSM_ARM11) += acpuclock-arm11.o idle.o
obj-$(CONFIG_ARCH_QSD8X50) += arch-init-scorpion.o acpuclock-scorpion.o
obj-$(CONFIG_ARCH_MSM7X30) += acpuclock-7x30.o internal_power_rail.o
diff --git a/arch/arm/mach-msm/board-vivow-panel.c b/arch/arm/mach-msm/board-vivow-panel.c
index 94ebc62..886ff8c 100644
--- a/arch/arm/mach-msm/board-vivow-panel.c
+++ b/arch/arm/mach-msm/board-vivow-panel.c
@@ -24,13 +24,13 @@
#include <linux/err.h>
#include <linux/gpio.h>
+#include <mach/msm_panel.h>
#include <asm/io.h>
#include <asm/mach-types.h>
#include <mach/msm_fb.h>
#include <mach/msm_iomap.h>
#include <mach/vreg.h>
#include <mach/panel_id.h>
-#include "../../../drivers/video/msm/mdp_hw.h"
#include "pmic.h"
#include "board-vivow.h"
@@ -70,7 +70,6 @@
.len = sizeof((u8 []){__VA_ARGS__}) / sizeof(u8) \
}
static struct clk *axi_clk;
-static int color_enhancement = 0;
static struct vreg *V_LCMIO_1V8, *V_LCM_2V85;
static struct cabc_t {
@@ -401,20 +400,6 @@
enum led_brightness vivow_brightness_value = DEFAULT_BRIGHTNESS;// multiple definition of `brightness_value' in board-glacier-panel.c
-void vivow_mdp_color_enhancement(struct mdp_device *mdp_dev)
-{
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
- mdp->write_regs(mdp, vivow_mdp_init_color, ARRAY_SIZE(vivow_mdp_init_color));
-}
-
-static struct msm_mdp_platform_data mdp_pdata = {
- .overrides = MSM_MDP4_MDDI_DMA_SWITCH
-#ifdef CONFIG_OVERLAY_FORCE_UPDATE
- | MSM_MDP_FORCE_UPDATE
-#endif
- ,
-};
-
static void
do_renesas_cmd(struct msm_mddi_client_data *client_data, struct mddi_cmd *cmd_table, ssize_t size)
{
@@ -513,7 +498,6 @@
static enum led_brightness
vivow_get_brightness(struct led_classdev *led_cdev)
{
- /*FIXME:workaround for NOVATEK driver IC*/
#if 0
struct msm_mddi_client_data *client = cabc.client_data;
return client->remote_read(client, 0x5100);
@@ -928,14 +912,8 @@
struct msm_mddi_client_data *client_data)
{
B(KERN_DEBUG "%s(%d)\n", __func__, __LINE__);
-
-
client_data->auto_hibernate(client_data, 0);
if(panel_type == PANEL_VIVOW_HITACHI) {
- if (color_enhancement == 0) {
- vivow_mdp_color_enhancement(mdp_pdata.mdp_dev);
- color_enhancement = 1;
- }
client_data->remote_write(client_data, 0x0, 0x11);
hr_msleep(125);
vivow_backlight_switch(LED_FULL);
@@ -1099,21 +1077,40 @@
},
};
+static struct msm_mdp_platform_data mdp_pdata = {
+#ifdef CONFIG_MDP4_HW_VSYNC
+ .xres = 480,
+ .yres = 800,
+ .back_porch = 2,
+ .front_porch = 42,
+ .pulse_width = 2,
+#else
+ .overrides = MSM_MDP4_MDDI_DMA_SWITCH,
+#endif
+};
+
+static struct msm_mdp_platform_data mdp_pdata_sony = {
+#ifdef CONFIG_MDP4_HW_VSYNC
+ .xres = 480,
+ .yres = 800,
+ .back_porch = 4,
+ .front_porch = 2,
+ .pulse_width = 4,
+#else
+ .overrides = MSM_MDP4_MDDI_DMA_SWITCH,
+#endif
+};
int __init vivow_init_panel(unsigned int sys_rev)
{
int rc;
B(KERN_INFO "%s(%d): enter. panel_type 0x%08x\n", __func__, __LINE__, panel_type);
+ if (panel_type == PANEL_VIVOW_HITACHI)
+ msm_device_mdp.dev.platform_data = &mdp_pdata;
+ else
+ msm_device_mdp.dev.platform_data = &mdp_pdata_sony;
- //use dmap for hitachi panel
- if(panel_type == PANEL_VIVOW_HITACHI)
- {
- mdp_pdata.overrides = 0;
- pr_err("%s: mdp_pdata.overrides = 0\n", __func__);
- }
-
- msm_device_mdp.dev.platform_data = &mdp_pdata;
rc = platform_device_register(&msm_device_mdp);
if (rc)
return rc;
diff --git a/arch/arm/mach-msm/devices_htc.c b/arch/arm/mach-msm/devices_htc.c
index e6b076b..08c43e4 100644
--- a/arch/arm/mach-msm/devices_htc.c
+++ b/arch/arm/mach-msm/devices_htc.c
@@ -182,14 +182,8 @@
.set_grp_async = set_grp3d_async,
.idle_timeout = HZ/20,
.nap_allowed = true,
- .clk = {
- .clk = "grp_clk",
- .pclk = "grp_pclk",
- },
- .imem_clk_name = {
- .clk = "imem_clk",
- .pclk = NULL,
- },
+ .clk_map = KGSL_CLK_SRC | KGSL_CLK_CORE |
+ KGSL_CLK_IFACE | KGSL_CLK_MEM,
};
static struct platform_device msm_kgsl_3d0 = {
@@ -231,10 +225,7 @@
.set_grp_async = NULL,
.idle_timeout = HZ/10,
.nap_allowed = true,
- .clk = {
- .clk = "grp_2d_clk",
- .pclk = "grp_2d_pclk",
- },
+ .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE,
};
static struct platform_device msm_kgsl_2d0 = {
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index b10f483..3d9993f 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -315,6 +315,19 @@
struct dec_instance_table *dec_instance_list;
};
+enum msm_mdp_hw_revision {
+ MDP_REV_20 = 1,
+ MDP_REV_22,
+ MDP_REV_30,
+ MDP_REV_303,
+ MDP_REV_31,
+ MDP_REV_40,
+ MDP_REV_41,
+ MDP_REV_42,
+ MDP_REV_43,
+ MDP_REV_44,
+};
+
struct msm_panel_common_pdata {
uintptr_t hw_revision_addr;
int gpio;
@@ -324,14 +337,15 @@
void (*panel_config_gpio)(int);
int (*vga_switch)(int select_vga);
int *gpio_num;
- int mdp_core_clk_rate;
- unsigned num_mdp_clk;
- int *mdp_core_clk_table;
- int (*rgb_format)(void);
- unsigned char (*shrink_pwm)(int val);
+ u32 mdp_max_clk;
#ifdef CONFIG_MSM_BUS_SCALING
struct msm_bus_scale_pdata *mdp_bus_scale_table;
#endif
+ int mdp_rev;
+ u32 ov0_wb_size; /* overlay0 writeback size */
+ u32 ov1_wb_size; /* overlay1 writeback size */
+ u32 mem_hid;
+ char cont_splash_enabled;
};
struct lcdc_platform_data {
@@ -362,10 +376,13 @@
int (*dsi_power_save)(int on);
};
+#define PANEL_NAME_MAX_LEN 50
struct msm_fb_platform_data {
int (*detect_client)(const char *name);
int mddi_prescan;
int (*allow_set_offset)(void);
+ char prim_panel_name[PANEL_NAME_MAX_LEN];
+ char ext_panel_name[PANEL_NAME_MAX_LEN];
};
struct msm_hdmi_platform_data {
@@ -417,6 +434,19 @@
void __init msm_clock_init(void);
#endif
+struct msm_vidc_platform_data {
+ int memtype;
+ u32 enable_ion;
+ int disable_dmx;
+ int disable_fullhd;
+ u32 cp_enabled;
+#ifdef CONFIG_MSM_BUS_SCALING
+ struct msm_bus_scale_pdata *vidc_bus_client_pdata;
+#endif
+ int disable_turbo;
+ int cont_mode_dpb_count;
+};
+
void __init msm_acpu_clock_init(struct msm_acpu_clock_platform_data *);
struct msm_usb_host_platform_data;
diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index 48eae0c..f3e24d1 100644
--- a/arch/arm/mach-msm/include/mach/iommu_domains.h
+++ b/arch/arm/mach-msm/include/mach/iommu_domains.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, 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
@@ -14,14 +14,17 @@
#define _ARCH_IOMMU_DOMAINS_H
enum {
- GLOBAL_DOMAIN,
+ VIDEO_DOMAIN,
+ CAMERA_DOMAIN,
+ DISPLAY_DOMAIN,
+ ROTATOR_DOMAIN,
MAX_DOMAINS
};
enum {
VIDEO_FIRMWARE_POOL,
- LOW_256MB_POOL,
- HIGH_POOL,
+ VIDEO_MAIN_POOL,
+ GEN_POOL,
};
@@ -48,8 +51,14 @@
extern int msm_iommu_map_extra(struct iommu_domain *domain,
unsigned long start_iova,
unsigned long size,
+ unsigned long page_size,
int cached);
+extern void msm_iommu_unmap_extra(struct iommu_domain *domain,
+ unsigned long start_iova,
+ unsigned long size,
+ unsigned long page_size);
+
#else
static inline struct iommu_domain
*msm_get_iommu_domain(int subsys_id) { return NULL; }
@@ -84,10 +93,18 @@
static inline int msm_iommu_map_extra(struct iommu_domain *domain,
unsigned long start_iova,
unsigned long size,
+ unsigned long page_size,
int cached)
{
return -ENODEV;
}
+
+static inline void msm_iommu_unmap_extra(struct iommu_domain *domain,
+ unsigned long start_iova,
+ unsigned long size,
+ unsigned long page_size)
+{
+}
#endif
#endif
diff --git a/arch/arm/mach-msm/include/mach/ion.h b/arch/arm/mach-msm/include/mach/ion.h
index 4d12249..fffb552 100644
--- a/arch/arm/mach-msm/include/mach/ion.h
+++ b/arch/arm/mach-msm/include/mach/ion.h
@@ -20,4 +20,10 @@
ION_SMI_TYPE,
};
+enum ion_permission_type {
+ IPT_TYPE_MM_CARVEOUT = 0,
+ IPT_TYPE_MFC_SHAREDMEM = 1,
+ IPT_TYPE_MDP_WRITEBACK = 2,
+};
+
#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_fb.h b/arch/arm/mach-msm/include/mach/msm_fb.h
index 526a29a..77ce2bf 100644
--- a/arch/arm/mach-msm/include/mach/msm_fb.h
+++ b/arch/arm/mach-msm/include/mach/msm_fb.h
@@ -408,11 +408,12 @@
extern int display_notifier_call_chain(unsigned long val, void *data);
#define display_notifier(fn, pri) { \
- static struct notifier_block fn##_nb = \
- { .notifier_call = fn, .priority = pri }; \
- register_display_notifier(&fn##_nb); \
+ static struct notifier_block fn##_nb = \
+ { .notifier_call = fn, .priority = pri }; \
+ register_display_notifier(&fn##_nb); \
}
+
#if (defined(CONFIG_USB_FUNCTION_PROJECTOR) || defined(CONFIG_USB_ANDROID_PROJECTOR))
/* For USB Projector to quick access the frame buffer info */
struct msm_fb_info {
diff --git a/arch/arm/mach-msm/include/mach/msm_subsystem_map.h b/arch/arm/mach-msm/include/mach/msm_subsystem_map.h
new file mode 100644
index 0000000..ebb2327
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_subsystem_map.h
@@ -0,0 +1,83 @@
+/*
+ * 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 __ARCH_MACH_MSM_SUBSYSTEM_MAP_H
+#define __ARCH_MACH_MSM_SUBSYSTEM_MAP_H
+
+#include <linux/iommu.h>
+#include <mach/iommu_domains.h>
+
+/* map the physical address in the kernel vaddr space */
+#define MSM_SUBSYSTEM_MAP_KADDR 0x1
+/* map the physical address in the iova address space */
+#define MSM_SUBSYSTEM_MAP_IOVA 0x2
+/* ioremaps in the kernel address space are cached */
+#define MSM_SUBSYSTEM_MAP_CACHED 0x4
+/* ioremaps in the kernel address space are uncached */
+#define MSM_SUBSYSTEM_MAP_UNCACHED 0x8
+/*
+ * Will map 2x the length requested.
+ */
+#define MSM_SUBSYSTEM_MAP_IOMMU_2X 0x10
+
+/*
+ * Shortcut flags for alignment.
+ * The flag must be equal to the alignment requested.
+ * e.g. for 8k alignment the flags must be (0x2000 | other flags)
+ */
+#define MSM_SUBSYSTEM_ALIGN_IOVA_8K SZ_8K
+#define MSM_SUBSYSTEM_ALIGN_IOVA_1M SZ_1M
+
+
+enum msm_subsystem_id {
+ INVALID_SUBSYS_ID = -1,
+ MSM_SUBSYSTEM_VIDEO,
+ MSM_SUBSYSTEM_VIDEO_FWARE,
+ MSM_SUBSYSTEM_CAMERA,
+ MSM_SUBSYSTEM_DISPLAY,
+ MSM_SUBSYSTEM_ROTATOR,
+ MAX_SUBSYSTEM_ID
+};
+
+static inline int msm_subsystem_check_id(int subsys_id)
+{
+ return subsys_id > INVALID_SUBSYS_ID && subsys_id < MAX_SUBSYSTEM_ID;
+}
+
+struct msm_mapped_buffer {
+ /*
+ * VA mapped in the kernel address space. This field shall be NULL if
+ * MSM_SUBSYSTEM_MAP_KADDR was not passed to the map buffer function.
+ */
+ void *vaddr;
+ /*
+ * iovas mapped in the iommu address space. The ith entry of this array
+ * corresponds to the iova mapped in the ith subsystem in the array
+ * pased in to msm_subsystem_map_buffer. This field shall be NULL if
+ * MSM_SUBSYSTEM_MAP_IOVA was not passed to the map buffer function,
+ */
+ unsigned long *iova;
+};
+
+extern struct msm_mapped_buffer *msm_subsystem_map_buffer(
+ unsigned long phys,
+ unsigned int length,
+ unsigned int flags,
+ int *subsys_ids,
+ unsigned int nsubsys);
+
+extern int msm_subsystem_unmap_buffer(struct msm_mapped_buffer *buf);
+
+extern phys_addr_t msm_subsystem_check_iova_mapping(int subsys_id,
+ unsigned long iova);
+
+#endif /* __ARCH_MACH_MSM_SUBSYSTEM_MAP_H */
diff --git a/arch/arm/mach-msm/include/mach/scm-io.h b/arch/arm/mach-msm/include/mach/scm-io.h
new file mode 100644
index 0000000..5393da1
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/scm-io.h
@@ -0,0 +1,29 @@
+/* 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 __MACH_SCM_IO_H
+#define __MACH_SCM_IO_H
+
+#include <linux/types.h>
+
+#ifdef CONFIG_MSM_SECURE_IO
+
+extern u32 secure_readl(void __iomem *c);
+extern void secure_writel(u32 v, void __iomem *c);
+
+#else
+
+#define secure_readl(c) readl(c)
+#define secure_writel(v, c) writel(v, c)
+
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
new file mode 100644
index 0000000..7fbc8f6
--- /dev/null
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -0,0 +1,403 @@
+/* Copyright (c) 2010-2012, 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_subsystem_map.h>
+#include <linux/memory_alloc.h>
+#include <linux/iommu.h>
+#include <linux/vmalloc.h>
+#include <asm/sizes.h>
+#include <asm/page.h>
+#include <linux/init.h>
+#include <mach/iommu.h>
+#include <mach/iommu_domains.h>
+#include <mach/socinfo.h>
+
+/* dummy 64K for overmapping */
+char iommu_dummy[2*SZ_64K-4];
+
+struct msm_iommu_domain {
+ /* iommu domain to map in */
+ struct iommu_domain *domain;
+ /* total number of allocations from this domain */
+ atomic_t allocation_cnt;
+ /* number of iova pools */
+ int npools;
+ /*
+ * array of gen_pools for allocating iovas.
+ * behavior is undefined if these overlap
+ */
+ struct mem_pool *iova_pools;
+
+};
+
+
+struct {
+ char *name;
+ int domain;
+} msm_iommu_ctx_names[] = {
+ /* Camera */
+ {
+ .name = "vpe_src",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "vpe_dst",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "vfe_imgwr",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "vfe_misc",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "ijpeg_src",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "ijpeg_dst",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "jpegd_src",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "jpegd_dst",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Rotator */
+ {
+ .name = "rot_src",
+ .domain = ROTATOR_DOMAIN,
+ },
+ /* Rotator */
+ {
+ .name = "rot_dst",
+ .domain = ROTATOR_DOMAIN,
+ },
+ /* Video */
+ {
+ .name = "vcodec_a_mm1",
+ .domain = VIDEO_DOMAIN,
+ },
+ /* Video */
+ {
+ .name = "vcodec_b_mm2",
+ .domain = VIDEO_DOMAIN,
+ },
+ /* Video */
+ {
+ .name = "vcodec_a_stream",
+ .domain = VIDEO_DOMAIN,
+ },
+};
+
+static struct mem_pool video_pools[] = {
+ /*
+ * Video hardware has the following requirements:
+ * 1. All video addresses used by the video hardware must be at a higher
+ * address than video firmware address.
+ * 2. Video hardware can only access a range of 256MB from the base of
+ * the video firmware.
+ */
+ [VIDEO_FIRMWARE_POOL] =
+ /* Low addresses, intended for video firmware */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_16M - SZ_128K,
+ },
+ [VIDEO_MAIN_POOL] =
+ /* Main video pool */
+ {
+ .paddr = SZ_16M,
+ .size = SZ_256M - SZ_16M,
+ },
+ [GEN_POOL] =
+ /* Remaining address space up to 2G */
+ {
+ .paddr = SZ_256M,
+ .size = SZ_2G - SZ_256M,
+ },
+};
+
+static struct mem_pool camera_pools[] = {
+ [GEN_POOL] =
+ /* One address space for camera */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ },
+};
+
+static struct mem_pool display_pools[] = {
+ [GEN_POOL] =
+ /* One address space for display */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ },
+};
+
+static struct mem_pool rotator_pools[] = {
+ [GEN_POOL] =
+ /* One address space for rotator */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ },
+};
+
+static struct msm_iommu_domain msm_iommu_domains[] = {
+ [VIDEO_DOMAIN] = {
+ .iova_pools = video_pools,
+ .npools = ARRAY_SIZE(video_pools),
+ },
+ [CAMERA_DOMAIN] = {
+ .iova_pools = camera_pools,
+ .npools = ARRAY_SIZE(camera_pools),
+ },
+ [DISPLAY_DOMAIN] = {
+ .iova_pools = display_pools,
+ .npools = ARRAY_SIZE(display_pools),
+ },
+ [ROTATOR_DOMAIN] = {
+ .iova_pools = rotator_pools,
+ .npools = ARRAY_SIZE(rotator_pools),
+ },
+};
+
+int msm_iommu_map_extra(struct iommu_domain *domain,
+ unsigned long start_iova,
+ unsigned long size,
+ unsigned long page_size,
+ int cached)
+{
+ int i, ret_value = 0;
+ unsigned long order = get_order(page_size);
+ unsigned long aligned_size = ALIGN(size, page_size);
+ unsigned long nrpages = aligned_size >> (PAGE_SHIFT + order);
+ unsigned long phy_addr = ALIGN(virt_to_phys(iommu_dummy), page_size);
+ unsigned long temp_iova = start_iova;
+
+ for (i = 0; i < nrpages; i++) {
+ int ret = iommu_map(domain, temp_iova, phy_addr, order, cached);
+ if (ret) {
+ pr_err("%s: could not map %lx in domain %p, error: %d\n",
+ __func__, start_iova, domain, ret);
+ ret_value = -EAGAIN;
+ goto out;
+ }
+ temp_iova += page_size;
+ }
+ return ret_value;
+out:
+ for (; i > 0; --i) {
+ temp_iova -= page_size;
+ iommu_unmap(domain, start_iova, order);
+ }
+ return ret_value;
+}
+
+void msm_iommu_unmap_extra(struct iommu_domain *domain,
+ unsigned long start_iova,
+ unsigned long size,
+ unsigned long page_size)
+{
+ int i;
+ unsigned long order = get_order(page_size);
+ unsigned long aligned_size = ALIGN(size, page_size);
+ unsigned long nrpages = aligned_size >> (PAGE_SHIFT + order);
+ unsigned long temp_iova = start_iova;
+
+ for (i = 0; i < nrpages; ++i) {
+ iommu_unmap(domain, temp_iova, order);
+ temp_iova += page_size;
+ }
+}
+
+
+struct iommu_domain *msm_get_iommu_domain(int domain_num)
+{
+ if (domain_num >= 0 && domain_num < MAX_DOMAINS)
+ return msm_iommu_domains[domain_num].domain;
+ else
+ return NULL;
+}
+
+static unsigned long subsystem_to_domain_tbl[] = {
+ VIDEO_DOMAIN,
+ VIDEO_DOMAIN,
+ CAMERA_DOMAIN,
+ DISPLAY_DOMAIN,
+ ROTATOR_DOMAIN,
+ 0xFFFFFFFF
+};
+
+unsigned long msm_subsystem_get_domain_no(int subsys_id)
+{
+ if (subsys_id > INVALID_SUBSYS_ID && subsys_id <= MAX_SUBSYSTEM_ID &&
+ subsys_id < ARRAY_SIZE(subsystem_to_domain_tbl))
+ return subsystem_to_domain_tbl[subsys_id];
+ else
+ return subsystem_to_domain_tbl[MAX_SUBSYSTEM_ID];
+}
+
+unsigned long msm_subsystem_get_partition_no(int subsys_id)
+{
+ switch (subsys_id) {
+ case MSM_SUBSYSTEM_VIDEO_FWARE:
+ return VIDEO_FIRMWARE_POOL;
+ case MSM_SUBSYSTEM_VIDEO:
+ return VIDEO_MAIN_POOL;
+ case MSM_SUBSYSTEM_CAMERA:
+ case MSM_SUBSYSTEM_DISPLAY:
+ case MSM_SUBSYSTEM_ROTATOR:
+ return GEN_POOL;
+ default:
+ return 0xFFFFFFFF;
+ }
+}
+
+unsigned long msm_allocate_iova_address(unsigned int iommu_domain,
+ unsigned int partition_no,
+ unsigned long size,
+ unsigned long align)
+{
+ struct mem_pool *pool;
+ unsigned long iova;
+
+ if (iommu_domain >= MAX_DOMAINS)
+ return 0;
+
+ if (partition_no >= msm_iommu_domains[iommu_domain].npools)
+ return 0;
+
+ pool = &msm_iommu_domains[iommu_domain].iova_pools[partition_no];
+
+ if (!pool->gpool)
+ return 0;
+
+ iova = gen_pool_alloc_aligned(pool->gpool, size, ilog2(align));
+ if (iova)
+ pool->free -= size;
+
+ return iova;
+}
+
+void msm_free_iova_address(unsigned long iova,
+ unsigned int iommu_domain,
+ unsigned int partition_no,
+ unsigned long size)
+{
+ struct mem_pool *pool;
+
+ if (iommu_domain >= MAX_DOMAINS) {
+ WARN(1, "Invalid domain %d\n", iommu_domain);
+ return;
+ }
+
+ if (partition_no >= msm_iommu_domains[iommu_domain].npools) {
+ WARN(1, "Invalid partition %d for domain %d\n",
+ partition_no, iommu_domain);
+ return;
+ }
+
+ pool = &msm_iommu_domains[iommu_domain].iova_pools[partition_no];
+
+ if (!pool)
+ return;
+
+ pool->free += size;
+ gen_pool_free(pool->gpool, iova, size);
+}
+
+int msm_use_iommu()
+{
+ return iommu_found();
+}
+
+static int __init msm_subsystem_iommu_init(void)
+{
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(msm_iommu_domains); i++) {
+ msm_iommu_domains[i].domain = iommu_domain_alloc(0);
+ if (!msm_iommu_domains[i].domain)
+ continue;
+
+ for (j = 0; j < msm_iommu_domains[i].npools; j++) {
+ struct mem_pool *pool = &msm_iommu_domains[i].
+ iova_pools[j];
+ mutex_init(&pool->pool_mutex);
+ if (pool->size) {
+ pool->gpool = gen_pool_create(PAGE_SHIFT, -1);
+
+ if (!pool->gpool) {
+ pr_err("%s: could not allocate pool\n",
+ __func__);
+ pr_err("%s: domain %d iova space %d\n",
+ __func__, i, j);
+ continue;
+ }
+
+ if (gen_pool_add(pool->gpool, pool->paddr,
+ pool->size, -1)) {
+ pr_err("%s: could not add memory\n",
+ __func__);
+ pr_err("%s: domain %d pool %d\n",
+ __func__, i, j);
+ gen_pool_destroy(pool->gpool);
+ pool->gpool = NULL;
+ continue;
+ }
+ } else {
+ pool->gpool = NULL;
+ }
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_names); i++) {
+ int domain_idx;
+ struct device *ctx = msm_iommu_get_ctx(
+ msm_iommu_ctx_names[i].name);
+
+ if (!ctx)
+ continue;
+
+ domain_idx = msm_iommu_ctx_names[i].domain;
+
+ if (!msm_iommu_domains[domain_idx].domain)
+ continue;
+
+ if (iommu_attach_device(msm_iommu_domains[domain_idx].domain,
+ ctx)) {
+ WARN(1, "%s: could not attach domain %d to context %s."
+ " iommu programming will not occur.\n",
+ __func__, domain_idx,
+ msm_iommu_ctx_names[i].name);
+ continue;
+ }
+ }
+
+ return 0;
+}
+device_initcall(msm_subsystem_iommu_init);
diff --git a/arch/arm/mach-msm/msm_pm_qos.c b/arch/arm/mach-msm/msm_pm_qos.c
index e9ca886..145c721 100644
--- a/arch/arm/mach-msm/msm_pm_qos.c
+++ b/arch/arm/mach-msm/msm_pm_qos.c
@@ -20,17 +20,6 @@
#include <linux/err.h>
#include <mach/msm_reqs.h>
-struct pm_qos_request_list {
- struct list_head list;
- union {
- s32 value;
- s32 usec;
- s32 kbps;
- };
- int pm_qos_class;
-};
-
-
struct pm_qos_object {
struct pm_qos_request_list requests;
struct blocking_notifier_head *notifiers;
diff --git a/arch/arm/mach-msm/subsystem_map.c b/arch/arm/mach-msm/subsystem_map.c
new file mode 100644
index 0000000..d37da30
--- /dev/null
+++ b/arch/arm/mach-msm/subsystem_map.c
@@ -0,0 +1,506 @@
+/* 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/io.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/memory_alloc.h>
+#include <linux/module.h>
+#include <mach/iommu.h>
+#include <mach/iommu_domains.h>
+#include <mach/msm_subsystem_map.h>
+
+struct msm_buffer_node {
+ struct rb_node rb_node_all_buffer;
+ struct rb_node rb_node_paddr;
+ struct msm_mapped_buffer *buf;
+ unsigned long length;
+ unsigned int *subsystems;
+ unsigned int nsubsys;
+ unsigned int phys;
+};
+
+static struct rb_root buffer_root;
+static struct rb_root phys_root;
+DEFINE_MUTEX(msm_buffer_mutex);
+
+static struct msm_buffer_node *find_buffer(void *key)
+{
+ struct rb_root *root = &buffer_root;
+ struct rb_node *p = root->rb_node;
+
+ mutex_lock(&msm_buffer_mutex);
+
+ while (p) {
+ struct msm_buffer_node *node;
+
+ node = rb_entry(p, struct msm_buffer_node, rb_node_all_buffer);
+ if (node->buf->vaddr) {
+ if (key < node->buf->vaddr)
+ p = p->rb_left;
+ else if (key > node->buf->vaddr)
+ p = p->rb_right;
+ else {
+ mutex_unlock(&msm_buffer_mutex);
+ return node;
+ }
+ } else {
+ if (key < (void *)node->buf)
+ p = p->rb_left;
+ else if (key > (void *)node->buf)
+ p = p->rb_right;
+ else {
+ mutex_unlock(&msm_buffer_mutex);
+ return node;
+ }
+ }
+ }
+ mutex_unlock(&msm_buffer_mutex);
+ return NULL;
+}
+
+static struct msm_buffer_node *find_buffer_phys(unsigned int phys)
+{
+ struct rb_root *root = &phys_root;
+ struct rb_node *p = root->rb_node;
+
+ mutex_lock(&msm_buffer_mutex);
+
+ while (p) {
+ struct msm_buffer_node *node;
+
+ node = rb_entry(p, struct msm_buffer_node, rb_node_paddr);
+ if (phys < node->phys)
+ p = p->rb_left;
+ else if (phys > node->phys)
+ p = p->rb_right;
+ else {
+ mutex_unlock(&msm_buffer_mutex);
+ return node;
+ }
+ }
+ mutex_unlock(&msm_buffer_mutex);
+ return NULL;
+
+}
+
+static int add_buffer(struct msm_buffer_node *node)
+{
+ struct rb_root *root = &buffer_root;
+ struct rb_node **p = &root->rb_node;
+ struct rb_node *parent = NULL;
+ void *key;
+
+ if (node->buf->vaddr)
+ key = node->buf->vaddr;
+ else
+ key = node->buf;
+
+ mutex_lock(&msm_buffer_mutex);
+ while (*p) {
+ struct msm_buffer_node *tmp;
+ parent = *p;
+
+ tmp = rb_entry(parent, struct msm_buffer_node,
+ rb_node_all_buffer);
+
+ if (tmp->buf->vaddr) {
+ if (key < tmp->buf->vaddr)
+ p = &(*p)->rb_left;
+ else if (key > tmp->buf->vaddr)
+ p = &(*p)->rb_right;
+ else {
+ WARN(1, "tried to add buffer twice! buf = %p"
+ " vaddr = %p iova = %p", tmp->buf,
+ tmp->buf->vaddr,
+ tmp->buf->iova);
+ mutex_unlock(&msm_buffer_mutex);
+ return -EINVAL;
+
+ }
+ } else {
+ if (key < (void *)tmp->buf)
+ p = &(*p)->rb_left;
+ else if (key > (void *)tmp->buf)
+ p = &(*p)->rb_right;
+ else {
+ WARN(1, "tried to add buffer twice! buf = %p"
+ " vaddr = %p iova = %p", tmp->buf,
+ tmp->buf->vaddr,
+ tmp->buf->iova);
+ mutex_unlock(&msm_buffer_mutex);
+ return -EINVAL;
+ }
+ }
+ }
+ rb_link_node(&node->rb_node_all_buffer, parent, p);
+ rb_insert_color(&node->rb_node_all_buffer, root);
+ mutex_unlock(&msm_buffer_mutex);
+ return 0;
+}
+
+static int add_buffer_phys(struct msm_buffer_node *node)
+{
+ struct rb_root *root = &phys_root;
+ struct rb_node **p = &root->rb_node;
+ struct rb_node *parent = NULL;
+
+ mutex_lock(&msm_buffer_mutex);
+ while (*p) {
+ struct msm_buffer_node *tmp;
+ parent = *p;
+
+ tmp = rb_entry(parent, struct msm_buffer_node, rb_node_paddr);
+
+ if (node->phys < tmp->phys)
+ p = &(*p)->rb_left;
+ else if (node->phys > tmp->phys)
+ p = &(*p)->rb_right;
+ else {
+ WARN(1, "tried to add buffer twice! buf = %p"
+ " vaddr = %p iova = %p", tmp->buf,
+ tmp->buf->vaddr,
+ tmp->buf->iova);
+ mutex_unlock(&msm_buffer_mutex);
+ return -EINVAL;
+
+ }
+ }
+ rb_link_node(&node->rb_node_paddr, parent, p);
+ rb_insert_color(&node->rb_node_paddr, root);
+ mutex_unlock(&msm_buffer_mutex);
+ return 0;
+}
+
+static int remove_buffer(struct msm_buffer_node *victim_node)
+{
+ struct rb_root *root = &buffer_root;
+
+ if (!victim_node)
+ return -EINVAL;
+
+ mutex_lock(&msm_buffer_mutex);
+ rb_erase(&victim_node->rb_node_all_buffer, root);
+ mutex_unlock(&msm_buffer_mutex);
+ return 0;
+}
+
+static int remove_buffer_phys(struct msm_buffer_node *victim_node)
+{
+ struct rb_root *root = &phys_root;
+
+ if (!victim_node)
+ return -EINVAL;
+
+ mutex_lock(&msm_buffer_mutex);
+ rb_erase(&victim_node->rb_node_paddr, root);
+ mutex_unlock(&msm_buffer_mutex);
+ return 0;
+}
+
+phys_addr_t msm_subsystem_check_iova_mapping(int subsys_id, unsigned long iova)
+{
+ struct iommu_domain *subsys_domain;
+
+ if (!msm_use_iommu())
+ /*
+ * If there is no iommu, Just return the iova in this case.
+ */
+ return iova;
+
+ subsys_domain = msm_get_iommu_domain(msm_subsystem_get_domain_no
+ (subsys_id));
+
+ return iommu_iova_to_phys(subsys_domain, iova);
+}
+EXPORT_SYMBOL(msm_subsystem_check_iova_mapping);
+
+struct msm_mapped_buffer *msm_subsystem_map_buffer(unsigned long phys,
+ unsigned int length,
+ unsigned int flags,
+ int *subsys_ids,
+ unsigned int nsubsys)
+{
+ struct msm_mapped_buffer *buf, *err;
+ struct msm_buffer_node *node;
+ int i = 0, j = 0, ret;
+ unsigned long iova_start = 0, temp_phys, temp_va = 0;
+ struct iommu_domain *d = NULL;
+ int map_size = length;
+
+ if (!((flags & MSM_SUBSYSTEM_MAP_KADDR) ||
+ (flags & MSM_SUBSYSTEM_MAP_IOVA))) {
+ pr_warn("%s: no mapping flag was specified. The caller"
+ " should explicitly specify what to map in the"
+ " flags.\n", __func__);
+ err = ERR_PTR(-EINVAL);
+ goto outret;
+ }
+
+ buf = kzalloc(sizeof(*buf), GFP_ATOMIC);
+ if (!buf) {
+ err = ERR_PTR(-ENOMEM);
+ goto outret;
+ }
+
+ node = kzalloc(sizeof(*node), GFP_ATOMIC);
+ if (!node) {
+ err = ERR_PTR(-ENOMEM);
+ goto outkfreebuf;
+ }
+
+ node->phys = phys;
+
+ if (flags & MSM_SUBSYSTEM_MAP_KADDR) {
+ struct msm_buffer_node *old_buffer;
+
+ old_buffer = find_buffer_phys(phys);
+
+ if (old_buffer) {
+ WARN(1, "%s: Attempting to map %lx twice in the kernel"
+ " virtual space. Don't do that!\n", __func__,
+ phys);
+ err = ERR_PTR(-EINVAL);
+ goto outkfreenode;
+ }
+
+ if (flags & MSM_SUBSYSTEM_MAP_CACHED)
+ buf->vaddr = ioremap(phys, length);
+ else if (flags & MSM_SUBSYSTEM_MAP_KADDR)
+ buf->vaddr = ioremap_nocache(phys, length);
+ else {
+ pr_warn("%s: no cachability flag was indicated. Caller"
+ " must specify a cachability flag.\n",
+ __func__);
+ err = ERR_PTR(-EINVAL);
+ goto outkfreenode;
+ }
+
+ if (!buf->vaddr) {
+ pr_err("%s: could not ioremap\n", __func__);
+ err = ERR_PTR(-EINVAL);
+ goto outkfreenode;
+ }
+
+ if (add_buffer_phys(node)) {
+ err = ERR_PTR(-EINVAL);
+ goto outiounmap;
+ }
+ }
+
+ if ((flags & MSM_SUBSYSTEM_MAP_IOVA) && subsys_ids) {
+ int min_align;
+
+ length = round_up(length, SZ_4K);
+
+ if (flags & MSM_SUBSYSTEM_MAP_IOMMU_2X)
+ map_size = 2 * length;
+ else
+ map_size = length;
+
+ buf->iova = kzalloc(sizeof(unsigned long)*nsubsys, GFP_ATOMIC);
+ if (!buf->iova) {
+ err = ERR_PTR(-ENOMEM);
+ goto outremovephys;
+ }
+
+ /*
+ * The alignment must be specified as the exact value wanted
+ * e.g. 8k alignment must pass (0x2000 | other flags)
+ */
+ min_align = flags & ~(SZ_4K - 1);
+
+ for (i = 0; i < nsubsys; i++) {
+ unsigned int domain_no, partition_no;
+
+ if (!msm_use_iommu()) {
+ buf->iova[i] = phys;
+ continue;
+ }
+
+ d = msm_get_iommu_domain(
+ msm_subsystem_get_domain_no(subsys_ids[i]));
+
+ if (!d) {
+ pr_err("%s: could not get domain for subsystem"
+ " %d\n", __func__, subsys_ids[i]);
+ continue;
+ }
+
+ domain_no = msm_subsystem_get_domain_no(subsys_ids[i]);
+ partition_no = msm_subsystem_get_partition_no(
+ subsys_ids[i]);
+
+ iova_start = msm_allocate_iova_address(domain_no,
+ partition_no,
+ map_size,
+ max(min_align, SZ_4K));
+
+ if (!iova_start) {
+ pr_err("%s: could not allocate iova address\n",
+ __func__);
+ continue;
+ }
+
+ temp_phys = phys;
+ temp_va = iova_start;
+ for (j = length; j > 0; j -= SZ_4K,
+ temp_phys += SZ_4K,
+ temp_va += SZ_4K) {
+ ret = iommu_map(d, temp_va, temp_phys,
+ get_order(SZ_4K),
+ (IOMMU_READ | IOMMU_WRITE));
+ if (ret) {
+ pr_err("%s: could not map iommu for"
+ " domain %p, iova %lx,"
+ " phys %lx\n", __func__, d,
+ temp_va, temp_phys);
+ err = ERR_PTR(-EINVAL);
+ goto outdomain;
+ }
+ }
+ buf->iova[i] = iova_start;
+
+ if (flags & MSM_SUBSYSTEM_MAP_IOMMU_2X)
+ msm_iommu_map_extra
+ (d, temp_va, length, SZ_4K,
+ (IOMMU_READ | IOMMU_WRITE));
+ }
+
+ }
+
+ node->buf = buf;
+ node->subsystems = subsys_ids;
+ node->length = map_size;
+ node->nsubsys = nsubsys;
+
+ if (add_buffer(node)) {
+ err = ERR_PTR(-EINVAL);
+ goto outiova;
+ }
+
+ return buf;
+
+outiova:
+ if (flags & MSM_SUBSYSTEM_MAP_IOVA)
+ iommu_unmap(d, temp_va, get_order(SZ_4K));
+outdomain:
+ if (flags & MSM_SUBSYSTEM_MAP_IOVA) {
+ /* Unmap the rest of the current domain, i */
+ for (j -= SZ_4K, temp_va -= SZ_4K;
+ j > 0; temp_va -= SZ_4K, j -= SZ_4K)
+ iommu_unmap(d, temp_va, get_order(SZ_4K));
+
+ /* Unmap all the other domains */
+ for (i--; i >= 0; i--) {
+ unsigned int domain_no, partition_no;
+ if (!msm_use_iommu())
+ continue;
+ domain_no = msm_subsystem_get_domain_no(subsys_ids[i]);
+ partition_no = msm_subsystem_get_partition_no(
+ subsys_ids[i]);
+
+ temp_va = buf->iova[i];
+ for (j = length; j > 0; j -= SZ_4K,
+ temp_va += SZ_4K)
+ iommu_unmap(d, temp_va, get_order(SZ_4K));
+ msm_free_iova_address(buf->iova[i], domain_no,
+ partition_no, length);
+ }
+
+ kfree(buf->iova);
+ }
+
+outremovephys:
+ if (flags & MSM_SUBSYSTEM_MAP_KADDR)
+ remove_buffer_phys(node);
+outiounmap:
+ if (flags & MSM_SUBSYSTEM_MAP_KADDR)
+ iounmap(buf->vaddr);
+outkfreenode:
+ kfree(node);
+outkfreebuf:
+ kfree(buf);
+outret:
+ return err;
+}
+EXPORT_SYMBOL(msm_subsystem_map_buffer);
+
+int msm_subsystem_unmap_buffer(struct msm_mapped_buffer *buf)
+{
+ struct msm_buffer_node *node;
+ int i, j, ret;
+ unsigned long temp_va;
+
+ if (IS_ERR_OR_NULL(buf))
+ goto out;
+
+ if (buf->vaddr)
+ node = find_buffer(buf->vaddr);
+ else
+ node = find_buffer(buf);
+
+ if (!node)
+ goto out;
+
+ if (node->buf != buf) {
+ pr_err("%s: caller must pass in the same buffer structure"
+ " returned from map_buffer when freeding\n", __func__);
+ goto out;
+ }
+
+ if (buf->iova) {
+ if (msm_use_iommu())
+ for (i = 0; i < node->nsubsys; i++) {
+ struct iommu_domain *subsys_domain;
+ unsigned int domain_no, partition_no;
+
+ subsys_domain = msm_get_iommu_domain(
+ msm_subsystem_get_domain_no(
+ node->subsystems[i]));
+
+ domain_no = msm_subsystem_get_domain_no(
+ node->subsystems[i]);
+ partition_no = msm_subsystem_get_partition_no(
+ node->subsystems[i]);
+
+ temp_va = buf->iova[i];
+ for (j = node->length; j > 0; j -= SZ_4K,
+ temp_va += SZ_4K) {
+ ret = iommu_unmap(subsys_domain,
+ temp_va,
+ get_order(SZ_4K));
+ WARN(ret, "iommu_unmap returned a "
+ " non-zero value.\n");
+ }
+ msm_free_iova_address(buf->iova[i], domain_no,
+ partition_no, node->length);
+ }
+ kfree(buf->iova);
+
+ }
+
+ if (buf->vaddr) {
+ remove_buffer_phys(node);
+ iounmap(buf->vaddr);
+ }
+
+ remove_buffer(node);
+ kfree(node);
+ kfree(buf);
+
+ return 0;
+out:
+ return -EINVAL;
+}
+EXPORT_SYMBOL(msm_subsystem_unmap_buffer);
diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c
index baafb17..ce351bf 100644
--- a/drivers/char/msm_rotator.c
+++ b/drivers/char/msm_rotator.c
@@ -800,7 +800,7 @@
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))
+ if (get_fb_phys_info(start, len, fb_num, DISPLAY_SUBSYSTEM_ID))
ret = -1;
else {
*p_file = file;
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 820cc61..d38528a 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -17,7 +17,6 @@
#include <linux/sched.h>
#include <mach/socinfo.h>
-#include <mach/internal_power_rail.h>
#include "kgsl.h"
#include "kgsl_pwrscale.h"
@@ -94,8 +93,6 @@
.pwrctrl = {
.regulator_name = "fs_gfx3d",
.irq_name = KGSL_3D0_IRQ,
- .src_clk_name = "grp_src_clk",
- .pwr_rail = PWR_RAIL_GRP_CLK,
},
.mutex = __MUTEX_INITIALIZER(device_3d0.dev.mutex),
.state = KGSL_STATE_INIT,
@@ -269,6 +266,7 @@
}
static void adreno_setstate(struct kgsl_device *device,
+ unsigned int context_id,
uint32_t flags)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
@@ -276,6 +274,8 @@
unsigned int *cmds = &link[0];
int sizedwords = 0;
unsigned int mh_mmu_invalidate = 0x00000003; /*invalidate all and tc */
+ struct kgsl_context *context;
+ struct adreno_context *adreno_ctx = NULL;
/*
* If possible, then set the state via the command stream to avoid
@@ -284,6 +284,9 @@
* easier to filter out the mmu accesses from the dump
*/
if (!kgsl_cff_dump_enable && adreno_dev->drawctxt_active) {
+ context = idr_find(&device->context_idr, context_id);
+ adreno_ctx = context->devctxt;
+
if (flags & KGSL_MMUFLAGS_PTUPDATE) {
/* wait for graphics pipe to be idle */
*cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
@@ -356,7 +359,8 @@
sizedwords += 2;
}
- adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
+ adreno_ringbuffer_issuecmds(device, adreno_ctx,
+ KGSL_CMD_FLAGS_PMODE,
&link[0], sizedwords);
} else {
kgsl_mmu_device_setstate(device, flags);
@@ -466,6 +470,8 @@
kgsl_pwrscale_init(device);
kgsl_pwrscale_attach_policy(device, ADRENO_DEFAULT_PWRSCALE_POLICY);
+ INIT_WORK(&device->print_fault_ib, adreno_print_fault_ib_work);
+
device->flags &= ~KGSL_FLAGS_SOFT_RESET;
return 0;
@@ -499,7 +505,8 @@
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
int init_reftimestamp = 0x7fffffff;
- kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
+ if (KGSL_STATE_DUMP_AND_RECOVER != device->state)
+ kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
/* Power up the device */
kgsl_pwrctrl_enable(device);
@@ -592,13 +599,15 @@
device->ftbl->irqctrl(device, 1);
status = adreno_ringbuffer_start(&adreno_dev->ringbuffer, init_ram);
- if (status != 0)
- goto error_irq_off;
- mod_timer(&device->idle_timer, jiffies + FIRST_TIMEOUT);
- return status;
+ if (status == 0) {
+ /* While recovery is on we do not want timer to
+ * fire and attempt to change any device state */
+ if (KGSL_STATE_DUMP_AND_RECOVER != device->state)
+ mod_timer(&device->idle_timer, jiffies + FIRST_TIMEOUT);
+ return 0;
+ }
-error_irq_off:
kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
kgsl_mmu_stop(device);
error_clk_off:
@@ -627,53 +636,74 @@
return 0;
}
+static void adreno_mark_context_status(struct kgsl_device *device,
+ int recovery_status)
+{
+ struct kgsl_context *context;
+ int next = 0;
+ /*
+ * Set the reset status of all contexts to
+ * INNOCENT_CONTEXT_RESET_EXT except for the bad context
+ * since thats the guilty party, if recovery failed then
+ * mark all as guilty
+ */
+ while ((context = idr_get_next(&device->context_idr, &next))) {
+ struct adreno_context *adreno_context = context->devctxt;
+ if (recovery_status) {
+ context->reset_status =
+ KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT;
+ adreno_context->flags |= CTXT_FLAGS_GPU_HANG;
+ } else if (KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT !=
+ context->reset_status) {
+ if (adreno_context->flags & (CTXT_FLAGS_GPU_HANG ||
+ CTXT_FLAGS_GPU_HANG_RECOVERED))
+ context->reset_status =
+ KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT;
+ else
+ context->reset_status =
+ KGSL_CTX_STAT_INNOCENT_CONTEXT_RESET_EXT;
+ }
+ next = next + 1;
+ }
+}
+
static int
-adreno_recover_hang(struct kgsl_device *device)
+adreno_recover_hang(struct kgsl_device *device,
+ struct adreno_recovery_data *rec_data)
{
int ret;
- unsigned int *rb_buffer;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
unsigned int timestamp;
- unsigned int num_rb_contents;
- unsigned int bad_context;
- unsigned int reftimestamp;
- unsigned int enable_ts;
- unsigned int soptimestamp;
- unsigned int eoptimestamp;
- struct adreno_context *drawctxt;
struct kgsl_context *context;
- int next = 0;
+ struct adreno_context *adreno_context;
- KGSL_DRV_ERR(device, "Starting recovery from 3D GPU hang....\n");
- rb_buffer = vmalloc(rb->buffer_desc.size);
- if (!rb_buffer) {
- KGSL_MEM_ERR(device,
- "Failed to allocate memory for recovery: %x\n",
- rb->buffer_desc.size);
- return -ENOMEM;
+ KGSL_DRV_ERR(device,
+ "Starting recovery from 3D GPU hang. Recovery parameters: IB1: 0x%X, "
+ "Bad context_id: %u, global_eop: 0x%x\n", rec_data->ib1,
+ rec_data->context_id, rec_data->global_eop);
+
+ context = idr_find(&device->context_idr, rec_data->context_id);
+ if (context == NULL) {
+ KGSL_DRV_ERR(device, "Last context unknown id:%d\n",
+ rec_data->context_id);
+ rec_data->context_id = 0;
+ } else {
+ adreno_context = context->devctxt;
+ adreno_context->flags |= CTXT_FLAGS_GPU_HANG;
}
- /* Extract valid contents from rb which can stil be executed after
+ /* Extract valid contents from rb which can still be executed after
* hang */
- ret = adreno_ringbuffer_extract(rb, rb_buffer, &num_rb_contents);
+ ret = adreno_ringbuffer_extract(rb, rec_data);
if (ret)
goto done;
+
timestamp = rb->timestamp;
- KGSL_DRV_ERR(device, "Last issued timestamp: %x\n", timestamp);
- kgsl_sharedmem_readl(&device->memstore, &bad_context,
- KGSL_DEVICE_MEMSTORE_OFFSET(current_context));
- kgsl_sharedmem_readl(&device->memstore, &reftimestamp,
- KGSL_DEVICE_MEMSTORE_OFFSET(ref_wait_ts));
- kgsl_sharedmem_readl(&device->memstore, &enable_ts,
- KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable));
- kgsl_sharedmem_readl(&device->memstore, &soptimestamp,
- KGSL_DEVICE_MEMSTORE_OFFSET(soptimestamp));
- kgsl_sharedmem_readl(&device->memstore, &eoptimestamp,
- KGSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp));
+ KGSL_DRV_ERR(device, "Last issued global timestamp: %x\n", timestamp);
+
/* Make sure memory is synchronized before restarting the GPU */
mb();
- KGSL_CTXT_ERR(device,
- "Context that caused a GPU hang: %x\n", bad_context);
+
/* restart device */
ret = adreno_stop(device);
if (ret)
@@ -682,66 +712,76 @@
if (ret)
goto done;
KGSL_DRV_ERR(device, "Device has been restarted after hang\n");
- /* Restore timestamp states */
- kgsl_sharedmem_writel(&device->memstore,
- KGSL_DEVICE_MEMSTORE_OFFSET(soptimestamp),
- soptimestamp);
- kgsl_sharedmem_writel(&device->memstore,
- KGSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp),
- eoptimestamp);
- kgsl_sharedmem_writel(&device->memstore,
- KGSL_DEVICE_MEMSTORE_OFFSET(soptimestamp),
- soptimestamp);
- if (num_rb_contents) {
- kgsl_sharedmem_writel(&device->memstore,
- KGSL_DEVICE_MEMSTORE_OFFSET(ref_wait_ts),
- reftimestamp);
- kgsl_sharedmem_writel(&device->memstore,
- KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable),
- enable_ts);
- }
- /* Make sure all writes are posted before the GPU reads them */
- wmb();
- /* Mark the invalid context so no more commands are accepted from
- * that context */
-
- drawctxt = (struct adreno_context *) bad_context;
-
- KGSL_CTXT_ERR(device,
- "Context that caused a GPU hang: %x\n", bad_context);
-
- drawctxt->flags |= CTXT_FLAGS_GPU_HANG;
-
- /*
- * Set the reset status of all contexts to
- * INNOCENT_CONTEXT_RESET_EXT except for the bad context
- * since thats the guilty party
- */
- while ((context = idr_get_next(&device->context_idr, &next))) {
- if (KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT !=
- context->reset_status) {
- if (context->devctxt != drawctxt)
- context->reset_status =
- KGSL_CTX_STAT_INNOCENT_CONTEXT_RESET_EXT;
- else
- context->reset_status =
- KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT;
- }
- next = next + 1;
- }
/* Restore valid commands in ringbuffer */
- adreno_ringbuffer_restore(rb, rb_buffer, num_rb_contents);
+ adreno_ringbuffer_restore(rb, rec_data->rb_buffer, rec_data->rb_size);
rb->timestamp = timestamp;
+
+ /* wait for idle */
+ ret = adreno_idle(device, KGSL_TIMEOUT_DEFAULT);
done:
- vfree(rb_buffer);
+ kgsl_sharedmem_writel(&device->memstore,
+ KGSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp),
+ rb->timestamp);
+ adreno_mark_context_status(device, ret);
return ret;
}
-static int
-adreno_dump_and_recover(struct kgsl_device *device)
+static void adreno_destroy_recovery_data(struct adreno_recovery_data *rec_data)
+{
+ vfree(rec_data->rb_buffer);
+ vfree(rec_data->bad_rb_buffer);
+}
+
+static int adreno_setup_recovery_data(struct kgsl_device *device,
+ struct adreno_recovery_data *rec_data)
+{
+ int ret = 0;
+ unsigned int ib1_sz, ib2_sz;
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
+
+ memset(rec_data, 0, sizeof(*rec_data));
+
+ adreno_regread(device, REG_CP_IB1_BUFSZ, &ib1_sz);
+ adreno_regread(device, REG_CP_IB2_BUFSZ, &ib2_sz);
+ if (ib1_sz || ib2_sz)
+ adreno_regread(device, REG_CP_IB1_BASE, &rec_data->ib1);
+
+ kgsl_sharedmem_readl(&device->memstore, &rec_data->context_id,
+ KGSL_DEVICE_MEMSTORE_OFFSET(current_context));
+
+ kgsl_sharedmem_readl(&device->memstore,
+ &rec_data->global_eop,
+ KGSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp));
+
+ rec_data->rb_buffer = vmalloc(rb->buffer_desc.size);
+ if (!rec_data->rb_buffer) {
+ KGSL_MEM_ERR(device, "vmalloc(%d) failed\n",
+ rb->buffer_desc.size);
+ return -ENOMEM;
+ }
+
+ rec_data->bad_rb_buffer = vmalloc(rb->buffer_desc.size);
+ if (!rec_data->bad_rb_buffer) {
+ KGSL_MEM_ERR(device, "vmalloc(%d) failed\n",
+ rb->buffer_desc.size);
+ ret = -ENOMEM;
+ goto done;
+ }
+
+done:
+ if (ret) {
+ vfree(rec_data->rb_buffer);
+ vfree(rec_data->bad_rb_buffer);
+ }
+ return ret;
+}
+
+int adreno_dump_and_recover(struct kgsl_device *device)
{
int result = -ETIMEDOUT;
+ struct adreno_recovery_data rec_data;
if (device->state == KGSL_STATE_HUNG)
goto done;
@@ -756,7 +796,8 @@
INIT_COMPLETION(device->recovery_gate);
/* Detected a hang */
-
+ /* Get the recovery data as soon as hang is detected */
+ result = adreno_setup_recovery_data(device, &rec_data);
/*
* Trigger an automatic dump of the state to
* the console
@@ -769,16 +810,20 @@
*/
kgsl_device_snapshot(device, 1);
- result = adreno_recover_hang(device);
- if (result)
+ result = adreno_recover_hang(device, &rec_data);
+ adreno_destroy_recovery_data(&rec_data);
+ if (result) {
kgsl_pwrctrl_set_state(device, KGSL_STATE_HUNG);
- else
+ } else {
kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE);
+ mod_timer(&device->idle_timer, jiffies + FIRST_TIMEOUT);
+ }
complete_all(&device->recovery_gate);
}
done:
return result;
}
+EXPORT_SYMBOL(adreno_dump_and_recover);
static int adreno_getproperty(struct kgsl_device *device,
enum kgsl_property_type type,
@@ -893,7 +938,11 @@
unsigned int rbbm_status;
unsigned long wait_timeout =
msecs_to_jiffies(adreno_dev->wait_timeout);
- unsigned long wait_time = jiffies + wait_timeout;
+ unsigned long wait_time;
+ unsigned long wait_time_part;
+ unsigned int msecs;
+ unsigned int msecs_first;
+ unsigned int msecs_part;
kgsl_cffdump_regpoll(device->id, REG_RBBM_STATUS << 2,
0x00000000, 0x80000000);
@@ -902,8 +951,18 @@
*/
retry:
if (rb->flags & KGSL_FLAGS_STARTED) {
+ msecs = adreno_dev->wait_timeout;
+ msecs_first = (msecs <= 100) ? ((msecs + 4) / 5) : 100;
+ msecs_part = (msecs - msecs_first + 3) / 4;
+ wait_time = jiffies + wait_timeout;
+ wait_time_part = jiffies + msecs_to_jiffies(msecs_first);
adreno_poke(device);
do {
+ if (time_after(jiffies, wait_time_part)) {
+ adreno_poke(device);
+ wait_time_part = jiffies +
+ msecs_to_jiffies(msecs_part);
+ }
GSL_RB_GET_READPTR(rb, &rb->rptr);
if (time_after(jiffies, wait_time)) {
KGSL_DRV_ERR(device, "rptr: %x, wptr: %x\n",
@@ -923,7 +982,8 @@
err:
KGSL_DRV_ERR(device, "spun too long waiting for RB to idle\n");
- if (!adreno_dump_and_recover(device)) {
+ if (KGSL_STATE_DUMP_AND_RECOVER != device->state &&
+ !adreno_dump_and_recover(device)) {
wait_time = jiffies + wait_timeout;
goto retry;
}
@@ -1091,6 +1151,8 @@
int status;
unsigned int ref_ts, enableflag;
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+
status = kgsl_check_timestamp(device, timestamp);
if (!status) {
mutex_lock(&device->mutex);
@@ -1123,8 +1185,15 @@
* get an interrupt */
cmds[0] = cp_type3_packet(CP_NOP, 1);
cmds[1] = 0;
- adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
- &cmds[0], 2);
+
+ if (adreno_dev->drawctxt_active)
+ adreno_ringbuffer_issuecmds(device,
+ adreno_dev->drawctxt_active,
+ KGSL_CMD_FLAGS_NONE, &cmds[0], 2);
+ else
+ /* We would never call this function if there
+ * was no active contexts running */
+ BUG();
}
mutex_unlock(&device->mutex);
}
@@ -1218,6 +1287,14 @@
}
/*this wait timed out*/
}
+
+ /* Check if timestamp has retired here because we may have hit
+ * recovery which can take some time and cause waiting threads
+ * to timeout
+ */
+ if (kgsl_check_timestamp(device, timestamp))
+ goto done;
+
status = -ETIMEDOUT;
KGSL_DRV_ERR(device,
"Device hang detected while waiting for timestamp: %x,"
@@ -1225,10 +1302,9 @@
timestamp, adreno_dev->ringbuffer.timestamp,
adreno_dev->ringbuffer.wptr);
if (!adreno_dump_and_recover(device)) {
- /* wait for idle after recovery as the
- * timestamp that this process wanted
- * to wait on may be invalid */
- if (!adreno_idle(device, KGSL_TIMEOUT_DEFAULT))
+ /* The timestamp that this process wanted
+ * to wait on may be invalid or expired now
+ * after successful recovery */
status = 0;
}
done:
@@ -1339,17 +1415,10 @@
adreno_dev->gpudev->irq_control(adreno_dev, state);
}
-static unsigned int adreno_gpuid(struct kgsl_device *device,
- unsigned int *chipid)
+static unsigned int adreno_gpuid(struct kgsl_device *device)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- /* Some applications need to know the chip ID too, so pass
- * that as a parameter */
-
- if (chipid != NULL)
- *chipid = adreno_dev->chip_id;
-
/* Standard KGSL gpuid format:
* top word is 0x0002 for 2D or 0x0003 for 3D
* Bottom word is core specific identifer
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 1259507..9c75f6d 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -27,11 +27,12 @@
#define KGSL_CMD_FLAGS_NONE 0x00000000
#define KGSL_CMD_FLAGS_PMODE 0x00000001
#define KGSL_CMD_FLAGS_NO_TS_CMP 0x00000002
-#define KGSL_CMD_FLAGS_NOT_KERNEL_CMD 0x00000004
/* Command identifiers */
#define KGSL_CONTEXT_TO_MEM_IDENTIFIER 0xDEADBEEF
#define KGSL_CMD_IDENTIFIER 0xFEEDFACE
+#define KGSL_START_OF_IB_IDENTIFIER 0x2EADEABE
+#define KGSL_END_OF_IB_IDENTIFIER 0x2ABEDEAD
#ifdef CONFIG_MSM_SCM
#define ADRENO_DEFAULT_PWRSCALE_POLICY (&kgsl_pwrscale_policy_tz)
@@ -85,12 +86,36 @@
int (*ctxt_create)(struct adreno_device *, struct adreno_context *);
void (*ctxt_save)(struct adreno_device *, struct adreno_context *);
void (*ctxt_restore)(struct adreno_device *, struct adreno_context *);
- void (*ctxt_draw_workaround)(struct adreno_device *);
+ void (*ctxt_draw_workaround)(struct adreno_device *, struct adreno_context *);
irqreturn_t (*irq_handler)(struct adreno_device *);
void (*irq_control)(struct adreno_device *, int);
void * (*snapshot)(struct adreno_device *, void *, int *, int);
};
+/*
+ * struct adreno_recovery_data - Structure that contains all information to
+ * perform gpu recovery from hangs
+ * @ib1 - IB1 that the GPU was executing when hang happened
+ * @context_id - Context which caused the hang
+ * @global_eop - eoptimestamp at time of hang
+ * @rb_buffer - Buffer that holds the commands from good contexts
+ * @rb_size - Number of valid dwords in rb_buffer
+ * @bad_rb_buffer - Buffer that holds commands from the hanging context
+ * bad_rb_size - Number of valid dwords in bad_rb_buffer
+ * @last_valid_ctx_id - The last context from which commands were placed in
+ * ringbuffer before the GPU hung
+ */
+struct adreno_recovery_data {
+ unsigned int ib1;
+ unsigned int context_id;
+ unsigned int global_eop;
+ unsigned int *rb_buffer;
+ unsigned int rb_size;
+ unsigned int *bad_rb_buffer;
+ unsigned int bad_rb_size;
+ unsigned int last_valid_ctx_id;
+};
+
extern struct adreno_gpudev adreno_a2xx_gpudev;
/* A2XX register sets defined in adreno_a2xx.c */
@@ -116,6 +141,8 @@
void *adreno_snapshot(struct kgsl_device *device, void *snapshot, int *remain,
int hang);
+int adreno_dump_and_recover(struct kgsl_device *device);
+
static inline int adreno_is_a200(struct adreno_device *adreno_dev)
{
return (adreno_dev->gpurev == ADRENO_REV_A200);
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 62628e4..9efd587 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1421,55 +1421,45 @@
return ret;
}
-static void a2xx_drawctxt_workaround(struct adreno_device *adreno_dev)
+static void a2xx_drawctxt_draw_workaround(struct adreno_device *adreno_dev,
+ struct adreno_context *context)
{
struct kgsl_device *device = &adreno_dev->dev;
unsigned int cmd[11];
unsigned int *cmds = &cmd[0];
- if (adreno_is_a225(adreno_dev)) {
- adreno_dev->gpudev->ctx_switches_since_last_draw++;
- /* If there have been > than
- * ADRENO_NUM_CTX_SWITCH_ALLOWED_BEFORE_DRAW calls to context
- * switches w/o gmem being saved then we need to execute
- * this workaround */
- if (adreno_dev->gpudev->ctx_switches_since_last_draw >
- ADRENO_NUM_CTX_SWITCH_ALLOWED_BEFORE_DRAW)
- adreno_dev->gpudev->ctx_switches_since_last_draw = 0;
- else
- return;
- /*
- * Issue an empty draw call to avoid possible hangs due to
- * repeated idles without intervening draw calls.
- * On adreno 225 the PC block has a cache that is only
- * flushed on draw calls and repeated idles can make it
- * overflow. The gmem save path contains draw calls so
- * this workaround isn't needed there.
- */
- *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
- *cmds++ = (0x4 << 16) | (REG_PA_SU_SC_MODE_CNTL - 0x2000);
- *cmds++ = 0;
- *cmds++ = cp_type3_packet(CP_DRAW_INDX, 5);
- *cmds++ = 0;
- *cmds++ = 1<<14;
- *cmds++ = 0;
- *cmds++ = device->mmu.setstate_memory.gpuaddr;
- *cmds++ = 0;
- *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
- *cmds++ = 0x00000000;
- } else {
- /* On Adreno 20x/220, if the events for shader space reuse
- * gets dropped, the CP block would wait indefinitely.
- * Sending CP_SET_SHADER_BASES packet unblocks the CP from
- * this wait.
- */
- *cmds++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
- *cmds++ = adreno_encode_istore_size(adreno_dev)
- | adreno_dev->pix_shader_start;
- }
+ adreno_dev->gpudev->ctx_switches_since_last_draw++;
+ /* If there have been > than ADRENO_NUM_CTX_SWITCH_ALLOWED_BEFORE_DRAW
+ * calls to context switches w/o gmem being saved then we need to
+ * execute this workaround */
+ if (adreno_dev->gpudev->ctx_switches_since_last_draw >
+ ADRENO_NUM_CTX_SWITCH_ALLOWED_BEFORE_DRAW)
+ adreno_dev->gpudev->ctx_switches_since_last_draw = 0;
+ else
+ return;
+ /*
+ * Issue an empty draw call to avoid possible hangs due to
+ * repeated idles without intervening draw calls.
+ * On adreno 225 the PC block has a cache that is only
+ * flushed on draw calls and repeated idles can make it
+ * overflow. The gmem save path contains draw calls so
+ * this workaround isn't needed there.
+ */
+ *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+ *cmds++ = (0x4 << 16) | (REG_PA_SU_SC_MODE_CNTL - 0x2000);
+ *cmds++ = 0;
+ *cmds++ = cp_type3_packet(CP_DRAW_INDX, 5);
+ *cmds++ = 0;
+ *cmds++ = 1<<14;
+ *cmds++ = 0;
+ *cmds++ = device->mmu.setstate_memory.gpuaddr;
+ *cmds++ = 0;
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
- adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
- &cmd[0], cmds - cmd);
+ adreno_ringbuffer_issuecmds(device, context,
+ KGSL_CMD_FLAGS_PMODE,
+ &cmd[0], 11);
}
static void a2xx_drawctxt_save(struct adreno_device *adreno_dev,
@@ -1487,12 +1477,13 @@
if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
/* save registers and constants. */
- adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
+ adreno_ringbuffer_issuecmds(device, context,
+ KGSL_CMD_FLAGS_NONE,
context->reg_save, 3);
if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
/* save shader partitioning and instructions. */
- adreno_ringbuffer_issuecmds(device,
+ adreno_ringbuffer_issuecmds(device, context,
KGSL_CMD_FLAGS_PMODE,
context->shader_save, 3);
@@ -1500,7 +1491,8 @@
* fixup shader partitioning parameter for
* SET_SHADER_BASES.
*/
- adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
+ adreno_ringbuffer_issuecmds(device, context,
+ KGSL_CMD_FLAGS_NONE,
context->shader_fixup, 3);
context->flags |= CTXT_FLAGS_SHADER_RESTORE;
@@ -1512,19 +1504,21 @@
/* save gmem.
* (note: changes shader. shader must already be saved.)
*/
- adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
+ adreno_ringbuffer_issuecmds(device, context,
+ KGSL_CMD_FLAGS_PMODE,
context->context_gmem_shadow.gmem_save, 3);
/* Restore TP0_CHICKEN */
if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
- adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
+ adreno_ringbuffer_issuecmds(device, context,
+ KGSL_CMD_FLAGS_NONE,
context->chicken_restore, 3);
}
adreno_dev->gpudev->ctx_switches_since_last_draw = 0;
context->flags |= CTXT_FLAGS_GMEM_RESTORE;
- } else if (adreno_is_a2xx(adreno_dev))
- a2xx_drawctxt_workaround(adreno_dev);
+ } else if (adreno_is_a225(adreno_dev))
+ a2xx_drawctxt_draw_workaround(adreno_dev, context);
}
static void a2xx_drawctxt_restore(struct adreno_device *adreno_dev,
@@ -1535,7 +1529,8 @@
if (context == NULL) {
/* No context - set the default apgetable and thats it */
- kgsl_mmu_setstate(device, device->mmu.defaultpagetable);
+ kgsl_mmu_setstate(device, device->mmu.defaultpagetable,
+ adreno_dev->drawctxt_active->id);
return;
}
@@ -1547,8 +1542,9 @@
cmds[3] = device->memstore.gpuaddr +
KGSL_DEVICE_MEMSTORE_OFFSET(current_context);
cmds[4] = (unsigned int) context;
- adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE, cmds, 5);
- kgsl_mmu_setstate(device, context->pagetable);
+ adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE,
+ cmds, 5);
+ kgsl_mmu_setstate(device, context->pagetable, context->id);
#ifndef CONFIG_MSM_KGSL_CFF_DUMP_NO_CONTEXT_MEM_DUMP
kgsl_cffdump_syncmem(NULL, &context->gpustate,
@@ -1560,12 +1556,14 @@
* (note: changes shader. shader must not already be restored.)
*/
if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
- adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
+ adreno_ringbuffer_issuecmds(device, context,
+ KGSL_CMD_FLAGS_PMODE,
context->context_gmem_shadow.gmem_restore, 3);
if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
/* Restore TP0_CHICKEN */
- adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
+ adreno_ringbuffer_issuecmds(device, context,
+ KGSL_CMD_FLAGS_NONE,
context->chicken_restore, 3);
}
@@ -1575,12 +1573,12 @@
if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
/* restore registers and constants. */
- adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
- context->reg_restore, 3);
+ adreno_ringbuffer_issuecmds(device, context,
+ KGSL_CMD_FLAGS_NONE, context->reg_restore, 3);
/* restore shader instructions & partitioning. */
if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
- adreno_ringbuffer_issuecmds(device,
+ adreno_ringbuffer_issuecmds(device, context,
KGSL_CMD_FLAGS_NONE,
context->shader_restore, 3);
}
@@ -1589,8 +1587,8 @@
if (adreno_is_a20x(adreno_dev)) {
cmds[0] = cp_type3_packet(CP_SET_BIN_BASE_OFFSET, 1);
cmds[1] = context->bin_base_offset;
- adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
- cmds, 2);
+ adreno_ringbuffer_issuecmds(device, context,
+ KGSL_CMD_FLAGS_NONE, cmds, 2);
}
}
@@ -1785,7 +1783,7 @@
.ctxt_create = a2xx_drawctxt_create,
.ctxt_save = a2xx_drawctxt_save,
.ctxt_restore = a2xx_drawctxt_restore,
- .ctxt_draw_workaround = a2xx_drawctxt_workaround,
+ .ctxt_draw_workaround = a2xx_drawctxt_draw_workaround,
.irq_handler = a2xx_irq_handler,
.irq_control = a2xx_irq_control,
.snapshot = a2xx_snapshot,
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index 566efa1..81d3419 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -24,6 +24,7 @@
unsigned int kgsl_cff_dump_enable;
int kgsl_pm_regs_enabled;
+int adreno_ib_dump_on_pagef_enabled;
static struct dentry *pm_d_debugfs;
@@ -60,6 +61,21 @@
pm_regs_enabled_get,
pm_regs_enabled_set, "%llu\n");
+static int ib_dump_on_pagef_enabled_get(void *data, u64 *val)
+{
+ *val = adreno_ib_dump_on_pagef_enabled;
+ return 0;
+}
+
+static int ib_dump_on_pagef_enabled_set(void *data, u64 val)
+{
+ adreno_ib_dump_on_pagef_enabled = val ? 1 : 0;
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(ib_dump_on_pagef_enabled_fops,
+ ib_dump_on_pagef_enabled_get,
+ ib_dump_on_pagef_enabled_set, "%llu\n");
static int kgsl_cff_dump_enable_set(void *data, u64 val)
{
@@ -359,4 +375,7 @@
&pm_dump_fops);
debugfs_create_file("regs_enabled", 0644, pm_d_debugfs, device,
&pm_regs_enabled_fops);
+
+ debugfs_create_file("ib_dump_on_pagefault", 0644, device->d_debugfs,
+ device, &ib_dump_on_pagef_enabled_fops);
}
diff --git a/drivers/gpu/msm/adreno_debugfs.h b/drivers/gpu/msm/adreno_debugfs.h
index 0356ac6..be73ef7 100644
--- a/drivers/gpu/msm/adreno_debugfs.h
+++ b/drivers/gpu/msm/adreno_debugfs.h
@@ -18,6 +18,7 @@
int adreno_debugfs_init(struct kgsl_device *device);
extern int kgsl_pm_regs_enabled;
+extern int adreno_ib_dump_on_pagef_enabled;
static inline int kgsl_pmregs_enabled(void)
{
@@ -35,6 +36,12 @@
/* If debugfs is turned off, then always print registers */
return 1;
}
+
#endif
+static inline int is_adreno_ib_dump_on_pagef_enabled(struct kgsl_device *device)
+{
+ return adreno_ib_dump_on_pagef_enabled;
+}
+
#endif /* __ADRENO_DEBUGFS_H */
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index ab70ece..990af5f 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -138,6 +138,7 @@
drawctxt->pagetable = pagetable;
drawctxt->bin_base_offset = 0;
+ drawctxt->id = context->id;
if (flags & KGSL_CONTEXT_PREAMBLE)
drawctxt->flags |= CTXT_FLAGS_PREAMBLE;
@@ -171,11 +172,13 @@
struct kgsl_context *context)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- struct adreno_context *drawctxt = context->devctxt;
+ struct adreno_context *drawctxt;
if (context == NULL || context->devctxt == NULL)
return;
+ drawctxt = context->devctxt;
+
/* deactivate context */
if (adreno_dev->drawctxt_active == drawctxt) {
/* no need to save GMEM or shader, the context is
@@ -247,7 +250,7 @@
if (adreno_dev->gpudev->ctxt_draw_workaround &&
adreno_is_a225(adreno_dev))
adreno_dev->gpudev->ctxt_draw_workaround(
- adreno_dev);
+ adreno_dev, drawctxt);
return;
}
@@ -258,6 +261,8 @@
adreno_dev->gpudev->ctxt_save(adreno_dev, adreno_dev->drawctxt_active);
/* Set the new context */
- adreno_dev->drawctxt_active = drawctxt;
adreno_dev->gpudev->ctxt_restore(adreno_dev, drawctxt);
+ adreno_dev->drawctxt_active = drawctxt;
}
+
+
diff --git a/drivers/gpu/msm/adreno_drawctxt.h b/drivers/gpu/msm/adreno_drawctxt.h
index 3047660..763d0a1 100644
--- a/drivers/gpu/msm/adreno_drawctxt.h
+++ b/drivers/gpu/msm/adreno_drawctxt.h
@@ -40,6 +40,12 @@
#define CTXT_FLAGS_GPU_HANG 0x00008000
/* Specifies there is no need to save GMEM */
#define CTXT_FLAGS_NOGMEMALLOC 0x00010000
+/* Trash state for context */
+#define CTXT_FLAGS_TRASHSTATE 0x00020000
+/* per context timestamps enabled */
+#define CTXT_FLAGS_PER_CONTEXT_TS 0x00040000
+/* Context has caused a GPU hang and recovered properly */
+#define CTXT_FLAGS_GPU_HANG_RECOVERED 0x00008000
struct kgsl_device;
struct adreno_device;
@@ -69,6 +75,7 @@
};
struct adreno_context {
+ unsigned int id;
uint32_t flags;
struct kgsl_pagetable *pagetable;
struct kgsl_memdesc gpustate;
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 63f5caa..af4bb85 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -156,7 +156,7 @@
}
}
-static void dump_ib(struct kgsl_device *device, char* buffId, uint32_t pt_base,
+void dump_ib(struct kgsl_device *device, char *buffId, uint32_t pt_base,
uint32_t base_offset, uint32_t ib_base, uint32_t ib_size, bool dump)
{
uint8_t *base_addr = adreno_convertaddr(device, pt_base,
@@ -172,15 +172,7 @@
base_addr ? "" : " [Invalid]");
}
-#define IB_LIST_SIZE 64
-struct ib_list {
- int count;
- uint32_t bases[IB_LIST_SIZE];
- uint32_t sizes[IB_LIST_SIZE];
- uint32_t offsets[IB_LIST_SIZE];
-};
-
-static void dump_ib1(struct kgsl_device *device, uint32_t pt_base,
+void dump_ib1(struct kgsl_device *device, uint32_t pt_base,
uint32_t base_offset,
uint32_t ib1_base, uint32_t ib1_size,
struct ib_list *ib_list, bool dump)
@@ -547,7 +539,8 @@
" %08X\n", r1, r2, pt_base);
cur_pt_base = pt_base;
- KGSL_LOG_DUMP(device, "PAGETABLE SIZE: %08X ", KGSL_PAGETABLE_SIZE);
+ KGSL_LOG_DUMP(device, "PAGETABLE SIZE: %08X ",
+ kgsl_mmu_get_ptsize());
kgsl_regread(device, MH_MMU_TRAN_ERROR, &r1);
KGSL_LOG_DUMP(device, " TRAN_ERROR = %08X\n", r1);
diff --git a/drivers/gpu/msm/adreno_postmortem.h b/drivers/gpu/msm/adreno_postmortem.h
index b677800..c652558 100644
--- a/drivers/gpu/msm/adreno_postmortem.h
+++ b/drivers/gpu/msm/adreno_postmortem.h
@@ -16,6 +16,22 @@
struct kgsl_device;
+#define IB_LIST_SIZE 64
+struct ib_list {
+ int count;
+ uint32_t bases[IB_LIST_SIZE];
+ uint32_t sizes[IB_LIST_SIZE];
+ uint32_t offsets[IB_LIST_SIZE];
+};
+
int adreno_postmortem_dump(struct kgsl_device *device, int manual);
+void dump_ib(struct kgsl_device *device, char *buffId, uint32_t pt_base,
+ uint32_t base_offset, uint32_t ib_base, uint32_t ib_size, bool dump);
+
+void dump_ib1(struct kgsl_device *device, uint32_t pt_base,
+ uint32_t base_offset,
+ uint32_t ib1_base, uint32_t ib1_size,
+ struct ib_list *ib_list, bool dump);
+
#endif /* __ADRENO_POSTMORTEM_H */
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 57883fd..f9d9df1 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -23,6 +23,7 @@
#include "adreno_pm4types.h"
#include "adreno_ringbuffer.h"
#include "adreno_debugfs.h"
+#include "adreno_postmortem.h"
#include "a2xx_reg.h"
@@ -70,6 +71,9 @@
unsigned int freecmds;
unsigned int *cmds;
uint cmds_gpu;
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device);
+ unsigned long wait_timeout = msecs_to_jiffies(adreno_dev->wait_timeout);
+ unsigned long wait_time;
/* if wptr ahead, fill the remaining with NOPs */
if (wptr_ahead) {
@@ -96,15 +100,58 @@
rb->wptr = 0;
}
+ wait_time = jiffies + wait_timeout;
/* wait for space in ringbuffer */
- do {
+ while (1) {
GSL_RB_GET_READPTR(rb, &rb->rptr);
freecmds = rb->rptr - rb->wptr;
- } while ((freecmds != 0) && (freecmds <= numcmds));
+ if (freecmds == 0 || freecmds > numcmds)
+ break;
+
+ if (time_after(jiffies, wait_time)) {
+ KGSL_DRV_ERR(rb->device,
+ "Timed out while waiting for freespace in ringbuffer "
+ "rptr: 0x%x, wptr: 0x%x\n", rb->rptr, rb->wptr);
+ if (!adreno_dump_and_recover(rb->device))
+ wait_time = jiffies + wait_timeout;
+ else
+ /* GPU is hung and we cannot recover */
+ BUG();
+ }
+ }
}
+static unsigned int find_faulting_ib1_size(struct adreno_ringbuffer *rb,
+ unsigned int rptr, unsigned int ib1)
+{
+ unsigned int value;
+ unsigned int temp_rptr = rptr * sizeof(unsigned int);
+ unsigned int rb_size = rb->buffer_desc.size;
+
+ do {
+ temp_rptr = adreno_ringbuffer_dec_wrapped(temp_rptr, rb_size);
+ kgsl_sharedmem_readl(&rb->buffer_desc, &value, temp_rptr);
+
+ if (ib1 == value) {
+ temp_rptr = adreno_ringbuffer_dec_wrapped(temp_rptr,
+ rb_size);
+ kgsl_sharedmem_readl(&rb->buffer_desc, &value,
+ temp_rptr);
+ if (adreno_cmd_is_ib(value)) {
+ temp_rptr += 2 * sizeof(unsigned int);
+ kgsl_sharedmem_readl(&rb->buffer_desc, &value,
+ temp_rptr);
+ return value;
+ } else {
+ temp_rptr += sizeof(unsigned int);
+ }
+ }
+ } while (temp_rptr != rptr);
+
+ return 0;
+}
static unsigned int *adreno_ringbuffer_allocspace(struct adreno_ringbuffer *rb,
unsigned int numcmds)
@@ -461,6 +508,7 @@
static uint32_t
adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
+ struct adreno_context *context,
unsigned int flags, unsigned int *cmds,
int sizedwords)
{
@@ -475,16 +523,25 @@
*/
total_sizedwords += flags & KGSL_CMD_FLAGS_PMODE ? 4 : 0;
total_sizedwords += !(flags & KGSL_CMD_FLAGS_NO_TS_CMP) ? 7 : 0;
- total_sizedwords += !(flags & KGSL_CMD_FLAGS_NOT_KERNEL_CMD) ? 2 : 0;
+ /* 2 dwords to store the start of command sequence */
+ total_sizedwords += 2;
ringcmds = adreno_ringbuffer_allocspace(rb, total_sizedwords);
+ /* GPU may hang during space allocation, if thats the case the current
+ * context may have hung the GPU */
+ if (context->flags & CTXT_FLAGS_GPU_HANG) {
+ KGSL_CTXT_WARN(rb->device,
+ "Context %p caused a gpu hang. Will not accept commands for context %d\n",
+ context, context->id);
+ return rb->timestamp;
+ }
+
rcmd_gpu = rb->buffer_desc.gpuaddr
+ sizeof(uint)*(rb->wptr-total_sizedwords);
- if (!(flags & KGSL_CMD_FLAGS_NOT_KERNEL_CMD)) {
- GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_IDENTIFIER);
- }
+ GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1));
+ GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_IDENTIFIER);
+
if (flags & KGSL_CMD_FLAGS_PMODE) {
/* disable protected mode error checking */
GSL_RB_WRITE(ringcmds, rcmd_gpu,
@@ -541,6 +598,7 @@
void
adreno_ringbuffer_issuecmds(struct kgsl_device *device,
+ struct adreno_context *drawctxt,
unsigned int flags,
unsigned int *cmds,
int sizedwords)
@@ -550,7 +608,8 @@
if (device->state & KGSL_STATE_HUNG)
return;
- adreno_ringbuffer_addcmds(rb, flags, cmds, sizedwords);
+
+ adreno_ringbuffer_addcmds(rb, drawctxt, flags, cmds, sizedwords);
}
static bool _parse_ibs(struct kgsl_device_private *dev_priv, uint gpuaddr,
@@ -802,14 +861,14 @@
*cmds++ = ibdesc[i].sizedwords;
}
- kgsl_setstate(device,
+ kgsl_setstate(device, context->id,
kgsl_mmu_pt_get_flags(device->mmu.hwpagetable,
- device->id));
+ device->id));
adreno_drawctxt_switch(adreno_dev, drawctxt, flags);
*timestamp = adreno_ringbuffer_addcmds(&adreno_dev->ringbuffer,
- KGSL_CMD_FLAGS_NOT_KERNEL_CMD,
+ drawctxt, 0,
&link[0], (cmds - link));
KGSL_CMD_INFO(device, "ctxt %d g %08x numibs %d ts %d\n",
@@ -829,185 +888,329 @@
return 0;
}
-int adreno_ringbuffer_extract(struct adreno_ringbuffer *rb,
- unsigned int *temp_rb_buffer,
- int *rb_size)
+static int _find_start_of_cmd_seq(struct adreno_ringbuffer *rb,
+ unsigned int *ptr,
+ bool inc)
{
- struct kgsl_device *device = rb->device;
- unsigned int rb_rptr;
- unsigned int retired_timestamp;
- unsigned int temp_idx = 0;
- unsigned int value;
+ int status = -EINVAL;
unsigned int val1;
- unsigned int val2;
- unsigned int val3;
- unsigned int copy_rb_contents = 0;
- unsigned int cur_context;
- unsigned int j;
+ unsigned int size = rb->buffer_desc.size;
+ unsigned int start_ptr = *ptr;
- GSL_RB_GET_READPTR(rb, &rb->rptr);
-
- retired_timestamp = device->ftbl->readtimestamp(device,
- KGSL_TIMESTAMP_RETIRED);
- KGSL_DRV_ERR(device, "GPU successfully executed till ts: %x\n",
- retired_timestamp);
- /*
- * We need to go back in history by 4 dwords from the current location
- * of read pointer as 4 dwords are read to match the end of a command.
- * Also, take care of wrap around when moving back
- */
- if (rb->rptr >= 4)
- rb_rptr = (rb->rptr - 4) * sizeof(unsigned int);
- else
- rb_rptr = rb->buffer_desc.size -
- ((4 - rb->rptr) * sizeof(unsigned int));
- /* Read the rb contents going backwards to locate end of last
- * sucessfully executed command */
- while ((rb_rptr / sizeof(unsigned int)) != rb->wptr) {
- kgsl_sharedmem_readl(&rb->buffer_desc, &value, rb_rptr);
- if (value == retired_timestamp) {
- rb_rptr = adreno_ringbuffer_inc_wrapped(rb_rptr,
- rb->buffer_desc.size);
- kgsl_sharedmem_readl(&rb->buffer_desc, &val1, rb_rptr);
- rb_rptr = adreno_ringbuffer_inc_wrapped(rb_rptr,
- rb->buffer_desc.size);
- kgsl_sharedmem_readl(&rb->buffer_desc, &val2, rb_rptr);
- rb_rptr = adreno_ringbuffer_inc_wrapped(rb_rptr,
- rb->buffer_desc.size);
- kgsl_sharedmem_readl(&rb->buffer_desc, &val3, rb_rptr);
- /* match the pattern found at the end of a command */
- if ((val1 == 2 &&
- val2 == cp_type3_packet(CP_INTERRUPT, 1)
- && val3 == CP_INT_CNTL__RB_INT_MASK) ||
- (val1 == cp_type3_packet(CP_EVENT_WRITE, 3)
- && val2 == CACHE_FLUSH_TS &&
- val3 == (rb->device->memstore.gpuaddr +
- KGSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp)))) {
- rb_rptr = adreno_ringbuffer_inc_wrapped(rb_rptr,
- rb->buffer_desc.size);
- KGSL_DRV_ERR(device,
- "Found end of last executed "
- "command at offset: %x\n",
- rb_rptr / sizeof(unsigned int));
+ while ((start_ptr / sizeof(unsigned int)) != rb->wptr) {
+ if (inc)
+ start_ptr = adreno_ringbuffer_inc_wrapped(start_ptr,
+ size);
+ else
+ start_ptr = adreno_ringbuffer_dec_wrapped(start_ptr,
+ size);
+ kgsl_sharedmem_readl(&rb->buffer_desc, &val1, start_ptr);
+ if (KGSL_CMD_IDENTIFIER == val1) {
+ if ((start_ptr / sizeof(unsigned int)) != rb->wptr)
+ start_ptr = adreno_ringbuffer_dec_wrapped(
+ start_ptr, size);
+ *ptr = start_ptr;
+ status = 0;
break;
- } else {
- if (rb_rptr < (3 * sizeof(unsigned int)))
- rb_rptr = rb->buffer_desc.size -
- (3 * sizeof(unsigned int))
- + rb_rptr;
- else
- rb_rptr -= (3 * sizeof(unsigned int));
+ }
+ }
+ return status;
+}
+
+static int _find_cmd_seq_after_eop_ts(struct adreno_ringbuffer *rb,
+ unsigned int *rb_rptr,
+ unsigned int global_eop,
+ bool inc)
+{
+ int status = -EINVAL;
+ unsigned int temp_rb_rptr = *rb_rptr;
+ unsigned int size = rb->buffer_desc.size;
+ unsigned int val[3];
+ int i = 0;
+ bool check = false;
+
+ if (inc && temp_rb_rptr / sizeof(unsigned int) != rb->wptr)
+ return status;
+
+ do {
+ /* when decrementing we need to decrement first and
+ * then read make sure we cover all the data */
+ if (!inc)
+ temp_rb_rptr = adreno_ringbuffer_dec_wrapped(
+ temp_rb_rptr, size);
+ kgsl_sharedmem_readl(&rb->buffer_desc, &val[i],
+ temp_rb_rptr);
+
+ if (check && ((inc && val[i] == global_eop) ||
+ (!inc && (val[i] ==
+ cp_type3_packet(CP_MEM_WRITE, 2) ||
+ val[i] == CACHE_FLUSH_TS)))) {
+ /* decrement i, i.e i = (i - 1 + 3) % 3 if
+ * we are going forward, else increment i */
+ i = (i + 2) % 3;
+ if (val[i] == rb->device->memstore.gpuaddr +
+ KGSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp)) {
+ int j = ((i + 2) % 3);
+ if ((inc && (val[j] == CACHE_FLUSH_TS ||
+ val[j] == cp_type3_packet(
+ CP_MEM_WRITE, 2))) ||
+ (!inc && val[j] == global_eop)) {
+ /* Found the global eop */
+ status = 0;
+ break;
+ }
}
+ /* if no match found then increment i again
+ * since we decremented before matching */
+ i = (i + 1) % 3;
+ }
+ if (inc)
+ temp_rb_rptr = adreno_ringbuffer_inc_wrapped(
+ temp_rb_rptr, size);
+
+ i = (i + 1) % 3;
+ if (2 == i)
+ check = true;
+ } while (temp_rb_rptr / sizeof(unsigned int) != rb->wptr);
+ /* temp_rb_rptr points to the command stream after global eop,
+ * move backward till the start of command sequence */
+ if (!status) {
+ status = _find_start_of_cmd_seq(rb, &temp_rb_rptr, false);
+ if (!status) {
+ *rb_rptr = temp_rb_rptr;
+ KGSL_DRV_ERR(rb->device,
+ "Offset of cmd sequence after eop timestamp: 0x%x\n",
+ temp_rb_rptr / sizeof(unsigned int));
+ }
+ }
+ return status;
+}
+
+static int _find_hanging_ib_sequence(struct adreno_ringbuffer *rb,
+ unsigned int *rb_rptr,
+ unsigned int ib1)
+{
+ int status = -EINVAL;
+ unsigned int temp_rb_rptr = *rb_rptr;
+ unsigned int size = rb->buffer_desc.size;
+ unsigned int val[2];
+ int i = 0;
+ bool check = false;
+ bool ctx_switch = false;
+
+ while (temp_rb_rptr / sizeof(unsigned int) != rb->wptr) {
+ kgsl_sharedmem_readl(&rb->buffer_desc, &val[i], temp_rb_rptr);
+
+ if (check && val[i] == ib1) {
+ /* decrement i, i.e i = (i - 1 + 2) % 2 */
+ i = (i + 1) % 2;
+ if (adreno_cmd_is_ib(val[i])) {
+ /* go till start of command sequence */
+ status = _find_start_of_cmd_seq(rb,
+ &temp_rb_rptr, false);
+ KGSL_DRV_ERR(rb->device,
+ "Found the hanging IB at offset 0x%x\n",
+ temp_rb_rptr / sizeof(unsigned int));
+ break;
+ }
+ /* if no match the increment i since we decremented
+ * before checking */
+ i = (i + 1) % 2;
+ }
+ /* Make sure you do not encounter a context switch twice, we can
+ * encounter it once for the bad context as the start of search
+ * can point to the context switch */
+ if (val[i] == KGSL_CONTEXT_TO_MEM_IDENTIFIER) {
+ if (ctx_switch) {
+ KGSL_DRV_ERR(rb->device,
+ "Context switch encountered before bad "
+ "IB found\n");
+ break;
+ }
+ ctx_switch = true;
+ }
+ i = (i + 1) % 2;
+ if (1 == i)
+ check = true;
+ temp_rb_rptr = adreno_ringbuffer_inc_wrapped(temp_rb_rptr,
+ size);
+ }
+ if (!status)
+ *rb_rptr = temp_rb_rptr;
+ return status;
+}
+
+static void _turn_preamble_on_for_ib_seq(struct adreno_ringbuffer *rb,
+ unsigned int rb_rptr)
+{
+ unsigned int temp_rb_rptr = rb_rptr;
+ unsigned int size = rb->buffer_desc.size;
+ unsigned int val[2];
+ int i = 0;
+ bool check = false;
+ bool cmd_start = false;
+
+ /* Go till the start of the ib sequence and turn on preamble */
+ while (temp_rb_rptr / sizeof(unsigned int) != rb->wptr) {
+ kgsl_sharedmem_readl(&rb->buffer_desc, &val[i], temp_rb_rptr);
+ if (check && KGSL_START_OF_IB_IDENTIFIER == val[i]) {
+ /* decrement i */
+ i = (i + 1) % 2;
+ if (val[i] == cp_nop_packet(4)) {
+ temp_rb_rptr = adreno_ringbuffer_dec_wrapped(
+ temp_rb_rptr, size);
+ kgsl_sharedmem_writel(&rb->buffer_desc,
+ temp_rb_rptr, cp_nop_packet(1));
+ }
+ KGSL_DRV_ERR(rb->device,
+ "Turned preamble on at offset 0x%x\n",
+ temp_rb_rptr / 4);
+ break;
+ }
+ /* If you reach beginning of next command sequence then exit
+ * First command encountered is the current one so don't break
+ * on that. */
+ if (KGSL_CMD_IDENTIFIER == val[i]) {
+ if (cmd_start)
+ break;
+ cmd_start = true;
}
- if (rb_rptr == 0)
- rb_rptr = rb->buffer_desc.size - sizeof(unsigned int);
- else
- rb_rptr -= sizeof(unsigned int);
+ i = (i + 1) % 2;
+ if (1 == i)
+ check = true;
+ temp_rb_rptr = adreno_ringbuffer_inc_wrapped(temp_rb_rptr,
+ size);
}
+}
- if ((rb_rptr / sizeof(unsigned int)) == rb->wptr) {
- KGSL_DRV_ERR(device,
- "GPU recovery from hang not possible because last"
- " successful timestamp is overwritten\n");
- return -EINVAL;
- }
- /* rb_rptr is now pointing to the first dword of the command following
- * the last sucessfully executed command sequence. Assumption is that
- * GPU is hung in the command sequence pointed by rb_rptr */
- /* make sure the GPU is not hung in a command submitted by kgsl
- * itself */
- kgsl_sharedmem_readl(&rb->buffer_desc, &val1, rb_rptr);
- kgsl_sharedmem_readl(&rb->buffer_desc, &val2,
- adreno_ringbuffer_inc_wrapped(rb_rptr,
- rb->buffer_desc.size));
- if (val1 == cp_nop_packet(1) && val2 == KGSL_CMD_IDENTIFIER) {
- KGSL_DRV_ERR(device,
- "GPU recovery from hang not possible because "
- "of hang in kgsl command\n");
- return -EINVAL;
- }
+static void _copy_valid_rb_content(struct adreno_ringbuffer *rb,
+ unsigned int rb_rptr, unsigned int *temp_rb_buffer,
+ int *rb_size, unsigned int *bad_rb_buffer,
+ int *bad_rb_size,
+ int *last_valid_ctx_id)
+{
+ unsigned int good_rb_idx = 0, cmd_start_idx = 0;
+ unsigned int val1 = 0;
+ struct kgsl_context *k_ctxt;
+ struct adreno_context *a_ctxt;
+ unsigned int bad_rb_idx = 0;
+ int copy_rb_contents = 0;
+ unsigned int temp_rb_rptr;
+ unsigned int size = rb->buffer_desc.size;
+ unsigned int good_cmd_start_idx = 0;
- /* current_context is the context that is presently active in the
- * GPU, i.e the context in which the hang is caused */
- kgsl_sharedmem_readl(&device->memstore, &cur_context,
- KGSL_DEVICE_MEMSTORE_OFFSET(current_context));
+ /* Walk the rb from the context switch. Omit any commands
+ * for an invalid context. */
while ((rb_rptr / sizeof(unsigned int)) != rb->wptr) {
- kgsl_sharedmem_readl(&rb->buffer_desc, &value, rb_rptr);
- rb_rptr = adreno_ringbuffer_inc_wrapped(rb_rptr,
- rb->buffer_desc.size);
+ kgsl_sharedmem_readl(&rb->buffer_desc, &val1, rb_rptr);
+
+ if (KGSL_CMD_IDENTIFIER == val1) {
+ /* Start is the NOP dword that comes before
+ * KGSL_CMD_IDENTIFIER */
+ cmd_start_idx = bad_rb_idx - 1;
+ if (copy_rb_contents)
+ good_cmd_start_idx = good_rb_idx - 1;
+ }
+
/* check for context switch indicator */
- if (value == KGSL_CONTEXT_TO_MEM_IDENTIFIER) {
- kgsl_sharedmem_readl(&rb->buffer_desc, &value, rb_rptr);
- rb_rptr = adreno_ringbuffer_inc_wrapped(rb_rptr,
- rb->buffer_desc.size);
- BUG_ON(value != cp_type3_packet(CP_MEM_WRITE, 2));
- kgsl_sharedmem_readl(&rb->buffer_desc, &val1, rb_rptr);
- rb_rptr = adreno_ringbuffer_inc_wrapped(rb_rptr,
- rb->buffer_desc.size);
- BUG_ON(val1 != (device->memstore.gpuaddr +
- KGSL_DEVICE_MEMSTORE_OFFSET(current_context)));
- kgsl_sharedmem_readl(&rb->buffer_desc, &value, rb_rptr);
- rb_rptr = adreno_ringbuffer_inc_wrapped(rb_rptr,
- rb->buffer_desc.size);
+ if (val1 == KGSL_CONTEXT_TO_MEM_IDENTIFIER) {
+ unsigned int temp_idx, val2;
+ /* increment by 3 to get to the context_id */
+ temp_rb_rptr = rb_rptr + (3 * sizeof(unsigned int)) %
+ size;
+ kgsl_sharedmem_readl(&rb->buffer_desc, &val2,
+ temp_rb_rptr);
- /*
- * If other context switches were already lost and
- * and the current context is the one that is hanging,
- * then we cannot recover. Print an error message
- * and leave.
- */
-
- if ((copy_rb_contents == 0) && (value == cur_context)) {
- KGSL_DRV_ERR(device, "GPU recovery could not "
- "find the previous context\n");
- return -EINVAL;
- }
-
- /*
- * If we were copying the commands and got to this point
- * then we need to remove the 3 commands that appear
- * before KGSL_CONTEXT_TO_MEM_IDENTIFIER
- */
- if (temp_idx)
- temp_idx -= 3;
/* if context switches to a context that did not cause
* hang then start saving the rb contents as those
* commands can be executed */
- if (value != cur_context) {
+ k_ctxt = idr_find(&rb->device->context_idr, val2);
+ if (k_ctxt) {
+ a_ctxt = k_ctxt->devctxt;
+
+ /* If we are changing to a good context and were not
+ * copying commands then copy over commands to the good
+ * context */
+ if (!copy_rb_contents && ((k_ctxt &&
+ !(a_ctxt->flags & CTXT_FLAGS_GPU_HANG)) ||
+ !k_ctxt)) {
+ for (temp_idx = cmd_start_idx;
+ temp_idx < bad_rb_idx;
+ temp_idx++)
+ temp_rb_buffer[good_rb_idx++] =
+ bad_rb_buffer[temp_idx];
+ *last_valid_ctx_id = val2;
copy_rb_contents = 1;
- temp_rb_buffer[temp_idx++] = cp_nop_packet(1);
- temp_rb_buffer[temp_idx++] =
- KGSL_CMD_IDENTIFIER;
- temp_rb_buffer[temp_idx++] = cp_nop_packet(1);
- temp_rb_buffer[temp_idx++] =
- KGSL_CONTEXT_TO_MEM_IDENTIFIER;
- temp_rb_buffer[temp_idx++] =
- cp_type3_packet(CP_MEM_WRITE, 2);
- temp_rb_buffer[temp_idx++] = val1;
- temp_rb_buffer[temp_idx++] = value;
- } else {
+ } else if (copy_rb_contents && k_ctxt &&
+ (a_ctxt->flags & CTXT_FLAGS_GPU_HANG)) {
+ /* If we are changing to bad context then remove
+ * the dwords we copied for this sequence from
+ * the good buffer */
+ good_rb_idx = good_cmd_start_idx;
copy_rb_contents = 0;
}
- } else if (copy_rb_contents)
- temp_rb_buffer[temp_idx++] = value;
+ }
+ }
+
+ if (copy_rb_contents)
+ temp_rb_buffer[good_rb_idx++] = val1;
+ /* Copy both good and bad commands for replay to the bad
+ * buffer */
+ bad_rb_buffer[bad_rb_idx++] = val1;
+
+ rb_rptr = adreno_ringbuffer_inc_wrapped(rb_rptr, size);
+ }
+ *rb_size = good_rb_idx;
+ *bad_rb_size = bad_rb_idx;
+}
+
+int adreno_ringbuffer_extract(struct adreno_ringbuffer *rb,
+ struct adreno_recovery_data *rec_data)
+{
+ int status;
+ struct kgsl_device *device = rb->device;
+ unsigned int rb_rptr = rb->wptr * sizeof(unsigned int);
+ struct kgsl_context *context;
+ struct adreno_context *adreno_context;
+
+ context = idr_find(&device->context_idr, rec_data->context_id);
+
+ /* Look for the command stream that is right after the global eop */
+ status = _find_cmd_seq_after_eop_ts(rb, &rb_rptr,
+ rec_data->global_eop + 1, false);
+
+ if (status)
+ goto done;
+
+ if (context) {
+ adreno_context = context->devctxt;
+
+ if (adreno_context->flags & CTXT_FLAGS_PREAMBLE) {
+ if (rec_data->ib1) {
+ status = _find_hanging_ib_sequence(rb, &rb_rptr,
+ rec_data->ib1);
+ if (status)
+ goto copy_rb_contents;
+ }
+ _turn_preamble_on_for_ib_seq(rb, rb_rptr);
+ }
}
- *rb_size = temp_idx;
- KGSL_DRV_ERR(device, "Extracted rb contents, size: %x\n", *rb_size);
- for (temp_idx = 0; temp_idx < *rb_size;) {
- char str[80];
- int idx = 0;
- if ((temp_idx + 8) <= *rb_size)
- j = 8;
- else
- j = *rb_size - temp_idx;
- for (; j != 0; j--)
- idx += scnprintf(str + idx, 80 - idx,
- "%8.8X ", temp_rb_buffer[temp_idx++]);
- printk(KERN_ALERT "%s", str);
+copy_rb_contents:
+ _copy_valid_rb_content(rb, rb_rptr, rec_data->rb_buffer,
+ &rec_data->rb_size,
+ rec_data->bad_rb_buffer,
+ &rec_data->bad_rb_size,
+ &rec_data->last_valid_ctx_id);
+ /* If we failed to get the hanging IB sequence then we cannot execute
+ * commands from the bad context */
+ if (status) {
+ rec_data->bad_rb_size = 0;
+ status = 0;
}
- return 0;
+done:
+ return status;
}
void
@@ -1033,3 +1236,52 @@
rb->wptr += num_rb_contents;
adreno_ringbuffer_submit(rb);
}
+
+void adreno_print_fault_ib_work(struct work_struct *work)
+{
+ struct kgsl_device *device = container_of(work, struct kgsl_device,
+ print_fault_ib);
+ mutex_lock(&device->mutex);
+ adreno_print_fault_ib(device);
+ mutex_unlock(&device->mutex);
+}
+
+void adreno_print_fault_ib(struct kgsl_device *device)
+{
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ struct ib_list ib_list;
+ int i;
+
+ unsigned int ib_sz;
+
+ if (!device->page_fault_ptbase ||
+ !is_adreno_ib_dump_on_pagef_enabled(device))
+ goto done;
+
+ ib_sz = find_faulting_ib1_size(&adreno_dev->ringbuffer,
+ device->page_fault_rptr,
+ device->page_fault_ib1);
+ if (!ib_sz) {
+ KGSL_DRV_ERR(device, "Could not find size of fault ib 0x%x\n",
+ device->page_fault_ib1);
+ goto done;
+ }
+ ib_list.count = 0;
+
+ KGSL_DRV_ERR(device, "Page faulting IB1 0x%x, size 0x%x\n",
+ device->page_fault_ib1, ib_sz);
+ dump_ib1(device, device->page_fault_ptbase, 0,
+ device->page_fault_ib1, ib_sz, &ib_list, true);
+
+ /* print ib2's in faulting ib1 */
+ for (i = 0; i < ib_list.count; i++) {
+ KGSL_DRV_ERR(device, "IB2 0x%x, size 0x%x\n",
+ ib_list.bases[i], ib_list.sizes[i]);
+ dump_ib(device, "IB2:", device->page_fault_ptbase,
+ ib_list.offsets[i], ib_list.bases[i], ib_list.sizes[i],
+ true);
+ }
+ KGSL_DRV_ERR(device, "Finished printing fault IB\n");
+done:
+ device->page_fault_ptbase = 0;
+}
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index 6c4926d..a30a930 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -31,6 +31,7 @@
struct kgsl_device;
struct kgsl_device_private;
+struct adreno_recovery_data;
#define GSL_RB_MEMPTRS_SCRATCH_COUNT 8
struct kgsl_rbmemptrs {
@@ -122,6 +123,7 @@
void adreno_ringbuffer_close(struct adreno_ringbuffer *rb);
void adreno_ringbuffer_issuecmds(struct kgsl_device *device,
+ struct adreno_context *drawctxt,
unsigned int flags,
unsigned int *cmdaddr,
int sizedwords);
@@ -129,13 +131,16 @@
void kgsl_cp_intrcallback(struct kgsl_device *device);
int adreno_ringbuffer_extract(struct adreno_ringbuffer *rb,
- unsigned int *temp_rb_buffer,
- int *rb_size);
+ struct adreno_recovery_data *rec_data);
void
adreno_ringbuffer_restore(struct adreno_ringbuffer *rb, unsigned int *rb_buff,
int num_rb_contents);
+void adreno_print_fault_ib_work(struct work_struct *work);
+
+void adreno_print_fault_ib(struct kgsl_device *device);
+
static inline int adreno_ringbuffer_count(struct adreno_ringbuffer *rb,
unsigned int rptr)
{
@@ -151,4 +156,11 @@
return (val + sizeof(unsigned int)) % size;
}
+/* Decrement a value by 4 bytes with wrap-around based on size */
+static inline unsigned int adreno_ringbuffer_dec_wrapped(unsigned int val,
+ unsigned int size)
+{
+ return (val + size - sizeof(unsigned int)) % size;
+}
+
#endif /* __ADRENO_RINGBUFFER_H */
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index c43c9c5..ba13f35 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -25,7 +25,6 @@
#include <linux/ashmem.h>
#include <linux/major.h>
#include <linux/ion.h>
-#include <mach/socinfo.h>
#include "kgsl.h"
#include "kgsl_debugfs.h"
@@ -536,8 +535,8 @@
struct kgsl_device, display_off);
KGSL_PWR_WARN(device, "late resume start\n");
mutex_lock(&device->mutex);
- kgsl_pwrctrl_wake(device);
device->pwrctrl.restore_slumber = 0;
+ kgsl_pwrctrl_wake(device);
kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_TURBO);
mutex_unlock(&device->mutex);
kgsl_check_idle(device);
@@ -1166,7 +1165,7 @@
goto error;
}
- result = kgsl_sharedmem_page_alloc_user(&entry->memdesc,
+ result = kgsl_sharedmem_vmalloc_user(&entry->memdesc,
private->pagetable, len,
param->flags);
if (result != 0)
@@ -1177,7 +1176,7 @@
result = kgsl_sharedmem_map_vma(vma, &entry->memdesc);
if (result) {
KGSL_CORE_ERR("kgsl_sharedmem_map_vma failed: %d\n", result);
- goto error_free_alloc;
+ goto error_free_vmalloc;
}
param->gpuaddr = entry->memdesc.gpuaddr;
@@ -1192,7 +1191,7 @@
kgsl_check_idle(dev_priv->device);
return 0;
-error_free_alloc:
+error_free_vmalloc:
kgsl_sharedmem_free(&entry->memdesc);
error_free_entry:
@@ -1491,8 +1490,11 @@
struct scatterlist *s;
unsigned long flags;
- if (IS_ERR_OR_NULL(kgsl_ion_client))
- return -ENODEV;
+ if (kgsl_ion_client == NULL) {
+ kgsl_ion_client = msm_ion_client_create(UINT_MAX, KGSL_NAME);
+ if (kgsl_ion_client == NULL)
+ return -ENODEV;
+ }
handle = ion_import_fd(kgsl_ion_client, fd);
if (IS_ERR_OR_NULL(handle))
@@ -2110,8 +2112,7 @@
kgsl_cffdump_close(device->id);
kgsl_pwrctrl_uninit_sysfs(device);
- if (cpu_is_msm8x60())
- wake_lock_destroy(&device->idle_wakelock);
+ wake_lock_destroy(&device->idle_wakelock);
idr_destroy(&device->context_idr);
@@ -2202,9 +2203,8 @@
if (ret != 0)
goto err_close_mmu;
- if (cpu_is_msm8x60())
- wake_lock_init(&device->idle_wakelock,
- WAKE_LOCK_IDLE, device->name);
+ wake_lock_init(&device->idle_wakelock, WAKE_LOCK_IDLE, device->name);
+ pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
idr_init(&device->context_idr);
@@ -2250,8 +2250,6 @@
if (status)
goto error;
- kgsl_ion_client = msm_ion_client_create(UINT_MAX, KGSL_NAME);
-
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
device->iomemname);
if (res == NULL) {
@@ -2340,8 +2338,8 @@
static int __devinit
kgsl_ptdata_init(void)
{
- kgsl_driver.ptpool = kgsl_mmu_ptpool_init(KGSL_PAGETABLE_SIZE,
- kgsl_pagetable_count);
+ kgsl_driver.ptpool = kgsl_mmu_ptpool_init(kgsl_pagetable_count);
+
if (!kgsl_driver.ptpool)
return -ENOMEM;
return 0;
@@ -2349,30 +2347,22 @@
static void kgsl_core_exit(void)
{
- kgsl_mmu_ptpool_destroy(kgsl_driver.ptpool);
+ unregister_chrdev_region(kgsl_driver.major, KGSL_DEVICE_MAX);
+
+ kgsl_mmu_ptpool_destroy(&kgsl_driver.ptpool);
kgsl_driver.ptpool = NULL;
- kgsl_drm_exit();
- kgsl_cffdump_destroy();
- kgsl_core_debugfs_close();
-
- /*
- * We call kgsl_sharedmem_uninit_sysfs() and device_unregister()
- * only if kgsl_driver.virtdev has been populated.
- * We check at least one member of kgsl_driver.virtdev to
- * see if it is not NULL (and thus, has been populated).
- */
- if (kgsl_driver.virtdev.class) {
- kgsl_sharedmem_uninit_sysfs();
- device_unregister(&kgsl_driver.virtdev);
- }
+ device_unregister(&kgsl_driver.virtdev);
if (kgsl_driver.class) {
class_destroy(kgsl_driver.class);
kgsl_driver.class = NULL;
}
- unregister_chrdev_region(kgsl_driver.major, KGSL_DEVICE_MAX);
+ kgsl_drm_exit();
+ kgsl_cffdump_destroy();
+ kgsl_core_debugfs_close();
+ kgsl_sharedmem_uninit_sysfs();
}
static int __init kgsl_core_init(void)
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 4df509d..25c4827 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -44,10 +44,6 @@
#define KGSL_PAGETABLE_ENTRIES(_sz) (((_sz) >> PAGE_SHIFT) + \
KGSL_PT_EXTRA_ENTRIES)
-#define KGSL_PAGETABLE_SIZE \
-ALIGN(KGSL_PAGETABLE_ENTRIES(CONFIG_MSM_KGSL_PAGE_TABLE_SIZE) * \
-KGSL_PAGETABLE_ENTRY_SIZE, PAGE_SIZE)
-
#ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE
#define KGSL_PAGETABLE_COUNT (CONFIG_MSM_KGSL_PAGE_TABLE_COUNT)
#else
@@ -95,8 +91,6 @@
struct {
unsigned int vmalloc;
unsigned int vmalloc_max;
- unsigned int page_alloc;
- unsigned int page_alloc_max;
unsigned int coherent;
unsigned int coherent_max;
unsigned int mapped;
@@ -118,8 +112,6 @@
int (*map_kernel_mem)(struct kgsl_memdesc *);
};
-#define KGSL_MEMDESC_GUARD_PAGE BIT(0)
-
/* shared memory allocation */
struct kgsl_memdesc {
struct kgsl_pagetable *pagetable;
@@ -131,7 +123,6 @@
struct scatterlist *sg;
unsigned int sglen;
struct kgsl_memdesc_ops *ops;
- int flags;
};
/* List of different memory entry types */
@@ -211,14 +202,13 @@
static inline uint8_t *kgsl_gpuaddr_to_vaddr(struct kgsl_memdesc *memdesc,
unsigned int gpuaddr)
{
- if (memdesc->gpuaddr == 0 ||
- gpuaddr < memdesc->gpuaddr ||
- gpuaddr >= (memdesc->gpuaddr + memdesc->size) ||
- (NULL == memdesc->hostptr && memdesc->ops->map_kernel_mem &&
- memdesc->ops->map_kernel_mem(memdesc)))
- return NULL;
+ void *hostptr = NULL;
- return memdesc->hostptr + (gpuaddr - memdesc->gpuaddr);
+ if ((gpuaddr >= memdesc->gpuaddr) &&
+ (gpuaddr < (memdesc->gpuaddr + memdesc->size)))
+ hostptr = kgsl_memdesc_map(memdesc);
+
+ return hostptr != NULL ? hostptr + (gpuaddr - memdesc->gpuaddr) : NULL;
}
static inline int timestamp_cmp(unsigned int a, unsigned int b)
diff --git a/drivers/gpu/msm/kgsl_cffdump.c b/drivers/gpu/msm/kgsl_cffdump.c
index 77aef1f..4e354d0 100644
--- a/drivers/gpu/msm/kgsl_cffdump.c
+++ b/drivers/gpu/msm/kgsl_cffdump.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -359,7 +359,7 @@
void kgsl_cffdump_open(enum kgsl_deviceid device_id)
{
kgsl_cffdump_memory_base(device_id, KGSL_PAGETABLE_BASE,
- CONFIG_MSM_KGSL_PAGE_TABLE_SIZE, SZ_256K);
+ kgsl_mmu_get_ptsize(), SZ_256K);
}
void kgsl_cffdump_memory_base(enum kgsl_deviceid device_id, unsigned int base,
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index bd74a51..fdb4a6e 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -15,6 +15,7 @@
#include <linux/idr.h>
#include <linux/wakelock.h>
+#include <linux/pm_qos_params.h>
#include <linux/earlysuspend.h>
#include "kgsl.h"
@@ -89,13 +90,14 @@
void (*power_stats)(struct kgsl_device *device,
struct kgsl_power_stats *stats);
void (*irqctrl)(struct kgsl_device *device, int state);
- unsigned int (*gpuid)(struct kgsl_device *device, unsigned int *chipid);
+ unsigned int (*gpuid)(struct kgsl_device *device);
void * (*snapshot)(struct kgsl_device *device, void *snapshot,
int *remain, int hang);
/* Optional functions - these functions are not mandatory. The
driver will check that the function pointer is not NULL before
calling the hook */
- void (*setstate) (struct kgsl_device *device, uint32_t flags);
+ void (*setstate) (struct kgsl_device *device, unsigned int context_id,
+ uint32_t flags);
int (*drawctxt_create) (struct kgsl_device *device,
struct kgsl_pagetable *pagetable, struct kgsl_context *context,
uint32_t flags);
@@ -184,9 +186,16 @@
struct wake_lock idle_wakelock;
struct kgsl_pwrscale pwrscale;
struct kobject pwrscale_kobj;
+ struct pm_qos_request_list pm_qos_req_dma;
struct work_struct ts_expired_ws;
struct list_head events;
s64 on_time;
+
+ /* page fault debugging parameters */
+ struct work_struct print_fault_ib;
+ unsigned int page_fault_ptbase;
+ unsigned int page_fault_ib1;
+ unsigned int page_fault_rptr;
};
struct kgsl_context {
@@ -258,10 +267,9 @@
return device->ftbl->idle(device, timeout);
}
-static inline unsigned int kgsl_gpuid(struct kgsl_device *device,
- unsigned int *chipid)
+static inline unsigned int kgsl_gpuid(struct kgsl_device *device)
{
- return device->ftbl->gpuid(device, chipid);
+ return device->ftbl->gpuid(device);
}
static inline int kgsl_create_device_sysfs_files(struct device *root,
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index ba48f9c..051fcfc 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -295,9 +295,8 @@
priv->memdesc.size = obj->size * priv->bufcount;
} else if (TYPE_IS_MEM(priv->type)) {
- result = kgsl_sharedmem_page_alloc(&priv->memdesc,
- priv->pagetable,
- obj->size * priv->bufcount, 0);
+ priv->memdesc.hostptr =
+ vmalloc_user(obj->size * priv->bufcount);
if (priv->memdesc.hostptr == NULL) {
DRM_ERROR("Unable to allocate vmalloc memory\n");
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index f038f04..7458cf2 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -21,6 +21,11 @@
#include "kgsl_mmu.h"
#include "kgsl_device.h"
#include "kgsl_sharedmem.h"
+#include "a2xx_reg.h"
+
+#define KGSL_PAGETABLE_SIZE \
+ ALIGN(KGSL_PAGETABLE_ENTRIES(CONFIG_MSM_KGSL_PAGE_TABLE_SIZE) * \
+ KGSL_PAGETABLE_ENTRY_SIZE, PAGE_SIZE)
static ssize_t
sysfs_show_ptpool_entries(struct kobject *kobj,
@@ -310,16 +315,15 @@
/**
* kgsl_ptpool_init
* @pool: A pointer to a ptpool structure to initialize
- * @ptsize: The size of each pagetable entry
* @entries: The number of inital entries to add to the pool
*
* Initalize a pool and allocate an initial chunk of entries.
*/
-void *kgsl_gpummu_ptpool_init(int ptsize, int entries)
+void *kgsl_gpummu_ptpool_init(int entries)
{
+ int ptsize = KGSL_PAGETABLE_SIZE;
struct kgsl_ptpool *pool;
int ret = 0;
- BUG_ON(ptsize == 0);
pool = kzalloc(sizeof(struct kgsl_ptpool), GFP_KERNEL);
if (!pool) {
@@ -354,8 +358,8 @@
int kgsl_gpummu_pt_equal(struct kgsl_pagetable *pt,
unsigned int pt_base)
{
- struct kgsl_gpummu_pt *gpummu_pt = pt ? pt->priv : NULL;
- return gpummu_pt && pt_base && (gpummu_pt->base.gpuaddr == pt_base);
+ struct kgsl_gpummu_pt *gpummu_pt = pt->priv;
+ return pt && pt_base && (gpummu_pt->base.gpuaddr == pt_base);
}
void kgsl_gpummu_destroy_pagetable(void *mmu_specific_pt)
@@ -421,11 +425,42 @@
kgsl_regread(device, MH_MMU_PAGE_FAULT, ®);
kgsl_regread(device, MH_MMU_PT_BASE, &ptbase);
- KGSL_MEM_CRIT(device,
- "mmu page fault: page=0x%lx pt=%d op=%s axi=%d\n",
+ if (KGSL_DEVICE_3D0 == device->id) {
+ unsigned int ib1;
+ unsigned int ib1_sz;
+ unsigned int ib2;
+ unsigned int ib2_sz;
+ unsigned int rptr;
+ kgsl_regread(device, REG_CP_IB1_BASE, &ib1);
+ kgsl_regread(device, REG_CP_IB1_BUFSZ, &ib1_sz);
+ kgsl_regread(device, REG_CP_IB2_BASE, &ib2);
+ kgsl_regread(device, REG_CP_IB2_BUFSZ, &ib2_sz);
+ kgsl_regread(device, REG_CP_RB_RPTR, &rptr);
+
+ /* queue a work which will print the IB that caused the
+ * pagefault, if we are in recovery then no need to q
+ * work as the recovery routine will mess with the ringbuffer
+ * contents and then the information will become stale
+ * anyways */
+ if (!device->page_fault_ptbase &&
+ KGSL_STATE_DUMP_AND_RECOVER != device->state) {
+ device->page_fault_ptbase = ptbase;
+ device->page_fault_ib1 = ib1;
+ device->page_fault_rptr = rptr;
+
+ queue_work(device->work_queue,
+ &device->print_fault_ib);
+ }
+
+ KGSL_MEM_CRIT(device,
+ "mmu page fault: page=0x%lx pt=%d op=%s axi=%d "
+ "ptbase=0x%x IB1=0x%x IB1_SZ=0x%x "
+ "IB2=0x%x IB2_SZ=0x%x\n",
reg & ~(PAGE_SIZE - 1),
kgsl_mmu_get_ptname_from_ptbase(ptbase),
- reg & 0x02 ? "WRITE" : "READ", (reg >> 4) & 0xF);
+ reg & 0x02 ? "WRITE" : "READ", (reg >> 4) & 0xF,
+ ptbase, ib1, ib1_sz, ib2, ib2_sz);
+ }
}
static void *kgsl_gpummu_create_pagetable(void)
@@ -498,7 +533,8 @@
}
static void kgsl_gpummu_setstate(struct kgsl_device *device,
- struct kgsl_pagetable *pagetable)
+ struct kgsl_pagetable *pagetable,
+ unsigned int context_id)
{
struct kgsl_mmu *mmu = &device->mmu;
struct kgsl_gpummu_pt *gpummu_pt;
@@ -515,7 +551,8 @@
spin_unlock(&mmu->hwpagetable->lock);
/* call device specific set page table */
- kgsl_setstate(mmu->device, KGSL_MMUFLAGS_TLBFLUSH |
+ kgsl_setstate(mmu->device, context_id,
+ KGSL_MMUFLAGS_TLBFLUSH |
KGSL_MMUFLAGS_PTUPDATE);
}
}
@@ -610,7 +647,7 @@
kgsl_regwrite(device, MH_MMU_VA_RANGE,
(KGSL_PAGETABLE_BASE |
(CONFIG_MSM_KGSL_PAGE_TABLE_SIZE >> 16)));
- kgsl_setstate(device, KGSL_MMUFLAGS_TLBFLUSH);
+ kgsl_setstate(device, 0, KGSL_MMUFLAGS_TLBFLUSH);
mmu->flags |= KGSL_FLAGS_STARTED;
return 0;
diff --git a/drivers/gpu/msm/kgsl_gpummu.h b/drivers/gpu/msm/kgsl_gpummu.h
index 46466a8..cac6930 100644
--- a/drivers/gpu/msm/kgsl_gpummu.h
+++ b/drivers/gpu/msm/kgsl_gpummu.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, 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
@@ -73,8 +73,7 @@
int chunks;
};
-void *kgsl_gpummu_ptpool_init(int ptsize,
- int entries);
+void *kgsl_gpummu_ptpool_init(int entries);
void kgsl_gpummu_ptpool_destroy(void *ptpool);
static inline unsigned int kgsl_pt_get_base_addr(struct kgsl_pagetable *pt)
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index a36739d..81e237f 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -34,8 +34,8 @@
static int kgsl_iommu_pt_equal(struct kgsl_pagetable *pt,
unsigned int pt_base)
{
- struct iommu_domain *domain = pt ? pt->priv : NULL;
- return domain && pt_base && ((unsigned int)domain == pt_base);
+ struct iommu_domain *domain = pt->priv;
+ return pt && pt_base && ((unsigned int)domain == pt_base);
}
static void kgsl_iommu_destroy_pagetable(void *mmu_specific_pt)
@@ -144,7 +144,8 @@
}
static void kgsl_iommu_setstate(struct kgsl_device *device,
- struct kgsl_pagetable *pagetable)
+ struct kgsl_pagetable *pagetable,
+ unsigned int context_id)
{
struct kgsl_mmu *mmu = &device->mmu;
@@ -262,7 +263,7 @@
iommu_virt_addr = memdesc->gpuaddr;
ret = iommu_map_range(domain, iommu_virt_addr, memdesc->sg,
- memdesc->size, 0);
+ memdesc->size, (IOMMU_READ | IOMMU_WRITE));
if (ret) {
KGSL_CORE_ERR("iommu_map_range(%p, %x, %p, %d, %d) "
"failed with err: %d\n", domain,
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 36248ef..975aa83 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -147,9 +147,10 @@
pt = _get_pt_from_kobj(kobj);
- if (pt)
+ if (pt) {
ret += snprintf(buf, PAGE_SIZE, "0x%x\n",
- CONFIG_MSM_KGSL_PAGE_TABLE_SIZE);
+ kgsl_mmu_get_ptsize());
+ }
kgsl_put_pagetable(pt);
return ret;
@@ -267,6 +268,22 @@
return ret;
}
+unsigned int kgsl_mmu_get_ptsize(void)
+{
+ /*
+ * For IOMMU, we could do up to 4G virtual range if we wanted to, but
+ * it makes more sense to return a smaller range and leave the rest of
+ * the virtual range for future improvements
+ */
+
+ if (KGSL_MMU_TYPE_GPU == kgsl_mmu_type)
+ return CONFIG_MSM_KGSL_PAGE_TABLE_SIZE;
+ else if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_type)
+ return SZ_2G;
+ else
+ return 0;
+}
+
unsigned int kgsl_mmu_get_current_ptbase(struct kgsl_device *device)
{
struct kgsl_mmu *mmu = &device->mmu;
@@ -297,7 +314,8 @@
EXPORT_SYMBOL(kgsl_mmu_get_ptname_from_ptbase);
void kgsl_mmu_setstate(struct kgsl_device *device,
- struct kgsl_pagetable *pagetable)
+ struct kgsl_pagetable *pagetable,
+ unsigned int context_id)
{
struct kgsl_mmu *mmu = &device->mmu;
@@ -305,7 +323,7 @@
return;
else
mmu->mmu_ops->mmu_setstate(device,
- pagetable);
+ pagetable, context_id);
}
EXPORT_SYMBOL(kgsl_mmu_setstate);
@@ -391,6 +409,7 @@
int status = 0;
struct kgsl_pagetable *pagetable = NULL;
unsigned long flags;
+ unsigned int ptsize;
pagetable = kzalloc(sizeof(struct kgsl_pagetable), GFP_KERNEL);
if (pagetable == NULL) {
@@ -402,9 +421,11 @@
kref_init(&pagetable->refcount);
spin_lock_init(&pagetable->lock);
+
+ ptsize = kgsl_mmu_get_ptsize();
+
pagetable->name = name;
- pagetable->max_entries = KGSL_PAGETABLE_ENTRIES(
- CONFIG_MSM_KGSL_PAGE_TABLE_SIZE);
+ pagetable->max_entries = KGSL_PAGETABLE_ENTRIES(ptsize);
pagetable->pool = gen_pool_create(PAGE_SHIFT, -1);
if (pagetable->pool == NULL) {
@@ -413,7 +434,7 @@
}
if (gen_pool_add(pagetable->pool, KGSL_PAGETABLE_BASE,
- CONFIG_MSM_KGSL_PAGE_TABLE_SIZE, -1)) {
+ ptsize, -1)) {
KGSL_CORE_ERR("gen_pool_add failed\n");
goto err_pool;
}
@@ -477,13 +498,14 @@
}
EXPORT_SYMBOL(kgsl_mmu_putpagetable);
-void kgsl_setstate(struct kgsl_device *device, uint32_t flags)
+void kgsl_setstate(struct kgsl_device *device, unsigned int context_id,
+ uint32_t flags)
{
struct kgsl_mmu *mmu = &device->mmu;
if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
return;
else if (device->ftbl->setstate)
- device->ftbl->setstate(device, flags);
+ device->ftbl->setstate(device, context_id, flags);
else if (mmu->mmu_ops->mmu_device_setstate)
mmu->mmu_ops->mmu_device_setstate(device, flags);
}
@@ -676,10 +698,10 @@
}
EXPORT_SYMBOL(kgsl_mmu_ptpool_destroy);
-void *kgsl_mmu_ptpool_init(int ptsize, int entries)
+void *kgsl_mmu_ptpool_init(int entries)
{
if (KGSL_MMU_TYPE_GPU == kgsl_mmu_type)
- return kgsl_gpummu_ptpool_init(ptsize, entries);
+ return kgsl_gpummu_ptpool_init(entries);
else
return (void *)(-1);
}
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 1338d0d..870f771 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2002,2007-2012, 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
@@ -112,7 +112,8 @@
int (*mmu_start) (struct kgsl_device *device);
int (*mmu_stop) (struct kgsl_device *device);
void (*mmu_setstate) (struct kgsl_device *device,
- struct kgsl_pagetable *pagetable);
+ struct kgsl_pagetable *pagetable,
+ unsigned int context_id);
void (*mmu_device_setstate) (struct kgsl_device *device,
uint32_t flags);
void (*mmu_pagefault) (struct kgsl_device *device);
@@ -168,20 +169,21 @@
int kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc);
unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr);
-void kgsl_setstate(struct kgsl_device *device, uint32_t flags);
+void kgsl_setstate(struct kgsl_device *device, unsigned int context_id,
+ uint32_t flags);
void kgsl_mmu_device_setstate(struct kgsl_device *device, uint32_t flags);
void kgsl_mmu_setstate(struct kgsl_device *device,
- struct kgsl_pagetable *pt);
+ struct kgsl_pagetable *pt, unsigned int context_id);
int kgsl_mmu_get_ptname_from_ptbase(unsigned int pt_base);
int kgsl_mmu_pt_get_flags(struct kgsl_pagetable *pt,
enum kgsl_deviceid id);
-
void kgsl_mmu_ptpool_destroy(void *ptpool);
-void *kgsl_mmu_ptpool_init(int ptsize, int entries);
+void *kgsl_mmu_ptpool_init(int entries);
int kgsl_mmu_enabled(void);
int kgsl_mmu_pt_equal(struct kgsl_pagetable *pt,
unsigned int pt_base);
void kgsl_mmu_set_mmutype(char *mmutype);
unsigned int kgsl_mmu_get_current_ptbase(struct kgsl_device *device);
enum kgsl_mmutype kgsl_mmu_get_mmutype(void);
+unsigned int kgsl_mmu_get_ptsize(void);
#endif /* __KGSL_MMU_H */
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index fb49c31..e9f2143 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -13,8 +13,6 @@
#include <linux/interrupt.h>
#include <mach/msm_iomap.h>
#include <mach/msm_bus.h>
-#include <mach/socinfo.h>
-#include <mach/internal_power_rail.h>
#include "kgsl.h"
#include "kgsl_pwrscale.h"
@@ -26,9 +24,38 @@
#define KGSL_PWRFLAGS_AXI_ON 2
#define KGSL_PWRFLAGS_IRQ_ON 3
+#define GPU_SWFI_LATENCY 3
#define UPDATE_BUSY_VAL 1000000
#define UPDATE_BUSY 50
+struct clk_pair {
+ const char *name;
+ uint map;
+};
+
+struct clk_pair clks[KGSL_MAX_CLKS] = {
+ {
+ .name = "src_clk",
+ .map = KGSL_CLK_SRC,
+ },
+ {
+ .name = "core_clk",
+ .map = KGSL_CLK_CORE,
+ },
+ {
+ .name = "iface_clk",
+ .map = KGSL_CLK_IFACE,
+ },
+ {
+ .name = "mem_clk",
+ .map = KGSL_CLK_MEM,
+ },
+ {
+ .name = "mem_iface_clk",
+ .map = KGSL_CLK_MEM_IFACE,
+ },
+};
+
void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device,
unsigned int new_level)
{
@@ -257,7 +284,7 @@
DEVICE_ATTR(gpuclk, 0644, kgsl_pwrctrl_gpuclk_show, kgsl_pwrctrl_gpuclk_store);
DEVICE_ATTR(max_gpuclk, 0644, kgsl_pwrctrl_max_gpuclk_show,
kgsl_pwrctrl_max_gpuclk_store);
-DEVICE_ATTR(pwrnap, 0666, kgsl_pwrctrl_pwrnap_show, kgsl_pwrctrl_pwrnap_store);
+DEVICE_ATTR(pwrnap, 0664, kgsl_pwrctrl_pwrnap_show, kgsl_pwrctrl_pwrnap_store);
DEVICE_ATTR(idle_timer, 0644, kgsl_pwrctrl_idle_timer_show,
kgsl_pwrctrl_idle_timer_store);
DEVICE_ATTR(gpubusy, 0644, kgsl_pwrctrl_gpubusy_show,
@@ -387,34 +414,16 @@
if (state == KGSL_PWRFLAGS_OFF) {
if (test_and_clear_bit(KGSL_PWRFLAGS_POWER_ON,
&pwr->power_flags)) {
- internal_pwr_rail_ctl(pwr->pwr_rail, 0);
trace_kgsl_rail(device, state);
- if (pwr->gpu_dig)
- regulator_disable(pwr->gpu_dig);
if (pwr->gpu_reg)
regulator_disable(pwr->gpu_reg);
}
} else if (state == KGSL_PWRFLAGS_ON) {
if (!test_and_set_bit(KGSL_PWRFLAGS_POWER_ON,
&pwr->power_flags)) {
- internal_pwr_rail_ctl(pwr->pwr_rail, 1);
trace_kgsl_rail(device, state);
- if (pwr->gpu_reg) {
- int status = regulator_enable(pwr->gpu_reg);
- if (status)
- KGSL_DRV_ERR(device,
- "core regulator_enable "
- "failed: %d\n",
- status);
- }
- if (pwr->gpu_dig) {
- int status = regulator_enable(pwr->gpu_dig);
- if (status)
- KGSL_DRV_ERR(device,
- "cx regulator_enable "
- "failed: %d\n",
- status);
- }
+ if (pwr->gpu_reg)
+ regulator_enable(pwr->gpu_reg);
}
}
}
@@ -451,16 +460,10 @@
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
struct kgsl_device_platform_data *pdata = pdev->dev.platform_data;
- const char *clk_names[KGSL_MAX_CLKS] = {pwr->src_clk_name,
- pdata->clk.clk,
- pdata->clk.pclk,
- pdata->imem_clk_name.clk,
- pdata->imem_clk_name.pclk};
-
/*acquire clocks */
for (i = 0; i < KGSL_MAX_CLKS; i++) {
- if (clk_names[i]) {
- clk = clk_get(&pdev->dev, clk_names[i]);
+ if (pdata->clk_map & clks[i].map) {
+ clk = clk_get(&pdev->dev, clks[i].name);
if (IS_ERR(clk))
goto clk_err;
pwr->grp_clks[i] = clk;
@@ -502,28 +505,12 @@
if (IS_ERR(pwr->gpu_reg))
pwr->gpu_reg = NULL;
- if (pwr->gpu_reg) {
- pwr->gpu_dig = regulator_get(&pdev->dev, "vdd_dig");
- if (IS_ERR(pwr->gpu_dig))
- pwr->gpu_dig = NULL;
- } else
- pwr->gpu_dig = NULL;
-
pwr->power_flags = 0;
pwr->nap_allowed = pdata->nap_allowed;
pwr->idle_needed = pdata->idle_needed;
pwr->interval_timeout = pdata->idle_timeout;
- pwr->strtstp_sleepwake = pdata->strtstp_sleepwake;
-
- if (internal_pwr_rail_mode(pwr->pwr_rail,
- PWR_RAIL_CTL_MANUAL)) {
- KGSL_PWR_ERR(device, "call internal_pwr_rail_mode failed\n");
- result = -EINVAL;
- goto done;
- }
-
- pwr->ebi1_clk = clk_get(NULL, "ebi1_kgsl_clk");
+ pwr->ebi1_clk = clk_get(&pdev->dev, "bus_clk");
if (IS_ERR(pwr->ebi1_clk))
pwr->ebi1_clk = NULL;
else
@@ -560,7 +547,7 @@
clk_err:
result = PTR_ERR(clk);
KGSL_PWR_ERR(device, "clk_get(%s) failed: %d\n",
- clk_names[i], result);
+ clks[i].name, result);
done:
return result;
@@ -595,11 +582,6 @@
pwr->gpu_reg = NULL;
}
- if (pwr->gpu_dig) {
- regulator_put(pwr->gpu_dig);
- pwr->gpu_dig = NULL;
- }
-
for (i = 1; i < KGSL_MAX_CLKS; i++)
if (pwr->grp_clks[i]) {
clk_put(pwr->grp_clks[i]);
@@ -650,8 +632,7 @@
KGSL_PWR_INFO(device, "idle timer expired device %d\n", device->id);
if (device->requested_state != KGSL_STATE_SUSPEND) {
- if (device->pwrctrl.restore_slumber ||
- device->pwrctrl.strtstp_sleepwake)
+ if (device->pwrctrl.restore_slumber)
kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER);
else
kgsl_pwrctrl_request_state(device, KGSL_STATE_SLEEP);
@@ -763,8 +744,9 @@
_sleep_accounting(device);
kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_OFF, KGSL_STATE_SLEEP);
kgsl_pwrctrl_set_state(device, KGSL_STATE_SLEEP);
- if (device->idle_wakelock.name)
- wake_unlock(&device->idle_wakelock);
+ wake_unlock(&device->idle_wakelock);
+ pm_qos_update_request(&device->pm_qos_req_dma,
+ PM_QOS_DEFAULT_VALUE);
break;
case KGSL_STATE_SLEEP:
case KGSL_STATE_SLUMBER:
@@ -791,16 +773,16 @@
case KGSL_STATE_NAP:
case KGSL_STATE_SLEEP:
del_timer_sync(&device->idle_timer);
- if (!device->pwrctrl.strtstp_sleepwake)
- kgsl_pwrctrl_pwrlevel_change(device,
- KGSL_PWRLEVEL_NOMINAL);
+ kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_NOMINAL);
+ device->pwrctrl.restore_slumber = true;
device->ftbl->suspend_context(device);
device->ftbl->stop(device);
- device->pwrctrl.restore_slumber = true;
_sleep_accounting(device);
kgsl_pwrctrl_set_state(device, KGSL_STATE_SLUMBER);
if (device->idle_wakelock.name)
wake_unlock(&device->idle_wakelock);
+ pm_qos_update_request(&device->pm_qos_req_dma,
+ PM_QOS_DEFAULT_VALUE);
break;
case KGSL_STATE_SLUMBER:
break;
@@ -869,9 +851,10 @@
/* Re-enable HW access */
mod_timer(&device->idle_timer,
jiffies + device->pwrctrl.interval_timeout);
-
- if (device->idle_wakelock.name)
- wake_lock(&device->idle_wakelock);
+ wake_lock(&device->idle_wakelock);
+ if (device->pwrctrl.restore_slumber == false)
+ pm_qos_update_request(&device->pm_qos_req_dma,
+ GPU_SWFI_LATENCY);
case KGSL_STATE_ACTIVE:
break;
default:
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 5e09b5b..f474c21 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -47,19 +47,15 @@
int thermal_pwrlevel;
unsigned int num_pwrlevels;
unsigned int interval_timeout;
- bool strtstp_sleepwake;
struct regulator *gpu_reg;
- struct regulator *gpu_dig;
uint32_t pcl;
unsigned int nap_allowed;
unsigned int idle_needed;
const char *regulator_name;
const char *irq_name;
- const char *src_clk_name;
s64 time;
struct kgsl_busy busy;
unsigned int restore_slumber;
- unsigned int pwr_rail;
};
void kgsl_pwrctrl_irq(struct kgsl_device *device, int state);
diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c
index 4c9a239..d0b2a41 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.c
+++ b/drivers/gpu/msm/kgsl_pwrscale.c
@@ -90,7 +90,7 @@
return ret;
}
-PWRSCALE_ATTR(policy, 0666, pwrscale_policy_show, pwrscale_policy_store);
+PWRSCALE_ATTR(policy, 0664, pwrscale_policy_show, pwrscale_policy_store);
static ssize_t pwrscale_avail_policies_show(struct kgsl_device *device,
char *buf)
diff --git a/drivers/gpu/msm/kgsl_pwrscale_idlestats.c b/drivers/gpu/msm/kgsl_pwrscale_idlestats.c
index 7c54936..2976b0b 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_idlestats.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_idlestats.c
@@ -89,7 +89,6 @@
struct kgsl_pwrscale *pwrscale)
{
struct idlestats_priv *priv = pwrscale->priv;
- struct kgsl_power_stats stats;
int i, busy, nr_cpu = 1;
if (priv->pulse.busy_start_time != 0) {
@@ -112,19 +111,6 @@
spin_unlock(&priv->cpu_info.lock);
}
priv->pulse.wait_interval /= nr_cpu;
-
- /* This is called from within a mutex protected function, so
- no additional locking required */
- device->ftbl->power_stats(device, &stats);
-
- /* If total_time is zero, then we don't have
- any interesting statistics to store */
- if (stats.total_time == 0) {
- priv->pulse.busy_start_time = 0;
- return;
- }
-
- priv->pulse.busy_interval = stats.busy_time;
msm_idle_stats_idle_end(&priv->idledev, &priv->pulse);
}
priv->pulse.busy_start_time = ktime_to_us(ktime_get());
@@ -134,8 +120,21 @@
struct kgsl_pwrscale *pwrscale)
{
int i, nr_cpu;
+ struct kgsl_power_stats stats;
struct idlestats_priv *priv = pwrscale->priv;
+ /* This is called from within a mutex protected function, so
+ no additional locking required */
+ device->ftbl->power_stats(device, &stats);
+
+ /* If total_time is zero, then we don't have
+ any interesting statistics to store */
+ if (stats.total_time == 0) {
+ priv->pulse.busy_start_time = 0;
+ return;
+ }
+
+ priv->pulse.busy_interval = stats.busy_time;
nr_cpu = num_possible_cpus();
for (i = 0; i < nr_cpu; i++)
if (cpu_online(i))
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index 5d2e787..bafb1c0 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -63,13 +63,6 @@
}
-/*
- * One page allocation for a guard region to protect against over-zealous
- * GPU pre-fetch
- */
-
-static struct page *kgsl_guard_page;
-
/**
* Given a kobj, find the process structure attached to it
*/
@@ -160,7 +153,7 @@
MEM_ENTRY_STAT(KGSL_MEM_ENTRY_USER, user),
#ifdef CONFIG_ION
MEM_ENTRY_STAT(KGSL_MEM_ENTRY_USER, ion),
-#endif
+#endif
};
void
@@ -210,10 +203,6 @@
val = kgsl_driver.stats.vmalloc;
else if (!strncmp(attr->attr.name, "vmalloc_max", 11))
val = kgsl_driver.stats.vmalloc_max;
- else if (!strncmp(attr->attr.name, "page_alloc", 10))
- val = kgsl_driver.stats.page_alloc;
- else if (!strncmp(attr->attr.name, "page_alloc_max", 14))
- val = kgsl_driver.stats.page_alloc_max;
else if (!strncmp(attr->attr.name, "coherent", 8))
val = kgsl_driver.stats.coherent;
else if (!strncmp(attr->attr.name, "coherent_max", 12))
@@ -243,8 +232,6 @@
DEVICE_ATTR(vmalloc, 0444, kgsl_drv_memstat_show, NULL);
DEVICE_ATTR(vmalloc_max, 0444, kgsl_drv_memstat_show, NULL);
-DEVICE_ATTR(page_alloc, 0444, kgsl_drv_memstat_show, NULL);
-DEVICE_ATTR(page_alloc_max, 0444, kgsl_drv_memstat_show, NULL);
DEVICE_ATTR(coherent, 0444, kgsl_drv_memstat_show, NULL);
DEVICE_ATTR(coherent_max, 0444, kgsl_drv_memstat_show, NULL);
DEVICE_ATTR(mapped, 0444, kgsl_drv_memstat_show, NULL);
@@ -254,8 +241,6 @@
static const struct device_attribute *drv_attr_list[] = {
&dev_attr_vmalloc,
&dev_attr_vmalloc_max,
- &dev_attr_page_alloc,
- &dev_attr_page_alloc_max,
&dev_attr_coherent,
&dev_attr_coherent_max,
&dev_attr_mapped,
@@ -310,7 +295,7 @@
}
#endif
-static int kgsl_page_alloc_vmfault(struct kgsl_memdesc *memdesc,
+static int kgsl_vmalloc_vmfault(struct kgsl_memdesc *memdesc,
struct vm_area_struct *vma,
struct vm_fault *vmf)
{
@@ -331,29 +316,20 @@
return 0;
}
-static int kgsl_page_alloc_vmflags(struct kgsl_memdesc *memdesc)
+static int kgsl_vmalloc_vmflags(struct kgsl_memdesc *memdesc)
{
return VM_RESERVED | VM_DONTEXPAND;
}
-static void kgsl_page_alloc_free(struct kgsl_memdesc *memdesc)
+static void kgsl_vmalloc_free(struct kgsl_memdesc *memdesc)
{
int i = 0;
struct scatterlist *sg;
- int sglen = memdesc->sglen;
-
- /* Don't free the guard page if it was used */
- if (memdesc->flags & KGSL_MEMDESC_GUARD_PAGE)
- sglen--;
-
- kgsl_driver.stats.page_alloc -= memdesc->size;
-
- if (memdesc->hostptr) {
+ kgsl_driver.stats.vmalloc -= memdesc->size;
+ if (memdesc->hostptr)
vunmap(memdesc->hostptr);
- kgsl_driver.stats.vmalloc -= memdesc->size;
- }
if (memdesc->sg)
- for_each_sg(memdesc->sg, sg, sglen, i)
+ for_each_sg(memdesc->sg, sg, memdesc->sglen, i)
__free_page(sg_page(sg));
}
@@ -363,39 +339,30 @@
}
/*
- * kgsl_page_alloc_map_kernel - Map the memory in memdesc to kernel address
- * space
+ * kgsl_vmalloc_map_kernel - Map the memory in memdesc to kernel address space
*
* @memdesc - The memory descriptor which contains information about the memory
*
* Return: 0 on success else error code
*/
-static int kgsl_page_alloc_map_kernel(struct kgsl_memdesc *memdesc)
+static int kgsl_vmalloc_map_kernel(struct kgsl_memdesc *memdesc)
{
if (!memdesc->hostptr) {
pgprot_t page_prot = pgprot_writecombine(PAGE_KERNEL);
struct page **pages = NULL;
struct scatterlist *sg;
- int sglen = memdesc->sglen;
int i;
-
- /* Don't map the guard page if it exists */
- if (memdesc->flags & KGSL_MEMDESC_GUARD_PAGE)
- sglen--;
-
/* create a list of pages to call vmap */
- pages = vmalloc(sglen * sizeof(struct page *));
+ pages = vmalloc(memdesc->sglen * sizeof(struct page *));
if (!pages) {
KGSL_CORE_ERR("vmalloc(%d) failed\n",
- sglen * sizeof(struct page *));
+ memdesc->sglen * sizeof(struct page *));
return -ENOMEM;
}
- for_each_sg(memdesc->sg, sg, sglen, i)
+ for_each_sg(memdesc->sg, sg, memdesc->sglen, i)
pages[i] = sg_page(sg);
- memdesc->hostptr = vmap(pages, sglen,
+ memdesc->hostptr = vmap(pages, memdesc->sglen,
VM_IOREMAP, page_prot);
- KGSL_STATS_ADD(memdesc->size, kgsl_driver.stats.vmalloc,
- kgsl_driver.stats.vmalloc_max);
vfree(pages);
}
if (!memdesc->hostptr)
@@ -443,13 +410,13 @@
}
/* Global - also used by kgsl_drm.c */
-struct kgsl_memdesc_ops kgsl_page_alloc_ops = {
- .free = kgsl_page_alloc_free,
- .vmflags = kgsl_page_alloc_vmflags,
- .vmfault = kgsl_page_alloc_vmfault,
- .map_kernel_mem = kgsl_page_alloc_map_kernel,
+struct kgsl_memdesc_ops kgsl_vmalloc_ops = {
+ .free = kgsl_vmalloc_free,
+ .vmflags = kgsl_vmalloc_vmflags,
+ .vmfault = kgsl_vmalloc_vmfault,
+ .map_kernel_mem = kgsl_vmalloc_map_kernel,
};
-EXPORT_SYMBOL(kgsl_page_alloc_ops);
+EXPORT_SYMBOL(kgsl_vmalloc_ops);
static struct kgsl_memdesc_ops kgsl_ebimem_ops = {
.free = kgsl_ebimem_free,
@@ -483,7 +450,7 @@
EXPORT_SYMBOL(kgsl_cache_range_op);
static int
-_kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc,
+_kgsl_sharedmem_vmalloc(struct kgsl_memdesc *memdesc,
struct kgsl_pagetable *pagetable,
size_t size, unsigned int protflags)
{
@@ -491,24 +458,14 @@
int sglen = PAGE_ALIGN(size) / PAGE_SIZE;
int i;
- /*
- * Add guard page to the end of the allocation when the
- * IOMMU is in use.
- */
-
- if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU)
- sglen++;
-
memdesc->size = size;
memdesc->pagetable = pagetable;
memdesc->priv = KGSL_MEMFLAGS_CACHED;
- memdesc->ops = &kgsl_page_alloc_ops;
+ memdesc->ops = &kgsl_vmalloc_ops;
memdesc->sg = kgsl_sg_alloc(sglen);
if (memdesc->sg == NULL) {
- KGSL_CORE_ERR("vmalloc(%d) failed\n",
- sglen * sizeof(struct scatterlist));
ret = -ENOMEM;
goto done;
}
@@ -518,7 +475,7 @@
memdesc->sglen = sglen;
sg_init_table(memdesc->sg, sglen);
- for (i = 0; i < PAGE_ALIGN(size) / PAGE_SIZE; i++) {
+ for (i = 0; i < memdesc->sglen; i++) {
struct page *page = alloc_page(GFP_KERNEL | __GFP_ZERO |
__GFP_HIGHMEM);
if (!page) {
@@ -529,22 +486,6 @@
flush_dcache_page(page);
sg_set_page(&memdesc->sg[i], page, PAGE_SIZE, 0);
}
-
- /* ADd the guard page to the end of the sglist */
-
- if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU) {
- if (kgsl_guard_page == NULL)
- kgsl_guard_page = alloc_page(GFP_KERNEL | __GFP_ZERO |
- __GFP_HIGHMEM);
-
- if (kgsl_guard_page != NULL) {
- sg_set_page(&memdesc->sg[sglen - 1], kgsl_guard_page,
- PAGE_SIZE, 0);
- memdesc->flags |= KGSL_MEMDESC_GUARD_PAGE;
- } else
- memdesc->sglen--;
- }
-
outer_cache_range_op_sg(memdesc->sg, memdesc->sglen,
KGSL_CACHE_OP_FLUSH);
@@ -553,8 +494,8 @@
if (ret)
goto done;
- KGSL_STATS_ADD(size, kgsl_driver.stats.page_alloc,
- kgsl_driver.stats.page_alloc_max);
+ KGSL_STATS_ADD(size, kgsl_driver.stats.vmalloc,
+ kgsl_driver.stats.vmalloc_max);
order = get_order(size);
@@ -569,7 +510,7 @@
}
int
-kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc,
+kgsl_sharedmem_vmalloc(struct kgsl_memdesc *memdesc,
struct kgsl_pagetable *pagetable, size_t size)
{
int ret = 0;
@@ -577,18 +518,18 @@
size = ALIGN(size, PAGE_SIZE * 2);
- ret = _kgsl_sharedmem_page_alloc(memdesc, pagetable, size,
+ ret = _kgsl_sharedmem_vmalloc(memdesc, pagetable, size,
GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
if (!ret)
- ret = kgsl_page_alloc_map_kernel(memdesc);
+ ret = kgsl_vmalloc_map_kernel(memdesc);
if (ret)
kgsl_sharedmem_free(memdesc);
return ret;
}
-EXPORT_SYMBOL(kgsl_sharedmem_page_alloc);
+EXPORT_SYMBOL(kgsl_sharedmem_vmalloc);
int
-kgsl_sharedmem_page_alloc_user(struct kgsl_memdesc *memdesc,
+kgsl_sharedmem_vmalloc_user(struct kgsl_memdesc *memdesc,
struct kgsl_pagetable *pagetable,
size_t size, int flags)
{
@@ -600,10 +541,10 @@
if (!(flags & KGSL_MEMFLAGS_GPUREADONLY))
protflags |= GSL_PT_PAGE_WV;
- return _kgsl_sharedmem_page_alloc(memdesc, pagetable, size,
+ return _kgsl_sharedmem_vmalloc(memdesc, pagetable, size,
protflags);
}
-EXPORT_SYMBOL(kgsl_sharedmem_page_alloc_user);
+EXPORT_SYMBOL(kgsl_sharedmem_vmalloc_user);
int
kgsl_sharedmem_alloc_coherent(struct kgsl_memdesc *memdesc, size_t size)
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index a67d9c6..9f8ac08 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -30,12 +30,12 @@
/** Set if the memdesc describes cached memory */
#define KGSL_MEMFLAGS_CACHED 0x00000001
-extern struct kgsl_memdesc_ops kgsl_page_alloc_ops;
+extern struct kgsl_memdesc_ops kgsl_vmalloc_ops;
-int kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc,
+int kgsl_sharedmem_vmalloc(struct kgsl_memdesc *memdesc,
struct kgsl_pagetable *pagetable, size_t size);
-int kgsl_sharedmem_page_alloc_user(struct kgsl_memdesc *memdesc,
+int kgsl_sharedmem_vmalloc_user(struct kgsl_memdesc *memdesc,
struct kgsl_pagetable *pagetable,
size_t size, int flags);
@@ -132,7 +132,7 @@
{
if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_NONE)
return kgsl_sharedmem_ebimem(memdesc, pagetable, size);
- return kgsl_sharedmem_page_alloc(memdesc, pagetable, size);
+ return kgsl_sharedmem_vmalloc(memdesc, pagetable, size);
}
static inline int
@@ -143,7 +143,7 @@
if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_NONE)
return kgsl_sharedmem_ebimem_user(memdesc, pagetable, size,
flags);
- return kgsl_sharedmem_page_alloc_user(memdesc, pagetable, size, flags);
+ return kgsl_sharedmem_vmalloc_user(memdesc, pagetable, size, flags);
}
static inline int
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index b07a462..394bc83 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -258,7 +258,7 @@
header->magic = SNAPSHOT_MAGIC;
- header->gpuid = kgsl_gpuid(device, NULL);
+ header->gpuid = kgsl_gpuid(device);
/* Get a pointer to the first section (right after the header) */
snapshot = ((void *) device->snapshot) + sizeof(*header);
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index ae83c1d..1b1ca0b 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -12,8 +12,6 @@
*/
#include <linux/uaccess.h>
-#include <mach/internal_power_rail.h>
-
#include "kgsl.h"
#include "kgsl_cffdump.h"
#include "kgsl_sharedmem.h"
@@ -153,7 +151,6 @@
.pwrctrl = {
.regulator_name = "fs_gfx2d0",
.irq_name = KGSL_2D0_IRQ,
- .pwr_rail = PWR_RAIL_GRP_2D_CLK,
},
.mutex = __MUTEX_INITIALIZER(device_2d0.dev.mutex),
.state = KGSL_STATE_INIT,
@@ -446,12 +443,13 @@
(ctrl & KGSL_CONTEXT_CTX_SWITCH)) {
KGSL_CMD_INFO(device, "context switch %d -> %d\n",
context->id, z180_dev->ringbuffer.prevctx);
- kgsl_mmu_setstate(device, pagetable);
+ kgsl_mmu_setstate(device, pagetable,
+ 0);
cnt = PACKETSIZE_STATESTREAM;
ofs = 0;
}
- kgsl_setstate(device, kgsl_mmu_pt_get_flags(device->mmu.hwpagetable,
- device->id));
+ kgsl_setstate(device, 0, kgsl_mmu_pt_get_flags(device->mmu.hwpagetable,
+ device->id));
result = wait_event_interruptible_timeout(device->wait_queue,
room_in_rb(z180_dev),
@@ -866,7 +864,8 @@
if (z180_dev->ringbuffer.prevctx == context->id) {
z180_dev->ringbuffer.prevctx = Z180_INVALID_CONTEXT;
device->mmu.hwpagetable = device->mmu.defaultpagetable;
- kgsl_setstate(device, KGSL_MMUFLAGS_PTUPDATE);
+ kgsl_setstate(device, 0,
+ KGSL_MMUFLAGS_PTUPDATE);
}
}
@@ -901,11 +900,8 @@
}
}
-static unsigned int z180_gpuid(struct kgsl_device *device, unsigned int *chipid)
+static unsigned int z180_gpuid(struct kgsl_device *device)
{
- if (chipid != NULL)
- *chipid = 0;
-
/* Standard KGSL gpuid format:
* top word is 0x0002 for 2D or 0x0003 for 3D
* Bottom word is core specific identifer
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index d3870fe..1aa9393 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -1,100 +1,821 @@
+
+source "drivers/video/msm/vidc/Kconfig"
+
config FB_MSM
- tristate
+ 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
- default y
+ ---help---
+ Support for MSM Framebuffer.
-config FB_MSM_LEGACY_MDP
+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
- depends on FB_MSM && (MSM_MDP30 || MSM_MDP31 || MSM_MDP302)
- default y
-
-config FB_MSM_MDP_PPP
- bool
- depends on FB_MSM_LEGACY_MDP
- default y
-
-config FB_MSM_LCDC
- bool "Support for integrated LCD controller in qsd8x50 ,MSM7x27 and MSM7x30"
- depends on FB_MSM && (MSM_MDP31 || MSM_MDP302 || MSM_MDP40)
- default y
-
-config FB_MSM_DTV
- bool "Support for TV-Out in qsd8x50"
- depends on FB_MSM && MSM_MDP40
default n
-config FB_MSM_TVOUT
- bool "Support for TV-Out in qsd8x50"
- depends on FB_MSM && (MSM_MDP31 || MSM_MDP40)
+config FB_MSM_TRIPLE_BUFFER
+ bool "Support for triple frame buffer"
+ default n
+
+config FB_MSM_MDP_HW
+ bool
+ default n
+
+choice
+ prompt "MDP HW version"
+ default FB_MSM_MDP22
+
+config FB_MSM_MDP22
+ select FB_MSM_MDP_HW
+ 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
+ select FB_MSM_MDP_HW
+ 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
+ select FB_MSM_MDP_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
+ select FB_MSM_MDP_HW
+ bool "MDP HW ver4.0"
+ ---help---
+ Support for MSM MDP HW revision 4.0
+ Say Y here if this is msm7x30 variant platform.
+
+config FB_MSM_MDP_NONE
+ bool "MDP HW None"
+ ---help---
+ Say Y here if this is mdm 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
- bool "Support for overlay in MSM7X30"
- depends on FB_MSM && MSM_MDP40
- default y
+ 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_MDP_ABL
- bool "Support QCT auto backlight scaling"
- depends on FB_MSM && (MSM_MDP40)
+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_TRULY
+ bool
+ select FB_MSM_MIPI_DSI
+
+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 MSM_ROTATOR
- tristate "MSM Offline Image Rotator Driver"
- depends on ARCH_MSM7X30 && ANDROID_PMEM
+config FB_MSM_MIPI_DSI_ORISE
+ bool
+ select FB_MSM_MIPI_DSI
+ default n
+
+config FB_MSM_MIPI_DSI_TC358764_DSI2LVDS
+ bool
+ select FB_MSM_MIPI_DSI
+ ---help---
+ Support for Toshiba MIPI DSI-to-LVDS bridge.
+ The chip supports 1366x768 24-bit
+ using a single LVDS link
+ and up to WUXGA 1920x1200 18-bit
+ using a dual LVDS link.
+
+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_NT35582_WVGA
+ 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_TOSHIBA_VIDEO_WUXGA
+ 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_ORISE_VIDEO_720P_PT
+ bool
+ select FB_MSM_MIPI_DSI_ORISE
+ default n
+
+config FB_MSM_MIPI_ORISE_CMD_720P_PT
+ bool
+ select FB_MSM_MIPI_DSI_ORISE
+ 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_CHIMEI_WXGA
+ bool "LVDS Chimei WXGA Panel using Toshiba MIPI DSI-to-LVDS bridge."
+ select FB_MSM_MIPI_DSI_TC358764_DSI2LVDS
+ ---help---
+ Support for Chimei WXGA (1366x768) panel.
+ The panel is using a serial LVDS input.
+ The panel is connected to the host
+ via Toshiba DSI-to-LVDS bridge.
+
+config FB_MSM_MIPI_CHIMEI_WUXGA
+ bool "LVDS Chimei WUXGA Panel using Toshiba MIPI DSI-to-LVDS bridge."
+ select FB_MSM_MIPI_DSI_TC358764_DSI2LVDS
+ ---help---
+ Support for Chimei WUXGA (1920x1200) panel.
+ The panel is using a serial LVDS input.
+ The panel is connected to the host
+ via Toshiba DSI-to-LVDS bridge.
+
+config FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT
+ bool
+ select FB_MSM_MIPI_DSI_TRULY
+
+config FB_MSM_MIPI_SIMULATOR_VIDEO
+ bool
+ select FB_MSM_MIPI_DSI_SIMULATOR
+ default n
+
+config FB_MSM_NO_MDP_PIPE_CTRL
+ depends on FB_MSM_OVERLAY
+ bool "Do not use mdp_pipe_ctrl"
+ ---help---
+ Saying 'Y' here obsoletes the mdp_pipe_ctrl function,
+ which was used to control mdp-related clocks. MDP4 vsync-driven
+ screen updates will use a different clock control mechanism if
+ this is selected.
+
+config FB_MSM_OVERLAY0_WRITEBACK
+ depends on FB_MSM_OVERLAY
+ bool "MDP overlay0 write back mode enable"
+ ---help---
+ Support for MDP4 OVERLAY0 write back mode
+
+
+config FB_MSM_OVERLAY1_WRITEBACK
+ depends on FB_MSM_OVERLAY
+ bool "MDP overlay1 write back mode enable"
+ ---help---
+ Support for MDP4 OVERLAY1 write back mode
+
+config FB_MSM_WRITEBACK_MSM_PANEL
+ depends on FB_MSM_OVERLAY
+ bool "MDP overlay write back panel 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_NT35582_PANEL
+ depends on FB_MSM_LCDC_HW
+ bool "LCDC NT35582 WVGA Panel"
+ select FB_MSM_LCDC_NT35582_WVGA
+ ---help---
+ Support for LCDC NT35582 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
+ bool "MIPI Panel Detect"
+ select FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT
+ select FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT
+ select FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA
+ select FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT
+ select FB_MSM_MIPI_RENESAS_CMD_FWVGA_PT
+ select FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT
+ select FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT
+ select FB_MSM_MIPI_NOVATEK_CMD_QHD_PT
+ select FB_MSM_MIPI_ORISE_VIDEO_720P_PT
+ select FB_MSM_MIPI_ORISE_CMD_720P_PT
+ select FB_MSM_MIPI_SIMULATOR_VIDEO
+ select FB_MSM_MIPI_CHIMEI_WXGA
+ select FB_MSM_MIPI_CHIMEI_WUXGA
+ ---help---
+ Support for MIPI panel auto detect
+
+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_NT35582_WVGA
+ select FB_MSM_LCDC_SAMSUNG_OLED_PT
+ ---help---
+ Support for LCDC panel auto detect
+
+config FB_MSM_LCDC_MIPI_PANEL_AUTO_DETECT
+ bool "LCDC + MIPI 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
+ select FB_MSM_LCDC_NT35582_WVGA
+ select FB_MSM_LCDC_TOSHIBA_FWVGA_PT
+ select FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT
+ select FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT
+ select FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT
+ select FB_MSM_MIPI_RENESAS_CMD_FWVGA_PT
+ select FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT
+ select FB_MSM_MIPI_NOVATEK_CMD_QHD_PT
+ select FB_MSM_MIPI_SIMULATOR_VIDEO
+ ---help---
+ Support for LCDC + MIPI 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_TOSHIBA_VIDEO_WUXGA_PANEL
+ bool "MIPI Toshiba WUXGA (1920x1200) Panel"
+ select FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA
+
+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_ORISE_VIDEO_720P_PT_PANEL
+ bool "MIPI ORISE VIDEO 720P PT Panel"
+ select FB_MSM_MIPI_ORISE_VIDEO_720P_PT
+
+config FB_MSM_MIPI_ORISE_CMD_720P_PT_PANEL
+ bool "MIPI ORISE CMD 720P PT Panel"
+ select FB_MSM_MIPI_ORISE_CMD_720P_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_CHIMEI_WXGA_PANEL
+ bool "MIPI Chimei WXGA PT Panel"
+ select FB_MSM_MIPI_CHIMEI_WXGA
+
+config FB_MSM_MIPI_CHIMEI_WUXGA_PANEL
+ bool "MIPI Chimei WUXGA Panel"
+ select FB_MSM_MIPI_CHIMEI_WUXGA
+
+config FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT_PANEL
+ bool "MIPI Truly Video WVGA PT Panel"
+ select FB_MSM_MIPI_TRULY_VIDEO_WVGA_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_HDMI_AS_PRIMARY
+ depends on FB_MSM_HDMI_COMMON
+ bool "Use HDMI as primary panel"
+ ---help---
+ Support for using HDMI as primary
+
+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
- This driver provides support for the image rotator HW block in the
- MSM 7x30 SoC.
+ ---help---
+ Support for HDCP mode for ADV7520 HDMI 720p Panel
+ Choose to enable HDCP
-config MSM_ROTATOR_USE_IMEM
- bool "Enable rotator driver to use iMem"
- depends on MSM_ROTATOR
- default y
- help
- This option enables the msm_rotator driver to use the move efficient
- iMem. Some MSM platforms may not have iMem available for the rotator
- block. Or some systems may want the iMem to be dedicated to a
- different function.
-config MSM_HDMI_COMMON
- bool "Turn on HDMI common interface"
- depends on FB_MSM_OVERLAY && MSM_MDP40
- bool
+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 MSM_HDMI
- bool "Support for HDMI in QCT platform"
- depends on MSM_MDP31 || MSM_MDP40
+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 MSM_HDMI_MHL
- bool "Turn on MHL chip driver"
- depends on FB_MSM_OVERLAY && MSM_MDP40
- bool
+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
+
+config FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+ depends on FB_MSM_HDMI_MSM_PANEL
+ bool "Enable CEC"
default n
+ ---help---
+ Support for HDMI CEC Feature
+ Choose to enable CEC
-config MSM_HDMI_MHL_SII9232
- bool "support sii9232 driver"
- depends on MSM_HDMI_MHL && MSM_MDP40
- bool
+config FB_MSM_HDMI_MHL
+ depends on FB_MSM_HDMI_MSM_PANEL
+ bool 'HDMI to MHL support'
default n
+ ---help---
+ Support the HDMI to MHL conversion.
+ MHL (Mobile High-Definition Link) technology
+ uses USB connector to output HDMI content
-config MDP_UNDERRUN_WORKAROUND_DISABLED
- bool "Disable MDP workaround"
- depends on FB_MSM
+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.
-config MDP4_HW_VSYNC
- bool "QCT hardware TE"
- depends on MSM_MDP40
+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 || FB_MSM_MDP303
+ 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
+
+config FB_MSM_EBI2_EPSON_S1D_QVGA_PANEL
+ bool "EBI2 Epson QVGA Panel"
+ select FB_MSM_EBI2
default n
+ ---help---
+ Support for EBI2 Epson QVGA (240x320) panel
-source "drivers/video/msm/vidc/Kconfig"
+config FB_MSM_EBI2_PANEL_DETECT
+ bool "EBI2 Panel Detect"
+ select FB_MSM_EBI2_EPSON_S1D_QVGA_PANEL
+ default n
+ ---help---
+ Support for EBI2 panel auto detect
+endif
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
index bf8b1cd..f3fe161 100644
--- a/drivers/video/msm/Makefile
+++ b/drivers/video/msm/Makefile
@@ -1,45 +1,176 @@
+obj-y := msm_fb.o
-# core framebuffer
-#
-obj-y := msm_fb.o logo.o
-ifeq ($(CONFIG_FB_MSM_LOGO),y)
-obj-y += logo.o
-endif
+obj-$(CONFIG_FB_MSM_LOGO) += logo.o
+obj-$(CONFIG_FB_BACKLIGHT) += msm_fb_bl.o
-# MDP DMA/PPP engine
-#
+ifeq ($(CONFIG_FB_MSM_MDP_HW),y)
+
+# MDP
obj-y += mdp.o
-obj-$(CONFIG_FB_MSM_OVERLAY) += mdp4_util.o
-obj-$(CONFIG_FB_MSM_OVERLAY) += mdp4_overlay.o
-obj-$(CONFIG_FB_MSM_OVERLAY) += mdp4_overlay_mddi.o
-obj-$(CONFIG_FB_MSM_LEGACY_MDP) += mdp_hw_legacy.o
+obj-$(CONFIG_DEBUG_FS) += mdp_debugfs.o
-obj-$(CONFIG_FB_MSM_MDP_PPP) += mdp_ppp.o
-obj-$(CONFIG_MSM_MDP22) += mdp_ppp22.o
-obj-$(CONFIG_MSM_MDP30) += mdp_ppp22.o
-obj-$(CONFIG_MSM_MDP302)+= mdp_ppp22.o
-obj-$(CONFIG_MSM_MDP31) += mdp_ppp31.o
-
-# MDDI interface
-#
-obj-y += mddi.o
-
-# MDDI client/panel drivers
-#
-ifdef CONFIG_ARCH_MSM7X30
-obj-y += mddi_client_dummy.o
-obj-y += mddi_client_toshiba.o
-obj-y += mddi_client_novb9f6_5580.o
-obj-y += mddi_client_novb9f6_5560.o
-obj-y += mddi_client_renesas_R61408.o
-obj-y += mddi_client_hx8356.o mddi_himax_cabc.o
+ifeq ($(CONFIG_FB_MSM_MDP40),y)
+obj-y += mdp4_util.o
+obj-y += mdp4_hsic.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
-# MDP LCD controller driver
-obj-$(CONFIG_FB_MSM_LCDC) += mdp_lcdc.o
-obj-$(CONFIG_FB_MSM_DTV) += mdp_dtv.o
-obj-$(CONFIG_FB_MSM_TVOUT) += tvenc.o tvfb.o
+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_ORISE) += mipi_orise.o
+obj-$(CONFIG_FB_MSM_MIPI_DSI_RENESAS) += mipi_renesas.o
+obj-$(CONFIG_FB_MSM_MIPI_DSI_TRULY) += mipi_truly.o
+obj-$(CONFIG_FB_MSM_MIPI_DSI_SIMULATOR) += mipi_simulator.o
+
+# MIPI Bridge
+obj-$(CONFIG_FB_MSM_MIPI_DSI_TC358764_DSI2LVDS) += mipi_tc358764_dsi2lvds.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 mipi_toshiba_video_wuxga.o
+obj-y += mipi_novatek_video_qhd_pt.o mipi_novatek_cmd_qhd_pt.o
+obj-y += mipi_orise_video_720p_pt.o mipi_orise_cmd_720p_pt.o
+obj-y += mipi_renesas_video_fwvga_pt.o mipi_renesas_cmd_fwvga_pt.o
+obj-y += mipi_chimei_wxga_pt.o
+obj-y += mipi_chimei_wuxga.o
+obj-y += mipi_truly_video_wvga_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_TOSHIBA_VIDEO_WUXGA) += mipi_toshiba_video_wuxga.o
+obj-$(CONFIG_FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT) += mipi_novatek_video_qhd_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_ORISE_VIDEO_720P_PT) += mipi_orise_video_720p_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_ORISE_CMD_720P_PT) += mipi_orise_cmd_720p_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_TRULY_VIDEO_WVGA_PT) += mipi_truly_video_wvga_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_SIMULATOR_VIDEO) += mipi_simulator_video.o
+obj-$(CONFIG_FB_MSM_MIPI_CHIMEI_WXGA) += mipi_chimei_wxga_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_CHIMEI_WUXGA) += mipi_chimei_wuxga.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_NT35582_WVGA) += lcdc_nt35582_wvga.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_FB_MSM_WRITEBACK_MSM_PANEL) += mdp4_wfd_writeback_panel.o
+obj-$(CONFIG_FB_MSM_WRITEBACK_MSM_PANEL) += mdp4_wfd_writeback.o
+obj-$(CONFIG_FB_MSM_WRITEBACK_MSM_PANEL) += mdp4_overlay_writeback.o
+
+obj-$(CONFIG_MSM_VIDC_1080P) += vidc/
obj-$(CONFIG_MSM_VIDC_720P) += vidc/
+else
+obj-$(CONFIG_FB_MSM_EBI2) += ebi2_host.o
+obj-$(CONFIG_FB_MSM_EBI2) += ebi2_lcd.o
+obj-y += msm_fb_panel.o
+obj-$(CONFIG_FB_MSM_EBI2_EPSON_S1D_QVGA_PANEL) += ebi2_epson_s1d_qvga.o
+endif
+clean:
+ rm *.o .*cmd
diff --git a/drivers/video/msm/adv7520.c b/drivers/video/msm/adv7520.c
new file mode 100644
index 0000000..c0fb370
--- /dev/null
+++ b/drivers/video/msm/adv7520.c
@@ -0,0 +1,1029 @@
+/* Copyright (c) 2010,2012, 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 <linux/clk.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 struct clk *tv_enc_clk;
+
+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);
+ switch_set_state(&external_common_state->sdev, 1);
+ } else {
+ kobject_uevent(external_common_state->uevent_kobj,
+ KOBJ_OFFLINE);
+ switch_set_state(&external_common_state->sdev, 0);
+ }
+ 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);
+
+ clk_prepare_enable(tv_enc_clk);
+ 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);
+ clk_disable_unprepare(tv_enc_clk);
+ 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");
+
+ if (hdmi_prim_display)
+ external_common_state->sdev.name = "hdmi_as_primary";
+ else
+ external_common_state->sdev.name = "hdmi";
+
+ if (switch_dev_register(&external_common_state->sdev) < 0)
+ DEV_ERR("Hdmi switch registration failed\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;
+ }
+ switch_dev_unregister(&external_common_state->sdev);
+ 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;
+
+ tv_enc_clk = clk_get(NULL, "tv_enc_clk");
+ if (IS_ERR(tv_enc_clk)) {
+ printk(KERN_ERR "error: can't get tv_enc_clk!\n");
+ return IS_ERR(tv_enc_clk);
+ }
+
+ 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:
+ if (tv_enc_clk)
+ clk_put(tv_enc_clk);
+ 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_epson_s1d_qvga.c b/drivers/video/msm/ebi2_epson_s1d_qvga.c
new file mode 100644
index 0000000..8821eab
--- /dev/null
+++ b/drivers/video/msm/ebi2_epson_s1d_qvga.c
@@ -0,0 +1,374 @@
+/* Copyright (c) 2012, 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 CMD_NOP_C 0x00
+#define CMD_SOFT_RESET_C 0x99
+#define CMD_DISPLAY_ON_C 0xAF
+#define CMD_DISPLAY_OFF_C 0xAE
+#define CMD_SET_DISPLAY_C 0xCA
+#define CMD_SET_DISPLAY_TIMING_C 0xA1
+#define CMD_SET_DATA_C 0xBC
+#define CMD_SET_START_ADDRESS_C 0x15
+#define CMD_SET_END_ADDRESS_C 0x75
+#define CMD_RAM_WRITE_C 0x5C
+#define CMD_RAM_READ_C 0x5D
+#define CMD_SET_AREA_SCROLLING_C 0xAA
+#define CMD_SET_DISPLAY_START_LINE_C 0xAB
+#define CMD_PARTIAL_DISPLAY_IN_C 0xA8
+#define CMD_PARTIAL_DISPLAY_OUT_C 0xA9
+#define CMD_SET_DISPLAY_DATA_INTERFACE_C 0x31
+#define CMD_SET_DISPLAY_COLOR_MODE_C 0x8B
+#define CMD_SELECT_MTP_ROM_MODE_C 0x65
+#define CMD_MTP_ROM_MODE_IN_C 0x67
+#define CMD_MTP_ROM_MODE_OUT_C 0x68
+#define CMD_MTP_ROM_OPERATION_IN_C 0x69
+#define CMD_MTP_ROM_OPERATION_OUT_C 0x70
+#define CMD_GATE_LINE_SCAN_MODE_C 0x6F
+#define CMD_SET_AC_OPERATION_DRIVE_C 0x8C
+#define CMD_SET_ELECTRONIC_CONTROL_C 0x20
+#define CMD_SET_POSITIVE_CORRECTION_CHARS_C 0x22
+#define CMD_SET_NEGATIVE_CORRECTION_CHARS_C 0x25
+#define CMD_SET_POWER_CONTROL_C 0x21
+#define CMD_SET_PARTIAL_POWER_CONTROL_C 0x23
+#define CMD_SET_8_COLOR_CONTROL_C 0x24
+#define CMD_SLEEP_IN_C 0x95
+#define CMD_SLEEP_OUT_C 0x94
+#define CMD_VDD_OFF_C 0x97
+#define CMD_VDD_ON_C 0x96
+#define CMD_STOP_OSCILLATION_C 0x93
+#define CMD_START_OSCILLATION_C 0x92
+#define CMD_TEST_SOURCE_C 0xFD
+#define CMD_TEST_FUSE_C 0xFE
+#define CMD_TEST_C 0xFF
+#define CMD_STATUS_READ_C 0xE8
+#define CMD_REVISION_READ_C 0xE9
+
+#define PANEL_WIDTH 240
+#define PANEL_HEIGHT 320
+#define ACTIVE_WIN_WIDTH PANEL_WIDTH
+#define ACTIVE_WIN_HEIGHT PANEL_HEIGHT
+
+#define ACTIVE_WIN_H_START 0
+#define ACTIVE_WIN_V_START 0
+
+#define DISP_CMD_OUT(cmd) outpw(DISP_CMD_PORT, (cmd << 1));
+#define DISP_DATA_OUT(data) outpw(DISP_DATA_PORT, (data << 1));
+#define DISP_DATA_IN() inpw(DISP_DATA_PORT);
+
+static void *DISP_CMD_PORT;
+static void *DISP_DATA_PORT;
+static boolean disp_initialized;
+static boolean display_on;
+static struct msm_panel_common_pdata *ebi2_epson_pdata;
+
+static void epson_s1d_disp_init(struct platform_device *pdev);
+static int epson_s1d_disp_off(struct platform_device *pdev);
+static int epson_s1d_disp_on(struct platform_device *pdev);
+static void epson_s1d_disp_set_rect(int x, int y, int xres, int yres);
+
+static void epson_s1d_disp_set_rect(int x, int y, int xres, int yres)
+{
+ int right, bottom;
+
+ if (!disp_initialized)
+ return;
+
+ right = x + xres - 1;
+ bottom = y + yres - 1;
+
+ x += ACTIVE_WIN_H_START;
+ y += ACTIVE_WIN_V_START;
+ right += ACTIVE_WIN_H_START;
+ bottom += ACTIVE_WIN_V_START;
+
+ if ((PANEL_WIDTH > x) &&
+ (PANEL_HEIGHT > y) &&
+ (PANEL_WIDTH > right) &&
+ (PANEL_HEIGHT > bottom)) {
+ DISP_CMD_OUT(CMD_SET_START_ADDRESS_C);
+ DISP_DATA_OUT((uint8)x);
+ DISP_DATA_OUT((uint8)(y>>8));
+ DISP_DATA_OUT((uint8)y);
+
+ DISP_CMD_OUT(CMD_SET_END_ADDRESS_C);
+ DISP_DATA_OUT((uint8)right);
+ DISP_DATA_OUT((uint8)(bottom>>8));
+ DISP_DATA_OUT((uint8)bottom);
+ DISP_CMD_OUT(CMD_RAM_WRITE_C);
+ }
+}
+
+static void epson_s1d_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;
+
+ disp_initialized = TRUE;
+}
+
+static int epson_s1d_disp_off(struct platform_device *pdev)
+{
+ if (!disp_initialized)
+ epson_s1d_disp_init(pdev);
+
+ if (display_on) {
+ DISP_CMD_OUT(CMD_SOFT_RESET_C);
+ DISP_CMD_OUT(CMD_VDD_OFF_C);
+ display_on = FALSE;
+ }
+
+ return 0;
+}
+
+static int epson_s1d_disp_on(struct platform_device *pdev)
+{
+ int i;
+ if (!disp_initialized)
+ epson_s1d_disp_init(pdev);
+
+ if (!display_on) {
+ /* Enable Vdd regulator */
+ DISP_CMD_OUT(CMD_VDD_ON_C);
+ msleep(20);
+
+ /* Soft Reset before configuring display */
+ DISP_CMD_OUT(CMD_SOFT_RESET_C);
+ msleep(20);
+
+ /* Set display attributes */
+
+ /* GATESCAN */
+ DISP_CMD_OUT(CMD_GATE_LINE_SCAN_MODE_C);
+ DISP_DATA_OUT(0x0);
+
+ /* DISSET */
+ DISP_CMD_OUT(CMD_SET_DISPLAY_C);
+ DISP_DATA_OUT(0x31);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT((uint8)((PANEL_HEIGHT - 1)>>8));
+ DISP_DATA_OUT((uint8)(PANEL_HEIGHT - 1));
+ DISP_DATA_OUT(0x03);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x08);
+
+ /* VOLSET */
+ DISP_CMD_OUT(
+ CMD_SET_ELECTRONIC_CONTROL_C);
+ DISP_DATA_OUT(0x10);
+ DISP_DATA_OUT(0x80);
+ DISP_DATA_OUT(0x11);
+ DISP_DATA_OUT(0x1B);
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x0D);
+ DISP_DATA_OUT(0x00);
+
+ /* PWRCTL */
+ DISP_CMD_OUT(CMD_SET_POWER_CONTROL_C);
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x24);
+ DISP_DATA_OUT(0x0F);
+ DISP_DATA_OUT(0xFE);
+ DISP_DATA_OUT(0x33);
+ DISP_DATA_OUT(0x31);
+ DISP_DATA_OUT(0xFF);
+ DISP_DATA_OUT(0x03);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x77);
+ DISP_DATA_OUT(0x33);
+ DISP_DATA_OUT(0x11);
+ DISP_DATA_OUT(0x44);
+ DISP_DATA_OUT(0x00);
+
+ /* PPWRCTL */
+ DISP_CMD_OUT(CMD_SET_PARTIAL_POWER_CONTROL_C);
+ DISP_DATA_OUT(0x33);
+ DISP_DATA_OUT(0xFF);
+ DISP_DATA_OUT(0x03);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x44);
+ DISP_DATA_OUT(0x00);
+
+ /* SPLOUT */
+ DISP_CMD_OUT(CMD_SLEEP_OUT_C);
+ msleep(100);
+
+ /* DATSET */
+ DISP_CMD_OUT(CMD_SET_DATA_C);
+ DISP_DATA_OUT(0x00);
+
+ /* DISTMEMSET */
+ DISP_CMD_OUT(CMD_SET_DISPLAY_TIMING_C);
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x2E);
+ DISP_DATA_OUT(0x0A);
+ DISP_DATA_OUT(0x2C);
+ DISP_DATA_OUT(0x23);
+ DISP_DATA_OUT(0x2F);
+ DISP_DATA_OUT(0x00);
+
+ /* GAMSETP */
+ DISP_CMD_OUT(CMD_SET_POSITIVE_CORRECTION_CHARS_C);
+ DISP_DATA_OUT(0x37);
+ DISP_DATA_OUT(0xFF);
+ DISP_DATA_OUT(0x7F);
+ DISP_DATA_OUT(0x15);
+ DISP_DATA_OUT(0x37);
+ DISP_DATA_OUT(0x05);
+
+ /* GAMSETN */
+ DISP_CMD_OUT(CMD_SET_NEGATIVE_CORRECTION_CHARS_C);
+ DISP_DATA_OUT(0x37);
+ DISP_DATA_OUT(0xFF);
+ DISP_DATA_OUT(0x7F);
+ DISP_DATA_OUT(0x15);
+ DISP_DATA_OUT(0x37);
+ DISP_DATA_OUT(0x05);
+
+ /* ACDRIVE */
+ DISP_CMD_OUT(CMD_SET_AC_OPERATION_DRIVE_C);
+ DISP_DATA_OUT(0x00);
+
+ /* TEST */
+ DISP_CMD_OUT(CMD_TEST_C);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x01);
+
+ /* COLMOD */
+ DISP_CMD_OUT(CMD_SET_DISPLAY_COLOR_MODE_C);
+ DISP_DATA_OUT(0x00);
+
+ /* STADDSET */
+ DISP_CMD_OUT(CMD_SET_START_ADDRESS_C);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x00);
+
+ /* EDADDSET */
+ DISP_CMD_OUT(CMD_SET_END_ADDRESS_C);
+ DISP_DATA_OUT(0xEF);
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x3F);
+
+ /* Set Display Start Line */
+ DISP_CMD_OUT(CMD_SET_DISPLAY_START_LINE_C);
+ DISP_DATA_OUT(0x00);
+
+ /* Set Display Data Interface */
+ DISP_CMD_OUT(CMD_SET_DISPLAY_DATA_INTERFACE_C);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x04);
+
+ epson_s1d_disp_set_rect(0,
+ 0,
+ ACTIVE_WIN_WIDTH,
+ ACTIVE_WIN_HEIGHT);
+
+ for (i = 0; i < (ACTIVE_WIN_WIDTH * ACTIVE_WIN_HEIGHT); i++)
+ outpdw(DISP_DATA_PORT, 0);
+
+ /* DISON */
+ DISP_CMD_OUT(CMD_DISPLAY_ON_C);
+ msleep(60);
+
+ display_on = TRUE;
+ }
+
+ return 0;
+}
+
+static int epson_s1d_probe(struct platform_device *pdev)
+{
+ if (pdev->id == 0) {
+ ebi2_epson_pdata = pdev->dev.platform_data;
+ return 0;
+ }
+
+ msm_fb_add_device(pdev);
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = epson_s1d_probe,
+ .driver = {
+ .name = "ebi2_epson_s1d_qvga",
+ },
+};
+
+static struct msm_fb_panel_data epson_s1d_panel_data = {
+ .on = epson_s1d_disp_on,
+ .off = epson_s1d_disp_off,
+ .set_rect = epson_s1d_disp_set_rect,
+};
+
+static struct platform_device this_device = {
+ .name = "ebi2_epson_s1d_qvga",
+ .id = 1,
+ .dev = {
+ .platform_data = &epson_s1d_panel_data,
+ }
+};
+
+static int __init epson_s1d_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+ ret = platform_driver_register(&this_driver);
+ if (!ret) {
+ pinfo = &epson_s1d_panel_data.panel_info;
+ pinfo->xres = PANEL_WIDTH;
+ pinfo->yres = PANEL_HEIGHT;
+ MSM_FB_SINGLE_MODE_PANEL(pinfo);
+ pinfo->type = EBI2_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->wait_cycle = 0x048423E8;
+ pinfo->bpp = 18;
+ 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(epson_s1d_init);
diff --git a/drivers/video/msm/ebi2_host.c b/drivers/video/msm/ebi2_host.c
new file mode 100644
index 0000000..8ba5506
--- /dev/null
+++ b/drivers/video/msm/ebi2_host.c
@@ -0,0 +1,307 @@
+/* Copyright (c) 2012, 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.
+ */
+
+#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/delay.h>
+#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <mach/clk.h>
+#include <mach/hardware.h>
+#include "msm_fb.h"
+
+struct mdp_ccs mdp_ccs_rgb2yuv;
+struct mdp_ccs mdp_ccs_yuv2rgb;
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+static int ebi2_host_resource_initialized;
+static struct msm_panel_common_pdata *ebi2_host_pdata;
+
+static int ebi2_host_probe(struct platform_device *pdev);
+static int ebi2_host_remove(struct platform_device *pdev);
+
+static int ebi2_host_runtime_suspend(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: suspending...\n");
+ return 0;
+}
+
+static int ebi2_host_runtime_resume(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: resuming...\n");
+ return 0;
+}
+
+static const struct dev_pm_ops ebi2_host_dev_pm_ops = {
+ .runtime_suspend = ebi2_host_runtime_suspend,
+ .runtime_resume = ebi2_host_runtime_resume,
+};
+
+
+static struct platform_driver ebi2_host_driver = {
+ .probe = ebi2_host_probe,
+ .remove = ebi2_host_remove,
+ .shutdown = NULL,
+ .driver = {
+ /*
+ * Simulate mdp hw
+ */
+ .name = "mdp",
+ .pm = &ebi2_host_dev_pm_ops,
+ },
+};
+
+void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
+ boolean isr)
+{
+ return;
+}
+int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req)
+{
+ return 0;
+}
+int mdp_start_histogram(struct fb_info *info)
+{
+ return 0;
+}
+int mdp_stop_histogram(struct fb_info *info)
+{
+ return 0;
+}
+void mdp_refresh_screen(unsigned long data)
+{
+ return;
+}
+
+static int ebi2_host_off(struct platform_device *pdev)
+{
+ int ret;
+ ret = panel_next_off(pdev);
+ return ret;
+}
+
+static int ebi2_host_on(struct platform_device *pdev)
+{
+ int ret;
+ ret = panel_next_on(pdev);
+ return ret;
+}
+
+
+static int ebi2_host_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;
+
+ if ((pdev->id == 0) && (pdev->num_resources > 0)) {
+
+ ebi2_host_pdata = pdev->dev.platform_data;
+
+ ebi2_host_resource_initialized = 1;
+ return 0;
+ }
+
+ ebi2_host_resource_initialized = 1;
+ if (!ebi2_host_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;
+
+ if (ebi2_host_pdata) {
+ mfd->mdp_rev = ebi2_host_pdata->mdp_rev;
+ mfd->mem_hid = ebi2_host_pdata->mem_hid;
+ }
+
+ /* add panel data */
+ if (platform_device_add_data
+ (msm_fb_dev, pdev->dev.platform_data,
+ sizeof(struct msm_fb_panel_data))) {
+ pr_err("ebi2_host_probe: platform_device_add_data failed!\n");
+ rc = -ENOMEM;
+ goto ebi2_host_probe_err;
+ }
+ /* data chain */
+ pdata = msm_fb_dev->dev.platform_data;
+ pdata->on = ebi2_host_on;
+ pdata->off = ebi2_host_off;
+ pdata->next = pdev;
+
+ /* set driver data */
+ platform_set_drvdata(msm_fb_dev, mfd);
+
+ rc = platform_device_add(msm_fb_dev);
+ if (rc)
+ goto ebi2_host_probe_err;
+
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+ pdev_list[pdev_list_cnt++] = pdev;
+ return 0;
+
+ebi2_host_probe_err:
+ platform_device_put(msm_fb_dev);
+ return rc;
+}
+
+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;
+ struct fb_info *fbi = mfd->fbi;
+ struct msm_panel_info *panel_info = &mfd->panel_info;
+ MDPIBUF *iBuf;
+ int bpp = info->var.bits_per_pixel / 8;
+ int yres, remainder;
+
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
+ down(&mfd->sem);
+
+ iBuf = &mfd->ibuf;
+ /* use virtual address */
+ iBuf->buf = (uint8 *) fbi->screen_base;
+
+ if (fbi->var.yoffset < yres) {
+ iBuf->buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ iBuf->buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ iBuf->buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
+
+ 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;
+ int i, j;
+ uint32 data;
+ uint8 *src;
+ struct msm_fb_panel_data *pdata =
+ (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+ struct fb_info *fbi = mfd->fbi;
+
+ iBuf = &mfd->ibuf;
+
+ invalidate_caches((unsigned long)fbi->screen_base,
+ (unsigned long)info->fix.smem_len,
+ (unsigned long)info->fix.smem_start);
+
+ pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w,
+ iBuf->dma_h);
+ for (i = 0; i < iBuf->dma_h; i++) {
+ src = iBuf->buf + (fbi->fix.line_length * (iBuf->dma_y + i))
+ + (iBuf->dma_x * iBuf->bpp);
+ for (j = 0; j < iBuf->dma_w; j++) {
+ data = (uint32)(*src++ >> 2) << 12;
+ data |= (uint32)(*src++ >> 2) << 6;
+ data |= (uint32)(*src++ >> 2);
+ data = ((data&0x1FF)<<16) | ((data&0x3FE00)>>9);
+ outpdw(mfd->data_port, data);
+ }
+ }
+}
+
+static int ebi2_host_remove(struct platform_device *pdev)
+{
+ pm_runtime_disable(&pdev->dev);
+
+ return 0;
+}
+
+static int ebi2_host_register_driver(void)
+{
+ return platform_driver_register(&ebi2_host_driver);
+}
+
+static int __init ebi2_host_driver_init(void)
+{
+ int ret;
+
+ ret = ebi2_host_register_driver();
+ if (ret) {
+ pr_err("ebi2_host_register_driver() failed!\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+module_init(ebi2_host_driver_init);
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..966f974
--- /dev/null
+++ b/drivers/video/msm/ebi2_lcd.c
@@ -0,0 +1,308 @@
+/* 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,
+ .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 lcd01_base_phys;
+static int ebi2_lcd_resource_initialized;
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+static struct lcdc_platform_data *ebi2_pdata;
+
+static int ebi2_lcd_on(struct platform_device *pdev)
+{
+ int ret;
+
+ if (ebi2_pdata && ebi2_pdata->lcdc_power_save)
+ ebi2_pdata->lcdc_power_save(1);
+
+ ret = panel_next_on(pdev);
+ return ret;
+}
+
+static int ebi2_lcd_off(struct platform_device *pdev)
+{
+ int ret;
+
+ ret = panel_next_off(pdev);
+
+ if (ebi2_pdata && ebi2_pdata->lcdc_power_save)
+ ebi2_pdata->lcdc_power_save(0);
+
+ return ret;
+}
+
+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, hw_version;
+
+ 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_phys = pdev->resource[i].start;
+ 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_pdata = pdev->dev.platform_data;
+ 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 = ebi2_lcd_on;
+ pdata->off = ebi2_lcd_off;
+ pdata->next = pdev;
+
+ /* get/set panel specific fb info */
+ mfd->panel_info = pdata->panel_info;
+
+ hw_version = inp32((int)ebi2_base + 8);
+
+ if (mfd->panel_info.bpp == 24)
+ mfd->fb_imgType = MDP_RGB_888;
+ else if (mfd->panel_info.bpp == 18)
+ 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 (hw_version < 0x2020) {
+ 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;
+ if (hw_version >= 0x2020) {
+ mfd->data_port =
+ (void *)((uint32) mfd->cmd_port + 0x80);
+ mfd->data_port_phys =
+ (void *)(lcd01_base_phys + 0x80);
+ } else {
+ 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..c0e9145
--- /dev/null
+++ b/drivers/video/msm/external_common.c
@@ -0,0 +1,2108 @@
+/* Copyright (c) 2010-2012, 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: "
+
+/* The start of the data block collection within the CEA Extension Version 3 */
+#define DBC_START_OFFSET 4
+
+#include "msm_fb.h"
+#include "hdmi_msm.h"
+#include "external_common.h"
+#include "mhl_api.h"
+
+#include "mdp.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;
+ }
+ }
+}
+
+#ifdef DEBUG_EDID
+/*
+ * Block 0 - 1920x1080p, 1360x768p
+ * Block 1 - 1280x720p, 1920x540i, 720x480p
+ */
+const char edid_blk0[0x100] = {
+0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x4C, 0x2D, 0x03, 0x05, 0x00,
+0x00, 0x00, 0x00, 0x30, 0x12, 0x01, 0x03, 0x80, 0x10, 0x09, 0x78, 0x0A, 0xEE,
+0x91, 0xA3, 0x54, 0x4C, 0x99, 0x26, 0x0F, 0x50, 0x54, 0xBD, 0xEF, 0x80, 0x71,
+0x4F, 0x81, 0x00, 0x81, 0x40, 0x81, 0x80, 0x95, 0x00, 0x95, 0x0F, 0xB3, 0x00,
+0xA9, 0x40, 0x02, 0x3A, 0x80, 0x18, 0x71, 0x38, 0x2D, 0x40, 0x58, 0x2C, 0x45,
+0x00, 0xA0, 0x5A, 0x00, 0x00, 0x00, 0x1E, 0x66, 0x21, 0x50, 0xB0, 0x51, 0x00,
+0x1B, 0x30, 0x40, 0x70, 0x36, 0x00, 0xA0, 0x5A, 0x00, 0x00, 0x00, 0x1E, 0x00,
+0x00, 0x00, 0xFD, 0x00, 0x18, 0x4B, 0x1A, 0x51, 0x17, 0x00, 0x0A, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x53, 0x41, 0x4D, 0x53,
+0x55, 0x4E, 0x47, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x8F};
+
+const char edid_blk1[0x100] = {
+0x02, 0x03, 0x1E, 0xF1, 0x46, 0x90, 0x04, 0x05, 0x03, 0x20, 0x22, 0x23, 0x09,
+0x07, 0x07, 0x83, 0x01, 0x00, 0x00, 0xE2, 0x00, 0x0F, 0x67, 0x03, 0x0C, 0x00,
+0x10, 0x00, 0xB8, 0x2D, 0x01, 0x1D, 0x00, 0x72, 0x51, 0xD0, 0x1E, 0x20, 0x6E,
+0x28, 0x55, 0x00, 0xA0, 0x5A, 0x00, 0x00, 0x00, 0x1E, 0x01, 0x1D, 0x80, 0x18,
+0x71, 0x1C, 0x16, 0x20, 0x58, 0x2C, 0x25, 0x00, 0xA0, 0x5A, 0x00, 0x00, 0x00,
+0x9E, 0x8C, 0x0A, 0xD0, 0x8A, 0x20, 0xE0, 0x2D, 0x10, 0x10, 0x3E, 0x96, 0x00,
+0xA0, 0x5A, 0x00, 0x00, 0x00, 0x18, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDF};
+#endif /* DEBUG_EDID */
+
+#ifdef CONFIG_FB_MSM_HDMI_MHL
+#define DMA_E_BASE 0xB0000
+void mdp_vid_quant_set(void)
+{
+ if ((external_common_state->video_resolution == \
+ HDMI_VFRMT_720x480p60_4_3) || \
+ (external_common_state->video_resolution == \
+ HDMI_VFRMT_720x480p60_16_9)) {
+ MDP_OUTP(MDP_BASE + DMA_E_BASE + 0x70, 0x00EB0010);
+ MDP_OUTP(MDP_BASE + DMA_E_BASE + 0x74, 0x00EB0010);
+ MDP_OUTP(MDP_BASE + DMA_E_BASE + 0x78, 0x00EB0010);
+ } else {
+ MDP_OUTP(MDP_BASE + DMA_E_BASE + 0x70, 0x00FF0000);
+ MDP_OUTP(MDP_BASE + DMA_E_BASE + 0x74, 0x00FF0000);
+ MDP_OUTP(MDP_BASE + DMA_E_BASE + 0x78, 0x00FF0000);
+ }
+}
+#else
+void mdp_vid_quant_set(void)
+{
+ /*
+ * Support for quantization to be added
+ * only when MHL support is included.
+ */
+}
+#endif
+
+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);
+
+struct hdmi_disp_mode_timing_type
+ hdmi_mhl_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),
+ HDMI_SETTINGS_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),
+ HDMI_SETTINGS_1920x1080p24_16_9,
+ HDMI_SETTINGS_1920x1080p25_16_9,
+ HDMI_SETTINGS_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_mhl_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_edid_physical_address(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = snprintf(buf, PAGE_SIZE, "%d\n",
+ external_common_state->physical_address);
+
+ DEV_DBG("%s: '%d'\n", __func__,
+ external_common_state->physical_address);
+ return ret;
+}
+
+
+static ssize_t hdmi_common_rda_edid_scan_info(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = snprintf(buf, PAGE_SIZE, "%d, %d, %d\n",
+ external_common_state->pt_scan_info,
+ external_common_state->it_scan_info,
+ external_common_state->ce_scan_info);
+ DEV_DBG("%s: '%s'\n", __func__, buf);
+ return ret;
+}
+
+static ssize_t hdmi_common_wta_vendor_name(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ uint8 *s = (uint8 *) buf;
+ uint8 *d = external_common_state->spd_vendor_name;
+ ssize_t ret = strnlen(buf, PAGE_SIZE);
+ ret = (ret > 8) ? 8 : ret;
+
+ memset(external_common_state->spd_vendor_name, 0, 8);
+ while (*s) {
+ if (*s & 0x60 && *s ^ 0x7f) {
+ *d = *s;
+ } else {
+ /* stop copying if control character found */
+ break;
+ }
+
+ if (++s > (uint8 *) (buf + ret))
+ break;
+
+ d++;
+ }
+
+ DEV_DBG("%s: '%s'\n", __func__,
+ external_common_state->spd_vendor_name);
+
+ return ret;
+}
+
+static ssize_t hdmi_common_rda_vendor_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = snprintf(buf, PAGE_SIZE, "%s\n",
+ external_common_state->spd_vendor_name);
+ DEV_DBG("%s: '%s'\n", __func__,
+ external_common_state->spd_vendor_name);
+
+ return ret;
+}
+
+static ssize_t hdmi_common_wta_product_description(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ uint8 *s = (uint8 *) buf;
+ uint8 *d = external_common_state->spd_product_description;
+ ssize_t ret = strnlen(buf, PAGE_SIZE);
+ ret = (ret > 16) ? 16 : ret;
+
+ memset(external_common_state->spd_product_description, 0, 16);
+ while (*s) {
+ if (*s & 0x60 && *s ^ 0x7f) {
+ *d = *s;
+ } else {
+ /* stop copying if control character found */
+ break;
+ }
+
+ if (++s > (uint8 *) (buf + ret))
+ break;
+
+ d++;
+ }
+
+ DEV_DBG("%s: '%s'\n", __func__,
+ external_common_state->spd_product_description);
+
+ return ret;
+}
+
+static ssize_t hdmi_common_rda_product_description(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = snprintf(buf, PAGE_SIZE, "%s\n",
+ external_common_state->spd_product_description);
+ DEV_DBG("%s: '%s'\n", __func__,
+ external_common_state->spd_product_description);
+
+ return ret;
+}
+
+static ssize_t hdmi_common_rda_edid_3d_modes(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+ int i;
+ char buff_3d[128];
+
+ 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;
+ uint32 *video_3d_mode = external_common_state->disp_mode_list
+ .disp_3d_mode_list;
+ for (i = 0; i < external_common_state->disp_mode_list
+ .num_of_elements; ++i) {
+ video_3d_format_2string(*video_3d_mode++, buff_3d);
+ if (ret > 0)
+ ret += snprintf(buf+ret, PAGE_SIZE-ret,
+ ",%d=%s",
+ *video_mode++ + 1, buff_3d);
+ else
+ ret += snprintf(buf+ret, PAGE_SIZE-ret,
+ "%d=%s",
+ *video_mode++ + 1, buff_3d);
+ }
+ } 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;
+ if (hdmi_prim_display)
+ hpd = 1;
+ else
+ 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;
+}
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+/*
+ * This interface for CEC feature is defined to suit
+ * the current requirements. However, the actual functionality is
+ * added to accommodate different interfaces
+ */
+static ssize_t hdmi_msm_rda_cec(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ /* 0x028C CEC_CTRL */
+ ssize_t ret = snprintf(buf, PAGE_SIZE, "%d\n",
+ (HDMI_INP(0x028C) & BIT(0)));
+ return ret;
+}
+
+static ssize_t hdmi_msm_wta_cec(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ ssize_t ret = strnlen(buf, PAGE_SIZE);
+ int cec = atoi(buf);
+
+ if (cec != 0) {
+ mutex_lock(&hdmi_msm_state_mutex);
+ hdmi_msm_state->cec_enabled = true;
+ hdmi_msm_state->cec_logical_addr = 4;
+ mutex_unlock(&hdmi_msm_state_mutex);
+ hdmi_msm_cec_init();
+ hdmi_msm_cec_write_logical_addr(
+ hdmi_msm_state->cec_logical_addr);
+ DEV_DBG("CEC enabled\n");
+ } else {
+ mutex_lock(&hdmi_msm_state_mutex);
+ hdmi_msm_state->cec_enabled = false;
+ hdmi_msm_state->cec_logical_addr = 15;
+ mutex_unlock(&hdmi_msm_state_mutex);
+ hdmi_msm_cec_write_logical_addr(
+ hdmi_msm_state->cec_logical_addr);
+ /* 0x028C CEC_CTRL */
+ HDMI_OUTP(0x028C, 0);
+ DEV_DBG("CEC disabled\n");
+ }
+ return ret;
+}
+
+static ssize_t hdmi_msm_rda_cec_logical_addr(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret;
+
+ mutex_lock(&hdmi_msm_state_mutex);
+ ret = snprintf(buf, PAGE_SIZE, "%d\n",
+ hdmi_msm_state->cec_logical_addr);
+ mutex_unlock(&hdmi_msm_state_mutex);
+ return ret;
+}
+
+static ssize_t hdmi_msm_wta_cec_logical_addr(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+
+#ifdef DRVR_ONLY_CECT_NO_DAEMON
+ /*
+ * Only for testing
+ */
+ hdmi_msm_cec_one_touch_play();
+ return 0;
+#else
+ ssize_t ret = strnlen(buf, PAGE_SIZE);
+ int logical_addr = atoi(buf);
+
+ if (logical_addr < 0 || logical_addr > 15)
+ return -EINVAL;
+
+ mutex_lock(&hdmi_msm_state_mutex);
+ hdmi_msm_state->cec_logical_addr = logical_addr;
+ mutex_unlock(&hdmi_msm_state_mutex);
+
+ hdmi_msm_cec_write_logical_addr(logical_addr);
+
+ return ret;
+#endif
+}
+
+static ssize_t hdmi_msm_rda_cec_frame(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ mutex_lock(&hdmi_msm_state_mutex);
+ if (hdmi_msm_state->cec_queue_rd == hdmi_msm_state->cec_queue_wr
+ && !hdmi_msm_state->cec_queue_full) {
+ mutex_unlock(&hdmi_msm_state_mutex);
+ DEV_ERR("CEC message queue is empty\n");
+ return -EBUSY;
+ }
+ memcpy(buf, hdmi_msm_state->cec_queue_rd++,
+ sizeof(struct hdmi_msm_cec_msg));
+ hdmi_msm_state->cec_queue_full = false;
+ if (hdmi_msm_state->cec_queue_rd == CEC_QUEUE_END)
+ hdmi_msm_state->cec_queue_rd = hdmi_msm_state->cec_queue_start;
+ mutex_unlock(&hdmi_msm_state_mutex);
+
+ return sizeof(struct hdmi_msm_cec_msg);
+}
+
+static ssize_t hdmi_msm_wta_cec_frame(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int i;
+ int retry = ((struct hdmi_msm_cec_msg *) buf)->retransmit;
+
+ for (i = 0; i < RETRANSMIT_MAX_NUM; i++) {
+ hdmi_msm_cec_msg_send((struct hdmi_msm_cec_msg *) buf);
+ if (hdmi_msm_state->cec_frame_wr_status
+ & CEC_STATUS_WR_ERROR && retry--) {
+ mutex_lock(&hdmi_msm_state_mutex);
+ if (hdmi_msm_state->fsm_reset_done)
+ retry++;
+ mutex_unlock(&hdmi_msm_state_mutex);
+ msleep(360);
+ } else
+ break;
+ }
+
+ if (hdmi_msm_state->cec_frame_wr_status & CEC_STATUS_WR_DONE)
+ return sizeof(struct hdmi_msm_cec_msg);
+ else
+ return -EINVAL;
+}
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT */
+
+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
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+static DEVICE_ATTR(cec, S_IRUGO | S_IWUSR,
+ hdmi_msm_rda_cec,
+ hdmi_msm_wta_cec);
+
+static DEVICE_ATTR(cec_logical_addr, S_IRUGO | S_IWUSR,
+ hdmi_msm_rda_cec_logical_addr,
+ hdmi_msm_wta_cec_logical_addr);
+
+static DEVICE_ATTR(cec_rd_frame, S_IRUGO,
+ hdmi_msm_rda_cec_frame, NULL);
+
+static DEVICE_ATTR(cec_wr_frame, S_IWUSR,
+ NULL, hdmi_msm_wta_cec_frame);
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT */
+
+
+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;
+ DEV_INFO("%s: video_mode is %d\n", __func__, video_mode);
+ 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 ssize_t external_common_rda_hdmi_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret;
+
+ ret = snprintf(buf, PAGE_SIZE, "%d\n",
+ external_common_state->hdmi_sink);
+
+ DEV_DBG("%s: '%d'\n", __func__,
+ external_common_state->hdmi_sink);
+
+ return ret;
+}
+
+static ssize_t hdmi_common_rda_hdmi_primary(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = snprintf(buf, PAGE_SIZE, "%d\n",
+ hdmi_prim_display);
+ DEV_DBG("%s: '%d'\n", __func__, hdmi_prim_display);
+ 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);
+static DEVICE_ATTR(hdmi_mode, S_IRUGO, external_common_rda_hdmi_mode, 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(pa, S_IRUGO,
+ hdmi_common_rda_edid_physical_address, NULL);
+static DEVICE_ATTR(scan_info, S_IRUGO,
+ hdmi_common_rda_edid_scan_info, NULL);
+static DEVICE_ATTR(vendor_name, S_IRUGO | S_IWUSR, hdmi_common_rda_vendor_name,
+ hdmi_common_wta_vendor_name);
+static DEVICE_ATTR(product_description, S_IRUGO | S_IWUSR,
+ hdmi_common_rda_product_description,
+ hdmi_common_wta_product_description);
+static DEVICE_ATTR(edid_3d_modes, S_IRUGO,
+ hdmi_common_rda_edid_3d_modes, 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 DEVICE_ATTR(hdmi_primary, S_IRUGO, hdmi_common_rda_hdmi_primary, NULL);
+
+static struct attribute *external_common_fs_attrs[] = {
+ &dev_attr_video_mode.attr,
+ &dev_attr_video_mode_str.attr,
+ &dev_attr_connected.attr,
+ &dev_attr_hdmi_mode.attr,
+#ifdef CONFIG_FB_MSM_HDMI_COMMON
+ &dev_attr_edid_modes.attr,
+ &dev_attr_hdcp.attr,
+ &dev_attr_hpd.attr,
+ &dev_attr_pa.attr,
+ &dev_attr_scan_info.attr,
+ &dev_attr_vendor_name.attr,
+ &dev_attr_product_description.attr,
+ &dev_attr_edid_3d_modes.attr,
+ &dev_attr_3d_present.attr,
+ &dev_attr_hdcp_present.attr,
+#endif
+#ifdef CONFIG_FB_MSM_HDMI_3D
+ &dev_attr_format_3d.attr,
+#endif
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+ &dev_attr_cec.attr,
+ &dev_attr_cec_logical_addr.attr,
+ &dev_attr_cec_rd_frame.attr,
+ &dev_attr_cec_wr_frame.attr,
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT */
+ &dev_attr_hdmi_primary.attr,
+ 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,
+ uint32 start_offset, uint8 type, uint8 *len)
+{
+ /* the start of data block collection, start of Video Data Block */
+ uint32 offset = start_offset;
+ uint32 end_dbc_offset = in_buf[2];
+
+ *len = 0;
+
+ /*edid buffer 1, byte 2 being 4 means no non-DTD/Data block collection
+ present.
+ edid buffer 1, byte 2 being 0 menas no non-DTD/DATA block collection
+ present and no DTD data present.*/
+ if ((end_dbc_offset == 0) || (end_dbc_offset == 4)) {
+ DEV_WARN("EDID: no DTD or non-DTD data present\n");
+ return NULL;
+ }
+ while (offset < end_dbc_offset) {
+ 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: type=%d block 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, DBC_START_OFFSET, 3,
+ &len);
+
+ if (vsd == NULL)
+ return 0;
+
+ DEV_DBG("EDID: VSD PhyAddr=%04x, MaxTMDS=%dMHz\n",
+ ((uint32)vsd[4] << 8) + (uint32)vsd[5], (uint32)vsd[7] * 5);
+ external_common_state->physical_address =
+ ((uint16)vsd[4] << 8) + (uint16)vsd[5];
+ return ((uint32)vsd[3] << 16) + ((uint32)vsd[2] << 8) + (uint32)vsd[1];
+}
+
+#define HDMI_VSDB_3D_DATA_OFFSET(vsd) \
+ (!((vsd)[8] & BIT(7)) ? 9 : (!((vsd)[8] & BIT(6)) ? 11 : 13))
+
+static void hdmi_edid_extract_3d_present(const uint8 *in_buf)
+{
+ uint8 len, offset;
+ const uint8 *vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 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 = HDMI_VSDB_3D_DATA_OFFSET(vsd);
+ 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, DBC_START_OFFSET, 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, DBC_START_OFFSET, 4,
+ &len);
+
+ if (sad == NULL)
+ return;
+
+ external_common_state->speaker_allocation_block = sad[1];
+ DEV_DBG("EDID: speaker allocation data SP byte = %08x %s%s%s%s%s%s%s\n",
+ sad[1],
+ (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)) ? "RLC/RRC," : "");
+}
+
+static void hdmi_edid_extract_audio_data_blocks(const uint8 *in_buf)
+{
+ uint8 len;
+ const uint8 *sad = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 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_extract_extended_data_blocks(const uint8 *in_buf)
+{
+ uint8 len = 0;
+ uint32 start_offset = DBC_START_OFFSET;
+
+ /* A Tage code of 7 identifies extended data blocks */
+ uint8 const *etag = hdmi_edid_find_block(in_buf, start_offset, 7, &len);
+
+ while (etag != NULL) {
+ /* The extended data block should at least be 2 bytes long */
+ if (len < 2) {
+ DEV_DBG("EDID: Found an extended data block of length"
+ "less than 2 bytes. Ignoring ...\n");
+ } else {
+ /*
+ * The second byte of the extended data block has the
+ * extended tag code
+ */
+ switch (etag[1]) {
+ case 0:
+ /* Video Capability Data Block */
+ DEV_DBG("EDID: VCDB=%02X %02X\n", etag[1],
+ etag[2]);
+
+ /*
+ * Check if the sink specifies underscan
+ * support for:
+ * BIT 5: preferred video format
+ * BIT 3: IT video format
+ * BIT 1: CE video format
+ */
+ external_common_state->pt_scan_info = (etag[2] &
+ (BIT(4) | BIT(5))) >> 4;
+ external_common_state->it_scan_info = (etag[2] &
+ (BIT(3) | BIT(2))) >> 2;
+ external_common_state->ce_scan_info = etag[2] &
+ (BIT(1) | BIT(0));
+ DEV_DBG("EDID: Scan Information (pt|it|ce): "
+ "(%d|%d|%d)",
+ external_common_state->pt_scan_info,
+ external_common_state->it_scan_info,
+ external_common_state->ce_scan_info);
+ break;
+ default:
+ DEV_DBG("EDID: Extend Tag Code %d not"
+ "supported\n", etag[1]);
+ break;
+ }
+ }
+
+ /* There could be more that one extended data block */
+ start_offset = etag - in_buf + len + 1;
+ etag = hdmi_edid_find_block(in_buf, start_offset, 7, &len);
+ }
+}
+
+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 as 4:3 if within specificed range , rathaer than being
+ * absolute value
+ */
+ aspect_ratio_4_3 = (abs(img_size_h * 3 - img_size_v * 4) < 5) ? 1 : 0;
+
+ max_num_of_elements = sizeof(hdmi_edid_disp_mode_lut)
+ / sizeof(*hdmi_edid_disp_mode_lut);
+
+ /* EDID_TIMING_DESC_INTERLACE[0x11:7]: Relative Offset to the EDID
+ * detailed timing descriptors - Interlace flag */
+ DEV_DBG("Interlaced mode byte data_buf[0x11]=[%x]\n", data_buf[0x11]);
+ /*
+ * CEA 861-D: interlaced bit is bit[7] of byte[0x11]
+ */
+ interlaced = (data_buf[0x11] & 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) {
+ if (mhl_is_connected()) {
+ const struct hdmi_disp_mode_timing_type *mhl_timing =
+ hdmi_mhl_get_supported_mode(video_format);
+ boolean mhl_supported = mhl_timing != NULL;
+ DEV_DBG("EDID: format: %d [%s], %s by MHL\n",
+ video_format, video_format_2string(video_format),
+ mhl_supported ? "Supported" : "Not-Supported");
+ if (mhl_supported)
+ disp_mode_list->disp_mode_list[
+ disp_mode_list->num_of_elements++] = video_format;
+ } else
+ disp_mode_list->disp_mode_list[
+ disp_mode_list->num_of_elements++] = video_format;
+ }
+}
+
+const char *single_video_3d_format_2string(uint32 format)
+{
+ switch (format) {
+ case TOP_AND_BOTTOM: return "TAB";
+ case FRAME_PACKING: return "FP";
+ case SIDE_BY_SIDE_HALF: return "SSH";
+ }
+ return "";
+}
+
+ssize_t video_3d_format_2string(uint32 format, char *buf)
+{
+ ssize_t ret, len = 0;
+ ret = snprintf(buf, PAGE_SIZE, "%s",
+ single_video_3d_format_2string(format & FRAME_PACKING));
+ len += ret;
+
+ if (len && (format & TOP_AND_BOTTOM))
+ ret = snprintf(buf + len, PAGE_SIZE, ":%s",
+ single_video_3d_format_2string(
+ format & TOP_AND_BOTTOM));
+ else
+ ret = snprintf(buf + len, PAGE_SIZE, "%s",
+ single_video_3d_format_2string(
+ format & TOP_AND_BOTTOM));
+ len += ret;
+
+ if (len && (format & SIDE_BY_SIDE_HALF))
+ ret = snprintf(buf + len, PAGE_SIZE, ":%s",
+ single_video_3d_format_2string(
+ format & SIDE_BY_SIDE_HALF));
+ else
+ ret = snprintf(buf + len, PAGE_SIZE, "%s",
+ single_video_3d_format_2string(
+ format & SIDE_BY_SIDE_HALF));
+ len += ret;
+
+ return len;
+}
+
+static void add_supported_3d_format(
+ struct hdmi_disp_mode_list_type *disp_mode_list,
+ uint32 video_format,
+ uint32 video_3d_format)
+{
+ char string[128];
+ boolean added = FALSE;
+ int i;
+ for (i = 0; i < disp_mode_list->num_of_elements; ++i) {
+ if (disp_mode_list->disp_mode_list[i] == video_format) {
+ disp_mode_list->disp_3d_mode_list[i] |=
+ video_3d_format;
+ added = TRUE;
+ break;
+ }
+ }
+ video_3d_format_2string(video_3d_format, string);
+ DEV_DBG("EDID[3D]: format: %d [%s], %s %s\n",
+ video_format, video_format_2string(video_format),
+ string, added ? "added" : "NOT added");
+}
+
+static void hdmi_edid_get_display_vsd_3d_mode(const uint8 *data_buf,
+ struct hdmi_disp_mode_list_type *disp_mode_list,
+ uint32 num_og_cea_blocks)
+{
+ uint8 len, offset, present_multi_3d, hdmi_vic_len, hdmi_3d_len;
+ uint16 structure_all, structure_mask;
+ const uint8 *vsd = num_og_cea_blocks ?
+ hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET,
+ 3, &len) : NULL;
+ int i;
+
+ offset = HDMI_VSDB_3D_DATA_OFFSET(vsd);
+ present_multi_3d = (vsd[offset] & 0x60) >> 5;
+
+ offset += 1;
+ hdmi_vic_len = (vsd[offset] >> 5) & 0x7;
+ hdmi_3d_len = vsd[offset] & 0x1F;
+ DEV_DBG("EDID[3D]: HDMI_VIC_LEN = %d, HDMI_3D_LEN = %d\n",
+ hdmi_vic_len, hdmi_3d_len);
+
+ offset += (hdmi_vic_len + 1);
+ if (present_multi_3d == 1 || present_multi_3d == 2) {
+ DEV_DBG("EDID[3D]: multi 3D present (%d)\n", present_multi_3d);
+ /* 3d_structure_all */
+ structure_all = (vsd[offset] << 8) | vsd[offset + 1];
+ offset += 2;
+ hdmi_3d_len -= 2;
+ if (present_multi_3d == 2) {
+ /* 3d_structure_mask */
+ structure_mask = (vsd[offset] << 8) | vsd[offset + 1];
+ offset += 2;
+ hdmi_3d_len -= 2;
+ } else
+ structure_mask = 0xffff;
+
+ i = 0;
+ while (i < 16) {
+ if (i >= disp_mode_list->disp_multi_3d_mode_list_cnt)
+ break;
+
+ if (!(structure_mask & BIT(i))) {
+ ++i;
+ continue;
+ }
+
+ /* BIT0: FRAME PACKING */
+ if (structure_all & BIT(0))
+ add_supported_3d_format(disp_mode_list,
+ disp_mode_list->
+ disp_multi_3d_mode_list[i],
+ FRAME_PACKING);
+
+ /* BIT6: TOP AND BOTTOM */
+ if (structure_all & BIT(6))
+ add_supported_3d_format(disp_mode_list,
+ disp_mode_list->
+ disp_multi_3d_mode_list[i],
+ TOP_AND_BOTTOM);
+
+ /* BIT8: SIDE BY SIDE HALF */
+ if (structure_all & BIT(8))
+ add_supported_3d_format(disp_mode_list,
+ disp_mode_list->
+ disp_multi_3d_mode_list[i],
+ SIDE_BY_SIDE_HALF);
+
+ ++i;
+ }
+ }
+
+ i = 0;
+ while (hdmi_3d_len > 0) {
+ DEV_DBG("EDID[3D]: 3D_Structure_%d @ %d: %02x\n",
+ i + 1, offset, vsd[offset]);
+
+ if ((vsd[offset] >> 4) >=
+ disp_mode_list->disp_multi_3d_mode_list_cnt) {
+ if ((vsd[offset] & 0x0F) >= 8) {
+ offset += 1;
+ hdmi_3d_len -= 1;
+ DEV_DBG("EDID[3D]: 3D_Detail_%d @ %d: %02x\n",
+ i + 1, offset, vsd[offset]);
+ }
+ i += 1;
+ offset += 1;
+ hdmi_3d_len -= 1;
+ continue;
+ }
+
+ switch (vsd[offset] & 0x0F) {
+ case 0:
+ /* 0000b: FRAME PACKING */
+ add_supported_3d_format(disp_mode_list,
+ disp_mode_list->disp_multi_3d_mode_list
+ [vsd[offset] >> 4],
+ FRAME_PACKING);
+ break;
+ case 6:
+ /* 0110b: TOP AND BOTTOM */
+ add_supported_3d_format(disp_mode_list,
+ disp_mode_list->disp_multi_3d_mode_list
+ [vsd[offset] >> 4],
+ TOP_AND_BOTTOM);
+ break;
+ case 8:
+ /* 1000b: SIDE BY SIDE HALF */
+ add_supported_3d_format(disp_mode_list,
+ disp_mode_list->disp_multi_3d_mode_list
+ [vsd[offset] >> 4],
+ SIDE_BY_SIDE_HALF);
+ break;
+ }
+ if ((vsd[offset] & 0x0F) >= 8) {
+ offset += 1;
+ hdmi_3d_len -= 1;
+ DEV_DBG("EDID[3D]: 3D_Detail_%d @ %d: %02x\n",
+ i + 1, offset, vsd[offset]);
+ }
+ i += 1;
+ offset += 1;
+ hdmi_3d_len -= 1;
+ }
+}
+
+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 *edid_blk0 = &data_buf[0x0];
+ const uint8 *edid_blk1 = &data_buf[0x80];
+ const uint8 *svd = num_og_cea_blocks ?
+ hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET,
+ 2, &len) : NULL;
+ boolean has60hz_mode = FALSE;
+ boolean has50hz_mode = FALSE;
+
+
+ disp_mode_list->num_of_elements = 0;
+ disp_mode_list->disp_multi_3d_mode_list_cnt = 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);
+ /* Make a note of the preferred video format */
+ if (i == 0) {
+ external_common_state->preferred_video_format =
+ video_format;
+ }
+ if (i < 16) {
+ disp_mode_list->disp_multi_3d_mode_list[i]
+ = video_format;
+ disp_mode_list->disp_multi_3d_mode_list_cnt++;
+ }
+
+ if (video_format <= HDMI_VFRMT_1920x1080p60_16_9 ||
+ video_format == HDMI_VFRMT_2880x480p60_4_3 ||
+ video_format == HDMI_VFRMT_2880x480p60_16_9)
+ has60hz_mode = TRUE;
+
+ if ((video_format >= HDMI_VFRMT_720x576p50_4_3 &&
+ video_format <= HDMI_VFRMT_1920x1080p50_16_9) ||
+ video_format == HDMI_VFRMT_2880x576p50_4_3 ||
+ video_format == HDMI_VFRMT_2880x576p50_16_9 ||
+ video_format == HDMI_VFRMT_1920x1250i50_16_9)
+ has50hz_mode = TRUE;
+ 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 != edid_blk0[0x36+desc_offset]) {
+ hdmi_edid_detail_desc(edid_blk0+0x36+desc_offset,
+ &video_format);
+ DEV_DBG("[%s:%d] Block-0 Adding vid fmt = [%s]\n",
+ __func__, __LINE__,
+ video_format_2string(video_format));
+ add_supported_video_format(disp_mode_list,
+ video_format);
+ if (video_format == HDMI_VFRMT_640x480p60_4_3)
+ has480p = TRUE;
+ /* Make a note of the preferred video format */
+ if (i == 0) {
+ external_common_state->preferred_video_format =
+ video_format;
+ }
+ desc_offset += 0x12;
+ ++i;
+ }
+ } else if (1 == num_og_cea_blocks) {
+ uint32 desc_offset = 0;
+
+ /*
+ * Read from both block 0 and block 1
+ * Read EDID block[0] as above
+ */
+ while (4 > i && 0 != edid_blk0[0x36+desc_offset]) {
+ hdmi_edid_detail_desc(edid_blk0+0x36+desc_offset,
+ &video_format);
+ DEV_DBG("[%s:%d] Block-0 Adding vid fmt = [%s]\n",
+ __func__, __LINE__,
+ video_format_2string(video_format));
+ add_supported_video_format(disp_mode_list,
+ video_format);
+ if (video_format == HDMI_VFRMT_640x480p60_4_3)
+ has480p = TRUE;
+ /* Make a note of the preferred video format */
+ if (i == 0) {
+ external_common_state->preferred_video_format =
+ video_format;
+ }
+ desc_offset += 0x12;
+ ++i;
+ }
+
+ /* 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 = edid_blk1[0x02];
+ while (0 != edid_blk1[desc_offset]) {
+ hdmi_edid_detail_desc(edid_blk1+desc_offset,
+ &video_format);
+ DEV_DBG("[%s:%d] Block-1 Adding vid fmt = [%s]\n",
+ __func__, __LINE__,
+ video_format_2string(video_format));
+ add_supported_video_format(disp_mode_list,
+ video_format);
+ if (video_format == HDMI_VFRMT_640x480p60_4_3)
+ has480p = TRUE;
+ /* Make a note of the preferred video format */
+ if (i == 0) {
+ external_common_state->preferred_video_format =
+ video_format;
+ }
+ desc_offset += 0x12;
+ ++i;
+ }
+ }
+
+ /* mandaroty 3d format */
+ if (external_common_state->present_3d) {
+ if (has60hz_mode) {
+ add_supported_3d_format(disp_mode_list,
+ HDMI_VFRMT_1920x1080p24_16_9,
+ FRAME_PACKING | TOP_AND_BOTTOM);
+ add_supported_3d_format(disp_mode_list,
+ HDMI_VFRMT_1280x720p60_16_9,
+ FRAME_PACKING | TOP_AND_BOTTOM);
+ add_supported_3d_format(disp_mode_list,
+ HDMI_VFRMT_1920x1080i60_16_9,
+ SIDE_BY_SIDE_HALF);
+ }
+ if (has50hz_mode) {
+ add_supported_3d_format(disp_mode_list,
+ HDMI_VFRMT_1920x1080p24_16_9,
+ FRAME_PACKING | TOP_AND_BOTTOM);
+ add_supported_3d_format(disp_mode_list,
+ HDMI_VFRMT_1280x720p50_16_9,
+ FRAME_PACKING | TOP_AND_BOTTOM);
+ add_supported_3d_format(disp_mode_list,
+ HDMI_VFRMT_1920x1080i50_16_9,
+ SIDE_BY_SIDE_HALF);
+ }
+
+ /* 3d format described in Vendor Specific Data */
+ hdmi_edid_get_display_vsd_3d_mode(data_buf, disp_mode_list,
+ num_og_cea_blocks);
+ }
+
+ 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, print_len;
+#ifdef DEBUG
+ const u8 *b = edid_buf;
+#endif
+ int status = external_common_state->read_edid_block(block, edid_buf);
+ if (status)
+ goto error;
+
+ /* Calculate checksum */
+ check_sum = 0;
+ for (ndx = 0; ndx < 0x80; ++ndx)
+ check_sum += edid_buf[ndx];
+
+ if (check_sum & 0xFF) {
+ 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;
+ }
+ print_len = 0x80;
+ for (ndx = 0; ndx < print_len; 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]);
+
+
+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->pt_scan_info = 0;
+ external_common_state->it_scan_info = 0;
+ external_common_state->ce_scan_info = 0;
+ external_common_state->preferred_video_format = 0;
+ 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);
+ hdmi_edid_extract_extended_data_blocks(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;
+ DEV_DBG("reserved format is %d\n", format);
+ } 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);
+
+const struct hdmi_disp_mode_timing_type *hdmi_mhl_get_mode(uint32 mode)
+{
+ if (mode >= HDMI_VFRMT_MAX)
+ return NULL;
+
+ return &hdmi_mhl_supported_video_mode_lut[mode];
+}
+EXPORT_SYMBOL(hdmi_mhl_get_mode);
+
+const struct hdmi_disp_mode_timing_type *hdmi_mhl_get_supported_mode(
+ uint32 mode)
+{
+ const struct hdmi_disp_mode_timing_type *ret
+ = hdmi_mhl_get_mode(mode);
+
+ if (ret == NULL || !ret->supported)
+ return NULL;
+ return ret;
+}
+EXPORT_SYMBOL(hdmi_mhl_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->frame_rate = 60;
+
+ 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;
+ if (hdmi_prim_display)
+ pinfo->fb_num = 2;
+ else
+ 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..57c0804
--- /dev/null
+++ b/drivers/video/msm/external_common.h
@@ -0,0 +1,272 @@
+/* Copyright (c) 2010-2012, 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__
+#include <linux/switch.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];
+#define TOP_AND_BOTTOM 0x10
+#define FRAME_PACKING 0x20
+#define SIDE_BY_SIDE_HALF 0x40
+ uint32 disp_3d_mode_list[HDMI_VFRMT_MAX];
+ uint32 disp_multi_3d_mode_list[16];
+ uint32 disp_multi_3d_mode_list_cnt;
+ uint32 num_of_elements;
+};
+#endif
+
+struct external_common_state_type {
+ boolean hpd_state;
+ struct kobject *uevent_kobj;
+ uint32 video_resolution;
+ struct device *dev;
+ struct switch_dev sdev;
+#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;
+ uint16 physical_address;
+ uint32 preferred_video_format;
+ uint8 pt_scan_info;
+ uint8 it_scan_info;
+ uint8 ce_scan_info;
+ uint8 spd_vendor_name[8];
+ uint8 spd_product_description[16];
+ 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;
+extern struct mutex hdmi_msm_state_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);
+const struct hdmi_disp_mode_timing_type *hdmi_mhl_get_mode(uint32 mode);
+const struct hdmi_disp_mode_timing_type *hdmi_mhl_get_supported_mode(
+ uint32 mode);
+void hdmi_common_init_panel_info(struct msm_panel_info *pinfo);
+
+ssize_t video_3d_format_2string(uint32 format, char *buf);
+#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..1eae516
--- /dev/null
+++ b/drivers/video/msm/hdmi_msm.c
@@ -0,0 +1,4833 @@
+/* Copyright (c) 2010-2012, 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 */
+
+#define CEC_MSG_PRINT
+#define TOGGLE_CEC_HARDWARE_FSM
+
+#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 <mach/socinfo.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
+
+static int msm_hdmi_sample_rate = MSM_HDMI_SAMPLE_RATE_48KHZ;
+
+/* HDMI/HDCP Registers */
+#define HDCP_DDC_STATUS 0x0128
+#define HDCP_DDC_CTRL_0 0x0120
+#define HDCP_DDC_CTRL_1 0x0124
+#define HDMI_DDC_CTRL 0x020C
+
+struct workqueue_struct *hdmi_work_queue;
+struct hdmi_msm_state_type *hdmi_msm_state;
+
+DEFINE_MUTEX(hdmi_msm_state_mutex);
+EXPORT_SYMBOL(hdmi_msm_state_mutex);
+static DEFINE_MUTEX(hdcp_auth_state_mutex);
+
+static void hdmi_msm_dump_regs(const char *prefix);
+
+#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
+
+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);
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+
+static void hdmi_msm_cec_line_latch_detect(void);
+
+#ifdef TOGGLE_CEC_HARDWARE_FSM
+static boolean msg_send_complete = TRUE;
+static boolean msg_recv_complete = TRUE;
+#endif
+
+#define HDMI_MSM_CEC_REFTIMER_REFTIMER_ENABLE BIT(16)
+#define HDMI_MSM_CEC_REFTIMER_REFTIMER(___t) (((___t)&0xFFFF) << 0)
+
+#define HDMI_MSM_CEC_TIME_SIGNAL_FREE_TIME(___t) (((___t)&0x1FF) << 7)
+#define HDMI_MSM_CEC_TIME_ENABLE BIT(0)
+
+#define HDMI_MSM_CEC_ADDR_LOGICAL_ADDR(___la) (((___la)&0xFF) << 0)
+
+#define HDMI_MSM_CEC_CTRL_LINE_OE BIT(9)
+#define HDMI_MSM_CEC_CTRL_FRAME_SIZE(___sz) (((___sz)&0x1F) << 4)
+#define HDMI_MSM_CEC_CTRL_SOFT_RESET BIT(2)
+#define HDMI_MSM_CEC_CTRL_SEND_TRIG BIT(1)
+#define HDMI_MSM_CEC_CTRL_ENABLE BIT(0)
+
+#define HDMI_MSM_CEC_INT_FRAME_RD_DONE_MASK BIT(7)
+#define HDMI_MSM_CEC_INT_FRAME_RD_DONE_ACK BIT(6)
+#define HDMI_MSM_CEC_INT_FRAME_RD_DONE_INT BIT(6)
+#define HDMI_MSM_CEC_INT_MONITOR_MASK BIT(5)
+#define HDMI_MSM_CEC_INT_MONITOR_ACK BIT(4)
+#define HDMI_MSM_CEC_INT_MONITOR_INT BIT(4)
+#define HDMI_MSM_CEC_INT_FRAME_ERROR_MASK BIT(3)
+#define HDMI_MSM_CEC_INT_FRAME_ERROR_ACK BIT(2)
+#define HDMI_MSM_CEC_INT_FRAME_ERROR_INT BIT(2)
+#define HDMI_MSM_CEC_INT_FRAME_WR_DONE_MASK BIT(1)
+#define HDMI_MSM_CEC_INT_FRAME_WR_DONE_ACK BIT(0)
+#define HDMI_MSM_CEC_INT_FRAME_WR_DONE_INT BIT(0)
+
+#define HDMI_MSM_CEC_FRAME_WR_SUCCESS(___st) (((___st)&0xB) ==\
+ (HDMI_MSM_CEC_INT_FRAME_WR_DONE_INT |\
+ HDMI_MSM_CEC_INT_FRAME_WR_DONE_MASK |\
+ HDMI_MSM_CEC_INT_FRAME_ERROR_MASK))
+
+#define HDMI_MSM_CEC_RETRANSMIT_NUM(___num) (((___num)&0xF) << 4)
+#define HDMI_MSM_CEC_RETRANSMIT_ENABLE BIT(0)
+
+#define HDMI_MSM_CEC_WR_DATA_DATA(___d) (((___d)&0xFF) << 8)
+
+
+void hdmi_msm_cec_init(void)
+{
+ /* 0x02A8 CEC_REFTIMER */
+ HDMI_OUTP(0x02A8,
+ HDMI_MSM_CEC_REFTIMER_REFTIMER_ENABLE
+ | HDMI_MSM_CEC_REFTIMER_REFTIMER(27 * 50)
+ );
+
+ /* 0x02A4 CEC_TIME */
+ HDMI_OUTP(0x02A4,
+ HDMI_MSM_CEC_TIME_SIGNAL_FREE_TIME(350)
+ | HDMI_MSM_CEC_TIME_ENABLE
+ );
+
+ /*
+ * 0x02A0 CEC_ADDR
+ * Starting with a default address of 4
+ */
+ HDMI_OUTP(0x02A0, HDMI_MSM_CEC_ADDR_LOGICAL_ADDR(4));
+
+ hdmi_msm_state->first_monitor = 0;
+ hdmi_msm_state->fsm_reset_done = false;
+
+ /* 0x029C CEC_INT */
+ /* Enable CEC interrupts */
+ HDMI_OUTP(0x029C, \
+ HDMI_MSM_CEC_INT_FRAME_WR_DONE_MASK \
+ | HDMI_MSM_CEC_INT_FRAME_ERROR_MASK \
+ | HDMI_MSM_CEC_INT_MONITOR_MASK \
+ | HDMI_MSM_CEC_INT_FRAME_RD_DONE_MASK);
+
+ HDMI_OUTP(0x02B0, 0x7FF << 4 | 1);
+
+ /*
+ * Slight adjustment to logic 1 low periods on read,
+ * CEC Test 8.2-3 was failing, 8 for the
+ * BIT_1_ERR_RANGE_HI = 8 => 750us, the test used 775us,
+ * so increased this to 9 which => 800us.
+ */
+ /*
+ * CEC latch up issue - To fire monitor interrupt
+ * for every start of message
+ */
+ HDMI_OUTP(0x02E0, 0x880000);
+
+ /*
+ * Slight adjustment to logic 0 low period on write
+ */
+ HDMI_OUTP(0x02DC, 0x8888A888);
+
+ /*
+ * Enable Signal Free Time counter and set to 7 bit periods
+ */
+ HDMI_OUTP(0x02A4, 0x1 | (7 * 0x30) << 7);
+
+ /* 0x028C CEC_CTRL */
+ HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
+}
+
+void hdmi_msm_cec_write_logical_addr(int addr)
+{
+ /* 0x02A0 CEC_ADDR
+ * LOGICAL_ADDR 7:0 NUM
+ */
+ HDMI_OUTP(0x02A0, addr & 0xFF);
+}
+
+void hdmi_msm_dump_cec_msg(struct hdmi_msm_cec_msg *msg)
+{
+#ifdef CEC_MSG_PRINT
+ int i;
+ DEV_DBG("sender_id : %d", msg->sender_id);
+ DEV_DBG("recvr_id : %d", msg->recvr_id);
+ if (msg->frame_size < 2) {
+ DEV_DBG("polling message");
+ return;
+ }
+ DEV_DBG("opcode : %02x", msg->opcode);
+ for (i = 0; i < msg->frame_size - 2; i++)
+ DEV_DBG("operand(%2d) : %02x", i + 1, msg->operand[i]);
+#endif /* CEC_MSG_PRINT */
+}
+
+void hdmi_msm_cec_msg_send(struct hdmi_msm_cec_msg *msg)
+{
+ int i;
+ uint32 timeout_count = 1;
+ int retry = 10;
+
+ boolean frameType = (msg->recvr_id == 15 ? BIT(0) : 0);
+
+ mutex_lock(&hdmi_msm_state_mutex);
+ hdmi_msm_state->fsm_reset_done = false;
+ mutex_unlock(&hdmi_msm_state_mutex);
+#ifdef TOGGLE_CEC_HARDWARE_FSM
+ msg_send_complete = FALSE;
+#endif
+
+ INIT_COMPLETION(hdmi_msm_state->cec_frame_wr_done);
+ hdmi_msm_state->cec_frame_wr_status = 0;
+
+ /* 0x0294 HDMI_MSM_CEC_RETRANSMIT */
+ HDMI_OUTP(0x0294,
+ HDMI_MSM_CEC_RETRANSMIT_NUM(msg->retransmit)
+ | (msg->retransmit > 0) ? HDMI_MSM_CEC_RETRANSMIT_ENABLE : 0);
+
+ /* 0x028C CEC_CTRL */
+ HDMI_OUTP(0x028C, 0x1 | msg->frame_size << 4);
+
+ /* 0x0290 CEC_WR_DATA */
+
+ /* header block */
+ HDMI_OUTP(0x0290,
+ HDMI_MSM_CEC_WR_DATA_DATA(msg->sender_id << 4 | msg->recvr_id)
+ | frameType);
+
+ /* data block 0 : opcode */
+ HDMI_OUTP(0x0290,
+ HDMI_MSM_CEC_WR_DATA_DATA(msg->frame_size < 2 ? 0 : msg->opcode)
+ | frameType);
+
+ /* data block 1-14 : operand 0-13 */
+ for (i = 0; i < msg->frame_size - 1; i++)
+ HDMI_OUTP(0x0290,
+ HDMI_MSM_CEC_WR_DATA_DATA(msg->operand[i])
+ | (msg->recvr_id == 15 ? BIT(0) : 0));
+
+ for (; i < 14; i++)
+ HDMI_OUTP(0x0290,
+ HDMI_MSM_CEC_WR_DATA_DATA(0)
+ | (msg->recvr_id == 15 ? BIT(0) : 0));
+
+ while ((HDMI_INP(0x0298) & 1) && retry--) {
+ DEV_DBG("CEC line is busy(%d)\n", retry);
+ schedule();
+ }
+
+ /* 0x028C CEC_CTRL */
+ HDMI_OUTP(0x028C,
+ HDMI_MSM_CEC_CTRL_LINE_OE
+ | HDMI_MSM_CEC_CTRL_FRAME_SIZE(msg->frame_size)
+ | HDMI_MSM_CEC_CTRL_SEND_TRIG
+ | HDMI_MSM_CEC_CTRL_ENABLE);
+
+ timeout_count = wait_for_completion_interruptible_timeout(
+ &hdmi_msm_state->cec_frame_wr_done, HZ);
+
+ if (!timeout_count) {
+ hdmi_msm_state->cec_frame_wr_status |= CEC_STATUS_WR_TMOUT;
+ DEV_ERR("%s: timedout", __func__);
+ hdmi_msm_dump_cec_msg(msg);
+ } else {
+ DEV_DBG("CEC write frame done (frame len=%d)",
+ msg->frame_size);
+ hdmi_msm_dump_cec_msg(msg);
+ }
+
+#ifdef TOGGLE_CEC_HARDWARE_FSM
+ if (!msg_recv_complete) {
+ /* Toggle CEC hardware FSM */
+ HDMI_OUTP(0x028C, 0x0);
+ HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
+ msg_recv_complete = TRUE;
+ }
+ msg_send_complete = TRUE;
+#else
+ HDMI_OUTP(0x028C, 0x0);
+ HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
+#endif
+}
+
+void hdmi_msm_cec_line_latch_detect(void)
+{
+ /*
+ * CECT 9-5-1
+ * The timer period needs to be changed to appropriate value
+ */
+ /*
+ * Timedout without RD_DONE, WR_DONE or ERR_INT
+ * Toggle CEC hardware FSM
+ */
+ mutex_lock(&hdmi_msm_state_mutex);
+ if (hdmi_msm_state->first_monitor == 1) {
+ DEV_WARN("CEC line is probably latched up - CECT 9-5-1");
+ if (!msg_recv_complete)
+ hdmi_msm_state->fsm_reset_done = true;
+ HDMI_OUTP(0x028C, 0x0);
+ HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
+ hdmi_msm_state->first_monitor = 0;
+ }
+ mutex_unlock(&hdmi_msm_state_mutex);
+}
+
+void hdmi_msm_cec_msg_recv(void)
+{
+ uint32 data;
+ int i;
+#ifdef DRVR_ONLY_CECT_NO_DAEMON
+ struct hdmi_msm_cec_msg temp_msg;
+#endif
+ mutex_lock(&hdmi_msm_state_mutex);
+ if (hdmi_msm_state->cec_queue_wr == hdmi_msm_state->cec_queue_rd
+ && hdmi_msm_state->cec_queue_full) {
+ mutex_unlock(&hdmi_msm_state_mutex);
+ DEV_ERR("CEC message queue is overflowing\n");
+#ifdef DRVR_ONLY_CECT_NO_DAEMON
+ /*
+ * Without CEC daemon:
+ * Compliance tests fail once the queue gets filled up.
+ * so reset the pointers to the start of the queue.
+ */
+ hdmi_msm_state->cec_queue_wr = hdmi_msm_state->cec_queue_start;
+ hdmi_msm_state->cec_queue_rd = hdmi_msm_state->cec_queue_start;
+ hdmi_msm_state->cec_queue_full = false;
+#else
+ return;
+#endif
+ }
+ if (hdmi_msm_state->cec_queue_wr == NULL) {
+ DEV_ERR("%s: wp is NULL\n", __func__);
+ return;
+ }
+ mutex_unlock(&hdmi_msm_state_mutex);
+
+ /* 0x02AC CEC_RD_DATA */
+ data = HDMI_INP(0x02AC);
+
+ hdmi_msm_state->cec_queue_wr->sender_id = (data & 0xF0) >> 4;
+ hdmi_msm_state->cec_queue_wr->recvr_id = (data & 0x0F);
+ hdmi_msm_state->cec_queue_wr->frame_size = (data & 0x1F00) >> 8;
+ DEV_DBG("Recvd init=[%u] dest=[%u] size=[%u]\n",
+ hdmi_msm_state->cec_queue_wr->sender_id,
+ hdmi_msm_state->cec_queue_wr->recvr_id,
+ hdmi_msm_state->cec_queue_wr->frame_size);
+
+ if (hdmi_msm_state->cec_queue_wr->frame_size < 1) {
+ DEV_ERR("%s: invalid message (frame length = %d)",
+ __func__, hdmi_msm_state->cec_queue_wr->frame_size);
+ return;
+ } else if (hdmi_msm_state->cec_queue_wr->frame_size == 1) {
+ DEV_DBG("%s: polling message (dest[%x] <- init[%x])",
+ __func__,
+ hdmi_msm_state->cec_queue_wr->recvr_id,
+ hdmi_msm_state->cec_queue_wr->sender_id);
+ return;
+ }
+
+ /* data block 0 : opcode */
+ data = HDMI_INP(0x02AC);
+ hdmi_msm_state->cec_queue_wr->opcode = data & 0xFF;
+
+ /* data block 1-14 : operand 0-13 */
+ for (i = 0; i < hdmi_msm_state->cec_queue_wr->frame_size - 2; i++) {
+ data = HDMI_INP(0x02AC);
+ hdmi_msm_state->cec_queue_wr->operand[i] = data & 0xFF;
+ }
+
+ for (; i < 14; i++)
+ hdmi_msm_state->cec_queue_wr->operand[i] = 0;
+
+ DEV_DBG("CEC read frame done\n");
+ DEV_DBG("=======================================\n");
+ hdmi_msm_dump_cec_msg(hdmi_msm_state->cec_queue_wr);
+ DEV_DBG("=======================================\n");
+
+#ifdef DRVR_ONLY_CECT_NO_DAEMON
+ switch (hdmi_msm_state->cec_queue_wr->opcode) {
+ case 0x64:
+ /* Set OSD String */
+ DEV_INFO("Recvd OSD Str=[%x]\n",\
+ hdmi_msm_state->cec_queue_wr->operand[3]);
+ break;
+ case 0x83:
+ /* Give Phy Addr */
+ DEV_INFO("Recvd a Give Phy Addr cmd\n");
+ memset(&temp_msg, 0x00, sizeof(struct hdmi_msm_cec_msg));
+ /* Setup a frame for sending out phy addr */
+ temp_msg.sender_id = 0x4;
+
+ /* Broadcast */
+ temp_msg.recvr_id = 0xf;
+ temp_msg.opcode = 0x84;
+ i = 0;
+ temp_msg.operand[i++] = 0x10;
+ temp_msg.operand[i++] = 0x00;
+ temp_msg.operand[i++] = 0x04;
+ temp_msg.frame_size = i + 2;
+ hdmi_msm_cec_msg_send(&temp_msg);
+ break;
+ case 0xFF:
+ /* Abort */
+ DEV_INFO("Recvd an abort cmd 0xFF\n");
+ memset(&temp_msg, 0x00, sizeof(struct hdmi_msm_cec_msg));
+ temp_msg.sender_id = 0x4;
+ temp_msg.recvr_id = hdmi_msm_state->cec_queue_wr->sender_id;
+ i = 0;
+
+ /*feature abort */
+ temp_msg.opcode = 0x00;
+ temp_msg.operand[i++] =
+ hdmi_msm_state->cec_queue_wr->opcode;
+
+ /*reason for abort = "Refused" */
+ temp_msg.operand[i++] = 0x04;
+ temp_msg.frame_size = i + 2;
+ hdmi_msm_dump_cec_msg(&temp_msg);
+ hdmi_msm_cec_msg_send(&temp_msg);
+ break;
+ case 0x046:
+ /* Give OSD name */
+ DEV_INFO("Recvd cmd 0x046\n");
+ memset(&temp_msg, 0x00, sizeof(struct hdmi_msm_cec_msg));
+ temp_msg.sender_id = 0x4;
+ temp_msg.recvr_id = hdmi_msm_state->cec_queue_wr->sender_id;
+ i = 0;
+
+ /* OSD Name */
+ temp_msg.opcode = 0x47;
+
+ /* Display control byte */
+ temp_msg.operand[i++] = 0x00;
+ temp_msg.operand[i++] = 'H';
+ temp_msg.operand[i++] = 'e';
+ temp_msg.operand[i++] = 'l';
+ temp_msg.operand[i++] = 'l';
+ temp_msg.operand[i++] = 'o';
+ temp_msg.operand[i++] = ' ';
+ temp_msg.operand[i++] = 'W';
+ temp_msg.operand[i++] = 'o';
+ temp_msg.operand[i++] = 'r';
+ temp_msg.operand[i++] = 'l';
+ temp_msg.operand[i++] = 'd';
+ temp_msg.frame_size = i + 2;
+ hdmi_msm_cec_msg_send(&temp_msg);
+ break;
+ case 0x08F:
+ /* Give Device Power status */
+ DEV_INFO("Recvd a Power status message\n");
+ memset(&temp_msg, 0x00, sizeof(struct hdmi_msm_cec_msg));
+ temp_msg.sender_id = 0x4;
+ temp_msg.recvr_id = hdmi_msm_state->cec_queue_wr->sender_id;
+ i = 0;
+
+ /* OSD String */
+ temp_msg.opcode = 0x90;
+ temp_msg.operand[i++] = 'H';
+ temp_msg.operand[i++] = 'e';
+ temp_msg.operand[i++] = 'l';
+ temp_msg.operand[i++] = 'l';
+ temp_msg.operand[i++] = 'o';
+ temp_msg.operand[i++] = ' ';
+ temp_msg.operand[i++] = 'W';
+ temp_msg.operand[i++] = 'o';
+ temp_msg.operand[i++] = 'r';
+ temp_msg.operand[i++] = 'l';
+ temp_msg.operand[i++] = 'd';
+ temp_msg.frame_size = i + 2;
+ hdmi_msm_cec_msg_send(&temp_msg);
+ break;
+ case 0x080:
+ /* Routing Change cmd */
+ case 0x086:
+ /* Set Stream Path */
+ DEV_INFO("Recvd Set Stream\n");
+ memset(&temp_msg, 0x00, sizeof(struct hdmi_msm_cec_msg));
+ temp_msg.sender_id = 0x4;
+
+ /*Broadcast this message*/
+ temp_msg.recvr_id = 0xf;
+ i = 0;
+ temp_msg.opcode = 0x82; /* Active Source */
+ temp_msg.operand[i++] = 0x10;
+ temp_msg.operand[i++] = 0x00;
+ temp_msg.frame_size = i + 2;
+ hdmi_msm_cec_msg_send(&temp_msg);
+
+ /*
+ * sending <Image View On> message
+ */
+ memset(&temp_msg, 0x00, sizeof(struct hdmi_msm_cec_msg));
+ temp_msg.sender_id = 0x4;
+ temp_msg.recvr_id = hdmi_msm_state->cec_queue_wr->sender_id;
+ i = 0;
+ /* opcode for Image View On */
+ temp_msg.opcode = 0x04;
+ temp_msg.frame_size = i + 2;
+ hdmi_msm_cec_msg_send(&temp_msg);
+ break;
+ case 0x44:
+ /* User Control Pressed */
+ DEV_INFO("User Control Pressed\n");
+ break;
+ case 0x45:
+ /* User Control Released */
+ DEV_INFO("User Control Released\n");
+ break;
+ default:
+ DEV_INFO("Recvd an unknown cmd = [%u]\n",
+ hdmi_msm_state->cec_queue_wr->opcode);
+#ifdef __SEND_ABORT__
+ memset(&temp_msg, 0x00, sizeof(struct hdmi_msm_cec_msg));
+ temp_msg.sender_id = 0x4;
+ temp_msg.recvr_id = hdmi_msm_state->cec_queue_wr->sender_id;
+ i = 0;
+ /* opcode for feature abort */
+ temp_msg.opcode = 0x00;
+ temp_msg.operand[i++] =
+ hdmi_msm_state->cec_queue_wr->opcode;
+ /*reason for abort = "Unrecognized opcode" */
+ temp_msg.operand[i++] = 0x00;
+ temp_msg.frame_size = i + 2;
+ hdmi_msm_cec_msg_send(&temp_msg);
+ break;
+#else
+ memset(&temp_msg, 0x00, sizeof(struct hdmi_msm_cec_msg));
+ temp_msg.sender_id = 0x4;
+ temp_msg.recvr_id = hdmi_msm_state->cec_queue_wr->sender_id;
+ i = 0;
+ /* OSD String */
+ temp_msg.opcode = 0x64;
+ temp_msg.operand[i++] = 0x0;
+ temp_msg.operand[i++] = 'H';
+ temp_msg.operand[i++] = 'e';
+ temp_msg.operand[i++] = 'l';
+ temp_msg.operand[i++] = 'l';
+ temp_msg.operand[i++] = 'o';
+ temp_msg.operand[i++] = ' ';
+ temp_msg.operand[i++] = 'W';
+ temp_msg.operand[i++] = 'o';
+ temp_msg.operand[i++] = 'r';
+ temp_msg.operand[i++] = 'l';
+ temp_msg.operand[i++] = 'd';
+ temp_msg.frame_size = i + 2;
+ hdmi_msm_cec_msg_send(&temp_msg);
+ break;
+#endif /* __SEND_ABORT__ */
+ }
+
+#endif /* DRVR_ONLY_CECT_NO_DAEMON */
+ mutex_lock(&hdmi_msm_state_mutex);
+ hdmi_msm_state->cec_queue_wr++;
+ if (hdmi_msm_state->cec_queue_wr == CEC_QUEUE_END)
+ hdmi_msm_state->cec_queue_wr = hdmi_msm_state->cec_queue_start;
+ if (hdmi_msm_state->cec_queue_wr == hdmi_msm_state->cec_queue_rd)
+ hdmi_msm_state->cec_queue_full = true;
+ mutex_unlock(&hdmi_msm_state_mutex);
+ DEV_DBG("Exiting %s()\n", __func__);
+}
+
+void hdmi_msm_cec_one_touch_play(void)
+{
+ struct hdmi_msm_cec_msg temp_msg;
+ uint32 i = 0;
+ memset(&temp_msg, 0x00, sizeof(struct hdmi_msm_cec_msg));
+ temp_msg.sender_id = 0x4;
+ /*
+ * Broadcast this message
+ */
+ temp_msg.recvr_id = 0xf;
+ i = 0;
+ /* Active Source */
+ temp_msg.opcode = 0x82;
+ temp_msg.operand[i++] = 0x10;
+ temp_msg.operand[i++] = 0x00;
+ /*temp_msg.operand[i++] = 0x04;*/
+ temp_msg.frame_size = i + 2;
+ hdmi_msm_cec_msg_send(&temp_msg);
+ /*
+ * sending <Image View On> message
+ */
+ memset(&temp_msg, 0x00, sizeof(struct hdmi_msm_cec_msg));
+ temp_msg.sender_id = 0x4;
+ temp_msg.recvr_id = hdmi_msm_state->cec_queue_wr->sender_id;
+ i = 0;
+ /* Image View On */
+ temp_msg.opcode = 0x04;
+ temp_msg.frame_size = i + 2;
+ hdmi_msm_cec_msg_send(&temp_msg);
+
+}
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT */
+
+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_send_event(boolean on)
+{
+ char *envp[2];
+
+ /* QDSP OFF preceding the HPD event notification */
+ envp[0] = "HDCP_STATE=FAIL";
+ envp[1] = NULL;
+ DEV_ERR("hdmi: HDMI HPD: QDSP OFF\n");
+ kobject_uevent_env(external_common_state->uevent_kobj,
+ KOBJ_CHANGE, envp);
+
+ if (on) {
+ /* Build EDID table */
+ hdmi_msm_read_edid();
+ switch_set_state(&external_common_state->sdev, 1);
+ DEV_INFO("Hdmi state switched to %d: %s\n",
+ external_common_state->sdev.state, __func__);
+
+ DEV_INFO("HDMI HPD: CONNECTED: send ONLINE\n");
+ kobject_uevent(external_common_state->uevent_kobj, KOBJ_ONLINE);
+#ifndef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ /* Send Audio for HDMI Compliance Cases*/
+ envp[0] = "HDCP_STATE=PASS";
+ envp[1] = NULL;
+ DEV_INFO("HDMI HPD: sense : send HDCP_PASS\n");
+ kobject_uevent_env(external_common_state->uevent_kobj,
+ KOBJ_CHANGE, envp);
+#endif
+ } else {
+ switch_set_state(&external_common_state->sdev, 0);
+ DEV_INFO("hdmi: Hdmi state switch to %d: %s\n",
+ external_common_state->sdev.state, __func__);
+ DEV_INFO("hdmi: HDMI HPD: sense DISCONNECTED: send OFFLINE\n");
+ kobject_uevent(external_common_state->uevent_kobj,
+ KOBJ_OFFLINE);
+ }
+}
+
+static void hdmi_msm_hpd_state_work(struct work_struct *work)
+{
+ boolean hpd_state;
+
+ if (!hdmi_msm_state || !hdmi_msm_state->hpd_initialized ||
+ !MSM_HDMI_BASE) {
+ DEV_ERR("hdmi: %s: ignored, probe failed\n", __func__);
+ return;
+ }
+
+ mutex_lock(&hdmi_msm_state_mutex);
+ DEV_DBG("%s: Handling HPD event in the workqueue\n", __func__);
+
+ if (!hdmi_msm_state->hpd_cable_chg_detected) {
+ /* The work item got called from outside the ISR */
+ mutex_unlock(&hdmi_msm_state_mutex);
+ if (external_common_state->hpd_state) {
+ if (!external_common_state->
+ disp_mode_list.num_of_elements)
+ hdmi_msm_read_edid();
+ }
+ } else {
+ hdmi_msm_state->hpd_cable_chg_detected = FALSE;
+ mutex_unlock(&hdmi_msm_state_mutex);
+ mutex_lock(&external_common_state_hpd_mutex);
+ /*
+ * Handle the connect event only if the cable is
+ * still connected. This check is needed for the case
+ * where we get a connect event followed by a disconnect
+ * event in quick succession. In this case, there is no need
+ * to process the connect event.
+ */
+ if ((external_common_state->hpd_state) &&
+ !((HDMI_INP(0x0250) & 0x2) >> 1)) {
+ external_common_state->hpd_state = 0;
+ hdmi_msm_state->hpd_state_in_isr = 0;
+ mutex_unlock(&external_common_state_hpd_mutex);
+ DEV_DBG("%s: Ignoring HPD connect event\n", __func__);
+ return;
+ }
+ mutex_unlock(&external_common_state_hpd_mutex);
+ hdmi_msm_send_event(external_common_state->hpd_state);
+ }
+
+ /*
+ * Wait for a short time before checking for
+ * any changes in the connection status
+ */
+ udelay(100);
+
+ mutex_lock(&external_common_state_hpd_mutex);
+ /* HPD_INT_STATUS[0x0250] */
+ hpd_state = (HDMI_INP(0x0250) & 0x2) >> 1;
+
+ if (external_common_state->hpd_state != hpd_state) {
+ external_common_state->hpd_state = hpd_state;
+ hdmi_msm_state->hpd_state_in_isr = hpd_state;
+ mutex_unlock(&external_common_state_hpd_mutex);
+ hdmi_msm_send_event(hpd_state);
+ } else {
+ mutex_unlock(&external_common_state_hpd_mutex);
+ }
+}
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+static void hdmi_msm_cec_latch_work(struct work_struct *work)
+{
+ hdmi_msm_cec_line_latch_detect();
+}
+#endif
+
+#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)
+{
+
+ /* 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();
+ mutex_lock(&hdcp_auth_state_mutex);
+ hdmi_msm_state->reauth = TRUE;
+ mutex_unlock(&hdcp_auth_state_mutex);
+ mod_timer(&hdmi_msm_state->hdcp_timer, jiffies + HZ/2);
+ }
+}
+
+static void hdmi_msm_hdcp_work(struct work_struct *work)
+{
+ /* 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);
+ if (hdmi_msm_state->reauth == TRUE) {
+ DEV_DBG("%s: Starting HDCP re-authentication\n",
+ __func__);
+ hdmi_msm_turn_on();
+ } else {
+ DEV_DBG("%s: Starting HDCP authentication\n", __func__);
+ hdmi_msm_hdcp_enable();
+ }
+ } else {
+ mutex_unlock(&external_common_state_hpd_mutex);
+ DEV_DBG("%s: HDMI not connected or HDCP already active\n",
+ __func__);
+ hdmi_msm_state->reauth = FALSE;
+ }
+}
+#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;
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+ uint32 cec_intr_status;
+#endif
+ 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;
+ }
+
+ /* 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;
+ DEV_DBG("%s: HPD IRQ, Ctrl=%04x, State=%04x\n", __func__,
+ hpd_int_ctrl, hpd_int_status);
+
+ /* Ack the interrupt */
+ HDMI_OUTP(0x0254, (hpd_int_ctrl | (1 << 0)));
+
+ mutex_lock(&external_common_state_hpd_mutex);
+ if (hdmi_msm_state->hpd_state_in_isr == cable_detected) {
+ DEV_INFO("%s: HPD has the same state. Ignoring\n",
+ __func__);
+ mutex_unlock(&external_common_state_hpd_mutex);
+ } else {
+ if (!mod_timer(&hdmi_msm_state->hpd_state_timer,
+ jiffies + HZ/2)) {
+ hdmi_msm_state->hpd_state_in_isr =
+ cable_detected;
+ hdmi_msm_state->hpd_cable_chg_detected = TRUE;
+ DEV_DBG("%s: Scheduled work to handle HPD %s\n",
+ __func__,
+ cable_detected ? "connect"
+ : "disconnect");
+ }
+
+ mutex_unlock(&external_common_state_hpd_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->hdcp_activating &&
+ !(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);
+ }
+ }
+
+ /* Set up HPD_CTRL to sense HPD event */
+ HDMI_OUTP(0x0254, 4 | (cable_detected ? 0 : 2));
+ DEV_DBG("%s: Setting HPD_CTRL=%d\n", __func__,
+ HDMI_INP(0x0254));
+
+ 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 */
+ uint32 link_status = HDMI_INP_ND(0x011C);
+ HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 5))
+ & ~((1 << 6) | (1 << 4)));
+ DEV_INFO("HDCP: AUTH_FAIL_INT received, LINK0_STATUS=0x%08x\n",
+ link_status);
+ if (hdmi_msm_state->full_auth_done) {
+ switch_set_state(&external_common_state->sdev, 0);
+ DEV_INFO("Hdmi state switched to %d: %s\n",
+ external_common_state->sdev.state, __func__);
+
+ 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. Also, No need to reauthenticate
+ * if authentication failed because of cable disconnect
+ */
+ if (((link_status & 0xF0) >> 4) != 0x7) {
+ DEV_DBG("Reauthenticate From %s HDCP FAIL INT ",
+ __func__);
+ queue_work(hdmi_work_queue,
+ &hdmi_msm_state->hdcp_reauth_work);
+ } else {
+ DEV_INFO("HDCP: HDMI cable disconnected\n");
+ }
+ }
+
+ /* Clear AUTH_FAIL_INFO as well */
+ HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 7)));
+ 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 */
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+ /* Process CEC Interrupt */
+ /* HDMI_MSM_CEC_INT[0x029C] */
+ cec_intr_status = HDMI_INP_ND(0x029C);
+
+ DEV_DBG("cec interrupt status is [%u]\n", cec_intr_status);
+
+ if (HDMI_MSM_CEC_FRAME_WR_SUCCESS(cec_intr_status)) {
+ DEV_DBG("CEC_IRQ_FRAME_WR_DONE\n");
+ HDMI_OUTP(0x029C, cec_intr_status |
+ HDMI_MSM_CEC_INT_FRAME_WR_DONE_ACK);
+ mutex_lock(&hdmi_msm_state_mutex);
+ hdmi_msm_state->cec_frame_wr_status |= CEC_STATUS_WR_DONE;
+ hdmi_msm_state->first_monitor = 0;
+ del_timer(&hdmi_msm_state->cec_read_timer);
+ mutex_unlock(&hdmi_msm_state_mutex);
+ complete(&hdmi_msm_state->cec_frame_wr_done);
+ return IRQ_HANDLED;
+ }
+ if ((cec_intr_status & (1 << 2)) && (cec_intr_status & (1 << 3))) {
+ DEV_DBG("CEC_IRQ_FRAME_ERROR\n");
+#ifdef TOGGLE_CEC_HARDWARE_FSM
+ /* Toggle CEC hardware FSM */
+ HDMI_OUTP(0x028C, 0x0);
+ HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
+#endif
+ HDMI_OUTP(0x029C, cec_intr_status);
+ mutex_lock(&hdmi_msm_state_mutex);
+ hdmi_msm_state->first_monitor = 0;
+ del_timer(&hdmi_msm_state->cec_read_timer);
+ hdmi_msm_state->cec_frame_wr_status |= CEC_STATUS_WR_ERROR;
+ mutex_unlock(&hdmi_msm_state_mutex);
+ complete(&hdmi_msm_state->cec_frame_wr_done);
+ return IRQ_HANDLED;
+ }
+
+ if ((cec_intr_status & (1 << 4)) && (cec_intr_status & (1 << 5))) {
+ DEV_DBG("CEC_IRQ_MONITOR\n");
+ HDMI_OUTP(0x029C, cec_intr_status |
+ HDMI_MSM_CEC_INT_MONITOR_ACK);
+
+ /*
+ * CECT 9-5-1
+ * On the first occassion start a timer
+ * for few hundred ms, if it expires then
+ * reset the CEC block else go on with
+ * frame transactions as usual.
+ * Below adds hdmi_msm_cec_msg_recv() as an
+ * item into the work queue instead of running in
+ * interrupt context
+ */
+ mutex_lock(&hdmi_msm_state_mutex);
+ if (hdmi_msm_state->first_monitor == 0) {
+ /* This timer might have to be changed
+ * worst case theoritical =
+ * 16 bytes * 8 * 2.7msec = 346 msec
+ */
+ mod_timer(&hdmi_msm_state->cec_read_timer,
+ jiffies + HZ/2);
+ hdmi_msm_state->first_monitor = 1;
+ }
+ mutex_unlock(&hdmi_msm_state_mutex);
+ return IRQ_HANDLED;
+ }
+
+ if ((cec_intr_status & (1 << 6)) && (cec_intr_status & (1 << 7))) {
+ DEV_DBG("CEC_IRQ_FRAME_RD_DONE\n");
+
+ mutex_lock(&hdmi_msm_state_mutex);
+ hdmi_msm_state->first_monitor = 0;
+ del_timer(&hdmi_msm_state->cec_read_timer);
+ mutex_unlock(&hdmi_msm_state_mutex);
+ HDMI_OUTP(0x029C, cec_intr_status |
+ HDMI_MSM_CEC_INT_FRAME_RD_DONE_ACK);
+ hdmi_msm_cec_msg_recv();
+
+#ifdef TOGGLE_CEC_HARDWARE_FSM
+ if (!msg_send_complete)
+ msg_recv_complete = FALSE;
+ else {
+ /* Toggle CEC hardware FSM */
+ HDMI_OUTP(0x028C, 0x0);
+ HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
+ }
+#else
+ HDMI_OUTP(0x028C, 0x0);
+ HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
+#endif
+
+ return IRQ_HANDLED;
+ }
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT */
+
+ DEV_DBG("%s: HPD<Ctrl=%04x, State=%04x>, ddc_int_ctrl=%04x, "
+ "aud_int=%04x, cec_intr_status=%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;
+}
+
+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;
+ if (external_common_state->present_hdcp)
+ /* HDMI Encryption */
+ reg_val |= 0x00000004;
+ /* HDMI_CTRL */
+ HDMI_OUTP(0x0000, reg_val);
+ /* HDMI_DVI_SEL */
+ reg_val &= ~0x00000002;
+ } else {
+ if (external_common_state->present_hdcp)
+ /* HDMI_Encryption_ON */
+ reg_val |= 0x00000006;
+ else
+ reg_val |= 0x00000002;
+ }
+ } else
+ reg_val = 0x00000002;
+
+ /* HDMI_CTRL */
+ HDMI_OUTP(0x0000, reg_val);
+ DEV_DBG("HDMI Core: %s, HDMI_CTRL=0x%08x\n",
+ power_on ? "Enable" : "Disable", reg_val);
+}
+
+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
+ * Setting 31:24 bits : Time units to wait before timeout
+ * when clock is being stalled by external sink device
+ */
+ HDMI_OUTP_ND(0x0224, 0xff000000);
+
+ /* 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 = 0x5 (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 | (5 << 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);
+
+ /* Disable HDCP interrupts */
+ HDMI_OUTP(0x0118, 0x0);
+
+ mutex_lock(&hdcp_auth_state_mutex);
+ external_common_state->hdcp_active = FALSE;
+ mutex_unlock(&hdcp_auth_state_mutex);
+ /* 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 void check_and_clear_HDCP_DDC_Failure(void)
+{
+ int hdcp_ddc_ctrl1_reg;
+ int hdcp_ddc_status;
+ int failure;
+ int nack0;
+
+ /*
+ * Check for any DDC transfer failures
+ * 0x0128 HDCP_DDC_STATUS
+ * [16] FAILED Indicates that the last HDCP HW DDC transer
+ * failed. This occurs when a transfer is
+ * attempted with HDCP DDC disabled
+ * (HDCP_DDC_DISABLE=1) or the number of retries
+ * match HDCP_DDC_RETRY_CNT
+ *
+ * [14] NACK0 Indicates that the last HDCP HW DDC transfer
+ * was aborted due to a NACK on the first
+ * transaction - cleared by writing 0 to GO bit
+ */
+ hdcp_ddc_status = HDMI_INP(HDCP_DDC_STATUS);
+ failure = (hdcp_ddc_status >> 16) & 0x1;
+ nack0 = (hdcp_ddc_status >> 14) & 0x1;
+ DEV_DBG("%s: On Entry: HDCP_DDC_STATUS = 0x%x, FAILURE = %d,"
+ "NACK0 = %d\n", __func__ , hdcp_ddc_status, failure, nack0);
+
+ if (failure == 0x1) {
+ /*
+ * Indicates that the last HDCP HW DDC transfer failed.
+ * This occurs when a transfer is attempted with HDCP DDC
+ * disabled (HDCP_DDC_DISABLE=1) or the number of retries
+ * matches HDCP_DDC_RETRY_CNT.
+ * Failure occured, let's clear it.
+ */
+ DEV_INFO("%s: DDC failure detected. HDCP_DDC_STATUS=0x%08x\n",
+ __func__, hdcp_ddc_status);
+ /*
+ * First, Disable DDC
+ * 0x0120 HDCP_DDC_CTRL_0
+ * [0] DDC_DISABLE Determines whether HDCP Ri and Pj reads
+ * are done unassisted by hardware or by
+ * software via HDMI_DDC (HDCP provides
+ * interrupts to request software
+ * transfers)
+ * 0 : Use Hardware DDC
+ * 1 : Use Software DDC
+ */
+ HDMI_OUTP(HDCP_DDC_CTRL_0, 0x1);
+
+ /*
+ * ACK the Failure to Clear it
+ * 0x0124 HDCP_DDC_CTRL_1
+ * [0] DDC_FAILED_ACK Write 1 to clear
+ * HDCP_STATUS.HDCP_DDC_FAILED
+ */
+ hdcp_ddc_ctrl1_reg = HDMI_INP(HDCP_DDC_CTRL_1);
+ HDMI_OUTP(HDCP_DDC_CTRL_1, hdcp_ddc_ctrl1_reg | 0x1);
+
+ /* Check if the FAILURE got Cleared */
+ hdcp_ddc_status = HDMI_INP(HDCP_DDC_STATUS);
+ hdcp_ddc_status = (hdcp_ddc_status >> 16) & 0x1;
+ if (hdcp_ddc_status == 0x0) {
+ DEV_INFO("%s: HDCP DDC Failure has been cleared\n",
+ __func__);
+ } else {
+ DEV_WARN("%s: Error: HDCP DDC Failure DID NOT get"
+ "cleared\n", __func__);
+ }
+
+ /* Re-Enable HDCP DDC */
+ HDMI_OUTP(HDCP_DDC_CTRL_0, 0x0);
+ }
+
+ if (nack0 == 0x1) {
+ /*
+ * 0x020C HDMI_DDC_CTRL
+ * [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
+ */
+ HDMI_OUTP_ND(HDMI_DDC_CTRL,
+ HDMI_INP(HDMI_DDC_CTRL) | (0x1 << 3));
+ msleep(20);
+ HDMI_OUTP_ND(HDMI_DDC_CTRL,
+ HDMI_INP(HDMI_DDC_CTRL) & ~(0x1 << 3));
+ }
+
+ hdcp_ddc_status = HDMI_INP(HDCP_DDC_STATUS);
+
+ failure = (hdcp_ddc_status >> 16) & 0x1;
+ nack0 = (hdcp_ddc_status >> 14) & 0x1;
+ DEV_DBG("%s: On Exit: HDCP_DDC_STATUS = 0x%x, FAILURE = %d,"
+ "NACK0 = %d\n", __func__ , hdcp_ddc_status, failure, nack0);
+}
+
+
+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, 0x0);
+
+ /* 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));
+
+ /*
+ * Check to see if a HDCP DDC Failure is indicated in
+ * HDCP_DDC_STATUS. If yes, clear it.
+ */
+ check_and_clear_HDCP_DDC_Failure();
+
+ /* 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 */
+
+ mutex_lock(&hdcp_auth_state_mutex);
+ 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);
+ mutex_unlock(&hdcp_auth_state_mutex);
+ goto error;
+ }
+
+ /*
+ * A small delay is needed here to avoid device crash observed
+ * during reauthentication in MSM8960
+ */
+ msleep(20);
+
+ /* 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);
+ mutex_unlock(&hdcp_auth_state_mutex);
+
+ /* 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;
+ }
+
+ DEV_DBG("HDCP: R0'=%02x%02x\n", buf[1], buf[0]);
+ INIT_COMPLETION(hdmi_msm_state->hdcp_success_done);
+ /* 0x013C HDCP_RCVPORT_DATA2_0
+ [15:0] LINK0_RI */
+ HDMI_OUTP(0x013C, (((uint32)buf[1]) << 8) | buf[0]);
+
+ 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);
+
+ /* Once 64 bytes have been written, we need to poll for
+ * HDCP_SHA_BLOCK_DONE before writing any further
+ */
+ if (i && !((i+1)%64)) {
+ timeout_count = 100;
+ while (!(HDMI_INP_ND(0x0240) & 0x1)
+ && (--timeout_count)) {
+ DEV_DBG("HDCP Auth Part II: Waiting for the "
+ "computation of the current 64 byte to "
+ "complete. HDCP_SHA_STATUS=%08x. "
+ "timeout_count=%d\n",
+ HDMI_INP_ND(0x0240), timeout_count);
+ msleep(20);
+ }
+ if (!timeout_count) {
+ ret = -ETIMEDOUT;
+ DEV_ERR("%s(%d): timedout", __func__, __LINE__);
+ goto error;
+ }
+ }
+
+ }
+
+ /* 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) & 0xFFFFFF10)) && --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()) {
+ DEV_INFO("%s: HDCP NOT ENABLED\n", __func__);
+ 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();
+
+ 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;
+ external_common_state->hdcp_active = 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);
+ }
+
+ switch_set_state(&external_common_state->sdev, 1);
+ DEV_INFO("Hdmi state switched to %d: %s\n",
+ external_common_state->sdev.state, __func__);
+ 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);
+ }
+ switch_set_state(&external_common_state->sdev, 0);
+ DEV_INFO("Hdmi state switched to %d: %s\n",
+ external_common_state->sdev.state, __func__);
+}
+#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.027MHz */
+ HDMI_MSM_AUDIO_ARCS(27030, {
+ {4096, 27027}, {6272, 30030}, {6144, 27027}, {12544, 30030},
+ {12288, 27027}, {25088, 30030}, {24576, 27027} }),
+ /* 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);
+
+ mb();
+ pr_info("%s :HDMI_AUDIO_CFG 0x%08x\n", __func__,
+ HDMI_INP(HDMI_AUDIO_CFG));
+
+ return 0;
+}
+EXPORT_SYMBOL(hdmi_audio_enable);
+
+#define HDMI_AUDIO_PKT_CTRL 0x0020
+#define HDMI_AUDIO_SAMPLE_SEND_ENABLE 1
+
+int hdmi_audio_packet_enable(bool on)
+{
+ u32 hdmi_audio_pkt_ctrl;
+ hdmi_audio_pkt_ctrl = HDMI_INP(HDMI_AUDIO_PKT_CTRL);
+
+ if (on)
+ hdmi_audio_pkt_ctrl |= HDMI_AUDIO_SAMPLE_SEND_ENABLE;
+ else
+ hdmi_audio_pkt_ctrl &= ~(HDMI_AUDIO_SAMPLE_SEND_ENABLE);
+
+ HDMI_OUTP(HDMI_AUDIO_PKT_CTRL, hdmi_audio_pkt_ctrl);
+
+ mb();
+ pr_info("%s : HDMI_AUDIO_PKT_CTRL 0x%08x\n", __func__,
+ HDMI_INP(HDMI_AUDIO_PKT_CTRL));
+ return 0;
+}
+EXPORT_SYMBOL(hdmi_audio_packet_enable);
+
+
+/* TO-DO: return -EINVAL when num_of_channels and channel_allocation
+ * does not match CEA 861-D spec.
+*/
+int hdmi_msm_audio_info_setup(bool enabled, u32 num_of_channels,
+ u32 channel_allocation, u32 level_shift, bool down_mix)
+{
+ 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;
+ u32 aud_pck_ctrl_2_reg;
+ u32 layout;
+
+ layout = (MSM_HDMI_AUDIO_CHANNEL_2 == num_of_channels) ? 0 : 1;
+ aud_pck_ctrl_2_reg = 1 | (layout << 1);
+ HDMI_OUTP(0x00044, aud_pck_ctrl_2_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:
+ channel_allocation = 0; /* Default to FR,FL */
+ 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:
+ pr_err("%s(): Unsupported num_of_channels = %u\n",
+ __func__, num_of_channels);
+ return -EINVAL;
+ 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);
+
+
+ hdmi_msm_dump_regs("HDMI-AUDIO-ON: ");
+
+ return 0;
+
+}
+EXPORT_SYMBOL(hdmi_msm_audio_info_setup);
+
+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);
+}
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_ISRC_ACP_SUPPORT
+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);
+}
+#else
+static void hdmi_msm_en_isrc_packet(boolean isrc_is_continued)
+{
+ /*
+ * Until end-to-end support for various audio packets
+ */
+}
+#endif
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_ISRC_ACP_SUPPORT
+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);
+}
+#else
+static void hdmi_msm_en_acp_packet(uint32 byte1)
+{
+ /*
+ * Until end-to-end support for various audio packets
+ */
+}
+#endif
+
+int hdmi_msm_audio_get_sample_rate(void)
+{
+ return msm_hdmi_sample_rate;
+}
+EXPORT_SYMBOL(hdmi_msm_audio_get_sample_rate);
+
+void hdmi_msm_audio_sample_rate_reset(int rate)
+{
+ msm_hdmi_sample_rate = rate;
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ if (hdmi_msm_has_hdcp())
+ hdcp_deauthenticate();
+ else
+#endif
+ hdmi_msm_turn_on();
+}
+EXPORT_SYMBOL(hdmi_msm_audio_sample_rate_reset);
+
+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);
+ DEV_DBG("Not setting ACP, ISRC1, ISRC2 packets\n");
+ hdmi_msm_audio_acr_setup(TRUE,
+ external_common_state->video_resolution,
+ msm_hdmi_sample_rate, channels);
+ hdmi_msm_audio_info_setup(TRUE, channels, 0, 0, FALSE);
+
+ /* 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, 0, FALSE);
+ hdmi_msm_audio_acr_setup(FALSE, 0, 0, 0);
+ DEV_INFO("HDMI Audio: Disabled\n");
+ return 0;
+}
+
+
+static uint8 hdmi_msm_avi_iframe_lut[][16] = {
+/* 480p60 480i60 576p50 576i50 720p60 720p50 1080p60 1080i60 1080p50
+ 1080i50 1080p24 1080p30 1080p25 640x480p 480p60_16_9 576p50_4_3 */
+ {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, /*00*/
+ {0x18, 0x18, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+ 0x28, 0x28, 0x28, 0x28, 0x18, 0x28, 0x18}, /*01*/
+ {0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x88, 0x04, 0x04}, /*02*/
+ {0x02, 0x06, 0x11, 0x15, 0x04, 0x13, 0x10, 0x05, 0x1F,
+ 0x14, 0x20, 0x22, 0x21, 0x01, 0x03, 0x11}, /*03*/
+ {0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*04*/
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*05*/
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*06*/
+ {0xE1, 0xE1, 0x41, 0x41, 0xD1, 0xd1, 0x39, 0x39, 0x39,
+ 0x39, 0x39, 0x39, 0x39, 0xe1, 0xE1, 0x41}, /*07*/
+ {0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x01, 0x01, 0x02}, /*08*/
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*09*/
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*10*/
+ {0xD1, 0xD1, 0xD1, 0xD1, 0x01, 0x01, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0xD1, 0xD1}, /*11*/
+ {0x02, 0x02, 0x02, 0x02, 0x05, 0x05, 0x07, 0x07, 0x07,
+ 0x07, 0x07, 0x07, 0x07, 0x02, 0x02, 0x02} /*12*/
+};
+
+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;
+ boolean use_ce_scan_info = TRUE;
+
+ switch (external_common_state->video_resolution) {
+ case HDMI_VFRMT_720x480p60_4_3:
+ 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;
+ case HDMI_VFRMT_720x480p60_16_9:
+ mode = 14;
+ break;
+ case HDMI_VFRMT_720x576p50_4_3:
+ mode = 15;
+ 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];
+
+ /*
+ * If the sink specified support for both underscan/overscan
+ * then, by default, set the underscan bit.
+ * Only checking underscan support for preferred format and cea formats
+ */
+ if ((external_common_state->video_resolution ==
+ external_common_state->preferred_video_format)) {
+ use_ce_scan_info = FALSE;
+ switch (external_common_state->pt_scan_info) {
+ case 0:
+ /*
+ * Need to use the info specified for the corresponding
+ * IT or CE format
+ */
+ DEV_DBG("%s: No underscan information specified for the"
+ " preferred video format\n", __func__);
+ use_ce_scan_info = TRUE;
+ break;
+ case 3:
+ DEV_DBG("%s: Setting underscan bit for the preferred"
+ " video format\n", __func__);
+ aviInfoFrame[3] |= 0x02;
+ break;
+ default:
+ DEV_DBG("%s: Underscan information not set for the"
+ " preferred video format\n", __func__);
+ break;
+ }
+ }
+
+ if (use_ce_scan_info) {
+ if (3 == external_common_state->ce_scan_info) {
+ DEV_DBG("%s: Setting underscan bit for the CE video"
+ " format\n", __func__);
+ aviInfoFrame[3] |= 0x02;
+ } else {
+ DEV_DBG("%s: Not setting underscan bit for the CE video"
+ " format\n", __func__);
+ }
+ }
+
+ /* 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);
+}
+
+#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
+
+#define IFRAME_CHECKSUM_32(d) \
+ ((d & 0xff) + ((d >> 8) & 0xff) + \
+ ((d >> 16) & 0xff) + ((d >> 24) & 0xff))
+
+static void hdmi_msm_spd_infoframe_packetsetup(void)
+{
+ uint32 packet_header = 0;
+ uint32 check_sum = 0;
+ uint32 packet_payload = 0;
+ uint32 packet_control = 0;
+
+ uint8 *vendor_name = external_common_state->spd_vendor_name;
+ uint8 *product_description =
+ external_common_state->spd_product_description;
+
+ /* 0x00A4 GENERIC1_HDR
+ * HB0 7:0 NUM
+ * HB1 15:8 NUM
+ * HB2 23:16 NUM */
+ /* Setup Packet header and payload */
+ /* 0x83 InfoFrame Type Code
+ 0x01 InfoFrame Version Number
+ 0x19 Length of Source Product Description InfoFrame
+ */
+ packet_header = 0x83 | (0x01 << 8) | (0x19 << 16);
+ HDMI_OUTP(0x00A4, packet_header);
+ check_sum += IFRAME_CHECKSUM_32(packet_header);
+
+ /* 0x00AC GENERIC1_1
+ * BYTE4 7:0 VENDOR_NAME[3]
+ * BYTE5 15:8 VENDOR_NAME[4]
+ * BYTE6 23:16 VENDOR_NAME[5]
+ * BYTE7 31:24 VENDOR_NAME[6] */
+ packet_payload = (vendor_name[3] & 0x7f)
+ | ((vendor_name[4] & 0x7f) << 8)
+ | ((vendor_name[5] & 0x7f) << 16)
+ | ((vendor_name[6] & 0x7f) << 24);
+ HDMI_OUTP(0x00AC, packet_payload);
+ check_sum += IFRAME_CHECKSUM_32(packet_payload);
+
+ /* Product Description (7-bit ASCII code) */
+ /* 0x00B0 GENERIC1_2
+ * BYTE8 7:0 VENDOR_NAME[7]
+ * BYTE9 15:8 PRODUCT_NAME[ 0]
+ * BYTE10 23:16 PRODUCT_NAME[ 1]
+ * BYTE11 31:24 PRODUCT_NAME[ 2] */
+ packet_payload = (vendor_name[7] & 0x7f)
+ | ((product_description[0] & 0x7f) << 8)
+ | ((product_description[1] & 0x7f) << 16)
+ | ((product_description[2] & 0x7f) << 24);
+ HDMI_OUTP(0x00B0, packet_payload);
+ check_sum += IFRAME_CHECKSUM_32(packet_payload);
+
+ /* 0x00B4 GENERIC1_3
+ * BYTE12 7:0 PRODUCT_NAME[ 3]
+ * BYTE13 15:8 PRODUCT_NAME[ 4]
+ * BYTE14 23:16 PRODUCT_NAME[ 5]
+ * BYTE15 31:24 PRODUCT_NAME[ 6] */
+ packet_payload = (product_description[3] & 0x7f)
+ | ((product_description[4] & 0x7f) << 8)
+ | ((product_description[5] & 0x7f) << 16)
+ | ((product_description[6] & 0x7f) << 24);
+ HDMI_OUTP(0x00B4, packet_payload);
+ check_sum += IFRAME_CHECKSUM_32(packet_payload);
+
+ /* 0x00B8 GENERIC1_4
+ * BYTE16 7:0 PRODUCT_NAME[ 7]
+ * BYTE17 15:8 PRODUCT_NAME[ 8]
+ * BYTE18 23:16 PRODUCT_NAME[ 9]
+ * BYTE19 31:24 PRODUCT_NAME[10] */
+ packet_payload = (product_description[7] & 0x7f)
+ | ((product_description[8] & 0x7f) << 8)
+ | ((product_description[9] & 0x7f) << 16)
+ | ((product_description[10] & 0x7f) << 24);
+ HDMI_OUTP(0x00B8, packet_payload);
+ check_sum += IFRAME_CHECKSUM_32(packet_payload);
+
+ /* 0x00BC GENERIC1_5
+ * BYTE20 7:0 PRODUCT_NAME[11]
+ * BYTE21 15:8 PRODUCT_NAME[12]
+ * BYTE22 23:16 PRODUCT_NAME[13]
+ * BYTE23 31:24 PRODUCT_NAME[14] */
+ packet_payload = (product_description[11] & 0x7f)
+ | ((product_description[12] & 0x7f) << 8)
+ | ((product_description[13] & 0x7f) << 16)
+ | ((product_description[14] & 0x7f) << 24);
+ HDMI_OUTP(0x00BC, packet_payload);
+ check_sum += IFRAME_CHECKSUM_32(packet_payload);
+
+ /* 0x00C0 GENERIC1_6
+ * BYTE24 7:0 PRODUCT_NAME[15]
+ * BYTE25 15:8 Source Device Information
+ * BYTE26 23:16 NUM
+ * BYTE27 31:24 NUM */
+ /* Source Device Information
+ * 00h unknown
+ * 01h Digital STB
+ * 02h DVD
+ * 03h D-VHS
+ * 04h HDD Video
+ * 05h DVC
+ * 06h DSC
+ * 07h Video CD
+ * 08h Game
+ * 09h PC general */
+ packet_payload = (product_description[15] & 0x7f) | 0x00 << 8;
+ HDMI_OUTP(0x00C0, packet_payload);
+ check_sum += IFRAME_CHECKSUM_32(packet_payload);
+
+ /* Vendor Name (7bit ASCII code) */
+ /* 0x00A8 GENERIC1_0
+ * BYTE0 7:0 CheckSum
+ * BYTE1 15:8 VENDOR_NAME[0]
+ * BYTE2 23:16 VENDOR_NAME[1]
+ * BYTE3 31:24 VENDOR_NAME[2] */
+ packet_payload = ((vendor_name[0] & 0x7f) << 8)
+ | ((vendor_name[1] & 0x7f) << 16)
+ | ((vendor_name[2] & 0x7f) << 24);
+ check_sum += IFRAME_CHECKSUM_32(packet_payload);
+ packet_payload |= ((0x100 - (0xff & check_sum)) & 0xff);
+ HDMI_OUTP(0x00A8, packet_payload);
+
+ /* GENERIC1_LINE | GENERIC1_CONT | GENERIC1_SEND
+ * Setup HDMI TX generic packet control
+ * Enable this packet to transmit every frame
+ * Enable HDMI TX engine to transmit Generic packet 1 */
+ packet_control = HDMI_INP_ND(0x0034);
+ packet_control |= ((0x1 << 24) | (1 << 5) | (1 << 4));
+ HDMI_OUTP(0x0034, packet_control);
+}
+
+int hdmi_msm_clk(int on)
+{
+ int rc;
+
+ DEV_DBG("HDMI Clk: %s\n", on ? "Enable" : "Disable");
+ if (on) {
+ rc = clk_prepare_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_prepare_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_prepare_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_unprepare(hdmi_msm_state->hdmi_app_clk);
+ clk_disable_unprepare(hdmi_msm_state->hdmi_m_pclk);
+ clk_disable_unprepare(hdmi_msm_state->hdmi_s_pclk);
+ }
+
+ return 0;
+}
+
+static void hdmi_msm_turn_on(void)
+{
+ uint32 audio_pkt_ctrl, audio_cfg;
+ /*
+ * Number of wait iterations for QDSP to disable Audio Engine
+ * before resetting HDMI core
+ */
+ 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(20);
+ }
+
+ hdmi_msm_set_mode(FALSE);
+ mutex_lock(&hdcp_auth_state_mutex);
+ hdmi_msm_reset_core();
+ mutex_unlock(&hdcp_auth_state_mutex);
+
+ hdmi_msm_init_phy(external_common_state->video_resolution);
+ /* HDMI_USEC_REFTIMER[0x0208] */
+ HDMI_OUTP(0x0208, 0x0001001B);
+
+ hdmi_msm_set_mode(TRUE);
+
+ hdmi_msm_video_setup(external_common_state->video_resolution);
+ if (!hdmi_msm_is_dvi_mode())
+ hdmi_msm_audio_setup();
+ hdmi_msm_avi_info_frame();
+#ifdef CONFIG_FB_MSM_HDMI_3D
+ hdmi_msm_vendor_infoframe_packetsetup();
+#endif
+ hdmi_msm_spd_infoframe_packetsetup();
+
+#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 */
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+ /* re-initialize CEC if enabled */
+ mutex_lock(&hdmi_msm_state_mutex);
+ if (hdmi_msm_state->cec_enabled == true) {
+ hdmi_msm_cec_init();
+ hdmi_msm_cec_write_logical_addr(
+ hdmi_msm_state->cec_logical_addr);
+ }
+ mutex_unlock(&hdmi_msm_state_mutex);
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT */
+ DEV_INFO("HDMI Core: Initialized\n");
+}
+
+static void hdmi_msm_hpd_state_timer(unsigned long data)
+{
+ if (!work_busy(&hdmi_msm_state->hpd_state_work)) {
+ /*
+ * There is no event currently queued.
+ * Only queue the work if this event has not already
+ * been processed.
+ */
+ if (external_common_state->hpd_state !=
+ hdmi_msm_state->hpd_state_in_isr) {
+ /*
+ * There is no need to use any synchronization
+ * construct for safeguarding these state vairables
+ * here since the only other place these are modified
+ * is in the HPD work thread, which is known to be not
+ * pending/running.
+ */
+ external_common_state->hpd_state =
+ hdmi_msm_state->hpd_state_in_isr;
+ DEV_DBG("%s: Queuing work to handle HPD %s event\n",
+ __func__,
+ external_common_state->hpd_state ?
+ "connect" : "disconnect");
+ queue_work(hdmi_work_queue,
+ &hdmi_msm_state->hpd_state_work);
+ return;
+ }
+ }
+}
+
+#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
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+static void hdmi_msm_cec_read_timer_func(unsigned long data)
+{
+ queue_work(hdmi_work_queue, &hdmi_msm_state->cec_latch_detect_work);
+}
+#endif
+
+static void hdmi_msm_hpd_off(void)
+{
+ int rc = 0;
+
+ if (!hdmi_msm_state->hpd_initialized) {
+ DEV_DBG("%s: HPD is already OFF, returning\n", __func__);
+ return;
+ }
+
+ DEV_DBG("%s: (timer, 5V, IRQ off)\n", __func__);
+ del_timer(&hdmi_msm_state->hpd_state_timer);
+ disable_irq(hdmi_msm_state->irq);
+
+ /* Disable HPD interrupt */
+ HDMI_OUTP(0x0254, 0);
+ DEV_DBG("%s: Disabling HPD_CTRLd\n", __func__);
+
+ hdmi_msm_set_mode(FALSE);
+ hdmi_msm_state->pd->enable_5v(0);
+ hdmi_msm_clk(0);
+ rc = hdmi_msm_state->pd->gpio_config(0);
+ if (rc != 0)
+ DEV_INFO("%s: Failed to disable GPIOs. Error=%d\n",
+ __func__, rc);
+ hdmi_msm_state->hpd_initialized = FALSE;
+}
+
+static void hdmi_msm_dump_regs(const char *prefix)
+{
+#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(void)
+{
+ static int phy_reset_done;
+ uint32 hpd_ctrl;
+ int rc = 0;
+
+ if (hdmi_msm_state->hpd_initialized) {
+ DEV_DBG("%s: HPD is already ON\n", __func__);
+ } else {
+ rc = hdmi_msm_state->pd->gpio_config(1);
+ if (rc) {
+ DEV_ERR("%s: Failed to enable GPIOs. Error=%d\n",
+ __func__, rc);
+ goto error1;
+ }
+
+ rc = hdmi_msm_clk(1);
+ if (rc) {
+ DEV_ERR("%s: Failed to enable clocks. Error=%d\n",
+ __func__, rc);
+ goto error2;
+ }
+
+ rc = hdmi_msm_state->pd->enable_5v(1);
+ if (rc) {
+ DEV_ERR("%s: Failed to enable 5V regulator. Error=%d\n",
+ __func__, rc);
+ goto error3;
+ }
+ hdmi_msm_dump_regs("HDMI-INIT: ");
+
+ hdmi_msm_set_mode(FALSE);
+ if (!phy_reset_done) {
+ hdmi_phy_reset();
+ phy_reset_done = 1;
+ }
+ hdmi_msm_set_mode(TRUE);
+
+ /* HDMI_USEC_REFTIMER[0x0208] */
+ HDMI_OUTP(0x0208, 0x0001001B);
+
+ /* Set up HPD state variables */
+ mutex_lock(&external_common_state_hpd_mutex);
+ external_common_state->hpd_state = 0;
+ hdmi_msm_state->hpd_state_in_isr = 0;
+ mutex_unlock(&external_common_state_hpd_mutex);
+ mutex_lock(&hdmi_msm_state_mutex);
+ hdmi_msm_state->hpd_cable_chg_detected = TRUE;
+ mutex_unlock(&hdmi_msm_state_mutex);
+
+ /* Set up HPD_CTRL to sense HPD event */
+ HDMI_OUTP(0x0254, 0x6);
+ DEV_DBG("%s: Setting HPD_CTRL=%d\n", __func__,
+ HDMI_INP(0x0254));
+
+ hdmi_msm_state->hpd_initialized = TRUE;
+
+ enable_irq(hdmi_msm_state->irq);
+
+ /* set timeout to 4.1ms (max) for hardware debounce */
+ hpd_ctrl = HDMI_INP(0x0258) | 0x1FFF;
+
+ /* Toggle HPD circuit to trigger HPD sense */
+ HDMI_OUTP(0x0258, ~(1 << 28) & hpd_ctrl);
+ HDMI_OUTP(0x0258, (1 << 28) | hpd_ctrl);
+ }
+
+ DEV_DBG("%s: (IRQ, 5V on)\n", __func__);
+ return 0;
+
+error3:
+ hdmi_msm_clk(0);
+error2:
+ hdmi_msm_state->pd->gpio_config(0);
+error1:
+ return rc;
+}
+
+static int hdmi_msm_power_ctrl(boolean enable)
+{
+ int rc = 0;
+
+ if (enable) {
+ /*
+ * Enable HPD only if the UI option is on or if
+ * HDMI is configured as the primary display
+ */
+ if (hdmi_prim_display ||
+ external_common_state->hpd_feature_on) {
+ DEV_DBG("%s: Turning HPD ciruitry on\n", __func__);
+ rc = hdmi_msm_hpd_on();
+ }
+ } else {
+ DEV_DBG("%s: Turning HPD ciruitry off\n", __func__);
+ hdmi_msm_hpd_off();
+ }
+
+ return rc;
+}
+
+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;
+
+ DEV_INFO("power: ON (%dx%d %d)\n", mfd->var_xres, mfd->var_yres,
+ mfd->var_pixclock);
+
+ changed = hdmi_common_get_video_format_from_drv_data(mfd);
+ hdmi_msm_audio_info_setup(TRUE, 0, 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()) {
+ DEV_DBG("%s: Turning HDMI on\n", __func__);
+ mutex_unlock(&external_common_state_hpd_mutex);
+ hdmi_msm_turn_on();
+
+ /* Kick off HDCP Authentication */
+ mutex_lock(&hdcp_auth_state_mutex);
+ hdmi_msm_state->reauth = FALSE;
+ hdmi_msm_state->full_auth_done = FALSE;
+ mutex_unlock(&hdcp_auth_state_mutex);
+ mod_timer(&hdmi_msm_state->hdcp_timer, jiffies + HZ/2);
+ } 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_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_powerdown_phy();
+
+ 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 (cpu_is_apq8064())
+ return -ENODEV;
+
+ 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(&pdev->dev, "core_clk");
+ if (IS_ERR(hdmi_msm_state->hdmi_app_clk)) {
+ DEV_ERR("'core_clk' clk not found\n");
+ rc = IS_ERR(hdmi_msm_state->hdmi_app_clk);
+ goto error;
+ }
+
+ hdmi_msm_state->hdmi_m_pclk = clk_get(&pdev->dev, "master_iface_clk");
+ if (IS_ERR(hdmi_msm_state->hdmi_m_pclk)) {
+ DEV_ERR("'master_iface_clk' clk not found\n");
+ rc = IS_ERR(hdmi_msm_state->hdmi_m_pclk);
+ goto error;
+ }
+
+ hdmi_msm_state->hdmi_s_pclk = clk_get(&pdev->dev, "slave_iface_clk");
+ if (IS_ERR(hdmi_msm_state->hdmi_s_pclk)) {
+ DEV_ERR("'slave_iface_clk' 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;
+ }
+
+ if (!hdmi_msm_state->pd->cec_power) {
+ DEV_ERR("Init FAILED: cec_power 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;
+
+#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;
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+ init_timer(&hdmi_msm_state->cec_read_timer);
+ hdmi_msm_state->cec_read_timer.function =
+ hdmi_msm_cec_read_timer_func;
+ hdmi_msm_state->cec_read_timer.data = (uint32)NULL;
+
+ hdmi_msm_state->cec_read_timer.expires = 0xffffffffL;
+ #endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_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");
+
+ if (hdmi_prim_display) {
+ rc = hdmi_msm_hpd_on();
+ if (rc)
+ goto error;
+ }
+
+ if (hdmi_msm_has_hdcp()) {
+ /* Don't Set Encryption in case of non HDCP builds */
+ external_common_state->present_hdcp = FALSE;
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+ external_common_state->present_hdcp = TRUE;
+#endif
+ } 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
+ }
+
+ /* Initialize hdmi node and register with switch driver */
+ if (hdmi_prim_display)
+ external_common_state->sdev.name = "hdmi_as_primary";
+ else
+ external_common_state->sdev.name = "hdmi";
+ if (switch_dev_register(&external_common_state->sdev) < 0)
+ DEV_ERR("Hdmi switch registration failed\n");
+
+ 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");
+
+ /* Unregister hdmi node from switch driver */
+ switch_dev_unregister(&external_common_state->sdev);
+
+ 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();
+ } else {
+ hdmi_msm_hpd_off();
+ /* Set HDMI switch node to 0 on HPD feature disable */
+ switch_set_state(&external_common_state->sdev, 0);
+ }
+
+ return rc;
+}
+
+static struct platform_driver this_driver = {
+ .probe = hdmi_msm_probe,
+ .remove = hdmi_msm_remove,
+ .driver.name = "hdmi_msm",
+};
+
+static struct msm_fb_panel_data hdmi_msm_panel_data = {
+ .on = hdmi_msm_power_on,
+ .off = hdmi_msm_power_off,
+ .power_ctrl = hdmi_msm_power_ctrl,
+};
+
+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;
+
+ if (cpu_is_msm8930())
+ return 0;
+
+ if (msm_fb_detect_client("hdmi_msm"))
+ return 0;
+
+#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
+ hdmi_prim_display = 1;
+#endif
+
+ 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
+ memset(external_common_state->spd_vendor_name, 0,
+ sizeof(external_common_state->spd_vendor_name));
+ memset(external_common_state->spd_product_description, 0,
+ sizeof(external_common_state->spd_product_description));
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+ hdmi_msm_state->cec_queue_start =
+ kzalloc(sizeof(struct hdmi_msm_cec_msg)*CEC_QUEUE_SIZE,
+ GFP_KERNEL);
+ if (!hdmi_msm_state->cec_queue_start) {
+ pr_err("hdmi_msm_init FAILED: CEC queue out of memory\n");
+ rc = -ENOMEM;
+ goto init_exit;
+ }
+
+ hdmi_msm_state->cec_queue_wr = hdmi_msm_state->cec_queue_start;
+ hdmi_msm_state->cec_queue_rd = hdmi_msm_state->cec_queue_start;
+ hdmi_msm_state->cec_queue_full = false;
+#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);
+#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 */
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+ INIT_WORK(&hdmi_msm_state->cec_latch_detect_work,
+ hdmi_msm_cec_latch_work);
+ init_completion(&hdmi_msm_state->cec_frame_wr_done);
+ init_completion(&hdmi_msm_state->cec_line_latch_wait);
+#endif
+
+ 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..ede21dc
--- /dev/null
+++ b/drivers/video/msm/hdmi_msm.h
@@ -0,0 +1,137 @@
+/* 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
+
+
+/*
+ * Ref. HDMI 1.4a
+ * Supplement-1 CEC Section 6, 7
+ */
+struct hdmi_msm_cec_msg {
+ uint8 sender_id;
+ uint8 recvr_id;
+ uint8 opcode;
+ uint8 operand[15];
+ uint8 frame_size;
+ uint8 retransmit;
+};
+
+#define QFPROM_BASE ((uint32)hdmi_msm_state->qfprom_io)
+#define HDMI_BASE ((uint32)hdmi_msm_state->hdmi_io)
+
+struct hdmi_msm_state_type {
+ boolean panel_power_on;
+ boolean hpd_initialized;
+ boolean hpd_state_in_isr;
+#ifdef CONFIG_SUSPEND
+ boolean pm_suspended;
+#endif
+ boolean hpd_cable_chg_detected;
+ boolean full_auth_done;
+ boolean hpd_during_auth;
+ struct work_struct hpd_state_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 */
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+ boolean cec_enabled;
+ unsigned int first_monitor;
+ int cec_logical_addr;
+ struct completion cec_frame_wr_done;
+ struct timer_list cec_read_timer;
+#define CEC_STATUS_WR_ERROR 0x0001
+#define CEC_STATUS_WR_DONE 0x0002
+#define CEC_STATUS_WR_TMOUT 0x0004
+ uint32 cec_frame_wr_status;
+
+ struct hdmi_msm_cec_msg *cec_queue_start;
+ struct hdmi_msm_cec_msg *cec_queue_wr;
+ struct hdmi_msm_cec_msg *cec_queue_rd;
+ boolean cec_queue_full;
+ boolean fsm_reset_done;
+
+ /*
+ * CECT 9-5-1
+ */
+ struct completion cec_line_latch_wait;
+ struct work_struct cec_latch_detect_work;
+
+#define CEC_QUEUE_SIZE 16
+#define CEC_QUEUE_END (hdmi_msm_state->cec_queue_start + CEC_QUEUE_SIZE)
+#define RETRANSMIT_MAX_NUM 7
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_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_msm_set_mode(boolean power_on);
+int hdmi_msm_clk(int on);
+void hdmi_phy_reset(void);
+void hdmi_msm_reset_core(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
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+void hdmi_msm_cec_init(void);
+void hdmi_msm_cec_write_logical_addr(int addr);
+void hdmi_msm_cec_msg_recv(void);
+void hdmi_msm_cec_one_touch_play(void);
+void hdmi_msm_cec_msg_send(struct hdmi_msm_cec_msg *msg);
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT */
+
+#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..863d59d
--- /dev/null
+++ b/drivers/video/msm/lcdc.c
@@ -0,0 +1,289 @@
+/* Copyright (c) 2008-2012, 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 "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_unprepare(pixel_mdp_clk);
+ clk_disable_unprepare(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 (mfd->ebi1_clk) {
+ if (mdp_rev == MDP_REV_303) {
+ if (clk_set_rate(mfd->ebi1_clk, 0))
+ pr_err("%s: ebi1_lcdc_clk set rate failed\n",
+ __func__);
+ }
+ clk_disable_unprepare(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
+ if (panel_pixclock_freq > 65000000)
+ /* pm_qos_rate should be in Khz */
+ pm_qos_rate = panel_pixclock_freq / 1000 ;
+ else
+ pm_qos_rate = 65000;
+
+ if (mfd->ebi1_clk) {
+ if (mdp_rev == MDP_REV_303) {
+ if (clk_set_rate(mfd->ebi1_clk, 65000000))
+ pr_err("%s: ebi1_lcdc_clk set rate failed\n",
+ __func__);
+ } else {
+ clk_set_rate(mfd->ebi1_clk, pm_qos_rate * 1000);
+ }
+ clk_prepare_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_prepare_enable(pixel_mdp_clk);
+ clk_prepare_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;
+ struct clk *ebi1_clk = NULL;
+
+ if (pdev->id == 0) {
+ lcdc_pdata = pdev->dev.platform_data;
+ pixel_mdp_clk = clk_get(&pdev->dev, "mdp_clk");
+ if (IS_ERR(pixel_mdp_clk)) {
+ pr_err("Couldnt find pixel_mdp_clk\n");
+ return -EINVAL;
+ }
+
+ pixel_lcdc_clk = clk_get(&pdev->dev, "lcdc_clk");
+ if (IS_ERR(pixel_lcdc_clk)) {
+ pr_err("Couldnt find pixel_lcdc_clk\n");
+ return -EINVAL;
+ }
+
+#ifndef CONFIG_MSM_BUS_SCALING
+ ebi1_clk = clk_get(&pdev->dev, "mem_clk");
+ if (IS_ERR(ebi1_clk))
+ return PTR_ERR(ebi1_clk);
+#endif
+
+ return 0;
+ }
+
+ mfd = platform_get_drvdata(pdev);
+ mfd->ebi1_clk = ebi1_clk;
+
+ 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("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;
+
+ /*
+ * 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)
+{
+
+ 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..6b0733f
--- /dev/null
+++ b/drivers/video/msm/lcdc_auo_wvga.c
@@ -0,0 +1,411 @@
+/* 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;
+
+ if (msm_fb_detect_client(LCDC_AUO_PANEL_NAME)) {
+ pr_err("%s: detect failed\n", __func__);
+ return 0;
+ }
+
+ 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..7453ecb
--- /dev/null
+++ b/drivers/video/msm/lcdc_chimei_wxga.c
@@ -0,0 +1,231 @@
+/* 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;
+
+ if (msm_fb_detect_client("lcdc_chimei_wxga"))
+ return 0;
+
+ 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_nt35582_wvga.c b/drivers/video/msm/lcdc_nt35582_wvga.c
new file mode 100644
index 0000000..9ecf4b9
--- /dev/null
+++ b/drivers/video/msm/lcdc_nt35582_wvga.c
@@ -0,0 +1,472 @@
+/* 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.
+ *
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#ifdef CONFIG_SPI_QUP
+#include <linux/spi/spi.h>
+#endif
+#include <mach/gpio.h>
+#include <mach/pmic.h>
+#include "msm_fb.h"
+
+#define LCDC_NT35582_PANEL_NAME "lcdc_nt35582_wvga"
+
+#define WRITE_FIRST_TRANS 0x20
+#define WRITE_SECOND_TRANS 0x00
+#define WRITE_THIRD_TRANS 0x40
+#define READ_FIRST_TRANS 0x20
+#define READ_SECOND_TRANS 0x00
+#define READ_THIRD_TRANS 0xC0
+
+#ifdef CONFIG_SPI_QUP
+#define LCDC_NT35582_SPI_DEVICE_NAME "lcdc_nt35582_spi"
+static struct spi_device *spi_client;
+#endif
+
+struct nt35582_state_type {
+ boolean display_on;
+ int bl_level;
+};
+
+static struct nt35582_state_type nt35582_state = { 0 };
+static int gpio_backlight_en;
+static struct msm_panel_common_pdata *lcdc_nt35582_pdata;
+
+static int spi_write_2bytes(struct spi_device *spi,
+ unsigned char reg_high_addr, unsigned char reg_low_addr)
+{
+ char tx_buf[4];
+ int rc;
+ struct spi_message m;
+ struct spi_transfer t;
+
+ memset(&t, 0, sizeof t);
+ t.tx_buf = tx_buf;
+
+ spi_setup(spi);
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+
+ tx_buf[0] = WRITE_FIRST_TRANS;
+ tx_buf[1] = reg_high_addr;
+ tx_buf[2] = WRITE_SECOND_TRANS;
+ tx_buf[3] = reg_low_addr;
+ t.rx_buf = NULL;
+ t.len = 4;
+ t.bits_per_word = 16;
+ rc = spi_sync(spi, &m);
+ if (rc)
+ pr_err("write spi command failed!\n");
+
+ return rc;
+}
+
+static int spi_write_3bytes(struct spi_device *spi, unsigned char reg_high_addr,
+ unsigned char reg_low_addr, unsigned char write_data)
+{
+ char tx_buf[6];
+ int rc;
+ struct spi_message m;
+ struct spi_transfer t;
+
+ memset(&t, 0, sizeof t);
+ t.tx_buf = tx_buf;
+
+ spi_setup(spi);
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+
+ tx_buf[0] = WRITE_FIRST_TRANS;
+ tx_buf[1] = reg_high_addr;
+ tx_buf[2] = WRITE_SECOND_TRANS;
+ tx_buf[3] = reg_low_addr;
+ tx_buf[4] = WRITE_THIRD_TRANS;
+ tx_buf[5] = write_data;
+ t.rx_buf = NULL;
+ t.len = 6;
+ t.bits_per_word = 16;
+ rc = spi_sync(spi, &m);
+
+ if (rc)
+ pr_err("write spi command failed!\n");
+
+ return rc;
+}
+
+static int spi_read_bytes(struct spi_device *spi, unsigned char reg_high_addr,
+ unsigned char reg_low_addr, unsigned char *read_value)
+{
+ char tx_buf[6];
+ char rx_buf[6];
+ int rc;
+ struct spi_message m;
+ struct spi_transfer t;
+
+ memset(&t, 0, sizeof t);
+ t.tx_buf = tx_buf;
+
+ spi_setup(spi);
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+
+ tx_buf[0] = READ_FIRST_TRANS;
+ tx_buf[1] = reg_high_addr;
+ tx_buf[2] = READ_SECOND_TRANS;
+ tx_buf[3] = reg_low_addr;
+ tx_buf[4] = READ_THIRD_TRANS;
+ tx_buf[5] = 0x00;
+
+ t.rx_buf = rx_buf;
+ t.len = 6;
+ t.bits_per_word = 16;
+ rc = spi_sync(spi, &m);
+
+ if (rc)
+ pr_err("write spi command failed!\n");
+ else
+ *read_value = rx_buf[5];
+
+ return rc;
+}
+
+static void nt35582_disp_on(void)
+{
+ uint32 panel_id1 = 0, panel_id2 = 0;
+
+ if (!nt35582_state.display_on) {
+
+ /* GVDD setting */
+ spi_write_3bytes(spi_client, 0xC0, 0x00, 0xC0);
+ spi_write_3bytes(spi_client, 0xC0, 0x01, 0x00);
+ spi_write_3bytes(spi_client, 0xC0, 0x02, 0xC0);
+ spi_write_3bytes(spi_client, 0xC0, 0x03, 0x00);
+ /* Power setting */
+ spi_write_3bytes(spi_client, 0xC1, 0x00, 0x40);
+ spi_write_3bytes(spi_client, 0xC2, 0x00, 0x21);
+ spi_write_3bytes(spi_client, 0xC2, 0x02, 0x02);
+
+ /* Gamma setting */
+ spi_write_3bytes(spi_client, 0xE0, 0x00, 0x0E);
+ spi_write_3bytes(spi_client, 0xE0, 0x01, 0x54);
+ spi_write_3bytes(spi_client, 0xE0, 0x02, 0x63);
+ spi_write_3bytes(spi_client, 0xE0, 0x03, 0x76);
+ spi_write_3bytes(spi_client, 0xE0, 0x04, 0x1F);
+ spi_write_3bytes(spi_client, 0xE0, 0x05, 0x31);
+ spi_write_3bytes(spi_client, 0xE0, 0x06, 0x62);
+ spi_write_3bytes(spi_client, 0xE0, 0x07, 0x78);
+ spi_write_3bytes(spi_client, 0xE0, 0x08, 0x1F);
+ spi_write_3bytes(spi_client, 0xE0, 0x09, 0x25);
+ spi_write_3bytes(spi_client, 0xE0, 0x0A, 0xB3);
+ spi_write_3bytes(spi_client, 0xE0, 0x0B, 0x17);
+ spi_write_3bytes(spi_client, 0xE0, 0x0C, 0x38);
+ spi_write_3bytes(spi_client, 0xE0, 0x0D, 0x5A);
+ spi_write_3bytes(spi_client, 0xE0, 0x0E, 0xA2);
+ spi_write_3bytes(spi_client, 0xE0, 0x0F, 0xA2);
+ spi_write_3bytes(spi_client, 0xE0, 0x10, 0x24);
+ spi_write_3bytes(spi_client, 0xE0, 0x11, 0x57);
+
+ spi_write_3bytes(spi_client, 0xE1, 0x00, 0x0E);
+ spi_write_3bytes(spi_client, 0xE1, 0x01, 0x54);
+ spi_write_3bytes(spi_client, 0xE1, 0x02, 0x63);
+ spi_write_3bytes(spi_client, 0xE1, 0x03, 0x76);
+ spi_write_3bytes(spi_client, 0xE1, 0x04, 0x1F);
+ spi_write_3bytes(spi_client, 0xE1, 0x05, 0x31);
+ spi_write_3bytes(spi_client, 0xE1, 0x06, 0X62);
+ spi_write_3bytes(spi_client, 0xE1, 0x07, 0x78);
+ spi_write_3bytes(spi_client, 0xE1, 0x08, 0x1F);
+ spi_write_3bytes(spi_client, 0xE1, 0x09, 0x25);
+ spi_write_3bytes(spi_client, 0xE1, 0x0A, 0xB3);
+ spi_write_3bytes(spi_client, 0xE1, 0x0B, 0x17);
+ spi_write_3bytes(spi_client, 0xE1, 0x0C, 0x38);
+ spi_write_3bytes(spi_client, 0xE1, 0x0D, 0x5A);
+ spi_write_3bytes(spi_client, 0xE1, 0x0E, 0xA2);
+ spi_write_3bytes(spi_client, 0xE1, 0x0F, 0xA2);
+ spi_write_3bytes(spi_client, 0xE1, 0x10, 0x24);
+ spi_write_3bytes(spi_client, 0xE1, 0x11, 0x57);
+
+ spi_write_3bytes(spi_client, 0xE2, 0x00, 0x0E);
+ spi_write_3bytes(spi_client, 0xE2, 0x01, 0x54);
+ spi_write_3bytes(spi_client, 0xE2, 0x02, 0x63);
+ spi_write_3bytes(spi_client, 0xE2, 0x03, 0x76);
+ spi_write_3bytes(spi_client, 0xE2, 0x04, 0x1F);
+ spi_write_3bytes(spi_client, 0xE2, 0x05, 0x31);
+ spi_write_3bytes(spi_client, 0xE2, 0x06, 0x62);
+ spi_write_3bytes(spi_client, 0xE2, 0x07, 0x78);
+ spi_write_3bytes(spi_client, 0xE2, 0x08, 0x1F);
+ spi_write_3bytes(spi_client, 0xE2, 0x09, 0x25);
+ spi_write_3bytes(spi_client, 0xE2, 0x0A, 0xB3);
+ spi_write_3bytes(spi_client, 0xE2, 0x0B, 0x17);
+ spi_write_3bytes(spi_client, 0xE2, 0x0C, 0x38);
+ spi_write_3bytes(spi_client, 0xE2, 0x0D, 0x5A);
+ spi_write_3bytes(spi_client, 0xE2, 0x0E, 0xA2);
+ spi_write_3bytes(spi_client, 0xE2, 0x0F, 0xA2);
+ spi_write_3bytes(spi_client, 0xE2, 0x10, 0x24);
+ spi_write_3bytes(spi_client, 0xE2, 0x11, 0x57);
+
+ spi_write_3bytes(spi_client, 0xE3, 0x00, 0x0E);
+ spi_write_3bytes(spi_client, 0xE3, 0x01, 0x54);
+ spi_write_3bytes(spi_client, 0xE3, 0x02, 0x63);
+ spi_write_3bytes(spi_client, 0xE3, 0x03, 0x76);
+ spi_write_3bytes(spi_client, 0xE3, 0x04, 0x1F);
+ spi_write_3bytes(spi_client, 0xE3, 0x05, 0x31);
+ spi_write_3bytes(spi_client, 0xE3, 0x06, 0x62);
+ spi_write_3bytes(spi_client, 0xE3, 0x07, 0x78);
+ spi_write_3bytes(spi_client, 0xE3, 0x08, 0x1F);
+ spi_write_3bytes(spi_client, 0xE3, 0x09, 0x25);
+ spi_write_3bytes(spi_client, 0xE3, 0x0A, 0xB3);
+ spi_write_3bytes(spi_client, 0xE3, 0x0B, 0x17);
+ spi_write_3bytes(spi_client, 0xE3, 0x0C, 0x38);
+ spi_write_3bytes(spi_client, 0xE3, 0x0D, 0x5A);
+ spi_write_3bytes(spi_client, 0xE3, 0x0E, 0xA2);
+ spi_write_3bytes(spi_client, 0xE3, 0x0F, 0xA2);
+ spi_write_3bytes(spi_client, 0xE3, 0x10, 0x24);
+ spi_write_3bytes(spi_client, 0xE3, 0x11, 0x57);
+
+ spi_write_3bytes(spi_client, 0xE4, 0x00, 0x48);
+ spi_write_3bytes(spi_client, 0xE4, 0x01, 0x6B);
+ spi_write_3bytes(spi_client, 0xE4, 0x02, 0x84);
+ spi_write_3bytes(spi_client, 0xE4, 0x03, 0x9B);
+ spi_write_3bytes(spi_client, 0xE4, 0x04, 0x1F);
+ spi_write_3bytes(spi_client, 0xE4, 0x05, 0x31);
+ spi_write_3bytes(spi_client, 0xE4, 0x06, 0x62);
+ spi_write_3bytes(spi_client, 0xE4, 0x07, 0x78);
+ spi_write_3bytes(spi_client, 0xE4, 0x08, 0x1F);
+ spi_write_3bytes(spi_client, 0xE4, 0x09, 0x25);
+ spi_write_3bytes(spi_client, 0xE4, 0x0A, 0xB3);
+ spi_write_3bytes(spi_client, 0xE4, 0x0B, 0x17);
+ spi_write_3bytes(spi_client, 0xE4, 0x0C, 0x38);
+ spi_write_3bytes(spi_client, 0xE4, 0x0D, 0x5A);
+ spi_write_3bytes(spi_client, 0xE4, 0x0E, 0xA2);
+ spi_write_3bytes(spi_client, 0xE4, 0x0F, 0xA2);
+ spi_write_3bytes(spi_client, 0xE4, 0x10, 0x24);
+ spi_write_3bytes(spi_client, 0xE4, 0x11, 0x57);
+
+ spi_write_3bytes(spi_client, 0xE5, 0x00, 0x48);
+ spi_write_3bytes(spi_client, 0xE5, 0x01, 0x6B);
+ spi_write_3bytes(spi_client, 0xE5, 0x02, 0x84);
+ spi_write_3bytes(spi_client, 0xE5, 0x03, 0x9B);
+ spi_write_3bytes(spi_client, 0xE5, 0x04, 0x1F);
+ spi_write_3bytes(spi_client, 0xE5, 0x05, 0x31);
+ spi_write_3bytes(spi_client, 0xE5, 0x06, 0x62);
+ spi_write_3bytes(spi_client, 0xE5, 0x07, 0x78);
+ spi_write_3bytes(spi_client, 0xE5, 0x08, 0x1F);
+ spi_write_3bytes(spi_client, 0xE5, 0x09, 0x25);
+ spi_write_3bytes(spi_client, 0xE5, 0x0A, 0xB3);
+ spi_write_3bytes(spi_client, 0xE5, 0x0B, 0x17);
+ spi_write_3bytes(spi_client, 0xE5, 0x0C, 0x38);
+ spi_write_3bytes(spi_client, 0xE5, 0x0D, 0x5A);
+ spi_write_3bytes(spi_client, 0xE5, 0x0E, 0xA2);
+ spi_write_3bytes(spi_client, 0xE5, 0x0F, 0xA2);
+ spi_write_3bytes(spi_client, 0xE5, 0x10, 0x24);
+ spi_write_3bytes(spi_client, 0xE5, 0x11, 0x57);
+
+ /* Data format setting */
+ spi_write_3bytes(spi_client, 0x3A, 0x00, 0x70);
+
+ /* Reverse PCLK signal of LCM to meet Qualcomm's platform */
+ spi_write_3bytes(spi_client, 0x3B, 0x00, 0x2B);
+
+ /* Scan direstion setting */
+ spi_write_3bytes(spi_client, 0x36, 0x00, 0x00);
+
+ /* Sleep out */
+ spi_write_2bytes(spi_client, 0x11, 0x00);
+
+ msleep(120);
+
+ /* Display on */
+ spi_write_2bytes(spi_client, 0x29, 0x00);
+
+ pr_info("%s: LCM SPI display on CMD finished...\n", __func__);
+
+ msleep(200);
+
+ nt35582_state.display_on = TRUE;
+ }
+
+ /* Test to read RDDID. It should be 0x0055h and 0x0082h */
+ spi_read_bytes(spi_client, 0x10, 0x80, (unsigned char *)&panel_id1);
+ spi_read_bytes(spi_client, 0x11, 0x80, (unsigned char *)&panel_id2);
+
+ pr_info(KERN_INFO "nt35582_disp_on: LCM_ID=[0x%x, 0x%x]\n",
+ panel_id1, panel_id2);
+}
+
+static int lcdc_nt35582_panel_on(struct platform_device *pdev)
+{
+ nt35582_disp_on();
+ return 0;
+}
+
+static int lcdc_nt35582_panel_off(struct platform_device *pdev)
+{
+ nt35582_state.display_on = FALSE;
+ return 0;
+}
+
+static void lcdc_nt35582_set_backlight(struct msm_fb_data_type *mfd)
+{
+ int bl_level;
+ int i = 0, step = 0;
+
+ bl_level = mfd->bl_level;
+ if (bl_level == nt35582_state.bl_level)
+ return;
+ else
+ nt35582_state.bl_level = bl_level;
+
+ if (bl_level == 0) {
+ gpio_set_value_cansleep(gpio_backlight_en, 0);
+ return;
+ }
+
+ /* Level:0~31 mapping to step 32~1 */
+ step = 32 - bl_level;
+ for (i = 0; i < step; i++) {
+ gpio_set_value_cansleep(gpio_backlight_en, 0);
+ ndelay(5);
+ gpio_set_value_cansleep(gpio_backlight_en, 1);
+ ndelay(5);
+ }
+}
+
+static int __devinit nt35582_probe(struct platform_device *pdev)
+{
+ if (pdev->id == 0) {
+ lcdc_nt35582_pdata = pdev->dev.platform_data;
+ return 0;
+ }
+
+ gpio_backlight_en = *(lcdc_nt35582_pdata->gpio_num);
+
+ msm_fb_add_device(pdev);
+ return 0;
+}
+
+#ifdef CONFIG_SPI_QUP
+static int __devinit lcdc_nt35582_spi_probe(struct spi_device *spi)
+{
+ spi_client = spi;
+ spi_client->bits_per_word = 16;
+ spi_client->chip_select = 0;
+ spi_client->max_speed_hz = 1100000;
+ spi_client->mode = SPI_MODE_0;
+ spi_setup(spi_client);
+
+ return 0;
+}
+
+static int __devexit lcdc_nt35582_spi_remove(struct spi_device *spi)
+{
+ spi_client = NULL;
+ return 0;
+}
+
+static struct spi_driver lcdc_nt35582_spi_driver = {
+ .driver = {
+ .name = LCDC_NT35582_SPI_DEVICE_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = lcdc_nt35582_spi_probe,
+ .remove = __devexit_p(lcdc_nt35582_spi_remove),
+};
+#endif
+static struct platform_driver this_driver = {
+ .probe = nt35582_probe,
+ .driver = {
+ .name = LCDC_NT35582_PANEL_NAME,
+ },
+};
+
+static struct msm_fb_panel_data nt35582_panel_data = {
+ .on = lcdc_nt35582_panel_on,
+ .off = lcdc_nt35582_panel_off,
+ .set_backlight = lcdc_nt35582_set_backlight,
+};
+
+static struct platform_device this_device = {
+ .name = LCDC_NT35582_PANEL_NAME,
+ .id = 1,
+ .dev = {
+ .platform_data = &nt35582_panel_data,
+ }
+};
+
+static int __init lcdc_nt35582_panel_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_LCDC_AUTO_DETECT
+ if (msm_fb_detect_client(LCDC_NT35582_PANEL_NAME)) {
+ pr_err("detect failed\n");
+ return 0;
+ }
+#endif
+ ret = platform_driver_register(&this_driver);
+ if (ret) {
+ pr_err("Fails to platform_driver_register...\n");
+ return ret;
+ }
+
+ pinfo = &nt35582_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 = 24;
+ pinfo->fb_num = 2;
+ pinfo->clk_rate = 25600000;
+ pinfo->bl_max = 31;
+ pinfo->bl_min = 1;
+
+ pinfo->lcdc.h_back_porch = 10; /* hsw = 8 + hbp=184 */
+ pinfo->lcdc.h_front_porch = 10;
+ pinfo->lcdc.h_pulse_width = 2;
+ pinfo->lcdc.v_back_porch = 4; /* vsw=1 + vbp = 2 */
+ pinfo->lcdc.v_front_porch = 10;
+ 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) {
+ pr_err("not able to register the device\n");
+ goto fail_driver;
+ }
+#ifdef CONFIG_SPI_QUP
+ ret = spi_register_driver(&lcdc_nt35582_spi_driver);
+
+ if (ret) {
+ pr_err("not able to register spi\n");
+ goto fail_device;
+ }
+#endif
+ return ret;
+
+#ifdef CONFIG_SPI_QUP
+fail_device:
+ platform_device_unregister(&this_device);
+#endif
+fail_driver:
+ platform_driver_unregister(&this_driver);
+ return ret;
+}
+
+device_initcall(lcdc_nt35582_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..16790f3
--- /dev/null
+++ b/drivers/video/msm/lcdc_samsung_oled_pt.c
@@ -0,0 +1,588 @@
+/* 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;
+
+ if (msm_fb_detect_client("lcdc_samsung_oled")) {
+ pr_err("%s: detect failed\n", __func__);
+ return 0;
+ }
+
+ 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..6b35e52
--- /dev/null
+++ b/drivers/video/msm/lcdc_samsung_wsvga.c
@@ -0,0 +1,270 @@
+/* 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)
+{
+#ifdef CONFIG_PMIC8058_PWM
+ int bl_level;
+ int ret;
+
+ bl_level = mfd->bl_level;
+
+ 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;
+
+ if (msm_fb_detect_client("lcdc_samsung_wsvga"))
+ return 0;
+
+ 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
index ac44ca9..57d754e 100644
--- a/drivers/video/msm/logo.c
+++ b/drivers/video/msm/logo.c
@@ -23,7 +23,6 @@
#include <linux/irq.h>
#include <asm/system.h>
-#include <mach/debug_display.h>
#define fb_width(fb) ((fb)->var.xres)
#define fb_height(fb) ((fb)->var.yres)
@@ -38,46 +37,51 @@
}
/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */
-int load_565rle_image(char *filename)
+int load_565rle_image(char *filename, bool bf_supported)
{
struct fb_info *info;
- int fd, err = 0;
- unsigned count, max;
+ int fd, count, err = 0;
+ unsigned max;
unsigned short *data, *bits, *ptr;
info = registered_fb[0];
if (!info) {
- PR_DISP_WARN("%s: Can not access framebuffer\n",
+ printk(KERN_WARNING "%s: Can not access framebuffer\n",
__func__);
return -ENODEV;
}
fd = sys_open(filename, O_RDONLY, 0);
if (fd < 0) {
- PR_DISP_WARN("%s: Can not open %s\n",
+ printk(KERN_WARNING "%s: Can not open %s\n",
__func__, filename);
return -ENOENT;
}
- count = (unsigned)sys_lseek(fd, (off_t)0, 2);
- if (count == 0) {
- sys_close(fd);
+ 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) {
- PR_DISP_WARN("%s: Can not alloc data\n", __func__);
+ printk(KERN_WARNING "%s: Can not alloc data\n", __func__);
err = -ENOMEM;
goto err_logo_close_file;
}
- if ((unsigned)sys_read(fd, (char *)data, count) != count) {
+ if (sys_read(fd, (char *)data, count) != count) {
err = -EIO;
goto err_logo_free_data;
}
max = fb_width(info) * fb_height(info);
ptr = data;
+ if (bf_supported && (info->node == 1 || info->node == 2)) {
+ err = -EPERM;
+ pr_err("%s:%d no info->creen_base on fb%d!\n",
+ __func__, __LINE__, info->node);
+ goto err_logo_free_data;
+ }
bits = (unsigned short *)(info->screen_base);
while (count > 3) {
unsigned n = ptr[0];
diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c
index 7a6cf38..1154913 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-2012, 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,1199 +10,581 @@
*
* 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/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 <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
#include <linux/delay.h>
-#include <linux/earlysuspend.h>
-#include <linux/wakelock.h>
-#include <linux/debugfs.h>
-#include <asm/uaccess.h>
-#include <mach/msm_fb.h>
-#include <mach/debug_display.h>
-#include "mddi_hw.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);
-static uint32_t mddi_debug_flags;
-#ifdef CONFIG_MSM_MDP40
-static struct clk *mdp_clk;
+static int mddi_off(struct platform_device *pdev);
+static int mddi_on(struct platform_device *pdev);
+
+#ifdef CONFIG_PM
+static int mddi_suspend(struct platform_device *pdev, pm_message_t state);
+static int mddi_resume(struct platform_device *pdev);
#endif
-#ifdef CONFIG_MDP4_HW_VSYNC
-static struct clk *mdp_vsync_clk;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mddi_early_suspend(struct early_suspend *h);
+static void mddi_early_resume(struct early_suspend *h);
#endif
-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 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;
+
+DEFINE_MUTEX(mddi_timer_lock);
+
+static int mddi_runtime_suspend(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: suspending...\n");
+ return 0;
+}
+
+static int mddi_runtime_resume(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: resuming...\n");
+ return 0;
+}
+
+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,
};
-struct reg_read_info {
- struct completion done;
- uint32_t reg;
- uint32_t status;
- uint32_t result;
-};
-
-struct mddi_info {
- uint16_t flags;
- uint16_t version;
- char __iomem *base;
- int irq;
- struct clk *clk;
- struct msm_mddi_client_data client_data;
-
- /* 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;
-
- spinlock_t int_lock;
- uint32_t int_enable;
- uint32_t got_int;
- wait_queue_head_t int_wait;
-
- 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;
-
- struct wake_lock idle_lock;
- struct wake_lock link_active_idle_lock;
-
- 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;
- unsigned type;
- char debugfs_buf[32];
-};
-
-static void mddi_init_rev_encap(struct mddi_info *mddi);
-/* FIXME: Workaround for Novatek
-static void mddi_skew_calibration(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)
-{
- struct mddi_info *mddi = container_of(cdata, struct mddi_info,
- client_data);
- wake_lock(&mddi->link_active_idle_lock);
- 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)
-{
- PR_DISP_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)) {
- /* PR_DISP_INFO("rev: len=%04x type=%04x\n",
- * rev->hdr.length, rev->hdr.type); */
-
- 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:
- /* PR_DISP_INFO("rev: reg %x = %x\n",
- * rev->reg.register_address,
- * rev->reg.register_data_list); */
- ri = mddi->reg_read;
- if (ri == 0) {
- PR_DISP_INFO("rev: got reg %x = %x without "
- " pending read\n",
- rev->reg.register_address,
- rev->reg.u.reg_data);
- break;
- }
- if (ri->reg != rev->reg.register_address) {
- PR_DISP_INFO("rev: got reg %x = %x for "
- "wrong register, expected "
- "%x\n",
- rev->reg.register_address,
- rev->reg.u.reg_data, ri->reg);
- break;
- }
- mddi->reg_read = NULL;
- ri->status = 0;
- ri->result = rev->reg.u.reg_data;
- complete(&ri->done);
- break;
- default:
- PR_DISP_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)
- PR_DISP_INFO("\n");
- PR_DISP_INFO(" %02x", rev->raw[i]);
- }
- PR_DISP_INFO("\n");
- mddi_reset_rev_encap_ptr(mddi);
- }
- } else {
- PR_DISP_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)
-{
- union mddi_rev *rev = mddi->rev_data;
- uint32_t rev_data_count;
- uint32_t rev_crc_err_count;
- int i;
- 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)
- PR_DISP_INFO("rev_data_count %d\n", rev_data_count);
- /* PR_DISP_INFO("rev_data_count %d, INT %x\n", rev_data_count,
- * mddi_readl(INT)); */
-
- if (rev_crc_err_count) {
- PR_DISP_INFO("rev_crc_err_count %d, INT %x\n",
- rev_crc_err_count, mddi_readl(INT));
- ri = mddi->reg_read;
- if (ri == 0) {
- PR_DISP_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;
-
- if (mddi_debug_flags & 1) {
- PR_DISP_INFO("INT %x, STAT %x, CURR_REV_PTR %x\n",
- mddi_readl(INT), mddi_readl(STAT),
- mddi_readl(CURR_REV_PTR));
- for (i = 0; i < MDDI_REV_BUFFER_SIZE; i++) {
- if ((i % 16) == 0)
- PR_DISP_INFO("\n");
- PR_DISP_INFO(" %02x", rev->raw[i]);
- }
- PR_DISP_INFO("\n");
- }
-
- /* PR_DISP_INFO("rev_data_curr %d + %d\n", mddi->rev_data_curr,
- * crev->hdr.length); */
- 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) {
- PR_DISP_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);
- if (mddi_debug_flags & 2) {
- memset(mddi->rev_data + prev_offset, 0xee, rem);
- memset(mddi->rev_data, 0xee, mddi->rev_data_curr);
- }
- } else {
- mddi_handle_rev_data(mddi, crev);
- if (mddi_debug_flags & 2)
- memset(mddi->rev_data + prev_offset, 0xee,
- mddi->rev_data_curr - prev_offset);
- }
-
- /* if(mddi->rev_data_curr + MDDI_MAX_REV_PKT_SIZE >=
- * MDDI_REV_BUFFER_SIZE) { */
- if (prev_offset < MDDI_REV_BUFFER_SIZE / 2 &&
- mddi->rev_data_curr >= MDDI_REV_BUFFER_SIZE / 2) {
- /* PR_DISP_INFO("passed buffer half full: rev_data_curr
- * %d\n", mddi->rev_data_curr); */
- 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);
-
- /* PR_DISP_INFO("%s: isr a=%08x e=%08x s=%08x\n",
- mddi->name, active, mddi->int_enable, status); */
-
- /* 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;
- wake_lock(&mddi->link_active_idle_lock);
- }
-
- if (active & MDDI_INT_IN_HIBERNATION) {
- mddi->int_enable &= (~MDDI_INT_IN_HIBERNATION);
- mddi->int_enable |= MDDI_INT_LINK_ACTIVE;
- wake_unlock(&mddi->link_active_idle_lock);
- }
-
- 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 = 0;
-
- 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 KERN_ERR "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)
-{
-#ifdef CONFIG_MACH_MARVEL
- mddi_writel(0x0000, VERSION);
-#else
- mddi_writel(0x0001, VERSION);
-#endif
-
- mddi_writel(MDDI_HOST_BYTES_PER_SUBFRAME, BPS);
- mddi_writel(0x0003, SPM); /* subframes per media */
- if (mddi->type == MSM_MDP_MDDI_TYPE_II)
- mddi_writel(0x00C8, TA1_LEN);
- else
- mddi_writel(0x0005, TA1_LEN);
- mddi_writel(MDDI_HOST_TA2_LEN, TA2_LEN);
- mddi_writel(0x003C, DISP_WAKE); /* wakeup counter */
- mddi_writel(MDDI_HOST_REV_RATE_DIV, REV_RATE_DIV);
- if (mddi->type == MSM_MDP_MDDI_TYPE_II)
- mddi_writel(0x01, SF_LEN_CTL_REG);
-
- 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 */
- if (mddi->type == MSM_MDP_MDDI_TYPE_II)
- mddi_writel(0x402a850f, PAD_CTL);
- else
- mddi_writel(0xa850f, PAD_CTL);
-
-#if defined(CONFIG_ARCH_QSD8X50) || defined(CONFIG_ARCH_MSM7X30)
- /* Only for novatek driver IC*/
- mddi_writel(0x00C8, DRIVE_HI);
- /* 0x32 normal, 0x50 for Toshiba display */
- mddi_writel(0x0050, DRIVE_LO);
- mddi_writel(0x00320000, PAD_IO_CTL);
- if (mddi->type == MSM_MDP_MDDI_TYPE_II)
- mddi_writel(0x40884020, PAD_CAL);
- else
- mddi_writel(0x00220020, PAD_CAL);
-#else
- mddi_writel(0x0096, DRIVE_HI);
- /* 0x32 normal, 0x50 for Toshiba display */
- mddi_writel(0x0050, DRIVE_LO);
-#endif
-
- /* Need an even number for counts */
- mddi_writel(0x60006, DRIVER_START_CNT);
-
- mddi_set_auto_hibernate(&mddi->client_data, 0);
-
-#if 1 /* ignore listen */
- mddi_writel(MDDI_CMD_DISP_IGNORE, CMD);
-#else
- mddi_writel(MDDI_CMD_DISP_LISTEN, CMD);
-#endif
- 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);
- wake_lock(&mddi->idle_lock);
- /* 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);
-#ifdef CONFIG_MDP4_HW_VSYNC
- clk_disable(mdp_vsync_clk);
-#endif
-#ifdef CONFIG_MSM_MDP40
- clk_disable(mdp_clk);
-#endif
- wake_unlock(&mddi->idle_lock);
-}
-
-static void mddi_resume(struct msm_mddi_client_data *cdata)
-{
- struct mddi_info *mddi = container_of(cdata, struct mddi_info,
- client_data);
- wake_lock(&mddi->idle_lock);
- if (mddi->type == MSM_MDP_MDDI_TYPE_I)
- mddi_set_auto_hibernate(&mddi->client_data, 0);
- /* turn on the client */
- if (mddi->power_client)
- mddi->power_client(&mddi->client_data, 1);
-#ifdef CONFIG_MSM_MDP40
- clk_enable(mdp_clk);
-#endif
-#ifdef CONFIG_MDP4_HW_VSYNC
- clk_enable(mdp_vsync_clk);
-#endif
- /* turn on the clock */
- clk_enable(mddi->clk);
- /* set up the local registers */
- mddi->rev_data_curr = 0;
- mddi_init_registers(mddi);
-/* FIXME: Workaround for Novatek
- if (mddi->type == MSM_MDP_MDDI_TYPE_II)
- mddi_skew_calibration(mddi);
-*/
- mddi_writel(mddi->int_enable, INTEN);
- mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
- if (mddi->type == MSM_MDP_MDDI_TYPE_I)
- mddi_writel(MDDI_CMD_SEND_RTD, CMD);
- mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
- if (mddi->type == MSM_MDP_MDDI_TYPE_I)
- mddi_set_auto_hibernate(&mddi->client_data, 1);
- wake_unlock(&mddi->idle_lock);
-}
-
-static int __init mddi_get_client_caps(struct mddi_info *mddi)
-{
-#if !defined(CONFIG_ARCH_MSM7X30)
- int i, j;
-#endif
- /* 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);
- /*FIXME: mddi host can't get caps on MDDI type 2*/
-#if !defined(CONFIG_ARCH_MSM7X30)
- if (mddi->type == MSM_MDP_MDDI_TYPE_I) {
- 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);
- mdelay(1);
- mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
- stat = mddi_readl(STAT);
- PR_DISP_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) {
- mdelay(1);
- break;
- }
- msleep(1);
- }
-
- mddi_writel(CMD_GET_CLIENT_CAP, CMD);
- mdelay(1);
- 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 KERN_ERR "mddi_init, timeout waiting for "
- "caps\n");
- }
- return (mddi->flags & FLAG_HAVE_CAPS);
- } else
- return 1;
-#endif
- return 1;
-}
-
-/* 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)
- PR_DISP_INFO("mddi status: crc_error "
- "count: %d\n",
- mddi->status.crc_error_count);
- else
- ret = 0;
- break;
- } else
- PR_DISP_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;
-}
-
-
-/*
- * mddi_remote_write_vals - send the register access packet
- *
- * @cdata: mddi layer dedicated structure, holding info needed by mddi
- * @val : parameters
- * @reg : cmd
- * @nr_bytes: size of parameters in bytes
- *
- * jay, Nov 13, 08'
- * extend the single parameter to multiple.
- */
-static void _mddi_remote_write_vals(struct msm_mddi_client_data *cdata, uint8_t *val,
- uint32_t reg, unsigned int nr_bytes)
-{
- struct mddi_info *mddi = container_of(cdata, struct mddi_info,
- client_data);
- struct mddi_llentry *ll;
- struct mddi_register_access *ra;
- dma_addr_t bus_addr = 0;
-
- mutex_lock(&mddi->reg_write_lock);
-
- ll = mddi->reg_write_data;
-
- ra = &(ll->u.r);
- ra->length = 14 + nr_bytes;
- ra->type = TYPE_REGISTER_ACCESS;
- ra->client_id = 0;
- ra->read_write_info = MDDI_WRITE | (nr_bytes / 4);
- ra->crc16 = 0;
-
- ra->register_address = reg;
-
- ll->flags = 1;
- /* register access packet header occupies 14 bytes */
- ll->header_count = 14;
- ll->data_count = nr_bytes; /* num of bytes in the data field */
-
- if (nr_bytes == 4) {
- uint32_t *prm = (uint32_t *)val;
-
- ll->data = mddi->reg_write_addr +
- offsetof(struct mddi_llentry, u.r.u.reg_data);
- ra->u.reg_data = *prm;
- } else {
- int dma_retry = 5;
-
- while (dma_retry--) {
- bus_addr = dma_map_single(NULL, (void *)val, nr_bytes,
- DMA_TO_DEVICE);
- if (dma_mapping_error(NULL, bus_addr) == 0)
- break;
- msleep(1);
- }
- if (dma_retry == 0) {
- PR_DISP_ERR("%s: dma map fail!\n", __func__);
- mutex_unlock(&mddi->reg_write_lock);
- return;
- }
-
- ll->data = bus_addr;
- ra->u.reg_data_list = (uint32_t *)bus_addr;
- }
- ll->next = 0;
- ll->reserved = 0;
-
- /* inform mddi to start */
- mddi_writel(mddi->reg_write_addr, PRI_PTR);
- mddi_wait_interrupt(mddi, MDDI_INT_PRI_LINK_LIST_DONE);
- if (bus_addr)
- dma_unmap_single(NULL, bus_addr, nr_bytes, DMA_TO_DEVICE);
- mutex_unlock(&mddi->reg_write_lock);
-}
-
-void mddi_remote_write_vals(struct msm_mddi_client_data *cdata, uint8_t *val,
- uint32_t reg, unsigned int nr_bytes)
-{
- int sem_owned = overlay_semaphore_lock();
- _mddi_remote_write_vals(cdata, val, reg, nr_bytes);
- if (sem_owned == 0)
- overlay_semaphore_unlock();
-}
-
-void mddi_remote_write(struct msm_mddi_client_data *cdata, uint32_t val,
- uint32_t reg)
-{
- uint8_t *p = (uint8_t *)&val;
- mddi_remote_write_vals(cdata, p, reg, 4);
-}
-
-static 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 = 0;
-
- 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);
- /* PR_DISP_INFO("mddi_remote_read(%x), stat = %x\n", reg, s); */
-
- ri.reg = reg;
- ri.status = -1;
- ri.result = -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);
- /* s = mddi_readl(STAT); */
- /* PR_DISP_INFO("mddi_remote_read(%x) sent, stat = %x\n",
- * reg, s); */
-
- /* s = mddi_readl(STAT); */
- /* while((s & MDDI_STAT_PRI_LINK_LIST_DONE) == 0){ */
- /* s = mddi_readl(STAT); */
- /* } */
-
- /* 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) {
- PR_DISP_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;
-
- /* PR_DISP_INFO("mddi_remote_read: failed, sent
- * MDDI_CMD_SEND_RTD: int %x, stat %x, rtd val %x\n",
- * mddi_readl(INT), mddi_readl(STAT), mddi_readl(RTD_VAL)); */
- mddi_writel(MDDI_CMD_SEND_RTD, CMD);
- mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
- /* PR_DISP_INFO("mddi_remote_read: failed, sent
- * MDDI_CMD_SEND_RTD: int %x, stat %x, rtd val %x\n",
- * mddi_readl(INT), mddi_readl(STAT), mddi_readl(RTD_VAL)); */
- mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
- PR_DISP_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);
- /* PR_DISP_INFO("mddi_remote_read(%x) done, stat = %x,
- * return %x\n", reg, s, ri.result); */
- mddi->reg_read = NULL;
- mutex_unlock(&mddi->reg_read_lock);
- return ri.result;
-}
-
-uint32_t mddi_remote_read(struct msm_mddi_client_data *cdata, uint32_t reg)
-{
- uint32_t rtn_value;
-
- int sem_owned = overlay_semaphore_lock();
- rtn_value = _mddi_remote_read(cdata, reg);
- if (sem_owned == 0)
- overlay_semaphore_unlock();
-
- return rtn_value;
-}
-
-/*FIXME: workaround for Novatek*/
-void mddi_send_powerdown(struct msm_mddi_client_data *cdata)
-{
- 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);
-}
-
-
-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;
-#ifdef CONFIG_MSM_MDP40
- mdp_clk = clk_get(&pdev->dev, "mdp_clk");
- if (IS_ERR(mdp_clk)) {
- PR_DISP_INFO("mddi: failed to get mdp clk");
- return PTR_ERR(mdp_clk);
- }
- ret = clk_enable(mdp_clk);
- if (ret)
- goto fail;
-#endif
-#ifdef CONFIG_MDP4_HW_VSYNC
- mdp_vsync_clk = clk_get(&pdev->dev, "mdp_vsync_clk");
- if (IS_ERR(mdp_vsync_clk)) {
- PR_DISP_INFO("mddi: failed to get mdp_vsync_clk");
- return PTR_ERR(mdp_vsync_clk);
- }
- ret = clk_enable(mdp_vsync_clk);
- if (ret)
- goto fail;
-#endif
- /* set up the clocks */
- mddi->clk = clk_get(&pdev->dev, "mddi_clk");
- if (IS_ERR(mddi->clk)) {
- PR_DISP_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;
- PR_DISP_DEBUG("mddi runs at %ld\n", clk_get_rate(mddi->clk));
- 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);
- return 0;
-}
-/* FIXME: Workaround for Novatek
-static void mddi_skew_calibration(struct mddi_info *mddi)
-{
- struct msm_mddi_platform_data *pdata = mddi->client_pdev.dev.platform_data;
-
- clk_set_rate( mddi->clk, 50000000);
- mdelay(1);
- mddi_writel(MDDI_CMD_SKEW_CALIBRATION, CMD);
- mdelay(1);
- clk_set_rate( mddi->clk, pdata->clk_rate);
- mdelay(1);
-}
-*/
-
-static ssize_t mddi_reg_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
-static ssize_t mddi_reg_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos)
-{
- struct mddi_info *mddi = (struct mddi_info *)file->private_data;
-
- return simple_read_from_buffer(user_buf, count, ppos, mddi->debugfs_buf, strlen(mddi->debugfs_buf));
-}
-
-static ssize_t mddi_reg_write(struct file *file, const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- unsigned int reg, data;
- char debug_buf[32], type;
- int cnt, len;
- struct mddi_info *mddi = file->private_data;
-
- memset(debug_buf, 0x00, sizeof(debug_buf));
-
- if (count >= sizeof(debug_buf))
- return -EFAULT;
-
- if (copy_from_user(debug_buf, user_buf, count))
- return -EFAULT;
-
- debug_buf[count] = 0; /* end of string */
-
- if (debug_buf[0] == 'w') {
- cnt = sscanf(debug_buf, "%c %x %x", &type, ®, &data);
- mddi_set_auto_hibernate(&mddi->client_data, 0);
- mddi_remote_write(&mddi->client_data, data, reg);
- mddi_set_auto_hibernate(&mddi->client_data, 1);
-
- len = snprintf(mddi->debugfs_buf, sizeof(mddi->debugfs_buf),
- "[W] reg=0x%x val=0x%x\n", reg, data);
- PR_DISP_INFO("%s: reg=%x val=%x\n", __func__, reg, data);
- } else {
- cnt = sscanf(debug_buf, "%c %x", &type, ®);
-
- len = snprintf(mddi->debugfs_buf, sizeof(mddi->debugfs_buf),
- "[R] reg=0x%x val=0x%x\n", reg,
- mddi_remote_read(&mddi->client_data, reg));
-
- PR_DISP_INFO("%s: reg=%x val=%x buf=%s\n", __func__, reg,
- mddi_remote_read(&mddi->client_data, reg), debug_buf);
- }
-
- return count;
-}
-
-static struct file_operations mddi_reg_debugfs_fops[] = {
- {
- .open = mddi_reg_open,
- .read = mddi_reg_read,
- .write = mddi_reg_write,
- }
-};
-
-int mddi_reg_debugfs_init(struct mddi_info *mddi)
-{
- struct dentry *mddi_reg_dent;
-
- mddi_reg_dent = debugfs_create_dir("mddi", 0);
- if (IS_ERR(mddi_reg_dent))
- return PTR_ERR(mddi_reg_dent);
-
- debugfs_create_file("reg", 0600, mddi_reg_dent, mddi,
- &mddi_reg_debugfs_fops[0]);
-
- return 0;
-}
-
-static int mddi_probe(struct platform_device *pdev)
-{
- 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) {
- PR_DISP_ERR("mddi: no associated mem resource!\n");
- return -ENOMEM;
- }
- mddi->base = ioremap(resource->start, resource->end - resource->start);
- if (!mddi->base) {
- PR_DISP_ERR("mddi: failed to remap base!\n");
- ret = -EINVAL;
- goto error_ioremap;
- }
- resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!resource) {
- PR_DISP_ERR("mddi: no associated irq resource!\n");
- ret = -EINVAL;
- goto error_get_irq_resource;
- }
- mddi->irq = resource->start;
- PR_DISP_INFO("mddi: init() base=0x%p irq=%d\n", mddi->base,
- mddi->irq);
- mddi->power_client = pdata->power_client;
- if (pdata->type != MSM_MDP_MDDI_TYPE_I)
- mddi->type = pdata->type;
-
- mutex_init(&mddi->reg_write_lock);
- mutex_init(&mddi->reg_read_lock);
- spin_lock_init(&mddi->int_lock);
- init_waitqueue_head(&mddi->int_wait);
-
- wake_lock_init(&mddi->idle_lock, WAKE_LOCK_IDLE, "mddi_idle_lock");
- wake_lock_init(&mddi->link_active_idle_lock, WAKE_LOCK_IDLE,
- "mddi_link_active_idle_lock");
-
- ret = mddi_clk_setup(pdev, mddi, pdata->clk_rate);
- if (ret) {
- PR_DISP_ERR("mddi: failed to setup clock!\n");
- goto error_clk_setup;
- }
-
- ret = mddi_rev_data_setup(mddi);
- if (ret) {
- PR_DISP_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) {
- PR_DISP_ERR("mddi: failed to request enable irq!\n");
- goto error_request_irq;
- }
-
- /* turn on the mddi client bridge chip */
- #if 0 /*advised by SKY*/
- if (mddi->power_client)
- mddi->power_client(&mddi->client_data, 1);
- #endif
- /* 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) {
- PR_DISP_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)) {
- PR_DISP_INFO("mddi: no client found\n");
- /* power down the panel */
- mddi_writel(MDDI_CMD_POWERDOWN, CMD);
- PR_DISP_INFO("mddi powerdown: stat %x\n", mddi_readl(STAT));
- msleep(100);
- PR_DISP_INFO("mddi powerdown: stat %x\n", mddi_readl(STAT));
- goto dummy_client;
- }
-
- mddi_set_auto_hibernate(&mddi->client_data, 1);
-
- /*
- * FIXME: User kernel defconfig to link dedicated mddi client driver.
- */
- if (mddi->caps.Mfr_Name == 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) {
-dummy_client:
- mddi->client_data.private_client_data =
- pdata->client_platform_data[0].client_data;
- mddi->client_pdev.name =
- pdata->client_platform_data[0].name;
- mddi->client_pdev.id =
- pdata->client_platform_data[0].id;
- mddi->client_pdev.name = "mddi_c_dummy";
- clk_disable(mddi->clk);
- }
- PR_DISP_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_write_vals = mddi_remote_write_vals;
- 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;
- mddi->client_data.send_powerdown = mddi_send_powerdown;
- 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 {
- PR_DISP_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;
- PR_DISP_INFO("mddi: publish: %s\n", mddi->client_name);
- platform_device_register(&mddi->client_pdev);
- mddi_reg_debugfs_init(mddi);
-
- 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:
- wake_lock_destroy(&mddi->idle_lock);
- wake_lock_destroy(&mddi->link_active_idle_lock);
-error_get_irq_resource:
- iounmap(mddi->base);
-error_ioremap:
-
- PR_DISP_INFO("mddi: mddi_init() failed (%d)\n", ret);
- return ret;
-}
-
-#if 0 /* read/write mddi registers from userspace */
-module_param_named(debug, mddi_debug_flags, uint, 0644);
-
-static uint32_t selected_register;
-module_param_named(reg, selected_register, uint, 0644);
-
-static int set_reg(const char *val, struct kernel_param *kp)
-{
- char *endp;
- uint32_t l;
-
- if (!val)
- return -EINVAL;
- l = strict_strtoul(val, &endp, 0);
- if (endp == val || ((uint32_t)l != l))
- return -EINVAL;
- mddi_remote_write(kp->arg, l, selected_register);
- return 0;
-}
-
-static int get_reg(char *buffer, struct kernel_param *kp)
-{
- int val;
- val = mddi_remote_read(kp->arg, selected_register);
- return sprintf(buffer, "%x", val);
-}
-
-module_param_call(pmdh_val, set_reg, get_reg, &mddi_info[0], 0644);
-module_param_call(emdh_val, set_reg, get_reg, &mddi_info[1], 0644);
-
-#endif
+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_unprepare(mddi_clk);
+ pmdh_clk_status = 0;
+ }
+ if (mddi_pclk)
+ clk_disable_unprepare(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_prepare_enable(mddi_clk);
+ pmdh_clk_status = 1;
+ }
+ if (mddi_pclk)
+ clk_prepare_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_unprepare(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 */
+ clk_rate = clk_round_rate(mddi_clk, 49000000);
+ if (!clk_set_rate(mddi_clk, clk_rate)) {
+ 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_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);
+
+ clk_rate = clk_round_rate(mddi_clk, clk_rate);
+ if (clk_set_rate(mddi_clk, clk_rate) < 0)
+ printk(KERN_ERR "%s: clk_set_rate failed\n",
+ __func__);
+
+#ifdef CONFIG_MSM_BUS_SCALING
+ mdp_bus_scale_update_request(2);
+#else
+ if (mfd->ebi1_clk)
+ clk_prepare_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;
+ unsigned long rate;
+ int ret;
+ struct clk *ebi1_clk = NULL;
+
+ if ((pdev->id == 0) && (pdev->num_resources >= 0)) {
+ mddi_pdata = pdev->dev.platform_data;
+ pmdh_clk_status = 0;
+
+ mddi_clk = clk_get(&pdev->dev, "core_clk");
+ if (IS_ERR(mddi_clk)) {
+ pr_err("can't find mddi_clk\n");
+ return PTR_ERR(mddi_clk);
+ }
+ rate = clk_round_rate(mddi_clk, 49000000);
+ ret = clk_set_rate(mddi_clk, rate);
+ if (ret)
+ pr_err("Can't set mddi_clk min rate to %lu\n",
+ rate);
+
+ pr_info("mddi_clk init rate is %lu\n",
+ clk_get_rate(mddi_clk));
+ mddi_pclk = clk_get(&pdev->dev, "iface_clk");
+ if (IS_ERR(mddi_pclk))
+ mddi_pclk = NULL;
+ pmdh_clk_enable();
+
+#ifndef CONFIG_MSM_BUS_SCALING
+ ebi1_clk = clk_get(&pdev->dev, "mem_clk");
+ if (IS_ERR(ebi1_clk))
+ return PTR_ERR(ebi1_clk);
+ clk_set_rate(ebi1_clk, 65000000);
+#endif
+
+ 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);
+ mfd->ebi1_clk = ebi1_clk;
+
+ 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);
+ /*
+ * 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);
+
+ 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);
+
+ 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;
+
+ 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 9fa819d..ebbae87 100644
--- a/drivers/video/msm/mddi_client_dummy.c
+++ b/drivers/video/msm/mddi_client_dummy.c
@@ -17,7 +17,6 @@
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/slab.h>
#include <linux/platform_device.h>
#include <mach/msm_fb.h>
@@ -50,8 +49,6 @@
static int mddi_dummy_probe(struct platform_device *pdev)
{
struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
struct panel_info *panel =
kzalloc(sizeof(struct panel_info), GFP_KERNEL);
int ret;
@@ -67,7 +64,7 @@
panel->pdev.id = pdev->id;
platform_device_add_resources(&panel->pdev,
client_data->fb_resource, 1);
- panel->panel_data.fb_data = &bridge_data->fb_data;
+ panel->panel_data.fb_data = client_data->private_client_data;
panel->pdev.dev.platform_data = &panel->panel_data;
ret = platform_device_register(&panel->pdev);
if (ret) {
diff --git a/drivers/video/msm/mddi_client_eid.h b/drivers/video/msm/mddi_client_eid.h
deleted file mode 100644
index d31e031..0000000
--- a/drivers/video/msm/mddi_client_eid.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef _MDDI_CLIENT_EID_H_
-#define _MDDI_CLIENT_EID_H_
-
-#define SLPIN 0x10
-#define SLPOUT 0x11
-#define CASET 0x2a
-#define PASET 0x2b
-#define RAMWR 0x2c
-#define TEON 0x35
-#define MADCTL 0x36
-#define COLMOD 0x3a
-#define WRDISBV 0x51
-#define RDDISBV 0x52
-#define WRCTRLD 0x53
-#define WRCABC 0x55
-#define WRCABCMB 0x5e
-#define MIECTL1 0xca
-#define BCMODE 0xcb
-#define MIECTL2 0xcc
-#define MIECTL3 0xcd
-#define DCON 0xef
-#define DISCTL 0xf2
-#define PWRCTL 0xf3
-#define VCMCTL 0xf4
-#define SRCCTL 0xf5
-#define GAMCTL1 0xf7
-#define GAMCTL2 0xf8
-#define GATECTL 0xfd
-#define MDDICTL 0xe0
-#define DCON 0xef
-
-#endif
diff --git a/drivers/video/msm/mddi_client_hx8356.c b/drivers/video/msm/mddi_client_hx8356.c
deleted file mode 100644
index c9061e4..0000000
--- a/drivers/video/msm/mddi_client_hx8356.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/* drivers/video/msm_fb/mddi_client_hx8356.c
- *
- * Support for eid mddi client devices with Samsung S6D0154
- *
- * Copyright (C) 2007 HTC Incorporated
- * Author: Wade Wu (wade_wu@htc.com)
- *
- * 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/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <linux/kthread.h>
-#include <linux/wakelock.h>
-#include <linux/clk.h>
-#include <linux/slab.h>
-#include <asm/atomic.h>
-#include <asm/mach-types.h>
-#include "../../../arch/arm/mach-msm/proc_comm.h"
-#include <mach/msm_fb.h>
-#include <mach/msm_panel.h>
-#include <mach/msm_iomap.h>
-#include <mach/debug_display.h>
-
-
-#if 1
-#define B(s...) printk(s)
-#else
-#define B(s...) do {} while (0)
-#endif
-
-#define DEBUG_VSYNC_INT 0
-#define VSYNC_COUNTER 31
-
-#define VSYNC_CLEAR (MSM_GPIO1_BASE + 0x800 + 0x9c)
-#define VSYNC_STATUS (MSM_GPIO1_BASE + 0x800 + 0xac)
-#define VSYNC_EN (MSM_GPIO1_BASE + 0x800 + 0x8c)
-
-static DECLARE_WAIT_QUEUE_HEAD(himax_vsync_wait);
-
-#define INTERVAL_ADJUSTING 300
-
-struct panel_info {
- struct msm_mddi_client_data *client_data;
- struct platform_device pdev;
- struct msm_panel_data panel_data;
- struct work_struct adjust_panel_work;
- struct msmfb_callback *fb_callback;
- struct wake_lock idle_lock;
- atomic_t frame_counter;
- int himax_got_int;
-};
-
-static struct cabc_config cabc_config;
-static struct platform_device mddi_himax_cabc = {
- .name = "himax_cabc",
- .id = 0,
- .dev = {
- .platform_data = &cabc_config,
- }
-};
-
-static struct clk *ebi1_clk;
-
-static void himax_dump_vsync(void)
-{
- B(KERN_DEBUG "%s: enter.\n", __func__);
-}
-
-static void himax_adjust_work(struct work_struct *work)
-{
- struct panel_info *panel = container_of(work, struct panel_info, adjust_panel_work);
- struct msm_mddi_client_data *client_data = panel->client_data;
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
-
- if (bridge_data->adjust)
- bridge_data->adjust(client_data);
-
- atomic_set(&panel->frame_counter, INTERVAL_ADJUSTING);
-}
-
-static void
-himax_request_vsync(struct msm_panel_data *panel_data,
- struct msmfb_callback *callback)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
-
- panel->fb_callback = callback;
- if (panel->himax_got_int) {
- panel->himax_got_int = 0;
- client_data->activate_link(client_data); /* clears interrupt */
- }
-}
-
-static void himax_wait_vsync(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
-
- if (panel->himax_got_int) {
- panel->himax_got_int = 0;
- client_data->activate_link(client_data); /* clears interrupt */
- }
-
- if (wait_event_timeout(himax_vsync_wait, panel->himax_got_int,
- HZ/2) == 0)
- PR_DISP_ERR("timeout waiting for VSYNC\n");
-
- panel->himax_got_int = 0;
- /* interrupt clears when screen dma starts */
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-/* got called by msmfb_suspend */
-static int himax_suspend(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
- int ret;
-
- wake_lock(&panel->idle_lock);
- ret = bridge_data->uninit(bridge_data, client_data);
- wake_unlock(&panel->idle_lock);
-
- if (ret) {
- B(KERN_INFO "mddi himax client: non zero return from "
- "uninit\n");
- return ret;
- }
- client_data->suspend(client_data);
- return 0;
-}
-
-/* got called by msmfb_resume */
-static int himax_resume(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
- int ret;
-
- client_data->resume(client_data);
-
- wake_lock(&panel->idle_lock);
- ret = bridge_data->init(bridge_data, client_data);
- wake_unlock(&panel->idle_lock);
-
- if (ret)
- return ret;
- return 0;
-}
-
-static int himax_blank(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
-
- return bridge_data->blank(bridge_data, client_data);
-}
-
-static int himax_unblank(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
-
- if (cabc_config.bl_handle) {
- mdelay(40);
- cabc_config.bl_handle(&mddi_himax_cabc, LED_FULL);
- }
- return bridge_data->unblank(bridge_data, client_data);
-}
-
-static irqreturn_t himax_vsync_interrupt(int irq, void *data)
-{
- struct panel_info *panel = data;
-
- panel->himax_got_int = 1;
-
- if (atomic_dec_and_test(&panel->frame_counter)) {
- schedule_work(&panel->adjust_panel_work);
- return IRQ_HANDLED;
- }
-
- if (panel->fb_callback && atomic_read(&panel->frame_counter) > 0) {
- panel->fb_callback->func(panel->fb_callback);
- panel->fb_callback = NULL;
- }
- wake_up(&himax_vsync_wait);
-
- 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 = irq = gpio_to_irq(gpio);
- if (ret < 0)
- goto err_get_irq_num_failed;
-
- ret = request_irq(irq, himax_vsync_interrupt, IRQF_TRIGGER_RISING,
- "vsync", panel);
- if (ret)
- goto err_request_irq_failed;
-
- PR_DISP_INFO("vsync on gpio %d now %d\n", gpio,
- gpio_get_value(gpio));
- return 0;
-
-uninit:
- free_irq(gpio_to_irq(gpio), panel->client_data);
-err_request_irq_failed:
-err_get_irq_num_failed:
- gpio_free(gpio);
-err_request_gpio_failed:
- return ret;
-}
-
-static int mddi_himax_probe(struct platform_device *pdev)
-{
- int ret, err = -EINVAL;
- struct panel_info *panel;
- struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
- struct panel_data *panel_data = &bridge_data->panel_conf;
-
- B(KERN_DEBUG "%s: enter\n", __func__);
-
- panel = kzalloc(sizeof(struct panel_info), GFP_KERNEL);
- if (!panel) {
- err = -ENOMEM;
- goto err_out;
- }
-
- platform_set_drvdata(pdev, panel);
- ret = setup_vsync(panel, 1);
- if (ret) {
- dev_err(&pdev->dev, "mddi_himax_setup_vsync failed\n");
- err = -EIO;
- goto err_panel;
- }
-
- cabc_config.pwm_data = panel_data->pwm;
- cabc_config.min_level = panel_data->min_level;
- cabc_config.shrink = panel_data->shrink;
- cabc_config.shrink_br = panel_data->shrink_br;
- cabc_config.change_cabcmode = panel_data->change_cabcmode;
- if (panel_data->caps & MSMFB_CAP_CABC) {
- PR_DISP_INFO("CABC enabled\n");
- cabc_config.client = client_data;
- platform_device_register(&mddi_himax_cabc);
- }
-
- panel->client_data = client_data;
- panel->panel_data.suspend = himax_suspend;
- panel->panel_data.resume = himax_resume;
- panel->panel_data.wait_vsync = himax_wait_vsync;
- panel->panel_data.request_vsync = himax_request_vsync;
- panel->panel_data.blank = himax_blank;
- panel->panel_data.unblank = himax_unblank;
- panel->panel_data.dump_vsync = himax_dump_vsync;
- panel->panel_data.fb_data = &bridge_data->fb_data;
- panel->panel_data.caps = ~MSMFB_CAP_PARTIAL_UPDATES;
- panel->pdev.name = "msm_panel";
- panel->pdev.id = pdev->id;
- panel->pdev.resource = client_data->fb_resource;
- panel->pdev.num_resources = 1;
- panel->pdev.dev.platform_data = &panel->panel_data;
- platform_device_register(&panel->pdev);
- wake_lock_init(&panel->idle_lock, WAKE_LOCK_IDLE, "eid_idle_lock");
- /*for debugging vsync issue*/
- ebi1_clk = clk_get(NULL, "ebi1_clk");
-
- INIT_WORK(&panel->adjust_panel_work, himax_adjust_work);
- atomic_set(&panel->frame_counter, INTERVAL_ADJUSTING);
-
- return 0;
-
-err_panel:
- kfree(panel);
-err_out:
- return err;
-}
-
-static int mddi_himax_remove(struct platform_device *pdev)
-{
- struct panel_info *panel = platform_get_drvdata(pdev);
-
- setup_vsync(panel, 0);
- kfree(panel);
- return 0;
-}
-
-static struct platform_driver mddi_client_4858_0000 = {
- .probe = mddi_himax_probe,
- .remove = mddi_himax_remove,
- .driver = {.name = "mddi_c_4858_8356"},
-};
-
-static int __init mddi_client_himax_init(void)
-{
- return platform_driver_register(&mddi_client_4858_0000);
-}
-
-module_init(mddi_client_himax_init);
diff --git a/drivers/video/msm/mddi_client_novb9f6_5560.c b/drivers/video/msm/mddi_client_novb9f6_5560.c
deleted file mode 100644
index 16db47c..0000000
--- a/drivers/video/msm/mddi_client_novb9f6_5560.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright (C) 2008 HTC Corporation.
- *
- * 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/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/wakelock.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <mach/msm_fb.h>
-#include <mach/debug_display.h>
-#include <mach/panel_id.h>
-
-static DECLARE_WAIT_QUEUE_HEAD(novtec_vsync_wait);
-
-struct panel_info {
- struct msm_mddi_client_data *client_data;
- struct platform_device pdev;
- struct msm_panel_data panel_data;
- struct msmfb_callback *novtec_callback;
- struct wake_lock idle_lock;
- int novtec_got_int;
- int vsync_gpio;
-};
-
-static struct platform_device mddi_nov_cabc = {
- .name = "nov_cabc",
- .id = 0,
-};
-
-static void novtec_request_vsync(struct msm_panel_data *panel_data,
- struct msmfb_callback *callback)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
-
- panel->novtec_callback = callback;
- if (panel->novtec_got_int) {
- panel->novtec_got_int = 0;
- client_data->activate_link(client_data);
- }
-}
-
-static void novtec_clear_vsync(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
-
- client_data->activate_link(client_data);
-}
-
-static void novtec_wait_vsync(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
-
- if (panel->novtec_got_int) {
- panel->novtec_got_int = 0;
- client_data->activate_link(client_data); /* clears interrupt */
- }
- if (wait_event_timeout(novtec_vsync_wait, panel->novtec_got_int,
- HZ/2) == 0)
- PR_DISP_ERR("timeout waiting for VSYNC\n");
- panel->novtec_got_int = 0;
- /* interrupt clears when screen dma starts */
-}
-
-static int novtec_suspend(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
-
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
- int ret;
-
- wake_lock(&panel->idle_lock);
- ret = bridge_data->uninit(bridge_data, client_data);
- wake_unlock(&panel->idle_lock);
- if (ret) {
- PR_DISP_INFO("mddi novtec client: non zero return from "
- "uninit\n");
- return ret;
- }
- client_data->suspend(client_data);
- return 0;
-}
-
-static int novtec_resume(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
-
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
- int ret;
-
- wake_lock(&panel->idle_lock);
- client_data->resume(client_data);
- wake_unlock(&panel->idle_lock);
- ret = bridge_data->init(bridge_data, client_data);
- if (ret)
- return ret;
- return 0;
-}
-
-static int novtec_blank(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
-
- return bridge_data->blank(bridge_data, client_data);
-}
-
-static int novtec_unblank(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
-
- return bridge_data->unblank(bridge_data, client_data);
-}
-
-static int novtec_recover(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
-
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
- int ret;
-
- ret = bridge_data->init(bridge_data, client_data);
- if (ret)
- return ret;
- return 0;
-}
-
-static irqreturn_t novtec_vsync_interrupt(int irq, void *data)
-{
- struct panel_info *panel = data;
-
- panel->novtec_got_int = 1;
- if (panel->novtec_callback) {
- panel->novtec_callback->func(panel->novtec_callback);
- panel->novtec_callback = 0;
- }
- wake_up(&novtec_vsync_wait);
- return IRQ_HANDLED;
-}
-
-static int setup_vsync(struct panel_info *panel,
- int init)
-{
- int ret;
- int gpio = panel->vsync_gpio;
- 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;
-
- register_gpio_int_mask(gpio, 1);
-
- ret = request_irq(irq, novtec_vsync_interrupt, IRQF_TRIGGER_RISING,
- "vsync", panel);
- if (ret)
- goto err_request_irq_failed;
- PR_DISP_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_novtec_probe(struct platform_device *pdev)
-{
-#ifndef CONFIG_MDP4_HW_VSYNC
- int ret;
-#endif
- struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
- struct panel_data *panel_data = &bridge_data->panel_conf;
- struct panel_info *panel =
- kzalloc(sizeof(struct panel_info), GFP_KERNEL);
-
- if (!panel)
- return -ENOMEM;
- platform_set_drvdata(pdev, panel);
-
- PR_DISP_DEBUG("%s\n", __func__);
-
- if (panel_data->caps & MSMFB_CAP_CABC) {
- PR_DISP_INFO("CABC enabled\n");
- mddi_nov_cabc.dev.platform_data = client_data;
- platform_device_register(&mddi_nov_cabc);
- }
-
- if (panel_data->vsync_gpio == 0)
-#if defined(CONFIG_ARCH_MSM7X30)
- panel->vsync_gpio = 30;
-#else
- panel->vsync_gpio = 98;
-#endif
- else
- panel->vsync_gpio = panel_data->vsync_gpio;
-
-#ifndef CONFIG_MDP4_HW_VSYNC
- ret = setup_vsync(panel, 1);
- if (ret) {
- dev_err(&pdev->dev, "mddi_bridge_setup_vsync failed\n");
- return ret;
- }
-#endif
- panel->client_data = client_data;
- panel->panel_data.suspend = novtec_suspend;
- panel->panel_data.resume = novtec_resume;
- panel->panel_data.wait_vsync = novtec_wait_vsync;
- panel->panel_data.request_vsync = novtec_request_vsync;
- panel->panel_data.clear_vsync = novtec_clear_vsync;
- panel->panel_data.blank = novtec_blank;
- panel->panel_data.unblank = novtec_unblank;
- panel->panel_data.fb_data = &bridge_data->fb_data;
- panel->panel_data.caps = MSMFB_CAP_PARTIAL_UPDATES;
- panel->panel_data.recover_vsync = novtec_recover;
-
- panel->pdev.name = "msm_panel";
- panel->pdev.id = pdev->id;
- panel->pdev.resource = client_data->fb_resource;
- panel->pdev.num_resources = 1;
- panel->pdev.dev.platform_data = &panel->panel_data;
- platform_device_register(&panel->pdev);
- wake_lock_init(&panel->idle_lock, WAKE_LOCK_IDLE, "nov_idle_lock");
-
- return 0;
-}
-
-static int mddi_novtec_remove(struct platform_device *pdev)
-{
- struct panel_info *panel = platform_get_drvdata(pdev);
-
- setup_vsync(panel, 0);
- kfree(panel);
- return 0;
-}
-
-static struct platform_driver mddi_client_d263_0000 = {
- .probe = mddi_novtec_probe,
- .remove = mddi_novtec_remove,
- .driver = { .name = "mddi_c_b9f6_5560" },
-};
-
-static int __init mddi_client_novtec_init(void)
-{
- platform_driver_register(&mddi_client_d263_0000);
- return 0;
-}
-
-module_init(mddi_client_novtec_init);
-
diff --git a/drivers/video/msm/mddi_client_novb9f6_5580.c b/drivers/video/msm/mddi_client_novb9f6_5580.c
deleted file mode 100644
index 9629dd2..0000000
--- a/drivers/video/msm/mddi_client_novb9f6_5580.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2008 HTC Corporation.
- *
- * 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/sched.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/wakelock.h>
-#include <linux/slab.h>
-#include <mach/msm_fb.h>
-#include <mach/debug_display.h>
-#include <mach/panel_id.h>
-
-static DECLARE_WAIT_QUEUE_HEAD(novtec_vsync_wait);
-
-struct panel_info {
- struct msm_mddi_client_data *client_data;
- struct platform_device pdev;
- struct msm_panel_data panel_data;
- struct msmfb_callback *novtec_callback;
- struct wake_lock idle_lock;
- int novtec_got_int;
-};
-
-static struct platform_device mddi_nov_cabc = {
- .name = "nov_cabc",
- .id = 0,
-};
-
-static void novtec_request_vsync(struct msm_panel_data *panel_data,
- struct msmfb_callback *callback)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
-
- panel->novtec_callback = callback;
- if (panel->novtec_got_int) {
- panel->novtec_got_int = 0;
- client_data->activate_link(client_data);
- }
-}
-
-static void novtec_clear_vsync(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
-
- client_data->activate_link(client_data);
-}
-
-static void novtec_wait_vsync(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
-
- if (panel->novtec_got_int) {
- panel->novtec_got_int = 0;
- client_data->activate_link(client_data); /* clears interrupt */
- }
- if (wait_event_timeout(novtec_vsync_wait, panel->novtec_got_int,
- HZ/2) == 0)
- PR_DISP_ERR("timeout waiting for VSYNC\n");
- panel->novtec_got_int = 0;
- /* interrupt clears when screen dma starts */
-}
-
-static int novtec_suspend(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
-
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
- int ret;
-
- wake_lock(&panel->idle_lock);
- ret = bridge_data->uninit(bridge_data, client_data);
- wake_unlock(&panel->idle_lock);
- if (ret) {
- PR_DISP_INFO("mddi novtec client: non zero return from "
- "uninit\n");
- return ret;
- }
- client_data->suspend(client_data);
- return 0;
-}
-
-static int novtec_resume(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
-
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
- int ret;
-
- wake_lock(&panel->idle_lock);
- client_data->resume(client_data);
- wake_unlock(&panel->idle_lock);
- ret = bridge_data->init(bridge_data, client_data);
- if (ret)
- return ret;
- return 0;
-}
-
-static int novtec_blank(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
-
- return bridge_data->blank(bridge_data, client_data);
-}
-
-static int novtec_unblank(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
-
- return bridge_data->unblank(bridge_data, client_data);
-}
-
-static irqreturn_t novtec_vsync_interrupt(int irq, void *data)
-{
- struct panel_info *panel = data;
-
- panel->novtec_got_int = 1;
- if (panel->novtec_callback) {
- panel->novtec_callback->func(panel->novtec_callback);
- panel->novtec_callback = 0;
- }
- wake_up(&novtec_vsync_wait);
- return IRQ_HANDLED;
-}
-
-static int setup_vsync(struct panel_info *panel,
- int init)
-{
- int ret;
-#if defined(CONFIG_ARCH_MSM7X30)
- int gpio = 30;
-#else
- int gpio = 98;
-#endif
- 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, novtec_vsync_interrupt, IRQF_TRIGGER_FALLING,
- "vsync", panel);
- if (ret)
- goto err_request_irq_failed;
- PR_DISP_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_novtec_probe(struct platform_device *pdev)
-{
-#ifndef CONFIG_MDP4_HW_VSYNC
- int ret;
-#endif
- struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
- struct panel_data *panel_data = &bridge_data->panel_conf;
- struct panel_info *panel =
- kzalloc(sizeof(struct panel_info), GFP_KERNEL);
-
- if (!panel)
- return -ENOMEM;
- platform_set_drvdata(pdev, panel);
-
- PR_DISP_DEBUG("%s\n", __func__);
-
- if (panel_data->caps & MSMFB_CAP_CABC) {
- PR_DISP_INFO("CABC enabled\n");
- mddi_nov_cabc.dev.platform_data = client_data;
- platform_device_register(&mddi_nov_cabc);
- }
-
-#ifndef CONFIG_MDP4_HW_VSYNC
- ret = setup_vsync(panel, 1);
- if (ret) {
- dev_err(&pdev->dev, "mddi_bridge_setup_vsync failed\n");
- return ret;
- }
-#endif
- panel->client_data = client_data;
- panel->panel_data.suspend = novtec_suspend;
- panel->panel_data.resume = novtec_resume;
- panel->panel_data.wait_vsync = novtec_wait_vsync;
- panel->panel_data.request_vsync = novtec_request_vsync;
- panel->panel_data.clear_vsync = novtec_clear_vsync;
- panel->panel_data.blank = novtec_blank;
- panel->panel_data.unblank = novtec_unblank;
- panel->panel_data.fb_data = &bridge_data->fb_data;
- panel->panel_data.caps = MSMFB_CAP_PARTIAL_UPDATES;
-
- panel->pdev.name = "msm_panel";
- panel->pdev.id = pdev->id;
- panel->pdev.resource = client_data->fb_resource;
- panel->pdev.num_resources = 1;
- panel->pdev.dev.platform_data = &panel->panel_data;
- platform_device_register(&panel->pdev);
- wake_lock_init(&panel->idle_lock, WAKE_LOCK_IDLE, "nov_idle_lock");
-
- return 0;
-}
-
-static int mddi_novtec_remove(struct platform_device *pdev)
-{
- struct panel_info *panel = platform_get_drvdata(pdev);
-
- setup_vsync(panel, 0);
- kfree(panel);
- return 0;
-}
-
-static struct platform_driver mddi_client_d263_0000 = {
- .probe = mddi_novtec_probe,
- .remove = mddi_novtec_remove,
- .driver = { .name = "mddi_c_b9f6_5580" },
-};
-
-static int __init mddi_client_novtec_init(void)
-{
- platform_driver_register(&mddi_client_d263_0000);
- return 0;
-}
-
-module_init(mddi_client_novtec_init);
-
diff --git a/drivers/video/msm/mddi_client_nt35399.c b/drivers/video/msm/mddi_client_nt35399.c
new file mode 100644
index 0000000..c9e9349
--- /dev/null
+++ b/drivers/video/msm/mddi_client_nt35399.c
@@ -0,0 +1,256 @@
+/* drivers/video/msm_fb/mddi_client_nt35399.c
+ *
+ * Support for Novatek NT35399 MDDI client of Sapphire
+ *
+ * Copyright (C) 2008 HTC Incorporated
+ * Author: Solomon Chiu (solomon_chiu@htc.com)
+ *
+ * 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/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/gpio.h>
+#include <mach/msm_fb.h>
+
+static DECLARE_WAIT_QUEUE_HEAD(nt35399_vsync_wait);
+
+struct panel_info {
+ struct msm_mddi_client_data *client_data;
+ struct platform_device pdev;
+ struct msm_panel_data panel_data;
+ struct msmfb_callback *fb_callback;
+ struct work_struct panel_work;
+ struct workqueue_struct *fb_wq;
+ int nt35399_got_int;
+};
+
+static void
+nt35399_request_vsync(struct msm_panel_data *panel_data,
+ struct msmfb_callback *callback)
+{
+ struct panel_info *panel = container_of(panel_data, struct panel_info,
+ panel_data);
+ struct msm_mddi_client_data *client_data = panel->client_data;
+
+ panel->fb_callback = callback;
+ if (panel->nt35399_got_int) {
+ panel->nt35399_got_int = 0;
+ client_data->activate_link(client_data); /* clears interrupt */
+ }
+}
+
+static void nt35399_wait_vsync(struct msm_panel_data *panel_data)
+{
+ struct panel_info *panel = container_of(panel_data, struct panel_info,
+ panel_data);
+ struct msm_mddi_client_data *client_data = panel->client_data;
+
+ if (panel->nt35399_got_int) {
+ panel->nt35399_got_int = 0;
+ client_data->activate_link(client_data); /* clears interrupt */
+ }
+
+ if (wait_event_timeout(nt35399_vsync_wait, panel->nt35399_got_int,
+ HZ/2) == 0)
+ printk(KERN_ERR "timeout waiting for VSYNC\n");
+
+ panel->nt35399_got_int = 0;
+ /* interrupt clears when screen dma starts */
+}
+
+static int nt35399_suspend(struct msm_panel_data *panel_data)
+{
+ struct panel_info *panel = container_of(panel_data, struct panel_info,
+ panel_data);
+ struct msm_mddi_client_data *client_data = panel->client_data;
+
+ struct msm_mddi_bridge_platform_data *bridge_data =
+ client_data->private_client_data;
+ int ret;
+
+ ret = bridge_data->uninit(bridge_data, client_data);
+ if (ret) {
+ printk(KERN_INFO "mddi nt35399 client: non zero return from "
+ "uninit\n");
+ return ret;
+ }
+ client_data->suspend(client_data);
+ return 0;
+}
+
+static int nt35399_resume(struct msm_panel_data *panel_data)
+{
+ struct panel_info *panel = container_of(panel_data, struct panel_info,
+ panel_data);
+ struct msm_mddi_client_data *client_data = panel->client_data;
+
+ struct msm_mddi_bridge_platform_data *bridge_data =
+ client_data->private_client_data;
+ int ret;
+
+ client_data->resume(client_data);
+ ret = bridge_data->init(bridge_data, client_data);
+ if (ret)
+ return ret;
+ return 0;
+}
+
+static int nt35399_blank(struct msm_panel_data *panel_data)
+{
+ struct panel_info *panel = container_of(panel_data, struct panel_info,
+ panel_data);
+ struct msm_mddi_client_data *client_data = panel->client_data;
+ struct msm_mddi_bridge_platform_data *bridge_data =
+ client_data->private_client_data;
+
+ return bridge_data->blank(bridge_data, client_data);
+}
+
+static int nt35399_unblank(struct msm_panel_data *panel_data)
+{
+ struct panel_info *panel = container_of(panel_data, struct panel_info,
+ panel_data);
+ struct msm_mddi_client_data *client_data = panel->client_data;
+ struct msm_mddi_bridge_platform_data *bridge_data =
+ client_data->private_client_data;
+
+ return bridge_data->unblank(bridge_data, client_data);
+}
+
+irqreturn_t nt35399_vsync_interrupt(int irq, void *data)
+{
+ struct panel_info *panel = data;
+
+ panel->nt35399_got_int = 1;
+
+ if (panel->fb_callback) {
+ panel->fb_callback->func(panel->fb_callback);
+ panel->fb_callback = NULL;
+ }
+
+ wake_up(&nt35399_vsync_wait);
+
+ 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, nt35399_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->client_data);
+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_nt35399_probe(struct platform_device *pdev)
+{
+ struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
+ struct msm_mddi_bridge_platform_data *bridge_data =
+ client_data->private_client_data;
+
+ int ret;
+
+ struct panel_info *panel = kzalloc(sizeof(struct panel_info),
+ GFP_KERNEL);
+
+ printk(KERN_DEBUG "%s: enter.\n", __func__);
+
+ if (!panel)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, panel);
+
+ ret = setup_vsync(panel, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "mddi_nt35399_setup_vsync failed\n");
+ return ret;
+ }
+
+ panel->client_data = client_data;
+ panel->panel_data.suspend = nt35399_suspend;
+ panel->panel_data.resume = nt35399_resume;
+ panel->panel_data.wait_vsync = nt35399_wait_vsync;
+ panel->panel_data.request_vsync = nt35399_request_vsync;
+ panel->panel_data.blank = nt35399_blank;
+ panel->panel_data.unblank = nt35399_unblank;
+ panel->panel_data.fb_data = &bridge_data->fb_data;
+ panel->panel_data.caps = 0;
+
+ panel->pdev.name = "msm_panel";
+ panel->pdev.id = pdev->id;
+ panel->pdev.resource = client_data->fb_resource;
+ panel->pdev.num_resources = 1;
+ panel->pdev.dev.platform_data = &panel->panel_data;
+
+ if (bridge_data->init)
+ bridge_data->init(bridge_data, client_data);
+
+ platform_device_register(&panel->pdev);
+
+ return 0;
+}
+
+static int mddi_nt35399_remove(struct platform_device *pdev)
+{
+ struct panel_info *panel = platform_get_drvdata(pdev);
+
+ setup_vsync(panel, 0);
+ kfree(panel);
+ return 0;
+}
+
+static struct platform_driver mddi_client_0bda_8a47 = {
+ .probe = mddi_nt35399_probe,
+ .remove = mddi_nt35399_remove,
+ .driver = { .name = "mddi_c_0bda_8a47" },
+};
+
+static int __init mddi_client_nt35399_init(void)
+{
+ return platform_driver_register(&mddi_client_0bda_8a47);
+}
+
+module_init(mddi_client_nt35399_init);
+
diff --git a/drivers/video/msm/mddi_client_renesas_R61408.c b/drivers/video/msm/mddi_client_renesas_R61408.c
deleted file mode 100644
index 1e001b4..0000000
--- a/drivers/video/msm/mddi_client_renesas_R61408.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2008 HTC Corporation.
- *
- * 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/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/wakelock.h>
-#include <linux/slab.h>
-#include <linux/wait.h>
-#include <linux/sched.h>
-#include <mach/msm_fb.h>
-#include <mach/debug_display.h>
-
-static DECLARE_WAIT_QUEUE_HEAD(renesas_vsync_wait);
-
-struct panel_info {
- struct msm_mddi_client_data *client_data;
- struct platform_device pdev;
- struct msm_panel_data panel_data;
- struct msmfb_callback *renesas_callback;
- struct wake_lock idle_lock;
- int renesas_got_int;
- int vsync_gpio;
-};
-
-static struct platform_device mddi_renesas_backlight = {
- .name = "renesas_backlight",
- .id = 0,
-};
-
-static void renesas_request_vsync(struct msm_panel_data *panel_data,
- struct msmfb_callback *callback)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
-
- panel->renesas_callback = callback;
- if (panel->renesas_got_int) {
- panel->renesas_got_int = 0;
- client_data->activate_link(client_data);
- }
-}
-
-static void renesas_clear_vsync(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
-
- client_data->activate_link(client_data);
-}
-
-static void renesas_wait_vsync(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
-
- if (panel->renesas_got_int) {
- panel->renesas_got_int = 0;
- client_data->activate_link(client_data); /* clears interrupt */
- }
- if (wait_event_timeout(renesas_vsync_wait, panel->renesas_got_int,
- HZ/2) == 0)
- PR_DISP_ERR("timeout waiting for VSYNC\n");
- panel->renesas_got_int = 0;
- /* interrupt clears when screen dma starts */
-}
-
-static int renesas_suspend(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
-
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
- int ret;
-
- wake_lock(&panel->idle_lock);
- ret = bridge_data->uninit(bridge_data, client_data);
- wake_unlock(&panel->idle_lock);
- if (ret) {
- PR_DISP_INFO("mddi renesas client: non zero return from "
- "uninit\n");
- return ret;
- }
- client_data->suspend(client_data);
- return 0;
-}
-
-static int renesas_resume(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
-
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
- int ret;
-
- wake_lock(&panel->idle_lock);
- client_data->resume(client_data);
- wake_unlock(&panel->idle_lock);
- ret = bridge_data->init(bridge_data, client_data);
- if (ret)
- return ret;
- return 0;
-}
-
-static int renesas_blank(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
-
- return bridge_data->blank(bridge_data, client_data);
-}
-
-static int renesas_unblank(struct msm_panel_data *panel_data)
-{
- struct panel_info *panel = container_of(panel_data, struct panel_info,
- panel_data);
- struct msm_mddi_client_data *client_data = panel->client_data;
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
-
- return bridge_data->unblank(bridge_data, client_data);
-}
-
-static irqreturn_t renesas_vsync_interrupt(int irq, void *data)
-{
- struct panel_info *panel = data;
-
- panel->renesas_got_int = 1;
- if (panel->renesas_callback) {
- panel->renesas_callback->func(panel->renesas_callback);
- panel->renesas_callback = 0;
- }
- wake_up(&renesas_vsync_wait);
- return IRQ_HANDLED;
-}
-
-static int setup_vsync(struct panel_info *panel,
- int init)
-{
- int ret;
- int gpio = panel->vsync_gpio;
- 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;
-
- register_gpio_int_mask(gpio, 1);
-
- ret = request_irq(irq, renesas_vsync_interrupt, IRQF_TRIGGER_RISING,
- "vsync", panel);
- if (ret)
- goto err_request_irq_failed;
- PR_DISP_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_renesas_probe(struct platform_device *pdev)
-{
- int ret;
- struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
- struct msm_mddi_bridge_platform_data *bridge_data =
- client_data->private_client_data;
- struct panel_data *panel_data = &bridge_data->panel_conf;
- struct panel_info *panel =
- kzalloc(sizeof(struct panel_info), GFP_KERNEL);
-
- if (!panel)
- return -ENOMEM;
- platform_set_drvdata(pdev, panel);
-
- PR_DISP_DEBUG("%s\n", __func__);
-
- mddi_renesas_backlight.dev.platform_data = client_data;
- platform_device_register(&mddi_renesas_backlight);
-
- if (panel_data->vsync_gpio == 0)
-#if defined(CONFIG_ARCH_MSM7X30)
- panel->vsync_gpio = 30;
-#else
- panel->vsync_gpio = 98;
-#endif
- else
- panel->vsync_gpio = panel_data->vsync_gpio;
-
- ret = setup_vsync(panel, 1);
- if (ret) {
- dev_err(&pdev->dev, "mddi_bridge_setup_vsync failed\n");
- return ret;
- }
- panel->client_data = client_data;
- panel->panel_data.suspend = renesas_suspend;
- panel->panel_data.resume = renesas_resume;
- panel->panel_data.wait_vsync = renesas_wait_vsync;
- panel->panel_data.request_vsync = renesas_request_vsync;
- panel->panel_data.clear_vsync = renesas_clear_vsync;
- panel->panel_data.blank = renesas_blank;
- panel->panel_data.unblank = renesas_unblank;
- panel->panel_data.fb_data = &bridge_data->fb_data;
- panel->panel_data.caps = MSMFB_CAP_PARTIAL_UPDATES;
- panel->pdev.name = "msm_panel";
- panel->pdev.id = pdev->id;
- panel->pdev.resource = client_data->fb_resource;
- panel->pdev.num_resources = 1;
- panel->pdev.dev.platform_data = &panel->panel_data;
- platform_device_register(&panel->pdev);
- wake_lock_init(&panel->idle_lock, WAKE_LOCK_IDLE, "renesas_idle_lock");
-
- return 0;
-}
-
-static int mddi_renesas_remove(struct platform_device *pdev)
-{
- struct panel_info *panel = platform_get_drvdata(pdev);
-
- setup_vsync(panel, 0);
- kfree(panel);
- return 0;
-}
-
-static struct platform_driver mddi_client_b9f6_61408 = {
- .probe = mddi_renesas_probe,
- .remove = mddi_renesas_remove,
- .driver = { .name = "mddi_renesas_b9f6_61408" },
-};
-
-static int __init mddi_client_renesas_init(void)
-{
- platform_driver_register(&mddi_client_b9f6_61408);
- return 0;
-}
-
-module_init(mddi_client_renesas_init);
-
diff --git a/drivers/video/msm/mddi_client_toshiba.c b/drivers/video/msm/mddi_client_toshiba.c
index 2c8d73b..8868781 100644
--- a/drivers/video/msm/mddi_client_toshiba.c
+++ b/drivers/video/msm/mddi_client_toshiba.c
@@ -21,9 +21,7 @@
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/sched.h>
-#include <linux/slab.h>
#include <mach/msm_fb.h>
-#include <mach/debug_display.h>
#define LCD_CONTROL_BLOCK_BASE 0x110000
@@ -61,6 +59,7 @@
struct msm_panel_data panel_data;
struct msmfb_callback *toshiba_callback;
int toshiba_got_int;
+ int irq;
};
@@ -97,8 +96,9 @@
panel->toshiba_got_int = 0;
client_data->activate_link(client_data); /* clears interrupt */
}
- if (wait_event_timeout(toshiba_vsync_wait, panel->toshiba_got_int, HZ/2) == 0)
- PR_DISP_ERR("timeout waiting for VSYNC\n");
+ if (wait_event_timeout(toshiba_vsync_wait, panel->toshiba_got_int,
+ HZ/2) == 0)
+ printk(KERN_ERR "timeout waiting for VSYNC\n");
panel->toshiba_got_int = 0;
/* interrupt clears when screen dma starts */
}
@@ -115,7 +115,7 @@
ret = bridge_data->uninit(bridge_data, client_data);
if (ret) {
- PR_DISP_INFO("mddi toshiba client: non zero return from "
+ printk(KERN_INFO "mddi toshiba client: non zero return from "
"uninit\n");
return ret;
}
@@ -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;
- PR_DISP_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..dc79fed
--- /dev/null
+++ b/drivers/video/msm/mddi_ext.c
@@ -0,0 +1,354 @@
+/* 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);
+
+ clk_rate = clk_round_rate(mddi_ext_clk, clk_rate);
+ if (clk_set_rate(mddi_ext_clk, clk_rate) < 0)
+ printk(KERN_ERR "%s: clk_set_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;
+ mddi_ext_clk = clk_get(&pdev->dev, "core_clk");
+ if (IS_ERR(mddi_ext_clk)) {
+ pr_err("can't find emdh_clk\n");
+ return PTR_ERR(mddi_ext_clk);
+ }
+ clk_prepare_enable(mddi_ext_clk);
+
+ mddi_ext_pclk = clk_get(&pdev->dev, "iface_clk");
+ if (IS_ERR(mddi_ext_pclk))
+ mddi_ext_pclk = NULL;
+ else
+ clk_prepare_enable(mddi_ext_pclk);
+
+ 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;
+
+ clk_disable_unprepare(mddi_ext_clk);
+ if (mddi_ext_pclk)
+ clk_disable_unprepare(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_prepare_enable(mddi_ext_clk);
+ if (mddi_ext_pclk)
+ clk_prepare_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;
+
+ ret = mddi_ext_register_driver();
+ if (ret) {
+ 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_himax_cabc.c b/drivers/video/msm/mddi_himax_cabc.c
deleted file mode 100644
index 23db904..0000000
--- a/drivers/video/msm/mddi_himax_cabc.c
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * Copyright (C) 2010 HTC Corporation.
- *
- * 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/leds.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <mach/msm_fb.h>
-#include <linux/wakelock.h>
-#include <mach/htc_pwrsink.h>
-#include <mach/msm_panel.h>
-#include "mddi_client_eid.h"
-#include <mach/debug_display.h>
-
-enum bc_mode {
- BC_OFF = 0,
- BC_MANUAL,
- BC_AUTO,
- BC_MERGED,
- BC_UNDEF,
-};
-
-enum cabc_mode {
- CABC_OFF = 0,
- CABC_UI,
- CABC_STILL,
- CABC_MOVING,
- CABC_UNDEF,
-};
-
-#if 0
-#define B(s...) printk(s)
-#else
-#define B(s...) do {} while (0)
-#endif
-
-#define DEBUG 0
-
-static int g_brightness;
-static char *str_bc_mode[] = {"BC_OFF", "BC_MANUAL", "BC_AUTO", "BC_MERGED"};
-static char *str_cabc_mode[] = {"CABC_OFF", "CABC_USER_INTERFACE",
- "CABC_STILL_IMAGE", "CABC_MOVING"};
-
-static ssize_t
-himax_show(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t
-himax_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count);
-
-struct cabc {
- struct cabc_config *cabc_config;
- struct led_classdev lcd_backlight; /* user */
- struct mutex lock;
- struct mutex data_lock;
- struct work_struct lcd_changed_work; /* lcd backlight */
- struct work_struct set_auto_work;
- struct wake_lock wakelock;
- struct workqueue_struct *cabc_queue;
-#ifdef CONFIG_HAS_EARLYSUSPEND
- struct early_suspend early_suspend;
-#endif
- unsigned long status;
- enum cabc_mode mode_cabc;
- enum bc_mode mode_bc;
-};
-
-enum {
- LS_STATE,
- GATE_ON,
- ENFORCE_ON,
- SUSPEND,
- AUTO_SETTING,
- LS_SWITCH,
-};
-
-#define to_cabc(p, m) container_of(p, struct cabc, m)
-
-static inline
-struct msm_mddi_client_data *cabc_get_client(struct cabc *cabc)
-{
- struct cabc_config *data = cabc->cabc_config;
- return data->client;
-}
-
-static inline int cabc_shrink(struct cabc *cabc, int brightness)
-{
- struct cabc_config *config = cabc->cabc_config;
-
- if (config->shrink) {
- if (brightness <= 102) {
- if (brightness <= 30)
- brightness = 8;
- else
- brightness = 123 * (brightness - 30) / 72 + 8;
- } else
- brightness = 124 * (brightness - 102) / 153 + 131;
- }
- return brightness;
-}
-
-static int
-himax_change_cabcmode(struct msm_mddi_client_data *client_data,
- int mode, u8 dimming)
-{
- PR_DISP_DEBUG("+%s, mode=%d, dimming=%d\n", __func__, mode, dimming);
- return 0;
-}
-
-static int
-__set_brightness(struct cabc *cabc, int brightness, u8 dimming)
-{
- struct msm_mddi_client_data *client_data = cabc_get_client(cabc);
-
- int shrink_br;
- /* no need to check brightness > LED_FULL, the led class
- * already does */
- PR_DISP_INFO("brightness = %d, %s ls-(%s)\n",
- brightness, str_bc_mode[cabc->mode_bc],
- (test_bit(LS_STATE, &cabc->status) ? "on" : "off"));
-
- mutex_lock(&cabc->data_lock);
- if (cabc->cabc_config->shrink && cabc->cabc_config->shrink_br)
- shrink_br = cabc->cabc_config->shrink_br(brightness);
- else
- shrink_br = cabc_shrink(cabc, brightness);
- client_data->remote_write(client_data, (u8)shrink_br, 0x94);
- g_brightness = brightness;
- mutex_unlock(&cabc->data_lock);
- return 0;
-}
-
-#if DEBUG
-static void cabc_dump(unsigned long status)
-{
- if (test_bit(LS_STATE, &status))
- B("LS ");
- if (test_bit(GATE_ON, &status))
- B("GATE ");
- if (test_bit(ENFORCE_ON, &status))
- B("EN_ON ");
- if (test_bit(SUSPEND, &status))
- B("SUSPEND ");
- if (test_bit(AUTO_SETTING, &status))
- B("AUTO_SETTING ");
- if (test_bit(LS_SWITCH, &status))
- B("SWITCH ");
- B("\n");
-}
-#endif
-
-static void cabc_lcd_work(struct work_struct *work)
-{
- struct cabc *cabc = to_cabc(work, lcd_changed_work);
- struct led_classdev *led_cdev = &cabc->lcd_backlight;
- char event_string[30];
- char *envp[] = { event_string, NULL };
-
- /* check again, if we are doing early_suspend, but the check
- * already passed. */
- if ((test_bit(SUSPEND, &cabc->status) == 0) &&
- (test_bit(ENFORCE_ON, &cabc->status) == 0)) {
- if (led_cdev->brightness >= 0 && led_cdev->brightness <= 255)
- __set_brightness(cabc, led_cdev->brightness, 1U << 3);
-
- sprintf(event_string, "CABC_BRIGHTNESS=%d",
- led_cdev->brightness);
- kobject_uevent_env(&led_cdev->dev->kobj, KOBJ_CHANGE, envp);
- }
-
- wake_unlock(&cabc->wakelock);
-}
-
-static void
-himax_set_brightness(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct cabc *cabc = to_cabc(led_cdev, lcd_backlight);
-
- B(KERN_DEBUG "%s\n", __func__);
-
- if ((test_bit(SUSPEND, &cabc->status)) ||
- (test_bit(ENFORCE_ON, &cabc->status)))
- return;
-
- wake_lock(&cabc->wakelock);
- queue_work(cabc->cabc_queue, &cabc->lcd_changed_work);
- wake_unlock(&cabc->wakelock);
-}
-
-static enum led_brightness
-himax_get_brightness(struct led_classdev *led_cdev)
-{
- B(KERN_DEBUG "%s\n", __func__);
-
- return led_cdev->brightness;
-}
-
-/*
- * for consistent with android UI,
- * 1: turn on, LABC
- * 0: turn off, Manual
- * */
-static void cabc_auto_work(struct work_struct *work)
-{
- struct cabc *cabc = to_cabc(work, set_auto_work);
- int on;
-
- on = test_bit(LS_SWITCH, &cabc->status);
- /* update on success */
- mutex_lock(&cabc->data_lock);
- if (on) {
- cabc->mode_bc = BC_MERGED;
- cabc->mode_cabc = CABC_MOVING;
- set_bit(LS_STATE, &cabc->status);
- mutex_unlock(&cabc->data_lock);
- } else {
- clear_bit(LS_STATE, &cabc->status);
- cabc->mode_bc = BC_MANUAL;
- cabc->mode_cabc = CABC_OFF;
- mutex_unlock(&cabc->data_lock);
- }
- clear_bit(AUTO_SETTING, &cabc->status);
-}
-
-static int
-cabc_bl_handle(struct platform_device *pdev, int brightness)
-{
- struct cabc *cabc = platform_get_drvdata(pdev);
- struct led_classdev *lcd_cdev;
-
- if (unlikely(cabc == NULL)) {
- PR_DISP_ERR("%s: do not have cabc data\n", __func__);
- return -ENOENT;
- }
-
- PR_DISP_DEBUG("turn %s backlight.\n",
- brightness == LED_FULL ? "on" : "off");
-
- lcd_cdev = &cabc->lcd_backlight;
- wake_lock(&cabc->wakelock);
-
- if (brightness != LED_FULL) {
- /* enter screen off */
- } else {
- __set_brightness(cabc, (g_brightness >= 0 && g_brightness <= LED_FULL)?
- g_brightness : LED_FULL, 0);
- }
-
- wake_unlock(&cabc->wakelock);
- return 0;
-}
-
-static int
-himax_auto_backlight(struct cabc *cabc, int on)
-{
- B(KERN_DEBUG "%s: %s\n", __func__, on ? "ON" : "OFF");
-
- if (test_bit(LS_STATE, &cabc->status) == on)
- return 0;
-
- if (on)
- set_bit(LS_SWITCH, &cabc->status);
- else
- clear_bit(LS_SWITCH, &cabc->status);
-
- if (test_bit(AUTO_SETTING, &cabc->status) == 0) {
- set_bit(AUTO_SETTING, &cabc->status);
-
- /* if we are not in suspend mode, we can
- * do it right away */
- if (test_bit(SUSPEND, &cabc->status) == 0)
- cabc_auto_work(&cabc->set_auto_work);
- }
-
- return 0;
-}
-
-#define CABC_ATTR(name) __ATTR(name, 0644, himax_show, himax_store)
-
-enum {
- CABC_MODE = 0,
- BC_MODE,
- LIGHT_SENSOR,
- AUTO_BACKLIGHT,
-};
-
-static struct device_attribute cabc_attrs[] = {
- CABC_ATTR(cabc_mode),
- CABC_ATTR(bc_mode),
- CABC_ATTR(light_sensor),
- CABC_ATTR(auto),
-};
-
-static ssize_t
-himax_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- int i = 0;
- const ptrdiff_t off = attr - cabc_attrs;
- struct led_classdev *led_cdev = dev_get_drvdata(dev);
- struct cabc *cabc = to_cabc(led_cdev, lcd_backlight);
-
- mutex_lock(&cabc->lock);
- switch (off) {
- case CABC_MODE:
- i += scnprintf(buf + i, PAGE_SIZE - 1, "%s\n",
- str_cabc_mode[cabc->mode_cabc]);
- break;
- case BC_MODE:
- i += scnprintf(buf + i, PAGE_SIZE - 1, "%s\n",
- str_bc_mode[cabc->mode_bc]);
- break;
- case AUTO_BACKLIGHT:
- i += scnprintf(buf + i, PAGE_SIZE - 1, "%d\n",
- test_bit(LS_STATE, &cabc->status));
- break;
- default:
- i = -EINVAL;
- break;
- }
- mutex_unlock(&cabc->lock);
- return i;
-}
-
-static ssize_t
-himax_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- int rc;
- unsigned long res;
- const ptrdiff_t off = attr - cabc_attrs;
- struct led_classdev *led_cdev = dev_get_drvdata(dev);
- struct cabc *cabc = to_cabc(led_cdev, lcd_backlight);
- struct msm_mddi_client_data *client_data = cabc_get_client(cabc);
-
- rc = strict_strtoul(buf, 10, &res);
- if (rc) {
- PR_DISP_ERR("invalid parameter, %s %d\n", buf, rc);
- count = -EINVAL;
- goto err_out;
- }
-
- mutex_lock(&cabc->lock);
- switch (off) {
- case CABC_MODE:
- if (res >= CABC_OFF && res < CABC_UNDEF) {
- cabc->mode_cabc = res;
- cabc->cabc_config->change_cabcmode(client_data, res, 0x25);
- }
- break;
- case BC_MODE:
- if (res >= BC_OFF && res < BC_UNDEF)
- cabc->mode_bc = res;
- break;
- case AUTO_BACKLIGHT:
- if (himax_auto_backlight(cabc, !!res))
- count = -EIO;
- break;
- default:
- count = -EINVAL;
- break;
- }
- mutex_unlock(&cabc->lock);
-err_out:
- return count;
-}
-
-
-static int himax_cabc_probe(struct platform_device *pdev)
-{
- int i, err;
- struct cabc *cabc;
- struct cabc_config *data;
-
- B(KERN_DEBUG "%s\n", __func__);
- cabc = kzalloc(sizeof(struct cabc), GFP_KERNEL);
- if (!cabc)
- return -ENOMEM;
- platform_set_drvdata(pdev, cabc);
-
- data = pdev->dev.platform_data;
- if (data == NULL || !data->client) {
- PR_DISP_ERR("No CABC config data\n");
- err = -EINVAL;
- goto err_client;
- }
- g_brightness = LED_FULL;
- cabc->cabc_config = data;
- cabc->cabc_config->bl_handle = cabc_bl_handle;
- if (!cabc->cabc_config->change_cabcmode)
- cabc->cabc_config->change_cabcmode = himax_change_cabcmode;
-
- INIT_WORK(&cabc->lcd_changed_work, cabc_lcd_work);
- INIT_WORK(&cabc->set_auto_work, cabc_auto_work);
- mutex_init(&cabc->lock);
- mutex_init(&cabc->data_lock);
- cabc->cabc_queue = create_singlethread_workqueue("cabc_work_q");
- wake_lock_init(&cabc->wakelock, WAKE_LOCK_IDLE, "cabc_present");
-
-
- cabc->lcd_backlight.name = "lcd-backlight";
- cabc->lcd_backlight.brightness_set = himax_set_brightness;
- cabc->lcd_backlight.brightness_get = himax_get_brightness;
- cabc->lcd_backlight.brightness = LED_FULL;
- err = led_classdev_register(&pdev->dev, &cabc->lcd_backlight);
- if (err)
- goto err_register_lcd_bl;
-
- for (i = 0; i < ARRAY_SIZE(cabc_attrs); i++) {
- err = device_create_file(cabc->lcd_backlight.dev,
- &cabc_attrs[i]);
- if (err)
- goto err_out;
- }
-
- return 0;
-
-err_out:
- while (i--)
- device_remove_file(&pdev->dev, &cabc_attrs[i]);
-
-err_register_lcd_bl:
- led_classdev_unregister(&cabc->lcd_backlight);
-err_client:
- kfree(cabc);
- return err;
-}
-
-static struct platform_driver himax_cabc_driver = {
- .probe = himax_cabc_probe,
- .driver = { .name = "himax_cabc" },
-};
-
-static int __init himax_cabc_init(void)
-{
- return platform_driver_register(&himax_cabc_driver);
-}
-
-module_init(himax_cabc_init);
diff --git a/drivers/video/msm/mddi_hw.h b/drivers/video/msm/mddi_hw.h
index 632fe70..47bb449 100644
--- a/drivers/video/msm/mddi_hw.h
+++ b/drivers/video/msm/mddi_hw.h
@@ -53,9 +53,9 @@
#define MDDI_MF_CNT 0x0084
#define MDDI_CURR_REV_PTR 0x0088
#define MDDI_CORE_VER 0x008c
-#define MDDI_SF_LEN_CTL_REG 0x0094
-#define MDDI_PAD_IO_CTL 0x00a0
-#define MDDI_PAD_CAL 0x00a4
+#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
@@ -115,7 +115,9 @@
#define MDDI_CMD_LINK_ACTIVE 0x0900
#define MDDI_CMD_PERIODIC_REV_ENCAP 0x0A00
#define MDDI_CMD_FORCE_NEW_REV_PTR 0x0C00
-#define MDDI_CMD_SKEW_CALIBRATION 0x0D00
+
+
+
#define MDDI_VIDEO_REV_PKT_SIZE 0x40
#define MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE 0x60
#define MDDI_MAX_REV_PKT_SIZE 0x60
@@ -126,20 +128,16 @@
/* 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_ARCH_QSD8X50) || defined(CONFIG_ARCH_MSM7X30)
+
+#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
-#endif
-
-#if defined(CONFIG_ARCH_QSD8X50)
-#define MDDI_HOST_REV_RATE_DIV 0x0004
-#elif defined(CONFIG_ARCH_MSM7X30)
-#define MDDI_HOST_REV_RATE_DIV 0x0010
-#else
#define MDDI_HOST_REV_RATE_DIV 0x0002
#endif
+
struct __attribute__((packed)) mddi_rev_packet {
uint16_t length;
uint16_t type;
@@ -295,12 +293,8 @@
uint16_t crc16;
- union {
- uint32_t reg_data;
- uint32_t *reg_data_list;
- } u;
-
- uint16_t crc_data;
+ uint32_t register_data_list;
+ /* list of 4-byte register data values for/from client registers */
};
struct __attribute__((packed)) mddi_llentry {
@@ -317,7 +311,4 @@
} u;
};
-extern int overlay_semaphore_lock(void);
-extern void overlay_semaphore_unlock(void);
-
#endif
diff --git a/drivers/video/msm/mddi_orise.c b/drivers/video/msm/mddi_orise.c
new file mode 100644
index 0000000..fa48c75
--- /dev/null
+++ b/drivers/video/msm/mddi_orise.c
@@ -0,0 +1,128 @@
+/* Copyright (c) 2010, 2012 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.is_type1 = TRUE;
+ 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..ec2bf57
--- /dev/null
+++ b/drivers/video/msm/mddi_prism.c
@@ -0,0 +1,112 @@
+/* Copyright (c) 2008-2010, 2012 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->mddi.is_type1 = TRUE;
+ 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..95e7d41
--- /dev/null
+++ b/drivers/video/msm/mddi_quickvx.c
@@ -0,0 +1,719 @@
+/* Copyright (c) 2010, 2012 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->mddi.is_type1 = TRUE;
+ 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..6a9008f
--- /dev/null
+++ b/drivers/video/msm/mddi_sharp.c
@@ -0,0 +1,901 @@
+/* Copyright (c) 2008-2010, 2012 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->mddi.is_type1 = 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..73749f9
--- /dev/null
+++ b/drivers/video/msm/mddi_toshiba_vga.c
@@ -0,0 +1,134 @@
+/* Copyright (c) 2009-2010, 2012 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.mddi.is_type1 = 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..c1925e1
--- /dev/null
+++ b/drivers/video/msm/mddi_toshiba_wvga.c
@@ -0,0 +1,61 @@
+/* Copyright (c) 2009-2010, 2012 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.mddi.is_type1 = 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..8da1485
--- /dev/null
+++ b/drivers/video/msm/mddi_toshiba_wvga_pt.c
@@ -0,0 +1,69 @@
+/* Copyright (c) 2009-2012, 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 = 6102; /* adjust refx100 to prevent tearing */
+ pinfo.mddi.is_type1 = TRUE;
+ pinfo.lcd.v_back_porch = 8; /* vsw=10 + vbp = 8 */
+ pinfo.lcd.v_front_porch = 2;
+ pinfo.lcd.v_pulse_width = 10;
+ 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..1a5a3fd
--- /dev/null
+++ b/drivers/video/msm/mddihosti.c
@@ -0,0 +1,2268 @@
+/* Copyright (c) 2008-2010, 2012 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);
+ }
+
+#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 39178d3..4125ef0 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-2012, Code Aurora Forum. All rights reserved.
* Copyright (C) 2007 Google Incorporated
*
* This software is licensed under the terms of the GNU General Public
@@ -15,1422 +15,2799 @@
* 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/timer.h>
-#include <linux/file.h>
-#include <linux/android_pmem.h>
-#include <linux/major.h>
-
-#include <mach/msm_iomap.h>
-#include <mach/msm_fb.h>
-#include <linux/platform_device.h>
-
-#include "mdp_hw.h"
-#include "mdp_ppp.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 <asm/system.h>
#include <asm/mach-types.h>
-
-#include <mach/debug_display.h>
-
-struct class *mdp_class;
-
-#define MDP_CMD_DEBUG_ACCESS_BASE (0x10000)
-
-static DECLARE_WAIT_QUEUE_HEAD(mdp_ppp_waitqueue);
-static unsigned int mdp_irq_mask;
-static unsigned int mdp_dma_timer_enable = 0;
-struct clk *mdp_clk_to_disable_later = 0;
-#ifdef CONFIG_MDP4_HW_VSYNC
-struct clk *mdp_vsync_clk_to_disable_later = 0;
-#endif
-static unsigned int mdp_dma_user_requested = 0;
-static struct mdp_blit_req *timeout_req;
-static uint32_t mdp_reg_addr = 0;
-static uint32_t mdp_reg_val = 0;
-
-#ifdef CONFIG_FB_MSM_OVERLAY
-
+#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
-#ifdef CONFIG_MSM_MDP40
-spinlock_t mdp_spin_lock;
-uint32_t mdp_intr_mask = MDP4_ANY_INTR_MASK;
-#endif
+#include "mipi_dsi.h"
-#if defined(CONFIG_FB_MSM_MDP_ABL)
-#define MDP_HIST_MAX_BIN 32
-struct mdp_histogram mdp_hist;
-struct completion mdp_hist_comp;
-bool mdp_is_hist_start = false;
-static DEFINE_MUTEX(mdp_hist_mutex);
-DEFINE_MUTEX(mdp_lut_push_sem);
-static int mdp_lut_push;
-static int mdp_lut_push_i;
-static unsigned int mdp_hist_r[MDP_HIST_MAX_BIN];
-static unsigned int mdp_hist_g[MDP_HIST_MAX_BIN];
-static unsigned int mdp_hist_b[MDP_HIST_MAX_BIN];
-#endif
+uint32 mdp4_extn_disp;
-#if defined(CONFIG_USB_FUNCTION_PROJECTOR) || defined(CONFIG_USB_ANDROID_PROJECTOR)
-extern char *get_fb_addr(void);
-#endif //defined(CONFIG_USB_FUNCTION_PROJECTOR) || defined(CONFIG_USB_ANDROID_PROJECTOR)
+static struct clk *mdp_clk;
+static struct clk *mdp_pclk;
+static struct clk *mdp_lut_clk;
+int mdp_rev;
+u32 mdp_max_clk = 200000000;
-static void mdp_do_standby_timer(unsigned long data)
-{
- struct mdp_info *mdp = (struct mdp_info *) data;
- if (!mdp_irq_mask) {
- clk_set_rate(mdp->ebi1_clk, 0);
- mdp->state |= MDP_STATE_STANDBY;
- } else {
- mod_timer(&mdp->standby_timer,
- jiffies + msecs_to_jiffies(200));
- }
-}
+static struct platform_device *mdp_init_pdev;
+static struct regulator *footswitch, *hdmi_pll_fs;
+static unsigned int mdp_footswitch_on;
-static int locked_enable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
-{
- BUG_ON(!mask);
+struct completion mdp_ppp_comp;
+struct semaphore mdp_ppp_mutex;
+struct semaphore mdp_pipe_ctrl_mutex;
- /* if the mask bits are already set return an error, this interrupt
- * is already enabled */
- if (mdp_irq_mask & mask) {
- PR_DISP_ERR("mdp irq already on %x %x\n", mdp_irq_mask, mask);
- return -1;
- }
- /* if the mdp irq is not already enabled enable it */
- if (!mdp_irq_mask) {
-#ifdef CONFIG_MDP4_HW_VSYNC
- clk_enable(mdp->vsync_clk);
-#endif
- clk_enable(mdp->clk);
- enable_irq(mdp->irq);
- if (mdp->state & MDP_STATE_STANDBY) {
-#ifdef CONFIG_MSM_MDP40
- #if defined(CONFIG_USB_FUNCTION_PROJECTOR) || defined(CONFIG_USB_ANDROID_PROJECTOR)
- static int mdp_in_high_speed = 0;
- if (get_fb_addr() && !mdp_in_high_speed) {
- /* In car mode and MDP clock was in low speed, speed up EBI and MDP clock to workaround MDP hang problem */
- clk_set_rate(mdp->ebi1_clk, 192000000);
- clk_set_rate(mdp->clk, 192000000);
- mdp_in_high_speed = 1;
- } else if (!get_fb_addr() && mdp_in_high_speed) {
- /* Leave car mode and MDP clock was in high speed, restore original EBI and MDP clock */
- clk_set_rate(mdp->ebi1_clk, 153000000);
- clk_set_rate(mdp->clk, 122880000);
- mdp_in_high_speed = 0;
- } else {
- if (mdp_in_high_speed) clk_set_rate(mdp->ebi1_clk, 192000000);
- else clk_set_rate(mdp->ebi1_clk, 153000000);
- }
- #else
- clk_set_rate(mdp->ebi1_clk, 153000000);
- #endif //defined(CONFIG_USB_FUNCTION_PROJECTOR) || defined(CONFIG_USB_ANDROID_PROJECTOR)
+unsigned long mdp_timer_duration = (HZ/20); /* 50 msecond */
+
+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;
+
+struct vsync vsync_cntrl;
+
+/*
+ * 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
- clk_set_rate(mdp->ebi1_clk, 128000000);
-#endif
- mdp->state &= ~MDP_STATE_STANDBY;
- } else {
- del_timer_sync(&mdp->standby_timer);
- barrier();
- }
- }
-
- /* clear out any previous irqs for the requested mask*/
- mdp_writel(mdp, mask, MDP_INTR_CLEAR);
-
- /* update the irq mask to reflect the fact that the interrupt is
- * enabled */
- mdp_irq_mask |= mask;
- mdp_writel(mdp, mdp_irq_mask, MDP_INTR_ENABLE);
- return 0;
-}
-
-static int enable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
-{
- unsigned long flags = 0;
- int ret;
-
- spin_lock_irqsave(&mdp->lock, flags);
- ret = locked_enable_mdp_irq(mdp, mask);
- spin_unlock_irqrestore(&mdp->lock, flags);
- return ret;
-}
-
-static int locked_disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
-{
- /* this interrupt is already disabled! */
- if (!(mdp_irq_mask & mask)) {
- PR_DISP_ERR("mdp irq already off %x %x\n",
- mdp_irq_mask, mask);
- return -1;
- }
- /* update the irq mask to reflect the fact that the interrupt is
- * disabled */
- mdp_irq_mask &= ~(mask);
- mdp_writel(mdp, mdp_irq_mask, MDP_INTR_ENABLE);
-
- /* if no one is waiting on the interrupt, disable it */
- if (!mdp_irq_mask) {
- disable_irq_nosync(mdp->irq);
- if (mdp->clk)
- clk_disable(mdp->clk);
-#ifdef CONFIG_MDP4_HW_VSYNC
- if (mdp->vsync_clk)
- clk_disable(mdp->vsync_clk);
-#endif
- if (!(mdp->state & MDP_STATE_STANDBY))
- mod_timer(&mdp->standby_timer,
- jiffies + msecs_to_jiffies(200));
- }
- return 0;
-}
-
-int disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
-{
- unsigned long irq_flags = 0;
- int ret;
-
- spin_lock_irqsave(&mdp->lock, irq_flags);
- ret = locked_disable_mdp_irq(mdp, mask);
- spin_unlock_irqrestore(&mdp->lock, irq_flags);
- return ret;
-}
-
-static irqreturn_t mdp_isr(int irq, void *data)
-{
- uint32_t status;
- unsigned long irq_flags = 0;
- struct mdp_info *mdp = data;
- int i;
-#if defined(CONFIG_FB_MSM_MDP_ABL)
- uint32_t hist_status;
- uint32_t hist_enable;
+uint32 mdp_intr_mask = MDP_ANY_INTR_MASK;
#endif
- spin_lock_irqsave(&mdp->lock, irq_flags);
+MDP_BLOCK_TYPE mdp_debug[MDP_MAX_BLOCK];
- status = mdp_readl(mdp, MDP_INTR_STATUS);
- mdp_writel(mdp, status, MDP_INTR_CLEAR);
+atomic_t mdp_block_power_cnt[MDP_MAX_BLOCK];
-#if 0
- PR_DISP_INFO("%s: status=%08x (irq_mask=%08x)\n", __func__, status,
- mdp_irq_mask);
+spinlock_t mdp_spin_lock;
+struct workqueue_struct *mdp_dma_wq; /*mdp dma wq */
+struct workqueue_struct *mdp_vsync_wq; /*mdp vsync wq */
+
+struct workqueue_struct *mdp_hist_wq; /*mdp histogram 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;
+ulong mdp4_display_intf;
+static 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;
+#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
- if (mdp_dma_timer_enable) {
- del_timer(&mdp->dma_timer);
- mdp_dma_timer_enable = 0;
- PR_DISP_ERR("%s: stop dma timer\n", __func__);
- }
-
- status &= mdp_irq_mask;
-#ifdef CONFIG_MSM_MDP40
- if (mdp->hw_version < MDP4_REVISION_V2_1 &&
- mdp->mdp_dev.overrides & MSM_MDP4_MDDI_DMA_SWITCH) {
- if (status && mdp->out_if[MSM_MDDI_PMDH_INTERFACE].dma_cb != NULL)
- status |= (INTR_OVERLAY0_DONE | MDP_DMA_S_DONE);
- }
-#endif
- for (i = 0; i < MSM_MDP_NUM_INTERFACES; ++i) {
- struct mdp_out_interface *out_if = &mdp->out_if[i];
- if (status & out_if->dma_mask) {
- if (out_if->dma_cb) {
- out_if->dma_cb->func(out_if->dma_cb);
- out_if->dma_cb = NULL;
- }
- wake_up(&out_if->dma_waitqueue);
- }
- if (status & out_if->irq_mask) {
- out_if->irq_cb->func(out_if->irq_cb);
- out_if->irq_cb = NULL;
- }
- }
-
-#ifndef CONFIG_MSM_MDP40
- mdp_ppp_handle_isr(mdp, status);
+#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
+struct mdp_dma_data dma_wb_data;
#endif
-#if defined(CONFIG_FB_MSM_MDP_ABL)
- if (status & INTR_DMA_P_HISTOGRAM) {
+static struct mdp_dma_data dma3_data;
- hist_status = mdp_readl(mdp, MDP_DMA_P_HIST_INTR_STATUS);
- mdp_writel(mdp, hist_status, MDP_DMA_P_HIST_INTR_CLEAR);
- hist_enable = mdp_readl(mdp, MDP_DMA_P_HIST_INTR_ENABLE);
+extern ktime_t mdp_dma2_last_update_time;
- hist_status &= hist_enable;
+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;
- if (hist_status & 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);
+extern int first_pixel_start_x;
+extern int first_pixel_start_y;
- if (mdp_is_hist_start == true) {
- mdp_writel(mdp, mdp_hist.frame_cnt, 0x95004);
- mdp_writel(mdp, 1, 0x95000);
- }
- }
- status &= ~(INTR_DMA_P_HISTOGRAM);
- }
-
- if (status & INTR_PRIMARY_INTF_UDERRUN) {
- /* When underun occurs mdp clear the histogram registers
- * that are set before in hw_init so restore them back so
- *
- * that histogram works.*/
- mdp_writel(mdp, 1, 0x95010);
- mdp_writel(mdp, INTR_HIST_DONE, 0x9501c);
- status &= ~(INTR_PRIMARY_INTF_UDERRUN);
-
- if (mdp_is_hist_start == true) {
- mdp_writel(mdp, mdp_hist.frame_cnt, 0x95004);
- mdp_writel(mdp, 1, 0x95000);
- }
- }
+#ifdef MSM_FB_ENABLE_DBGFS
+struct dentry *mdp_dir;
#endif
- if (status)
- locked_disable_mdp_irq(mdp, status);
+#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
- spin_unlock_irqrestore(&mdp->lock, irq_flags);
- return IRQ_HANDLED;
-}
+struct timeval mdp_dma2_timeval;
+struct timeval mdp_ppp_timeval;
-static void mdp_do_dma_timer(unsigned long data)
+#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
+
+struct list_head mdp_hist_lut_list;
+DEFINE_MUTEX(mdp_hist_lut_list_mutex);
+
+uint32_t mdp_block2base(uint32_t block)
{
- static int run_times = 0;
- uint32_t status;
- struct mdp_info *mdp = (struct mdp_info *) data;
- unsigned long irq_flags = 0;
- int i;
-
- spin_lock_irqsave(&mdp->lock, irq_flags);
- if (mdp_dma_timer_enable) {
- status = mdp_readl(mdp, MDP_INTR_STATUS);
- mdp_writel(mdp, mdp_irq_mask, MDP_INTR_CLEAR);
-
- PR_DISP_WARN("mdp_do_dma_timer(%d): status=0x%x mdp_irq_mask=0x%x\n", run_times++, status, mdp_irq_mask);
- for (i = 0; i < MSM_MDP_NUM_INTERFACES; ++i) {
- struct mdp_out_interface *out_if = &mdp->out_if[i];
- if (mdp_irq_mask & out_if->dma_mask) {
- if (out_if->dma_cb) {
- out_if->dma_cb->func(out_if->dma_cb);
- out_if->dma_cb = NULL;
- }
- wake_up(&out_if->dma_waitqueue);
- }
- if (mdp_irq_mask & out_if->irq_mask) {
- out_if->irq_cb->func(out_if->irq_cb);
- out_if->irq_cb = NULL;
- }
- }
-
- #ifndef CONFIG_MSM_MDP40
- if (mdp_irq_mask & DL0_ROI_DONE)
- mdp_ppp_handle_isr(mdp, DL0_ROI_DONE);
- #endif
-
- if (run_times >= 10) {
- /* Make sure the HW in correct state... */
- clk_enable(mdp->clk);
- enable_irq(mdp->irq);
-
- #ifdef CONFIG_MSM_MDP40
- clk_set_rate(mdp->ebi1_clk, 192000000);
- clk_set_rate(mdp->clk, 192000000);
- #else
- clk_set_rate(mdp->ebi1_clk, 128000000);
- #endif
- mdp->state &= ~MDP_STATE_STANDBY;
-
- del_timer_sync(&mdp->standby_timer);
- barrier();
-
- /* clear out any previous irqs for the requested mask*/
- mdp_writel(mdp, status, MDP_INTR_CLEAR);
-
- /* update the irq mask to reflect the fact that the interrupt is
- * enabled */
- mdp_writel(mdp, mdp_irq_mask, MDP_INTR_ENABLE);
-
- /* Reset the counter */
- run_times = 0;
- }
- }
- spin_unlock_irqrestore(&mdp->lock, irq_flags);
-
-}
-
-static uint32_t mdp_check_mask(struct mdp_info *mdp, uint32_t mask)
-{
- uint32_t ret;
- unsigned long irq_flags = 0;
-
- spin_lock_irqsave(&mdp->lock, irq_flags);
- ret = mdp_irq_mask & mask;
- spin_unlock_irqrestore(&mdp->lock, irq_flags);
- return ret;
-}
-
-void mdp_dump_blit(struct mdp_blit_req *req)
-{
- PR_DISP_INFO("%s: src: w=%d h=%d f=0x%x offs=0x%x mem_id=%d\n", __func__,
- req->src.width, req->src.height, req->src.format,
- req->src.offset, req->src.memory_id);
- PR_DISP_INFO("%s: dst: w=%d h=%d f=0x%x offs=0x%x mem_id=%d\n", __func__,
- req->dst.width, req->dst.height, req->dst.format,
- req->dst.offset, req->dst.memory_id);
- PR_DISP_INFO("%s: src_rect: x=%d y=%d w=%d h=%d\n", __func__,
- req->src_rect.x, req->src_rect.y, req->src_rect.w,
- req->src_rect.h);
- PR_DISP_INFO("%s: dst_rect: x=%d y=%d w=%d h=%d\n", __func__,
- req->dst_rect.x, req->dst_rect.y, req->dst_rect.w,
- req->dst_rect.h);
- PR_DISP_INFO("%s: alpha=0x%08x\n", __func__, req->alpha);
- PR_DISP_INFO("%s: transp_max=0x%08x\n", __func__, req->transp_mask);
- PR_DISP_INFO("%s: flags=%08x\n", __func__, req->flags);
-}
-
-int mdp_wait(struct mdp_info *mdp, uint32_t mask, wait_queue_head_t *wq)
-{
- int ret = 0;
- unsigned long irq_flags = 0;
-
- wait_event_timeout(*wq, !mdp_check_mask(mdp, mask), HZ);
-
- spin_lock_irqsave(&mdp->lock, irq_flags);
- if (mdp_irq_mask & mask) {
- locked_disable_mdp_irq(mdp, mask);
- PR_DISP_WARN("%s: timeout waiting for mdp to complete 0x%x\n",
- __func__, mask);
- if (timeout_req)
- mdp_dump_blit(timeout_req);
-
- ret = -ETIMEDOUT;
- }
- spin_unlock_irqrestore(&mdp->lock, irq_flags);
-
- return ret;
-}
-
-static void mdp_dma_wait(struct mdp_device *mdp_dev, int interface)
-{
-#define MDP_MAX_TIMEOUTS 20
- static int timeout_count;
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
- unsigned int mask = 0;
- wait_queue_head_t *wq;
-
- switch (interface) {
- case MSM_MDDI_PMDH_INTERFACE:
- case MSM_MDDI_EMDH_INTERFACE:
- case MSM_LCDC_INTERFACE:
- case MSM_TV_INTERFACE:
- mask = mdp->out_if[interface].dma_mask;
- wq = &mdp->out_if[interface].dma_waitqueue;
+ uint32_t base = 0x0;
+ switch (block) {
+ case MDP_BLOCK_DMA_P:
+ base = 0x90000;
+ break;
+ case MDP_BLOCK_DMA_S:
+ base = 0xA0000;
+ break;
+ case MDP_BLOCK_VG_1:
+ base = 0x20000;
+ break;
+ case MDP_BLOCK_VG_2:
+ base = 0x30000;
+ break;
+ case MDP_BLOCK_RGB_1:
+ base = 0x40000;
+ break;
+ case MDP_BLOCK_RGB_2:
+ base = 0x50000;
+ break;
+ case MDP_BLOCK_OVERLAY_0:
+ base = 0x10000;
+ break;
+ case MDP_BLOCK_OVERLAY_1:
+ base = 0x18000;
+ break;
+ case MDP_BLOCK_OVERLAY_2:
+ base = (mdp_rev >= MDP_REV_44) ? 0x88000 : 0;
break;
default:
- PR_DISP_ERR("%s: Unknown interface %d\n", __func__, interface);
- BUG();
+ break;
+ }
+ return base;
+}
+
+static uint32_t mdp_pp_block2hist_lut(uint32_t block)
+{
+ uint32_t valid = 0;
+ switch (block) {
+ case MDP_BLOCK_DMA_P:
+ valid = (mdp_rev >= MDP_REV_40) ? 1 : 0;
+ break;
+ case MDP_BLOCK_DMA_S:
+ valid = (mdp_rev >= MDP_REV_40) ? 1 : 0;
+ break;
+ case MDP_BLOCK_VG_1:
+ valid = (mdp_rev >= MDP_REV_40) ? 1 : 0;
+ break;
+ case MDP_BLOCK_VG_2:
+ valid = (mdp_rev >= MDP_REV_40) ? 1 : 0;
+ break;
+ default:
+ break;
+ }
+ return valid;
+}
+
+static void mdp_hist_lut_init_mgmt(struct mdp_hist_lut_mgmt *mgmt,
+ uint32_t block)
+{
+ mutex_init(&mgmt->lock);
+ mgmt->block = block;
+
+ mutex_lock(&mdp_hist_lut_list_mutex);
+ list_add(&mgmt->list, &mdp_hist_lut_list);
+ mutex_unlock(&mdp_hist_lut_list_mutex);
+}
+
+static int mdp_hist_lut_init(void)
+{
+ struct mdp_hist_lut_mgmt *temp;
+ struct list_head *pos, *q;
+ INIT_LIST_HEAD(&mdp_hist_lut_list);
+
+ if (mdp_rev >= MDP_REV_30) {
+ temp = kmalloc(sizeof(struct mdp_hist_lut_mgmt), GFP_KERNEL);
+ if (!temp)
+ goto exit;
+ mdp_hist_lut_init_mgmt(temp, MDP_BLOCK_DMA_P);
}
- if (mdp_wait(mdp, mask, wq) == -ETIMEDOUT)
- timeout_count++;
+ if (mdp_rev >= MDP_REV_40) {
+ temp = kmalloc(sizeof(struct mdp_hist_lut_mgmt), GFP_KERNEL);
+ if (!temp)
+ goto exit_list;
+ mdp_hist_lut_init_mgmt(temp, MDP_BLOCK_VG_1);
+
+ temp = kmalloc(sizeof(struct mdp_hist_lut_mgmt), GFP_KERNEL);
+ if (!temp)
+ goto exit_list;
+ mdp_hist_lut_init_mgmt(temp, MDP_BLOCK_VG_2);
+ }
+
+ if (mdp_rev > MDP_REV_42) {
+ temp = kmalloc(sizeof(struct mdp_hist_lut_mgmt), GFP_KERNEL);
+ if (!temp)
+ goto exit_list;
+ mdp_hist_lut_init_mgmt(temp, MDP_BLOCK_DMA_S);
+ }
+ return 0;
+
+exit_list:
+ mutex_lock(&mdp_hist_lut_list_mutex);
+ list_for_each_safe(pos, q, &mdp_hist_lut_list) {
+ temp = list_entry(pos, struct mdp_hist_lut_mgmt, list);
+ list_del(pos);
+ kfree(temp);
+ }
+ mutex_unlock(&mdp_hist_lut_list_mutex);
+exit:
+ pr_err("Failed initializing histogram LUT memory\n");
+ return -ENOMEM;
+}
+
+static int mdp_hist_lut_block2mgmt(uint32_t block,
+ struct mdp_hist_lut_mgmt **mgmt)
+{
+ struct mdp_hist_lut_mgmt *temp, *output;
+ int ret = 0;
+
+ output = NULL;
+
+ mutex_lock(&mdp_hist_lut_list_mutex);
+ list_for_each_entry(temp, &mdp_hist_lut_list, list) {
+ if (temp->block == block)
+ output = temp;
+ }
+ mutex_unlock(&mdp_hist_lut_list_mutex);
+
+ if (output == NULL)
+ ret = -EINVAL;
else
- timeout_count = 0;
+ *mgmt = output;
- if (timeout_count > MDP_MAX_TIMEOUTS) {
- PR_DISP_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);
-}
-*/
-#ifndef CONFIG_MSM_MDP40
-static void mdp_dmas_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;
- uint32_t video_packet_parameter = 0;
- uint16_t ld_param = 1;
-
- dma2_cfg = DMA_PACK_TIGHT |
- DMA_PACK_ALIGN_LSB |
- DMA_OUT_SEL_AHB |
- DMA_IBUF_NONCONTIGUOUS;
-
- dma2_cfg |= mdp->dma_format;
-
-#if defined CONFIG_MSM_MDP22 || defined CONFIG_MSM_MDP30
- if (mdp->dma_format == DMA_IBUF_FORMAT_RGB888_OR_ARGB8888)
-#else
- if (mdp->dma_format == DMA_IBUF_FORMAT_XRGB8888)
-#endif
- dma2_cfg |= DMA_PACK_PATTERN_BGR;
- else
- dma2_cfg |= DMA_PACK_PATTERN_RGB;
-
- dma2_cfg |= DMA_OUT_SEL_MDDI;
-
- dma2_cfg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
-
- dma2_cfg |= DMA_DITHER_EN;
-
- if (mdp->mdp_dev.color_format == MSM_MDP_OUT_IF_FMT_RGB565) {
- dma2_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
- video_packet_parameter = MDDI_VDO_PACKET_DESC_RGB565;
- } else if (mdp->mdp_dev.color_format == MSM_MDP_OUT_IF_FMT_RGB666) {
- dma2_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
- video_packet_parameter = MDDI_VDO_PACKET_DESC_RGB666;
- }
-
- /* setup size, address, and stride */
- mdp_writel(mdp, (height << 16) | (width), MDP_DMA_S_SIZE);
- mdp_writel(mdp, addr, MDP_DMA_S_IBUF_ADDR);
- mdp_writel(mdp, stride, MDP_DMA_S_IBUF_Y_STRIDE);
-
- /* set y & x offset and MDDI transaction parameters */
- mdp_writel(mdp, (y << 16) | (x), MDP_DMA_S_OUT_XY);
- mdp_writel(mdp, ld_param, MDP_MDDI_PARAM_WR_SEL);
- if (mdp->mdp_dev.overrides & MSM_MDP_PANEL_IGNORE_PIXEL_DATA) {
- mdp_writel(mdp, (video_packet_parameter << 16) | 0xE3,
- MDP_MDDI_PARAM);
- } else {
- mdp_writel(mdp, (video_packet_parameter << 16) | MDDI_VDO_PACKET_PRIM,
- MDP_MDDI_PARAM);
- }
-
- mdp_writel(mdp, dma2_cfg, MDP_DMA_S_CONFIG);
- mdp_writel(mdp, 0, MDP_DMA_S_START);
+ return ret;
}
-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)
+#define MDP_HIST_LUT_SIZE (256)
+static int mdp_hist_lut_write_off(struct mdp_hist_lut_data *data,
+ struct mdp_hist_lut_info *info, uint32_t offset)
{
- struct mdp_info *mdp = priv;
- uint32_t dma2_cfg = 0;
- uint32_t video_packet_parameter = 0;
- uint16_t ld_param = 0; /* 0=PRIM, 1=SECD, 2=EXT */
+ int i;
+ uint32_t element[MDP_HIST_LUT_SIZE];
+ uint32_t base = mdp_block2base(info->block);
+ uint32_t sel = info->bank_sel;
-#if !defined(CONFIG_MSM_MDP30)
- dma2_cfg = DMA_PACK_TIGHT |
- DMA_PACK_ALIGN_LSB |
- DMA_OUT_SEL_AHB |
- DMA_IBUF_NONCONTIGUOUS;
-#endif
- dma2_cfg |= mdp->dma_format;
-
-#if defined CONFIG_MSM_MDP22 || defined CONFIG_MSM_MDP30
- if (mdp->dma_format == DMA_IBUF_FORMAT_RGB888_OR_ARGB8888)
-#else
- if (mdp->dma_format == DMA_IBUF_FORMAT_XRGB8888)
-#endif
- dma2_cfg |= DMA_PACK_PATTERN_BGR;
- else
- dma2_cfg |= DMA_PACK_PATTERN_RGB;
-
- dma2_cfg |= DMA_OUT_SEL_MDDI;
-
- dma2_cfg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
-
-#if !defined(CONFIG_MSM_MDP30)
- dma2_cfg |= DMA_DITHER_EN;
-#endif
-
- if (mdp->mdp_dev.color_format == MSM_MDP_OUT_IF_FMT_RGB565) {
- dma2_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
- video_packet_parameter = MDDI_VDO_PACKET_DESC_RGB565;
- } else if (mdp->mdp_dev.color_format == MSM_MDP_OUT_IF_FMT_RGB666) {
- dma2_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
- video_packet_parameter = MDDI_VDO_PACKET_DESC_RGB666;
+ if (data->len != MDP_HIST_LUT_SIZE) {
+ pr_err("%s: data->len != %d", __func__, MDP_HIST_LUT_SIZE);
+ return -EINVAL;
}
-
-#if defined(CONFIG_MSM_MDP30) || defined(CONFIG_MSM_MDP302)
- writel(height << 16 | width, mdp->base + 0x90004);
- writel(addr, mdp->base + 0x90008);
- writel(stride, mdp->base + 0x9000c);
-
- /* set y & x offset and MDDI transaction parameters */
- writel(y << 16 | x, mdp->base + 0x90010);
- writel(ld_param, mdp->base + 0x00090);
- writel((video_packet_parameter << 16) | MDDI_VDO_PACKET_PRIM,
- mdp->base + 0x00094);
-
- writel(dma2_cfg, mdp->base + 0x90000);
-
- /* start DMA2 */
- writel(0, mdp->base + 0x0044);
-#elif defined(CONFIG_MSM_MDP22)
- /* 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);
-
- /* 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, (video_packet_parameter << 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);
-#else
- /* 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, (video_packet_parameter << 16) | MDDI_VDO_PACKET_PRIM,
- MDP_MDDI_PARAM);
-
- mdp_writel(mdp, dma2_cfg, MDP_DMA_P_CONFIG);
- mdp_writel(mdp, 0, MDP_DMA_P_START);
-#endif
-}
-#endif /* ifndef CONFIG_MSM_MDP40 */
-
-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);
- struct mdp_out_interface *out_if;
- unsigned long flags;
-
- if (interface < 0 || interface >= MSM_MDP_NUM_INTERFACES ||
- !mdp->out_if[interface].registered) {
- PR_DISP_ERR("%s: Unknown interface: %d\n", __func__, interface);
- BUG();
+ if (copy_from_user(&element, data->data,
+ MDP_HIST_LUT_SIZE * sizeof(uint32_t))) {
+ pr_err("%s: Error copying histogram data", __func__);
+ return -ENOMEM;
}
- out_if = &mdp->out_if[interface];
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ for (i = 0; i < MDP_HIST_LUT_SIZE; i++)
+ MDP_OUTP(MDP_BASE + base + offset + (0x400*(sel)) + (4*i),
+ element[i]);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
- spin_lock_irqsave(&mdp->lock, flags);
- if (locked_enable_mdp_irq(mdp, out_if->dma_mask)) {
- mdp_dma_user_requested++;
- if (mdp_dma_user_requested > 2) {
- PR_DISP_ERR("%s: really busy? start dma timer\n", __func__);
- /* something wrong in dma, workaround it */
- mdp_dma_timer_enable = 1;
- mdp_dma_user_requested = 0;
- } else {
- PR_DISP_ERR("%s: busy\n", __func__);
- goto done;
- }
- } else
- mdp_dma_user_requested = 0;
-
- out_if->dma_cb = callback;
- out_if->dma_start(out_if->priv, addr, stride, width, height, x, y);
-
- if (mdp_dma_timer_enable) {
- mdp_writel(mdp, mdp_irq_mask & ~out_if->dma_mask, MDP_INTR_ENABLE);
- PR_DISP_ERR("%s: start dma timer\n", __func__);
- mod_timer(&mdp->dma_timer,
- jiffies + msecs_to_jiffies(30));
- }
-done:
- spin_unlock_irqrestore(&mdp->lock, flags);
+ return 0;
}
-
-void mdp_configure_dma(struct mdp_device *mdp_dev)
+static int mdp_hist_lut_write(struct mdp_hist_lut_data *data,
+ struct mdp_hist_lut_info *info)
{
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
- uint32_t dma_cfg;
+ int ret = 0;
- if (!mdp->dma_config_dirty)
- return;
- dma_cfg = mdp_readl(mdp, MDP_DMA_P_CONFIG);
- dma_cfg &= ~DMA_IBUF_FORMAT_MASK;
- dma_cfg &= ~DMA_PACK_PATTERN_MASK;
- dma_cfg |= (mdp->dma_format | mdp->dma_pack_pattern);
- mdp_writel(mdp, dma_cfg, MDP_DMA_P_CONFIG);
- mdp->dma_config_dirty = false;
+ if (data->block != info->block) {
+ ret = -1;
+ pr_err("%s, data/info mdp_block mismatch! %d != %d\n",
+ __func__, data->block, info->block);
+ goto error;
+ }
+ switch (data->block) {
+ case MDP_BLOCK_VG_1:
+ case MDP_BLOCK_VG_2:
+ ret = mdp_hist_lut_write_off(data, info, 0x3400);
+ break;
+ case MDP_BLOCK_DMA_P:
+ case MDP_BLOCK_DMA_S:
+ ret = mdp_hist_lut_write_off(data, info, 0x4800);
+ break;
+ default:
+ ret = -EINVAL;
+ goto error;
+ }
+
+error:
+ return ret;
+}
+
+#define MDP_HIST_LUT_VG_EN_MASK (0x20000)
+#define MDP_HIST_LUT_VG_EN_SHIFT (17)
+#define MDP_HIST_LUT_VG_EN_OFFSET (0x0058)
+#define MDP_HIST_LUT_VG_SEL_OFFSET (0x0064)
+static void mdp_hist_lut_commit_vg(struct mdp_hist_lut_info *info)
+{
+ uint32_t out_en, temp_en;
+ uint32_t base = mdp_block2base(info->block);
+ temp_en = (info->is_enabled) ? (1 << MDP_HIST_LUT_VG_EN_SHIFT) : 0x0;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ out_en = inpdw(MDP_BASE + base + MDP_HIST_LUT_VG_EN_OFFSET) &
+ ~MDP_HIST_LUT_VG_EN_MASK;
+ MDP_OUTP(MDP_BASE + base + MDP_HIST_LUT_VG_EN_OFFSET, out_en | temp_en);
+
+ if (info->has_sel_update)
+ MDP_OUTP(MDP_BASE + base + MDP_HIST_LUT_VG_SEL_OFFSET,
+ info->bank_sel);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+#define MDP_HIST_LUT_DMA_EN_MASK (0x7)
+#define MDP_HIST_LUT_DMA_SEL_MASK (0x400)
+#define MDP_HIST_LUT_DMA_SEL_SHIFT (10)
+#define MDP_HIST_LUT_DMA_P_OFFSET (0x0070)
+#define MDP_HIST_LUT_DMA_S_OFFSET (0x0028)
+static void mdp_hist_lut_commit_dma(struct mdp_hist_lut_info *info)
+{
+ uint32_t out, temp, mask;
+ uint32_t base = mdp_block2base(info->block);
+ uint32_t offset = (info->block == MDP_BLOCK_DMA_P) ?
+ MDP_HIST_LUT_DMA_P_OFFSET : MDP_HIST_LUT_DMA_S_OFFSET;
+
+ mask = MDP_HIST_LUT_DMA_EN_MASK;
+ temp = (info->is_enabled) ? 0x7 : 0x0;
+
+ if (info->has_sel_update) {
+ mask |= MDP_HIST_LUT_DMA_SEL_MASK;
+ temp |= ((info->bank_sel & 0x1) << MDP_HIST_LUT_DMA_SEL_SHIFT);
+ }
+
+ out = inpdw(MDP_BASE + base + offset) & ~mask;
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ MDP_OUTP(MDP_BASE + base + offset, out | temp);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+static void mdp_hist_lut_commit_info(struct mdp_hist_lut_info *info)
+{
+ switch (info->block) {
+ case MDP_BLOCK_VG_1:
+ case MDP_BLOCK_VG_2:
+ mdp_hist_lut_commit_vg(info);
+ break;
+ case MDP_BLOCK_DMA_P:
+ case MDP_BLOCK_DMA_S:
+ mdp_hist_lut_commit_dma(info);
+ break;
+ default:
+ goto error;
+ }
+
+error:
return;
}
-int mdp_check_output_format(struct mdp_device *mdp_dev, int bpp)
+static void mdp_hist_lut_update_info(struct mdp_hist_lut_info *info, int ops)
{
- switch (bpp) {
- case 16:
- case 24:
- case 32:
+ info->bank_sel = (ops & 0x8) >> 3;
+ info->is_enabled = (ops & 0x1) ? TRUE : FALSE;
+ info->has_sel_update = (ops & 0x10) ? TRUE : FALSE;
+}
+
+int mdp_hist_lut_config(struct mdp_hist_lut_data *data)
+{
+ struct mdp_hist_lut_mgmt *mgmt = NULL;
+ struct mdp_hist_lut_info info;
+ int ret = 0;
+
+ if (!mdp_pp_block2hist_lut(data->block)) {
+ ret = -ENOTTY;
+ goto error;
+ }
+
+ ret = mdp_hist_lut_block2mgmt(data->block, &mgmt);
+ if (ret)
+ goto error;
+
+ mutex_lock(&mgmt->lock);
+
+ info.block = mgmt->block;
+
+ mdp_hist_lut_update_info(&info, data->ops);
+
+ switch ((data->ops & 0x6) >> 1) {
+ case 0x1:
+ pr_info("%s: histogram LUT read not supported\n", __func__);
+ break;
+ case 0x2:
+ ret = mdp_hist_lut_write(data, &info);
+ if (ret)
+ goto error_lock;
break;
default:
- return -EINVAL;
- }
- return 0;
-}
-
-void mdp_set_panel_size(struct mdp_device *mdp_dev, int width, int height)
-{
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
- mdp->mdp_dev.width = width;
- mdp->mdp_dev.height = height;
-}
-
-int mdp_set_output_format(struct mdp_device *mdp_dev, int bpp)
-{
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
- uint32_t format, pack_pattern = DMA_PACK_PATTERN_RGB;
-
- switch (bpp) {
- case 16:
- format = DMA_IBUF_FORMAT_RGB565;
- pack_pattern = DMA_PACK_PATTERN_RGB;
break;
-#if defined CONFIG_MSM_MDP22 || defined CONFIG_MSM_MDP30
- case 24:
- case 32:
- format = DMA_IBUF_FORMAT_RGB888_OR_ARGB8888;
- break;
-#else
- case 24:
- format = DMA_IBUF_FORMAT_RGB888;
- pack_pattern = DMA_PACK_PATTERN_BGR;
- break;
- case 32:
- format = DMA_IBUF_FORMAT_XRGB8888;
- pack_pattern = DMA_PACK_PATTERN_BGR;
- break;
-#endif
- default:
- return -EINVAL;
- }
- if (format != mdp->dma_format || pack_pattern != mdp->dma_pack_pattern) {
- mdp->dma_format = format;
- mdp->dma_pack_pattern = pack_pattern;
- mdp->dma_config_dirty = true;
}
- return 0;
+ mdp_hist_lut_commit_info(&info);
+
+error_lock:
+ mutex_unlock(&mgmt->lock);
+error:
+ return ret;
}
-int mdp_blit(struct mdp_device *mdp_dev, struct fb_info *fb,
- struct mdp_blit_req *req)
+DEFINE_MUTEX(mdp_lut_push_sem);
+static int mdp_lut_i;
+static int mdp_lut_hw_update(struct fb_cmap *cmap)
{
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
- timeout_req = req;
- return mdp_ppp_blit(mdp, fb, req);
-}
+ int i;
+ u16 *c[3];
+ u16 r, g, b;
-
-
-#if defined(CONFIG_FB_MSM_MDP_ABL)
-int mdp_lut_update(struct mdp_device *mdp_dev, struct fb_info *fb,
- struct fb_cmap *cmap)
-{
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
- unsigned int i, addr, val;
- unsigned short *r, *g, *b;
- int mdp_lut_i = 0;
+ c[0] = cmap->green;
+ c[1] = cmap->blue;
+ c[2] = cmap->red;
for (i = 0; i < cmap->len; i++) {
- r = cmap->red++;
- g = cmap->green++;
- b = cmap->blue++;
+ 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;
- addr = 0x94800 + (0x400 * mdp_lut_i) + cmap->start * 4 + i * 4;
- val = ((*g & 0xff)|((*b & 0xff) << 8)|((*r & 0xff) << 16));
- mdp_writel(mdp, val, addr);
+#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)));
}
- /* lcdc case */
- mdp_writel(mdp, (mdp_lut_i << 10) | 0x17, 0x90070);
+ return 0;
+}
+
+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)
+{
+ 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 void mdp_lut_enable(struct mdp_info *mdp)
+static int mdp_lut_update_lcdc(struct fb_info *info, struct fb_cmap *cmap)
{
+ int ret;
+ uint32_t out;
+
+ 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;
+ }
+
+ /*mask off non LUT select bits*/
+ out = inpdw(MDP_BASE + 0x90070) & ~((0x1 << 10) | 0x7);
+ MDP_OUTP(MDP_BASE + 0x90070, (mdp_lut_i << 10) | 0x7 | out);
+ 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)
+{
+ uint32_t out;
if (mdp_lut_push) {
mutex_lock(&mdp_lut_push_sem);
mdp_lut_push = 0;
+ out = inpdw(MDP_BASE + 0x90070) & ~((0x1 << 10) | 0x7);
+ MDP_OUTP(MDP_BASE + 0x90070,
+ (mdp_lut_push_i << 10) | 0x7 | out);
mutex_unlock(&mdp_lut_push_sem);
- mdp_writel(mdp, (mdp_lut_push_i << 10) | 0x17 | 1<<3, 0x90070);
}
}
-void mdp_pipe_kickoff(struct mdp_info *mdp, uint32_t term)
+#define MDP_REV42_HIST_MAX_BIN 128
+#define MDP_REV41_HIST_MAX_BIN 32
+
+#define MDP_HIST_DATA32_R_OFF 0x0100
+#define MDP_HIST_DATA32_G_OFF 0x0200
+#define MDP_HIST_DATA32_B_OFF 0x0300
+
+#define MDP_HIST_DATA128_R_OFF 0x0400
+#define MDP_HIST_DATA128_G_OFF 0x0800
+#define MDP_HIST_DATA128_B_OFF 0x0C00
+
+#define MDP_HIST_DATA_LUMA_OFF 0x0200
+
+#define MDP_HIST_EXTRA_DATA0_OFF 0x0028
+#define MDP_HIST_EXTRA_DATA1_OFF 0x002C
+
+struct mdp_hist_mgmt *mdp_hist_mgmt_array[MDP_HIST_MGMT_MAX];
+
+void __mdp_histogram_kickoff(struct mdp_hist_mgmt *mgmt)
+{
+ char *mdp_hist_base = MDP_BASE + mgmt->base;
+ if (mgmt->mdp_is_hist_data == TRUE) {
+ MDP_OUTP(mdp_hist_base + 0x0004, mgmt->frame_cnt);
+ MDP_OUTP(mdp_hist_base, 1);
+ }
+}
+
+void __mdp_histogram_reset(struct mdp_hist_mgmt *mgmt)
+{
+ char *mdp_hist_base = MDP_BASE + mgmt->base;
+ MDP_OUTP(mdp_hist_base + 0x000C, 1);
+}
+
+static void mdp_hist_read_work(struct work_struct *data);
+
+static int mdp_hist_init_mgmt(struct mdp_hist_mgmt *mgmt, uint32_t block)
+{
+ uint32_t bins, extra, index, term = 0;
+ init_completion(&mgmt->mdp_hist_comp);
+ mutex_init(&mgmt->mdp_hist_mutex);
+ mutex_init(&mgmt->mdp_do_hist_mutex);
+ mgmt->block = block;
+ mgmt->base = mdp_block2base(block);
+ mgmt->mdp_is_hist_start = FALSE;
+ mgmt->mdp_is_hist_data = FALSE;
+ mgmt->mdp_is_hist_valid = FALSE;
+ mgmt->mdp_is_hist_init = FALSE;
+ mgmt->frame_cnt = 0;
+ mgmt->bit_mask = 0;
+ mgmt->num_bins = 0;
+ switch (block) {
+ case MDP_BLOCK_DMA_P:
+ term = MDP_HISTOGRAM_TERM_DMA_P;
+ bins = (mdp_rev >= MDP_REV_42) ? MDP_REV42_HIST_MAX_BIN :
+ MDP_REV41_HIST_MAX_BIN;
+ extra = 2;
+ mgmt->base += (mdp_rev >= MDP_REV_40) ? 0x5000 : 0x4000;
+ index = MDP_HIST_MGMT_DMA_P;
+ break;
+ case MDP_BLOCK_DMA_S:
+ term = MDP_HISTOGRAM_TERM_DMA_S;
+ bins = MDP_REV42_HIST_MAX_BIN;
+ extra = 2;
+ mgmt->base += 0x5000;
+ index = MDP_HIST_MGMT_DMA_S;
+ break;
+ case MDP_BLOCK_VG_1:
+ term = MDP_HISTOGRAM_TERM_VG_1;
+ bins = MDP_REV42_HIST_MAX_BIN;
+ extra = 1;
+ mgmt->base += 0x6000;
+ index = MDP_HIST_MGMT_VG_1;
+ break;
+ case MDP_BLOCK_VG_2:
+ term = MDP_HISTOGRAM_TERM_VG_2;
+ bins = MDP_REV42_HIST_MAX_BIN;
+ extra = 1;
+ mgmt->base += 0x6000;
+ index = MDP_HIST_MGMT_VG_2;
+ break;
+ default:
+ term = MDP_HISTOGRAM_TERM_DMA_P;
+ bins = (mdp_rev >= MDP_REV_42) ? MDP_REV42_HIST_MAX_BIN :
+ MDP_REV41_HIST_MAX_BIN;
+ extra = 2;
+ mgmt->base += (mdp_rev >= MDP_REV_40) ? 0x5000 : 0x4000;
+ index = MDP_HIST_MGMT_DMA_P;
+ }
+ mgmt->irq_term = term;
+
+ mgmt->c0 = kmalloc(bins * sizeof(uint32_t), GFP_KERNEL);
+ if (mgmt->c0 == NULL)
+ goto error;
+
+ mgmt->c1 = kmalloc(bins * sizeof(uint32_t), GFP_KERNEL);
+ if (mgmt->c1 == NULL)
+ goto error_1;
+
+ mgmt->c2 = kmalloc(bins * sizeof(uint32_t), GFP_KERNEL);
+ if (mgmt->c2 == NULL)
+ goto error_2;
+
+ mgmt->extra_info = kmalloc(extra * sizeof(uint32_t), GFP_KERNEL);
+ if (mgmt->extra_info == NULL)
+ goto error_extra;
+
+ INIT_WORK(&mgmt->mdp_histogram_worker, mdp_hist_read_work);
+
+ mdp_hist_mgmt_array[index] = mgmt;
+ return 0;
+
+error_extra:
+ kfree(mgmt->c2);
+error_2:
+ kfree(mgmt->c1);
+error_1:
+ kfree(mgmt->c0);
+error:
+ return -ENOMEM;
+}
+
+static void mdp_hist_del_mgmt(struct mdp_hist_mgmt *mgmt)
+{
+ kfree(mgmt->extra_info);
+ kfree(mgmt->c2);
+ kfree(mgmt->c1);
+ kfree(mgmt->c0);
+}
+
+static int mdp_histogram_init(void)
+{
+ struct mdp_hist_mgmt *temp;
+ int i, ret;
+ mdp_hist_wq = alloc_workqueue("mdp_hist_wq", WQ_UNBOUND, 0);
+
+ for (i = 0; i < MDP_HIST_MGMT_MAX; i++)
+ mdp_hist_mgmt_array[i] = NULL;
+
+ if (mdp_rev >= MDP_REV_30) {
+ temp = kmalloc(sizeof(struct mdp_hist_mgmt), GFP_KERNEL);
+ if (!temp)
+ goto exit;
+ ret = mdp_hist_init_mgmt(temp, MDP_BLOCK_DMA_P);
+ if (ret) {
+ kfree(temp);
+ goto exit;
+ }
+ }
+
+ if (mdp_rev >= MDP_REV_40) {
+ temp = kmalloc(sizeof(struct mdp_hist_mgmt), GFP_KERNEL);
+ if (!temp)
+ goto exit_list;
+ ret = mdp_hist_init_mgmt(temp, MDP_BLOCK_VG_1);
+ if (ret)
+ goto exit_list;
+
+ temp = kmalloc(sizeof(struct mdp_hist_mgmt), GFP_KERNEL);
+ if (!temp)
+ goto exit_list;
+ ret = mdp_hist_init_mgmt(temp, MDP_BLOCK_VG_2);
+ if (ret)
+ goto exit_list;
+ }
+
+ if (mdp_rev >= MDP_REV_42) {
+ temp = kmalloc(sizeof(struct mdp_hist_mgmt), GFP_KERNEL);
+ if (!temp)
+ goto exit_list;
+ ret = mdp_hist_init_mgmt(temp, MDP_BLOCK_DMA_S);
+ if (ret)
+ goto exit_list;
+ }
+
+ return 0;
+
+exit_list:
+ for (i = 0; i < MDP_HIST_MGMT_MAX; i++) {
+ temp = mdp_hist_mgmt_array[i];
+ if (!temp)
+ continue;
+ mdp_hist_del_mgmt(temp);
+ kfree(temp);
+ mdp_hist_mgmt_array[i] = NULL;
+ }
+exit:
+ return -ENOMEM;
+}
+
+int mdp_histogram_block2mgmt(uint32_t block, struct mdp_hist_mgmt **mgmt)
+{
+ struct mdp_hist_mgmt *temp, *output;
+ int i, ret = 0;
+
+ output = NULL;
+
+ for (i = 0; i < MDP_HIST_MGMT_MAX; i++) {
+ temp = mdp_hist_mgmt_array[i];
+ if (!temp)
+ continue;
+
+ if (temp->block == block) {
+ output = temp;
+ break;
+ }
+ }
+
+ if (output == NULL)
+ ret = -EINVAL;
+ else
+ *mgmt = output;
+
+ return ret;
+}
+
+static int mdp_histogram_enable(struct mdp_hist_mgmt *mgmt)
+{
+ uint32_t base;
+ if (mgmt->mdp_is_hist_data == TRUE) {
+ pr_err("%s histogram already started\n", __func__);
+ return -EINVAL;
+ }
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ mdp_enable_irq(mgmt->irq_term);
+ INIT_COMPLETION(mgmt->mdp_hist_comp);
+
+ base = (uint32_t) (MDP_BASE + mgmt->base);
+ MDP_OUTP(base + 0x0018, INTR_HIST_DONE | INTR_HIST_RESET_SEQ_DONE);
+ MDP_OUTP(base + 0x0010, 1);
+ MDP_OUTP(base + 0x001C, INTR_HIST_DONE | INTR_HIST_RESET_SEQ_DONE);
+
+ MDP_OUTP(base + 0x0004, mgmt->frame_cnt);
+ if (mgmt->block != MDP_BLOCK_VG_1 && mgmt->block != MDP_BLOCK_VG_2)
+ MDP_OUTP(base + 0x0008, mgmt->bit_mask);
+ mgmt->mdp_is_hist_data = TRUE;
+ mgmt->mdp_is_hist_valid = TRUE;
+ mgmt->mdp_is_hist_init = FALSE;
+ __mdp_histogram_reset(mgmt);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ return 0;
+}
+
+static int mdp_histogram_disable(struct mdp_hist_mgmt *mgmt)
+{
+ uint32_t base, status;
+ if (mgmt->mdp_is_hist_data == FALSE) {
+ pr_err("%s histogram already stopped\n", __func__);
+ return -EINVAL;
+ }
+
+ mgmt->mdp_is_hist_data = FALSE;
+ mgmt->mdp_is_hist_valid = FALSE;
+ mgmt->mdp_is_hist_init = FALSE;
+
+ base = (uint32_t) (MDP_BASE + mgmt->base);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ if (mdp_rev >= MDP_REV_42)
+ MDP_OUTP(base + 0x0020, 1);
+ status = inpdw(base + 0x001C);
+ status &= ~(INTR_HIST_DONE | INTR_HIST_RESET_SEQ_DONE);
+ MDP_OUTP(base + 0x001C, status);
+
+ MDP_OUTP(base + 0x0018, INTR_HIST_DONE | INTR_HIST_RESET_SEQ_DONE);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ complete(&mgmt->mdp_hist_comp);
+ mdp_disable_irq(mgmt->irq_term);
+ return 0;
+}
+
+/*call when spanning mgmt_array only*/
+int _mdp_histogram_ctrl(boolean en, struct mdp_hist_mgmt *mgmt)
+{
+ int ret = 0;
+
+ mutex_lock(&mgmt->mdp_hist_mutex);
+ if (mgmt->mdp_is_hist_start == TRUE) {
+ if (en)
+ ret = mdp_histogram_enable(mgmt);
+ else
+ ret = mdp_histogram_disable(mgmt);
+ }
+ mutex_unlock(&mgmt->mdp_hist_mutex);
+
+ if (en == false)
+ cancel_work_sync(&mgmt->mdp_histogram_worker);
+
+ return ret;
+}
+
+int mdp_histogram_ctrl(boolean en, uint32_t block)
+{
+ struct mdp_hist_mgmt *mgmt = NULL;
+ int ret = 0;
+
+ ret = mdp_histogram_block2mgmt(block, &mgmt);
+ if (ret)
+ goto error;
+
+ ret = _mdp_histogram_ctrl(en, mgmt);
+error:
+ return ret;
+}
+
+int mdp_histogram_ctrl_all(boolean en)
+{
+ struct mdp_hist_mgmt *temp;
+ int i, ret = 0, ret_temp = 0;
+
+ for (i = 0; i < MDP_HIST_MGMT_MAX; i++) {
+ temp = mdp_hist_mgmt_array[i];
+ if (!temp)
+ continue;
+
+ ret_temp = _mdp_histogram_ctrl(en, temp);
+ if (ret_temp)
+ ret = ret_temp;
+ }
+ return ret;
+}
+
+int mdp_histogram_start(struct mdp_histogram_start_req *req)
+{
+ struct mdp_hist_mgmt *mgmt = NULL;
+ int ret;
+
+ ret = mdp_histogram_block2mgmt(req->block, &mgmt);
+ if (ret) {
+ ret = -ENOTTY;
+ goto error;
+ }
+
+ mutex_lock(&mgmt->mdp_hist_mutex);
+ if (mgmt->mdp_is_hist_start == TRUE) {
+ pr_err("%s histogram already started\n", __func__);
+ ret = -EPERM;
+ goto error_lock;
+ }
+
+ mgmt->block = req->block;
+ mgmt->frame_cnt = req->frame_cnt;
+ mgmt->bit_mask = req->bit_mask;
+ mgmt->num_bins = req->num_bins;
+
+ ret = mdp_histogram_enable(mgmt);
+
+ mgmt->mdp_is_hist_start = TRUE;
+
+error_lock:
+ mutex_unlock(&mgmt->mdp_hist_mutex);
+error:
+ return ret;
+}
+
+int mdp_histogram_stop(struct fb_info *info, uint32_t block)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *) info->par;
+ struct mdp_hist_mgmt *mgmt = NULL;
+ int ret;
+
+ ret = mdp_histogram_block2mgmt(block, &mgmt);
+ if (ret) {
+ ret = -ENOTTY;
+ goto error;
+ }
+
+ mutex_lock(&mgmt->mdp_hist_mutex);
+ if (mgmt->mdp_is_hist_start == FALSE) {
+ pr_err("%s histogram already stopped\n", __func__);
+ ret = -EPERM;
+ goto error_lock;
+ }
+
+ mgmt->mdp_is_hist_start = FALSE;
+
+ if (!mfd->panel_power_on) {
+ mgmt->mdp_is_hist_data = FALSE;
+ complete(&mgmt->mdp_hist_comp);
+ ret = -EINVAL;
+ goto error_lock;
+ }
+
+ ret = mdp_histogram_disable(mgmt);
+
+ mutex_unlock(&mgmt->mdp_hist_mutex);
+ cancel_work_sync(&mgmt->mdp_histogram_worker);
+ return ret;
+
+error_lock:
+ mutex_unlock(&mgmt->mdp_hist_mutex);
+error:
+ return ret;
+}
+
+/*call from within mdp_hist_mutex context*/
+static int _mdp_histogram_read_dma_data(struct mdp_hist_mgmt *mgmt)
+{
+ char *mdp_hist_base;
+ uint32_t r_data_offset, g_data_offset, b_data_offset;
+ int i, ret = 0;
+
+ mdp_hist_base = MDP_BASE + mgmt->base;
+
+ r_data_offset = (32 == mgmt->num_bins) ? MDP_HIST_DATA32_R_OFF :
+ MDP_HIST_DATA128_R_OFF;
+ g_data_offset = (32 == mgmt->num_bins) ? MDP_HIST_DATA32_G_OFF :
+ MDP_HIST_DATA128_G_OFF;
+ b_data_offset = (32 == mgmt->num_bins) ? MDP_HIST_DATA32_B_OFF :
+ MDP_HIST_DATA128_B_OFF;
+
+ if (mgmt->c0 == NULL || mgmt->c1 == NULL || mgmt->c2 == NULL) {
+ ret = -ENOMEM;
+ goto hist_err;
+ }
+
+ if (!mgmt->hist) {
+ pr_err("%s: mgmt->hist not set, mgmt->hist = 0x%08x",
+ __func__, (uint32_t) mgmt->hist);
+ return -EINVAL;
+ }
+
+ if (mgmt->hist->bin_cnt != mgmt->num_bins) {
+ pr_err("%s, bins config = %d, bin requested = %d", __func__,
+ mgmt->num_bins, mgmt->hist->bin_cnt);
+ return -EINVAL;
+ }
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ for (i = 0; i < mgmt->num_bins; i++) {
+ mgmt->c0[i] = inpdw(mdp_hist_base + r_data_offset + (4*i));
+ mgmt->c1[i] = inpdw(mdp_hist_base + g_data_offset + (4*i));
+ mgmt->c2[i] = inpdw(mdp_hist_base + b_data_offset + (4*i));
+ }
+
+ if (mdp_rev >= MDP_REV_42) {
+ if (mgmt->extra_info) {
+ mgmt->extra_info[0] = inpdw(mdp_hist_base +
+ MDP_HIST_EXTRA_DATA0_OFF);
+ mgmt->extra_info[1] = inpdw(mdp_hist_base +
+ MDP_HIST_EXTRA_DATA0_OFF + 4);
+ } else
+ ret = -ENOMEM;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ if (!ret)
+ return ret;
+
+hist_err:
+ pr_err("%s: invalid hist buffer\n", __func__);
+ return ret;
+}
+
+/*call from within mdp_hist_mutex context*/
+static int _mdp_histogram_read_vg_data(struct mdp_hist_mgmt *mgmt)
+{
+ char *mdp_hist_base;
+ int i, ret = 0;
+
+ mdp_hist_base = MDP_BASE + mgmt->base;
+
+ if (mgmt->c0 == NULL) {
+ ret = -ENOMEM;
+ goto hist_err;
+ }
+
+ if (!mgmt->hist) {
+ pr_err("%s: mgmt->hist not set", __func__);
+ return -EINVAL;
+ }
+
+ if (mgmt->hist->bin_cnt != mgmt->num_bins) {
+ pr_err("%s, bins config = %d, bin requested = %d", __func__,
+ mgmt->num_bins, mgmt->hist->bin_cnt);
+ return -EINVAL;
+ }
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ for (i = 0; i < mgmt->num_bins; i++)
+ mgmt->c0[i] = inpdw(mdp_hist_base + MDP_HIST_DATA_LUMA_OFF +
+ (4*i));
+
+ if (mdp_rev >= MDP_REV_42) {
+ if (mgmt->extra_info) {
+ mgmt->extra_info[0] = inpdw(mdp_hist_base +
+ MDP_HIST_EXTRA_DATA0_OFF);
+ } else
+ ret = -ENOMEM;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ if (!ret)
+ return ret;
+
+hist_err:
+ pr_err("%s: invalid hist buffer\n", __func__);
+ return ret;
+}
+
+static void mdp_hist_read_work(struct work_struct *data)
+{
+ struct mdp_hist_mgmt *mgmt = container_of(data, struct mdp_hist_mgmt,
+ mdp_histogram_worker);
+ int ret = 0;
+ mutex_lock(&mgmt->mdp_hist_mutex);
+ if (mgmt->mdp_is_hist_data == FALSE) {
+ pr_debug("%s, Histogram disabled before read.\n", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ switch (mgmt->block) {
+ case MDP_BLOCK_DMA_P:
+ case MDP_BLOCK_DMA_S:
+ ret = _mdp_histogram_read_dma_data(mgmt);
+ break;
+ case MDP_BLOCK_VG_1:
+ case MDP_BLOCK_VG_2:
+ ret = _mdp_histogram_read_vg_data(mgmt);
+ break;
+ default:
+ pr_err("%s, invalid MDP block = %d\n", __func__, mgmt->block);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ /* if read was triggered by an underrun, don't wake up readers*/
+ if (mgmt->mdp_is_hist_valid && mgmt->mdp_is_hist_init) {
+ mgmt->hist = NULL;
+ complete(&mgmt->mdp_hist_comp);
+ }
+
+ if (mgmt->mdp_is_hist_valid == FALSE)
+ mgmt->mdp_is_hist_valid = TRUE;
+ if (mgmt->mdp_is_hist_init == FALSE)
+ mgmt->mdp_is_hist_init = TRUE;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ if (!ret)
+ __mdp_histogram_kickoff(mgmt);
+ else
+ __mdp_histogram_reset(mgmt);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+error:
+ mutex_unlock(&mgmt->mdp_hist_mutex);
+}
+
+/*call from within mdp_hist_mutex*/
+static int _mdp_copy_hist_data(struct mdp_histogram_data *hist,
+ struct mdp_hist_mgmt *mgmt)
+{
+ int ret;
+
+ if (hist->c0) {
+ ret = copy_to_user(hist->c0, mgmt->c0,
+ sizeof(uint32_t) * (hist->bin_cnt));
+ if (ret)
+ goto err;
+ }
+ if (hist->c1) {
+ ret = copy_to_user(hist->c1, mgmt->c1,
+ sizeof(uint32_t) * (hist->bin_cnt));
+ if (ret)
+ goto err;
+ }
+ if (hist->c2) {
+ ret = copy_to_user(hist->c2, mgmt->c2,
+ sizeof(uint32_t) * (hist->bin_cnt));
+ if (ret)
+ goto err;
+ }
+ if (hist->extra_info) {
+ ret = copy_to_user(hist->extra_info, mgmt->extra_info,
+ sizeof(uint32_t) * ((hist->block > MDP_BLOCK_VG_2) ? 2 : 1));
+ if (ret)
+ goto err;
+ }
+err:
+ return ret;
+}
+
+static int mdp_do_histogram(struct fb_info *info,
+ struct mdp_histogram_data *hist)
+{
+ struct mdp_hist_mgmt *mgmt = NULL;
+ int ret = 0;
+
+ ret = mdp_histogram_block2mgmt(hist->block, &mgmt);
+ if (ret) {
+ pr_info("%s - %d", __func__, __LINE__);
+ ret = -EINVAL;
+ return ret;
+ }
+
+ mutex_lock(&mgmt->mdp_do_hist_mutex);
+ if (!mgmt->frame_cnt || (mgmt->num_bins == 0)) {
+ pr_info("%s - frame_cnt = %d, num_bins = %d", __func__,
+ mgmt->frame_cnt, mgmt->num_bins);
+ ret = -EINVAL;
+ goto error;
+}
+ if ((mdp_rev <= MDP_REV_41 && hist->bin_cnt > MDP_REV41_HIST_MAX_BIN)
+ || (mdp_rev == MDP_REV_42 &&
+ hist->bin_cnt > MDP_REV42_HIST_MAX_BIN)) {
+ pr_info("%s - mdp_rev = %d, num_bins = %d", __func__, mdp_rev,
+ hist->bin_cnt);
+ ret = -EINVAL;
+ goto error;
+}
+ mutex_lock(&mgmt->mdp_hist_mutex);
+ if (!mgmt->mdp_is_hist_data) {
+ pr_info("%s - hist_data = false!", __func__);
+ ret = -EINVAL;
+ goto error_lock;
+ }
+
+ if (!mgmt->mdp_is_hist_start) {
+ pr_err("%s histogram not started\n", __func__);
+ ret = -EPERM;
+ goto error_lock;
+ }
+
+ mgmt->hist = hist;
+ mutex_unlock(&mgmt->mdp_hist_mutex);
+
+ if (wait_for_completion_killable(&mgmt->mdp_hist_comp)) {
+ pr_err("%s(): histogram bin collection killed", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ mutex_lock(&mgmt->mdp_hist_mutex);
+ if (mgmt->mdp_is_hist_data && mgmt->mdp_is_hist_init)
+ ret = _mdp_copy_hist_data(hist, mgmt);
+ else
+ ret = -ENODATA;
+error_lock:
+ mutex_unlock(&mgmt->mdp_hist_mutex);
+error:
+ mutex_unlock(&mgmt->mdp_do_hist_mutex);
+ return ret;
+}
+#endif
+
+static void send_vsync_work(struct work_struct *work)
+{
+ char buf[64];
+ char *envp[2];
+
+ snprintf(buf, sizeof(buf), "VSYNC=%llu",
+ ktime_to_ns(vsync_cntrl.vsync_time));
+ envp[0] = buf;
+ envp[1] = NULL;
+ kobject_uevent_env(&(vsync_cntrl.dev->kobj), KOBJ_CHANGE, envp);
+}
+
+void mdp3_vsync_irq_enable(int intr, int term)
+{
+ unsigned long flag;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ outp32(MDP_INTR_CLEAR, intr);
+ mdp_intr_mask |= intr;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ mdp_enable_irq(term);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+}
+
+void mdp3_vsync_irq_disable(int intr, int term)
+{
+ unsigned long flag;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ /* required to synchronize between frame update and vsync
+ * since both use the same LCDC_FRAME_START interrupt
+ */
+ if (intr == LCDC_FRAME_START && dma2_data.waiting == FALSE) {
+ mdp_intr_mask &= ~intr;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ }
+ mdp_disable_irq(term);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+}
+
+#ifdef CONFIG_FB_MSM_MDP303
+/* vsync_isr_handler: Called from isr context*/
+static void vsync_isr_handler(void)
+{
+ vsync_cntrl.vsync_time = ktime_get();
+ schedule_work(&(vsync_cntrl.vsync_work));
+}
+#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__);
+ }
+
+ return ret;
+}
+
+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();
- if (term == MDP_OVERLAY0_TERM) {
- mdp_lut_enable(mdp);
- mdp_writel(mdp, 0, 0x0004);
- } else if (term == MDP_OVERLAY1_TERM) {
- mdp_lut_enable(mdp);
- mdp_writel(mdp, 0, 0x0008);
- }
-,}
+ /* kick off PPP engine */
+ if (term == MDP_PPP_TERM) {
+ if (mdp_debug[MDP_PPP_BLOCK])
+ jiffies_to_timeval(jiffies, &mdp_ppp_timeval);
-int mdp_start_histogram(struct mdp_device *mdp_dev, struct fb_info *info)
-{
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
- int ret = 0;
- int enable = 0;
+ /* let's turn on PPP block */
+ mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
- mutex_lock(&mdp_hist_mutex);
- if (mdp_is_hist_start == true) {
- PR_DISP_ERR("%s histogram already started\n", __func__);
- ret = -EPERM;
- goto mdp_hist_start_err;
- }
+ 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);
- mdp_is_hist_start = true;
+ if (mdp_debug[MDP_PPP_BLOCK]) {
+ struct timeval now;
- enable = mdp_readl(mdp, 0x0050);
- enable |= 0x80;
- mdp_writel(mdp, enable, 0x0050);
+ 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 */
+#ifdef CONFIG_FB_MSM_MDP22
+ outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x0044, 0x0);/* start DMA */
+#else
+ mdp_lut_enable();
- mdp_writel(mdp, 1, 0x95004);
- mdp_writel(mdp, 1, 0x95000);
+#ifdef CONFIG_FB_MSM_MDP40
+ outpdw(MDP_BASE + 0x000c, 0x0); /* start DMA */
+#else
+ outpdw(MDP_BASE + 0x0044, 0x0); /* start DMA */
-mdp_hist_start_err:
- mutex_unlock(&mdp_hist_mutex);
- return ret;
-}
+#ifdef CONFIG_FB_MSM_MDP303
-int mdp_stop_histogram(struct mdp_device *mdp_dev, struct fb_info *info)
-{
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
- int ret = 0;
- int enable = 0;
-
- mutex_lock(&mdp_hist_mutex);
- if (!mdp_is_hist_start) {
- PR_DISP_ERR("%s histogram already stopped\n", __func__);
- ret = -EPERM;
- goto mdp_hist_stop_err;
- }
- mdp_is_hist_start = false;
-
- /* disable the irq for histogram since we handled it
- when the control reaches here */
-
- enable = mdp_readl(mdp, 0x0050);
- enable &= ~0x80;
- mdp_writel(mdp, enable, 0x0050);
-
-mdp_hist_stop_err:
- mutex_unlock(&mdp_hist_mutex);
- return ret;
-}
-
-static int mdp_do_histogram(struct mdp_device *mdp_dev, struct mdp_histogram *hist, struct mdp_histogram *out)
-{
- int ret = 0;
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
- 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) {
- PR_DISP_ERR("%s histogram not started\n", __func__);
- mutex_unlock(&mdp_hist_mutex);
- return -EPERM;
- }
- enable_mdp_irq(mdp, INTR_DMA_P_HISTOGRAM | INTR_PRIMARY_INTF_UDERRUN);
- mutex_unlock(&mdp_hist_mutex);
-
- INIT_COMPLETION(mdp_hist_comp);
-
- 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);
-
- out->r = mdp_hist.r;
- out->g = mdp_hist.g;
- out->b = mdp_hist.b;
- disable_mdp_irq(mdp, INTR_DMA_P_HISTOGRAM | INTR_PRIMARY_INTF_UDERRUN);
- return ret;
-}
-
-int mdp_get_gamma_curvy(struct mdp_device *mdp_dev, struct gamma_curvy *gc)
-{
- uint32_t *ref_y_gamma;
- uint32_t *ref_y_shade;
- uint32_t *ref_bl_lvl;
- uint32_t *ref_y_lvl;
- int i = 0;
-
- if (!mdp_dev->abl_gamma_tbl)
- return -1;
-
- ref_y_gamma = mdp_dev->abl_gamma_tbl->ref_y_gamma;
- ref_y_shade = mdp_dev->abl_gamma_tbl->ref_y_shade;
- ref_bl_lvl = mdp_dev->abl_gamma_tbl->ref_bl_lvl;
- ref_y_lvl = mdp_dev->abl_gamma_tbl->ref_y_lvl;
-
- /* size fo ref_Y_gamma should be the same as size of ref_Y_shade*/
- if (sizeof(gc->ref_y_gamma) / 4 != sizeof(gc->ref_y_shade) / 4)
- return -1;
-
- /* size fo ref_bl_lvl should be the same as size of ref_Y_lvl*/
- if (sizeof(gc->ref_bl_lvl) / 4 != sizeof(gc->ref_y_lvl) / 4)
- return -1;
-
- gc->gamma_len = sizeof(gc->ref_y_gamma) / 4;
- gc->bl_len = sizeof(gc->ref_bl_lvl) / 4;
-
- for (i = 0; i < gc->gamma_len; i++) {
- gc->ref_y_gamma[i] = ref_y_gamma[i];
- gc->ref_y_shade[i] = ref_y_shade[i];
- }
-
- for (i = 0; i < gc->bl_len; i++) {
- gc->ref_bl_lvl[i] = ref_bl_lvl[i];
- gc->ref_y_lvl[i] = ref_y_lvl[i];
- }
- return 0;
-}
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+ mipi_dsi_cmd_mdp_start();
+#endif
#endif
-void mdp_set_grp_disp(struct mdp_device *mdp_dev, unsigned disp_id)
-{
- 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);
+#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 if (term == MDP_OVERLAY2_TERM) {
+ mdp_pipe_ctrl(MDP_OVERLAY2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ mdp_lut_enable();
+ outpdw(MDP_BASE + 0x00D0, 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
}
-/* used by output interface drivers like mddi and lcdc */
-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)
+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)
{
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
- unsigned long flags = 0;
- int ret = 0;
-
- if (interface < 0 || interface >= MSM_MDP_NUM_INTERFACES) {
- PR_DISP_ERR("%s: invalid interface (%d)\n", __func__, interface);
- return -EINVAL;
- }
-
- spin_lock_irqsave(&mdp->lock, flags);
-
- if (mdp->out_if[interface].registered) {
- PR_DISP_ERR("%s: interface (%d) already registered\n", __func__,
- interface);
- ret = -EINVAL;
- goto done;
- }
-
- init_waitqueue_head(&mdp->out_if[interface].dma_waitqueue);
- mdp->out_if[interface].registered = 1;
- mdp->out_if[interface].priv = private_data;
- mdp->out_if[interface].dma_mask = dma_mask;
- mdp->out_if[interface].dma_start = dma_start;
- mdp->out_if[interface].dma_cb = NULL;
-
-done:
- spin_unlock_irqrestore(&mdp->lock, flags);
- return ret;
+ mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
-int mdp_out_if_req_irq(struct mdp_device *mdp_dev, int interface,
- uint32_t mask, struct msmfb_callback *cb)
+static int mdp_clk_rate;
+
+#ifdef CONFIG_FB_MSM_NO_MDP_PIPE_CTRL
+
+/*
+ * mdp_clk_disable_unprepare(void) called from thread context
+ */
+static void mdp_clk_disable_unprepare(void)
{
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
- unsigned long flags = 0;
- int ret = 0;
+ mb();
+ vsync_clk_disable_unprepare();
- if (interface < 0 || interface >= MSM_MDP_NUM_INTERFACES) {
- PR_DISP_ERR("%s: invalid interface (%d)\n", __func__, interface);
- BUG();
- } else if (!mdp->out_if[interface].registered) {
- PR_DISP_ERR("%s: interface (%d) not registered\n", __func__,
- interface);
- BUG();
- }
+ if (mdp_clk != NULL)
+ clk_disable_unprepare(mdp_clk);
- spin_lock_irqsave(&mdp->lock, flags);
+ if (mdp_pclk != NULL)
+ clk_disable_unprepare(mdp_pclk);
- if (mask) {
- ret = locked_enable_mdp_irq(mdp, mask);
- if (ret) {
- PR_DISP_ERR("%s: busy\n", __func__);
- goto done;
- }
- mdp->out_if[interface].irq_mask = mask;
- mdp->out_if[interface].irq_cb = cb;
+ if (mdp_lut_clk != NULL)
+ clk_disable_unprepare(mdp_lut_clk);
+}
+
+/*
+ * mdp_clk_prepare_enable(void) called from thread context
+ */
+static void mdp_clk_prepare_enable(void)
+{
+ if (mdp_clk != NULL)
+ clk_prepare_enable(mdp_clk);
+
+ if (mdp_pclk != NULL)
+ clk_prepare_enable(mdp_pclk);
+
+ if (mdp_lut_clk != NULL)
+ clk_prepare_enable(mdp_lut_clk);
+
+ vsync_clk_prepare_enable();
+}
+
+/*
+ * mdp_clk_ctrl: called from thread context
+ */
+void mdp_clk_ctrl(int on)
+{
+ static int mdp_clk_cnt;
+
+ mutex_lock(&mdp_suspend_mutex);
+ if (on) {
+ if (mdp_clk_cnt == 0)
+ mdp_clk_prepare_enable();
+ mdp_clk_cnt++;
} else {
- locked_disable_mdp_irq(mdp, mask);
- mdp->out_if[interface].irq_mask = 0;
- mdp->out_if[interface].irq_cb = NULL;
+ if (mdp_clk_cnt) {
+ mdp_clk_cnt--;
+ if (mdp_clk_cnt == 0)
+ mdp_clk_disable_unprepare();
+ }
+ }
+ mutex_unlock(&mdp_suspend_mutex);
+}
+
+
+
+void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
+ boolean isr)
+{
+ /* do nothing */
+}
+#else
+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_unprepare(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_unprepare(mdp_pclk);
+ MSM_FB_DEBUG("MDP PCLK OFF\n");
+ }
+ if (mdp_lut_clk != NULL)
+ clk_disable_unprepare(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_prepare_enable(mdp_clk);
+ MSM_FB_DEBUG("MDP CLK ON\n");
+ }
+ if (mdp_pclk != NULL) {
+ clk_prepare_enable(mdp_pclk);
+ MSM_FB_DEBUG("MDP PCLK ON\n");
+ }
+ if (mdp_lut_clk != NULL)
+ clk_prepare_enable(mdp_lut_clk);
+ mdp_vsync_clk_enable();
+ }
+ up(&mdp_pipe_ctrl_mutex);
+ }
+}
+
+void mdp_clk_ctrl(int on)
+{
+ /* do nothing */
+}
+#endif
+
+void mdp_histogram_handle_isr(struct mdp_hist_mgmt *mgmt)
+{
+ uint32 isr, mask;
+ char *base_addr = MDP_BASE + mgmt->base;
+ isr = inpdw(base_addr + MDP_HIST_INTR_STATUS_OFF);
+ mask = inpdw(base_addr + MDP_HIST_INTR_ENABLE_OFF);
+ outpdw(base_addr + MDP_HIST_INTR_CLEAR_OFF, isr);
+ mb();
+ isr &= mask;
+ if (isr & INTR_HIST_RESET_SEQ_DONE)
+ __mdp_histogram_kickoff(mgmt);
+
+ if (isr & INTR_HIST_DONE) {
+ if (waitqueue_active(&mgmt->mdp_hist_comp.wait)) {
+ if (!queue_work(mdp_hist_wq,
+ &mgmt->mdp_histogram_worker)) {
+ pr_err("%s %d- can't queue hist_read\n",
+ __func__, mgmt->block);
+ }
+ } else {
+ __mdp_histogram_reset(mgmt);
+ }
+ }
+}
+
+#ifndef CONFIG_FB_MSM_MDP40
+irqreturn_t mdp_isr(int irq, void *ptr)
+{
+ uint32 mdp_interrupt = 0;
+ struct mdp_dma_data *dma;
+#ifndef CONFIG_FB_MSM_MDP22
+ struct mdp_hist_mgmt *mgmt = NULL;
+ char *base_addr;
+ int i, ret;
+#endif
+ /* Ensure all the register write are complete */
+ mb();
+
+ 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;
+
+ /*Primary Vsync interrupt*/
+ if (mdp_interrupt & MDP_PRIM_RDPTR)
+ vsync_isr_handler();
+
+ /* 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
+ /* Only DMA_P histogram exists for this MDP rev*/
+ if (mdp_interrupt & MDP_HIST_DONE) {
+ ret = mdp_histogram_block2mgmt(MDP_BLOCK_DMA_P, &mgmt);
+ if (!ret)
+ mdp_histogram_handle_isr(mgmt);
+ outp32(MDP_INTR_CLEAR, MDP_HIST_DONE);
}
-done:
- spin_unlock_irqrestore(&mdp->lock, flags);
- return ret;
-}
+ /* 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.*/
+ for (i = 0; i < MDP_HIST_MGMT_MAX; i++) {
+ mgmt = mdp_hist_mgmt_array[i];
+ if (!mgmt)
+ continue;
-int register_mdp_client(struct class_interface *cint)
-{
- if (!mdp_class) {
- PR_DISP_ERR("mdp: no mdp_class when registering mdp client\n");
- return -ENODEV;
+ base_addr = MDP_BASE + mgmt->base;
+ outpdw(base_addr + 0x010, 1);
+ outpdw(base_addr + 0x01C, INTR_HIST_DONE |
+ INTR_HIST_RESET_SEQ_DONE);
+ mgmt->mdp_is_hist_valid = FALSE;
+ __mdp_histogram_reset(mgmt);
+ }
}
- cint->class = mdp_class;
- return class_interface_register(cint);
+
+ /* LCDC Frame Start */
+ if (mdp_interrupt & LCDC_FRAME_START) {
+ dma = &dma2_data;
+ if (dma->waiting) {
+ dma->waiting = FALSE;
+ complete(&dma->comp);
+ }
+
+ if (vsync_cntrl.vsync_irq_enabled)
+ vsync_isr_handler();
+
+ if (!vsync_cntrl.vsync_irq_enabled && !(dma->waiting)) {
+ mdp_intr_mask &= ~LCDC_FRAME_START;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ }
+ }
+
+ /* 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 ssize_t mdp_reg_addr_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static void mdp_drv_init(void)
{
- int ret;
-
- ret = sprintf(buf, "0x%x\n", mdp_reg_addr);
-
- return ret;
-}
-
-static ssize_t mdp_reg_addr_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- unsigned reg_addr;
-
- sscanf(buf, "%x", ®_addr);
-
- if (reg_addr == 0)
- return -EINVAL;
-
- mdp_reg_addr = reg_addr;
-
- return count;
-}
-
-static DEVICE_ATTR(reg_addr, 0644, mdp_reg_addr_show, mdp_reg_addr_store);
-
-static ssize_t mdp_reg_val_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct mdp_device *mdp_dev = container_of(dev, struct mdp_device, dev);
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
- int ret;
-
- if (mdp_reg_addr == 0)
- return -EINVAL;
-
- mdp_reg_val = mdp_readl(mdp, mdp_reg_addr);
- ret = sprintf(buf, "0x%x\n", mdp_reg_val);
- return ret;
-}
-
-static ssize_t mdp_reg_val_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct mdp_device *mdp_dev = container_of(dev, struct mdp_device, dev);
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
- unsigned reg_val, val;
- unsigned mask = 0xffffffff;
-
- if (mdp_reg_addr == 0)
- return -EINVAL;
-
- sscanf(buf, "%x %x", ®_val, &mask);
- mdp_reg_val = reg_val;
- val = mdp_readl(mdp, mdp_reg_addr);
- val &= ~mask;
- mdp_reg_val &= mask;
- mdp_reg_val |= val;
- mdp_writel(mdp, mdp_reg_val, mdp_reg_addr);
- return count;
-}
-
-static DEVICE_ATTR(reg_val, 0644, mdp_reg_val_show, mdp_reg_val_store);
-
-
-static int
-mdp_write_reg_mask(struct mdp_info *mdp, uint32_t reg, uint32_t val, uint32_t mask)
-{
- uint32_t oldval, newval;
-
- oldval = mdp_readl(mdp, reg);
-
- oldval &= (~mask);
- val &= mask;
- newval = oldval | val;
-
- mdp_writel(mdp, newval, reg);
-
- return 0;
-
-}
-
-static int
-mdp_write_regs(struct mdp_info *mdp, const struct mdp_reg *reglist, int size)
-{
- const struct mdp_reg *reg_seq = reglist;
int i;
- for (i = 0; i < size; i++) {
- if (reg_seq[i].mask == 0x0)
- mdp_writel(mdp, reg_seq[i].val, reg_seq[i].reg);
- else
- mdp_write_reg_mask(mdp, reg_seq[i].reg, reg_seq[i].val, reg_seq[i].mask);
+ for (i = 0; i < MDP_MAX_BLOCK; i++) {
+ mdp_debug[i] = 0;
}
+ /* 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_hist_wq = create_singlethread_workqueue("mdp_hist_wq");
+ mdp_pipe_ctrl_wq = create_singlethread_workqueue("mdp_pipe_ctrl_wq");
+ INIT_DELAYED_WORK(&mdp_pipe_ctrl_worker,
+ mdp_pipe_ctrl_workqueue_handler);
+
+ /* initialize semaphore */
+ init_completion(&mdp_ppp_comp);
+ sema_init(&mdp_ppp_mutex, 1);
+ sema_init(&mdp_pipe_ctrl_mutex, 1);
+
+ 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);
+
+ dma3_data.busy = FALSE;
+ dma3_data.waiting = FALSE;
+ init_completion(&dma3_data.comp);
+ sema_init(&dma3_data.mutex, 1);
+
+ dma_s_data.busy = FALSE;
+ dma_s_data.waiting = FALSE;
+ init_completion(&dma_s_data.comp);
+ sema_init(&dma_s_data.mutex, 1);
+
+#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
+#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
+ dma_wb_data.busy = FALSE;
+ dma_wb_data.waiting = FALSE;
+ init_completion(&dma_wb_data.comp);
+ mutex_init(&dma_wb_data.ov_mutex);
+#endif
+
+ /* initializing mdp power block counter to 0 */
+ for (i = 0; i < MDP_MAX_BLOCK; i++) {
+ atomic_set(&mdp_block_power_cnt[i], 0);
+ }
+ INIT_WORK(&(vsync_cntrl.vsync_work), send_vsync_work);
+#ifdef MSM_FB_ENABLE_DBGFS
+ {
+ struct dentry *root;
+ char sub_name[] = "mdp";
+
+ 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
+ }
+ }
+ }
+#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;
}
-#ifdef CONFIG_MSM_MDP40
-static int mdp_hw_version(void)
+static int mdp_runtime_resume(struct device *dev)
{
- int mdp_hw_revision;
- char *cp;
- uint32_t *hp;
+ dev_dbg(dev, "pm_runtime: resuming...\n");
+ return 0;
+}
+static struct dev_pm_ops mdp_dev_pm_ops = {
+ .runtime_suspend = mdp_runtime_suspend,
+ .runtime_resume = mdp_runtime_resume,
+};
+
+
+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)
+{
+ int ret = 0;
+ struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
+
+ mdp_histogram_ctrl_all(FALSE);
+
+ if (mfd->panel.type == MIPI_CMD_PANEL)
+ mdp4_dsi_cmd_off(pdev);
+ else if (mfd->panel.type == MIPI_VIDEO_PANEL)
+ mdp4_dsi_video_off(pdev);
+ else if (mfd->panel.type == HDMI_PANEL ||
+ mfd->panel.type == LCDC_PANEL ||
+ mfd->panel.type == LVDS_PANEL)
+ mdp4_lcdc_off(pdev);
+
+ 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);
+
+ if (mdp_rev >= MDP_REV_41 && mfd->panel.type == MIPI_CMD_PANEL)
+ mdp_dsi_cmd_overlay_suspend(mfd);
+ return ret;
+}
+
+static int mdp_on(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct msm_fb_data_type *mfd;
+ mfd = platform_get_drvdata(pdev);
+
+#ifdef CONFIG_FB_MSM_MDP40
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ mdp_clk_ctrl(1);
+ mdp4_hw_init();
+ outpdw(MDP_BASE + 0x0038, mdp4_display_intf);
+ if (mfd->panel.type == MIPI_CMD_PANEL) {
+ mdp_vsync_cfg_regs(mfd, FALSE);
+ mdp4_dsi_cmd_on(pdev);
+ } else if (mfd->panel.type == MIPI_VIDEO_PANEL)
+ mdp4_dsi_video_on(pdev);
+ else if (mfd->panel.type == HDMI_PANEL ||
+ mfd->panel.type == LCDC_PANEL ||
+ mfd->panel.type == LVDS_PANEL)
+ mdp4_lcdc_on(pdev);
+
+ mdp_clk_ctrl(0);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+#endif
+
+ if ((mdp_rev == MDP_REV_303) &&
+ (mfd->panel.type == MIPI_CMD_PANEL))
+ vsync_cntrl.dev = mfd->fbi->dev;
+
+ 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);
+
+ mdp_histogram_ctrl_all(TRUE);
+
+ 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(0xac001270, 0x16);
+ cp = (char *)ioremap(mdp_pdata->hw_revision_addr, 0x16);
if (cp == NULL)
- return -1;
+ return;
- hp = (uint32_t *)cp; /* HW_REVISION_NUMBER */
+ hp = (uint32 *)cp; /* HW_REVISION_NUMBER */
mdp_hw_revision = *hp;
iounmap(cp);
mdp_hw_revision >>= 28; /* bit 31:28 */
mdp_hw_revision &= 0x0f;
- printk(KERN_INFO "%s: mdp_hw_revision=%x\n",
+ MSM_FB_DEBUG("%s: mdp_hw_revision=%x\n",
__func__, mdp_hw_revision);
- return mdp_hw_revision;
+}
+
+#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
-
-#ifdef DEBUG_OVERLAY
-int mdp4_overlay_debugfs_init(void);
-#endif
-
-#ifdef CONFIG_MDP4_HW_VSYNC
-void mdp_config_vsync(struct mdp_info *mdp)
+DEFINE_MUTEX(mdp_clk_lock);
+int mdp_set_core_clk(u32 rate)
{
- int total_porch_line;
- int vsync_cnt_cfg, vsync_cnt_cfg_dem, mdp_vsync_clk_speed_hz;
- struct clk *mdp_vsync_clk = NULL;
-
- total_porch_line = mdp->mdp_dev.back_porch +
- mdp->mdp_dev.front_porch +
- mdp->mdp_dev.pulse_width;
-
- mdp->total_lcd_line =
- total_porch_line + mdp->mdp_dev.yres;
-
- mdp_vsync_clk = clk_get(NULL, "mdp_vsync_clk");
- mdp_vsync_clk_speed_hz = clk_get_rate(mdp_vsync_clk);
-
- vsync_cnt_cfg_dem = 6000 * /*panel_info.lcd.refx100*/ mdp->total_lcd_line / 100;
- vsync_cnt_cfg = (mdp_vsync_clk_speed_hz) / vsync_cnt_cfg_dem;
-
- PR_DISP_INFO("total_lcd_line %x, vsync_cnt_cfg %x\n", mdp->total_lcd_line, vsync_cnt_cfg);
- mdp_writel(mdp, ((mdp->total_lcd_line-1)<<21)|(3<<19)|(vsync_cnt_cfg), 0x100/*MDP_SYNC_CONFIG_0*/);
-/* mdp_writel(mdp, (820<<21)|(3<<19)|(499), 0x100 //MDP_SYNC_CONFIG_0);*/
-
- /* threshold */
- mdp_writel(mdp, (4<<16) | 1, 0x200/*MDP_SYNC_THRESH_0*/);
-
- /*
- * external vsync source pulse width and
- * polarity flip
- */
- mdp_writel(mdp, 1, 0x118);
-
- /* line counter init value at the next pulse */
- mdp_writel(mdp, mdp->mdp_dev.yres, 0x128);
-
-
-/* mdp_writel(mdp, 795, 0x210//MDP_PRIM_START_POS);*/
-/* mdp_writel(mdp, 1, 0x20c//MDP_TEAR_CHECK_EN);*/
- PR_DISP_INFO("vsync_clk %d\n", (int)clk_get_rate(mdp->vsync_clk));
-}
-#endif
-
-int mdp_probe(struct platform_device *pdev)
-{
- struct resource *resource;
int ret = -EINVAL;
- struct mdp_info *mdp;
- struct msm_mdp_platform_data *pdata = pdev->dev.platform_data;
-
-
- resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!resource) {
- PR_DISP_ERR("mdp: can not get mdp mem resource!\n");
- return -ENOMEM;
- }
-
- mdp = kzalloc(sizeof(struct mdp_info), GFP_KERNEL);
- if (!mdp)
- return -ENOMEM;
-
- spin_lock_init(&mdp->lock);
-
- mdp->irq = platform_get_irq(pdev, 0);
- if (mdp->irq < 0) {
- PR_DISP_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) {
- PR_DISP_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;
-#ifdef CONFIG_FB_MSM_OVERLAY
- mdp->mdp_dev.overlay_get = mdp4_overlay_get;
- mdp->mdp_dev.overlay_set = mdp4_overlay_set;
- mdp->mdp_dev.overlay_unset = mdp4_overlay_unset;
- mdp->mdp_dev.overlay_play = mdp4_overlay_play;
-#endif
- mdp->mdp_dev.set_grp_disp = mdp_set_grp_disp;
- mdp->mdp_dev.set_output_format = mdp_set_output_format;
- mdp->mdp_dev.set_panel_size = mdp_set_panel_size;
- mdp->mdp_dev.check_output_format = mdp_check_output_format;
- mdp->mdp_dev.configure_dma = mdp_configure_dma;
-
-#if defined(CONFIG_FB_MSM_MDP_ABL)
- mdp->mdp_dev.lut_update = mdp_lut_update;
- mdp->mdp_dev.do_histogram = mdp_do_histogram;
- mdp->mdp_dev.start_histogram = mdp_start_histogram;
- mdp->mdp_dev.stop_histogram = mdp_stop_histogram;
- mdp->mdp_dev.get_gamma_curvy = mdp_get_gamma_curvy;
-#endif
- mdp->enable_irq = enable_mdp_irq;
- mdp->disable_irq = disable_mdp_irq;
- mdp->write_regs = mdp_write_regs;
-
- mdp->mdp_dev.fb0 = NULL;
- mdp->mdp_dev.fb1 = NULL;
- if (pdata == NULL || pdata->overrides == 0)
- mdp->mdp_dev.overrides = 0;
- else if (pdata->overrides)
- mdp->mdp_dev.overrides = pdata->overrides;
-
- if (pdata != NULL)
- pdata->mdp_dev = &mdp->mdp_dev;
-
- if (pdata == NULL || pdata->color_format == 0)
- mdp->mdp_dev.color_format = MSM_MDP_OUT_IF_FMT_RGB565;
- else if (pdata->color_format)
- mdp->mdp_dev.color_format = pdata->color_format;
-#ifdef CONFIG_MDP4_HW_VSYNC
- if (pdata == NULL || pdata->xres == 0) {
- mdp->mdp_dev.xres = 0;
- mdp->mdp_dev.yres = 0;
- mdp->mdp_dev.back_porch = 0;
- mdp->mdp_dev.front_porch = 0;
- mdp->mdp_dev.pulse_width = 0;
- } else if (pdata->xres) {
- mdp->mdp_dev.xres = pdata->xres;
- mdp->mdp_dev.yres = pdata->yres;
- mdp->mdp_dev.back_porch = pdata->back_porch;
- mdp->mdp_dev.front_porch = pdata->front_porch;
- mdp->mdp_dev.pulse_width = pdata->pulse_width;
- }
-#endif
-#ifdef CONFIG_MSM_MDP40
- mdp->hw_version = mdp_hw_version();
-
- if (mdp->hw_version < MDP4_REVISION_V2_1 &&
- mdp->mdp_dev.overrides & MSM_MDP4_MDDI_DMA_SWITCH) {
- ret = mdp_out_if_register(&mdp->mdp_dev,
- MSM_MDDI_PMDH_INTERFACE, mdp, INTR_OVERLAY0_DONE
- | MDP_DMA_S_DONE, mdp4_mddi_overlay);
- } else {
- ret = mdp_out_if_register(&mdp->mdp_dev,
- MSM_MDDI_PMDH_INTERFACE, mdp, INTR_OVERLAY0_DONE,
- mdp4_mddi_overlay);
- }
-#else
- if (pdata == NULL || pdata->dma_channel == MDP_DMA_P) {
- ret = mdp_out_if_register(&mdp->mdp_dev,
- MSM_MDDI_PMDH_INTERFACE, mdp, MDP_DMA_P_DONE,
- mdp_dma_to_mddi);
- } else if (pdata->dma_channel == MDP_DMA_S) {
- ret = mdp_out_if_register(&mdp->mdp_dev,
- MSM_MDDI_PMDH_INTERFACE, mdp, MDP_DMA_S_DONE,
- mdp_dmas_to_mddi);
- }
-#endif
-
-#if defined(CONFIG_FB_MSM_MDP_ABL)
- if (mdp->mdp_dev.overrides & MSM_MDP_ABL_ENABLE)
- mdp->mdp_dev.abl_gamma_tbl = pdata->abl_gamma_tbl;
-#endif
+ if (mdp_clk)
+ ret = clk_set_rate(mdp_clk, rate);
if (ret)
- goto error_mddi_pmdh_register;
-
- mdp->clk = clk_get(&pdev->dev, "mdp_clk");
- if (IS_ERR(mdp->clk)) {
- PR_DISP_INFO("mdp: failed to get mdp clk");
- ret = PTR_ERR(mdp->clk);
- goto error_get_mdp_clk;
- }
-
- mdp->ebi1_clk = clk_get(NULL, "ebi1_clk");
-
- if (IS_ERR(mdp->ebi1_clk)) {
- PR_DISP_ERR("mdp: failed to get ebi1 clk\n");
- ret = PTR_ERR(mdp->ebi1_clk);
- goto error_get_ebi1_clk;
- }
-#ifdef CONFIG_MDP4_HW_VSYNC
- mdp->vsync_clk = clk_get(&pdev->dev, "mdp_vsync_clk");
- if (IS_ERR(mdp->vsync_clk)) {
- PR_DISP_INFO("mdp: failed to get mdp vsync clk");
- ret = PTR_ERR(mdp->vsync_clk);
- goto error_get_mdp_clk;
- }
-#endif
- ret = request_irq(mdp->irq, mdp_isr, IRQF_DISABLED, "msm_mdp", mdp);
- if (ret)
- goto error_request_irq;
- disable_irq(mdp->irq);
-
- clk_enable(mdp->clk);
- mdp_clk_to_disable_later = mdp->clk;
-#ifdef CONFIG_MDP4_HW_VSYNC
- clk_enable(mdp->vsync_clk);
- mdp_vsync_clk_to_disable_later = mdp->vsync_clk;
-#endif
-
-#ifdef CONFIG_MSM_MDP40
- if (mdp_readl(mdp, 0xc0000))
- mdp_writel(mdp, 0x8, 0x0038);
+ pr_err("%s unable to set mdp clk rate", __func__);
else
- mdp_writel(mdp, 0xa, 0x0038);
-#endif
-
-#ifdef CONFIG_MSM_MDP40
- mdp4_hw_init(mdp);
-#else
- mdp_hw_init(mdp);
-#endif
-
-#ifdef CONFIG_MDP4_HW_VSYNC
- mdp_config_vsync(mdp);
-#endif
-
-
-#if defined CONFIG_MSM_MDP302
- /* enable the tearing check in MDP */
- if (pdata != NULL && pdata->tearing_check)
- mdp_check_tearing(mdp, pdata);
-#endif
- /* 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;
-
- ret = device_create_file(&mdp->mdp_dev.dev, &dev_attr_reg_addr);
- ret = device_create_file(&mdp->mdp_dev.dev, &dev_attr_reg_val);
-
- setup_timer(&mdp->standby_timer, mdp_do_standby_timer, (unsigned long)mdp);
- setup_timer(&mdp->dma_timer, mdp_do_dma_timer, (unsigned long)mdp);
-
-#if defined(CONFIG_FB_MSM_MDP_ABL)
- init_completion(&mdp_hist_comp);
-#endif
- PR_DISP_INFO("%s: initialized\n", __func__);
-
-#ifdef DEBUG_OVERLAY
- mdp4_overlay_debugfs_init();
-#endif
- return 0;
-
-error_device_register:
- free_irq(mdp->irq, mdp);
-error_request_irq:
- clk_put(mdp->ebi1_clk);
-error_get_ebi1_clk:
- clk_put(mdp->clk);
-error_get_mdp_clk:
-error_mddi_pmdh_register:
- iounmap(mdp->base);
-error_ioremap:
-error_get_irq:
- kfree(mdp);
+ pr_debug("%s mdp clk rate to be set %d: actual rate %ld\n",
+ __func__, rate, clk_get_rate(mdp_clk));
return ret;
}
-static struct platform_driver msm_mdp_driver = {
- .probe = mdp_probe,
- .driver = {.name = "msm_mdp"},
-};
-
-static int __init mdp_lateinit(void)
+int mdp_clk_round_rate(u32 rate)
{
- if (mdp_clk_to_disable_later)
- clk_disable(mdp_clk_to_disable_later);
-#ifdef CONFIG_MDP4_HW_VSYNC
- if (mdp_vsync_clk_to_disable_later)
- clk_disable(mdp_vsync_clk_to_disable_later);
+ return clk_round_rate(mdp_clk, rate);
+}
+
+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;
+}
+
+static int mdp_irq_clk_setup(struct platform_device *pdev,
+ char cont_splashScreen)
+{
+ 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);
+
+ hdmi_pll_fs = regulator_get(&pdev->dev, "hdmi_pll_fs");
+ if (IS_ERR(hdmi_pll_fs)) {
+ hdmi_pll_fs = NULL;
+ } else {
+ if (mdp_rev != MDP_REV_44) {
+ ret = regulator_set_voltage(hdmi_pll_fs, 1800000,
+ 1800000);
+ if (ret) {
+ pr_err("set_voltage failed for hdmi_pll_fs, ret=%d\n",
+ ret);
+ }
+ }
+ }
+
+ footswitch = regulator_get(NULL, "fs_mdp");
+ if (IS_ERR(footswitch)) {
+ footswitch = NULL;
+ } else {
+ if (hdmi_pll_fs)
+ regulator_enable(hdmi_pll_fs);
+
+ regulator_enable(footswitch);
+ mdp_footswitch_on = 1;
+
+ if (mdp_rev == MDP_REV_42 && !cont_splashScreen) {
+ regulator_disable(footswitch);
+ msleep(20);
+ regulator_enable(footswitch);
+ }
+ if (hdmi_pll_fs)
+ regulator_disable(hdmi_pll_fs);
+ }
+
+ mdp_clk = clk_get(&pdev->dev, "core_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(&pdev->dev, "iface_clk");
+ if (IS_ERR(mdp_pclk))
+ mdp_pclk = NULL;
+
+ if (mdp_rev == MDP_REV_42) {
+ mdp_lut_clk = clk_get(&pdev->dev, "lut_clk");
+ 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);
+ free_irq(mdp_irq, 0);
+ return ret;
+ }
+ } else {
+ mdp_lut_clk = NULL;
+ }
+
+#ifdef CONFIG_FB_MSM_MDP40
+
+ if (mdp_pdata)
+ mdp_max_clk = mdp_pdata->mdp_max_clk;
+ else
+ pr_err("%s cannot get mdp max clk!\n", __func__);
+
+ if (!mdp_max_clk)
+ pr_err("%s mdp max clk is zero!\n", __func__);
+
+ if (cont_splashScreen)
+ mdp_clk_rate = clk_get_rate(mdp_clk);
+ else
+ mdp_clk_rate = mdp_max_clk;
+
+ mutex_lock(&mdp_clk_lock);
+ clk_set_rate(mdp_clk, mdp_clk_rate);
+ if (mdp_lut_clk != NULL)
+ clk_set_rate(mdp_lut_clk, mdp_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 __init mdp_init(void)
+static int mdp_probe(struct platform_device *pdev)
{
- mdp_class = class_create(THIS_MODULE, "msm_mdp");
- if (IS_ERR(mdp_class)) {
- PR_DISP_ERR("Error creating mdp class\n");
- return PTR_ERR(mdp_class);
+ 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 ;
+ unsigned long flag;
+#ifdef CONFIG_FB_MSM_MDP40
+ int intf, if_no;
+#endif
+#if defined(CONFIG_FB_MSM_MIPI_DSI) && defined(CONFIG_FB_MSM_MDP40)
+ struct mipi_panel_info *mipi;
+#endif
+ static int contSplash_update_done;
+
+ if ((pdev->id == 0) && (pdev->num_resources > 0)) {
+ mdp_init_pdev = pdev;
+ 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(pdev, mdp_pdata->cont_splash_enabled);
+
+ if (rc)
+ return rc;
+
+ mdp_clk_ctrl(1);
+
+ mdp_hw_version();
+
+ /* initializing mdp hw */
+#ifdef CONFIG_FB_MSM_MDP40
+ if (!(mdp_pdata->cont_splash_enabled))
+ mdp4_hw_init();
+#else
+ mdp_hw_init();
+#endif
+
+#ifdef CONFIG_FB_MSM_OVERLAY
+ mdp_hw_cursor_init();
+#endif
+ mdp_clk_ctrl(0);
+
+ mdp_resource_initialized = 1;
+ return 0;
}
- return platform_driver_register(&msm_mdp_driver);
+
+ 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;
+ mfd->mdp_rev = mdp_rev;
+
+ if (mdp_pdata) {
+ if (mdp_pdata->cont_splash_enabled) {
+ mfd->cont_splash_done = 0;
+ if (!contSplash_update_done) {
+ mdp_pipe_ctrl(MDP_CMD_BLOCK,
+ MDP_BLOCK_POWER_ON, FALSE);
+ contSplash_update_done = 1;
+ }
+ } else
+ mfd->cont_splash_done = 1;
+ }
+
+ mfd->ov0_wb_buf = MDP_ALLOC(sizeof(struct mdp_buf_type));
+ mfd->ov1_wb_buf = MDP_ALLOC(sizeof(struct mdp_buf_type));
+ memset((void *)mfd->ov0_wb_buf, 0, sizeof(struct mdp_buf_type));
+ memset((void *)mfd->ov1_wb_buf, 0, sizeof(struct mdp_buf_type));
+
+ if (mdp_pdata) {
+ mfd->ov0_wb_buf->size = mdp_pdata->ov0_wb_size;
+ mfd->ov1_wb_buf->size = mdp_pdata->ov1_wb_size;
+ mfd->mem_hid = mdp_pdata->mem_hid;
+ } else {
+ mfd->ov0_wb_buf->size = 0;
+ mfd->ov1_wb_buf->size = 0;
+ mfd->mem_hid = 0;
+ }
+
+ /* initialize Post Processing data*/
+ mdp_hist_lut_init();
+ mdp_histogram_init();
+
+ /* 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_clk_ctrl(1);
+
+ 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
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_intr_mask |= INTR_OVERLAY0_DONE;
+ if (mdp_hw_revision < MDP4_REVISION_V2_1) {
+ /* dmas dmap switch */
+ mdp_intr_mask |= INTR_DMA_S_DONE;
+ }
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ 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(mdp_init_pdev, mfd);
+ break;
+
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+ case MIPI_VIDEO_PANEL:
+#ifndef CONFIG_FB_MSM_MDP303
+ mipi = &mfd->panel_info.mipi;
+ mdp4_dsi_vsync_init(0);
+ mfd->hw_refresh = TRUE;
+ mfd->dma_fnc = mdp4_dsi_video_overlay;
+ mfd->lut_update = mdp_lut_update_lcdc;
+ mfd->do_histogram = mdp_do_histogram;
+ 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;
+ mfd->vsync_ctrl = mdp_dma_video_vsync_ctrl;
+ 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
+ if (mdp_rev >= MDP_REV_40)
+ mfd->cursor_update = mdp_hw_cursor_sync_update;
+ else
+ mfd->cursor_update = mdp_hw_cursor_update;
+ break;
+
+ case MIPI_CMD_PANEL:
+#ifndef CONFIG_FB_MSM_MDP303
+ mfd->dma_fnc = mdp4_dsi_cmd_overlay;
+ mipi = &mfd->panel_info.mipi;
+ mdp4_dsi_rdptr_init(0);
+ 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;
+ }
+ mfd->lut_update = mdp_lut_update_nonlcdc;
+ mfd->do_histogram = mdp_do_histogram;
+ mdp4_display_intf_sel(if_no, DSI_CMD_INTF);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_intr_mask |= INTR_OVERLAY0_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+#else
+
+ mfd->dma_fnc = mdp_dma2_update;
+ mfd->do_histogram = mdp_do_histogram;
+ mfd->vsync_ctrl = mdp_dma_vsync_ctrl;
+ 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;
+ }
+ INIT_WORK(&mfd->dma_update_worker,
+ mdp_lcd_update_workqueue_handler);
+#endif
+ mdp_config_vsync(mdp_init_pdev, mfd);
+ break;
+#endif
+
+#ifdef CONFIG_FB_MSM_DTV
+ case DTV_PANEL:
+ mdp4_dtv_vsync_init(0);
+ 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:
+ case LVDS_PANEL:
+#ifdef CONFIG_FB_MSM_MDP303
+ pdata->on = mdp_lcdc_on;
+ pdata->off = mdp_lcdc_off;
+#endif
+ 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
+ mdp4_lcdc_vsync_init(0);
+ 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;
+ mfd->vsync_ctrl = mdp_dma_lcdc_vsync_ctrl;
+ 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;
+
+#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
+ case WRITEBACK_PANEL:
+ {
+ unsigned int mdp_version;
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON,
+ FALSE);
+ mdp_version = inpdw(MDP_BASE + 0x0);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF,
+ FALSE);
+ if (mdp_version < 0x04030303) {
+ pr_err("%s: writeback panel not supprted\n",
+ __func__);
+ platform_device_put(msm_fb_dev);
+ return -ENODEV;
+ }
+ pdata->on = mdp4_overlay_writeback_on;
+ pdata->off = mdp4_overlay_writeback_off;
+ mfd->dma_fnc = mdp4_writeback_overlay;
+ mfd->dma = &dma_wb_data;
+ mdp4_display_intf_sel(EXTERNAL_INTF_SEL, DTV_INTF);
+ }
+ break;
+#endif
+ default:
+ printk(KERN_ERR "mdp_probe: unknown device type!\n");
+ rc = -ENODEV;
+ mdp_clk_ctrl(0);
+ 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
+
+ mdp_clk_ctrl(0);
+
+#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;
+ }
+ }
+
+ /* req bus bandwidth immediately */
+ if (!(mfd->cont_splash_done))
+ mdp_bus_scale_update_request(5);
+
+#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;
}
-subsys_initcall(mdp_init);
-late_initcall(mdp_lateinit);
+unsigned int mdp_check_suspended(void)
+{
+ unsigned int ret;
+
+ mutex_lock(&mdp_suspend_mutex);
+ ret = mdp_suspended;
+ mutex_unlock(&mdp_suspend_mutex);
+
+ return ret;
+}
+
+void mdp_footswitch_ctrl(boolean on)
+{
+ mutex_lock(&mdp_suspend_mutex);
+ if (!mdp_suspended || mdp4_extn_disp || !footswitch ||
+ mdp_rev <= MDP_REV_41) {
+ mutex_unlock(&mdp_suspend_mutex);
+ return;
+ }
+
+ if (hdmi_pll_fs)
+ regulator_enable(hdmi_pll_fs);
+
+ if (on && !mdp_footswitch_on) {
+ pr_debug("Enable MDP FS\n");
+ regulator_enable(footswitch);
+ mdp_footswitch_on = 1;
+ } else if (!on && mdp_footswitch_on) {
+ pr_debug("Disable MDP FS\n");
+ regulator_disable(footswitch);
+ mdp_footswitch_on = 0;
+ }
+
+ if (hdmi_pll_fs)
+ regulator_disable(hdmi_pll_fs);
+
+ mutex_unlock(&mdp_suspend_mutex);
+}
+
+#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();
+#ifdef CONFIG_FB_MSM_DTV
+ mdp4_dtv_set_black_screen();
+#endif
+ mdp4_iommu_detach();
+ mdp_footswitch_ctrl(FALSE);
+}
+
+static void mdp_early_resume(struct early_suspend *h)
+{
+ mdp_footswitch_ctrl(TRUE);
+ 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..7f493ff
--- /dev/null
+++ b/drivers/video/msm/mdp.h
@@ -0,0 +1,902 @@
+/* Copyright (c) 2008-2012, 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 <linux/memory_alloc.h>
+#include <mach/hardware.h>
+#include <linux/ion.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;
+extern struct mdp_csc_cfg mdp_csc_convert[4];
+
+extern struct workqueue_struct *mdp_hist_wq;
+
+extern uint32 mdp_intr_mask;
+
+#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)
+#define MDP_ALLOC(x) kmalloc(x, GFP_KERNEL)
+
+struct mdp_buf_type {
+ struct ion_handle *ihdl;
+ u32 write_addr;
+ u32 read_addr;
+ u32 size;
+};
+
+struct mdp_table_entry {
+ uint32_t reg;
+ uint32_t val;
+};
+
+extern struct mdp_ccs mdp_ccs_yuv2rgb ;
+extern struct mdp_ccs mdp_ccs_rgb2yuv ;
+extern unsigned char hdmi_prim_display;
+
+struct vsync {
+ ktime_t vsync_time;
+ struct device *dev;
+ struct work_struct vsync_work;
+ int vsync_irq_enabled;
+};
+
+extern struct vsync vsync_cntrl;
+
+/*
+ * 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_OVERLAY2_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;
+};
+
+extern struct list_head mdp_hist_lut_list;
+extern struct mutex mdp_hist_lut_list_mutex;
+struct mdp_hist_lut_mgmt {
+ uint32_t block;
+ struct mutex lock;
+ struct list_head list;
+};
+
+struct mdp_hist_lut_info {
+ uint32_t block;
+ boolean is_enabled, has_sel_update;
+ int bank_sel;
+};
+
+struct mdp_hist_mgmt {
+ uint32_t block;
+ uint32_t irq_term;
+ uint32_t base;
+ struct completion mdp_hist_comp;
+ struct mutex mdp_hist_mutex;
+ struct mutex mdp_do_hist_mutex;
+ boolean mdp_is_hist_start, mdp_is_hist_data;
+ boolean mdp_is_hist_valid, mdp_is_hist_init;
+ uint8_t frame_cnt, bit_mask, num_bins;
+ struct work_struct mdp_histogram_worker;
+ struct mdp_histogram_data *hist;
+ uint32_t *c0, *c1, *c2;
+ uint32_t *extra_info;
+};
+
+enum {
+ MDP_HIST_MGMT_DMA_P = 0,
+ MDP_HIST_MGMT_DMA_S,
+ MDP_HIST_MGMT_VG_1,
+ MDP_HIST_MGMT_VG_2,
+ MDP_HIST_MGMT_MAX,
+};
+
+extern struct mdp_hist_mgmt *mdp_hist_mgmt_array[];
+
+#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
+#define MDP_DMAP_TERM MDP_DMA2_TERM /* dmap == dma2 */
+#define MDP_PRIM_VSYNC_TERM 0x100
+#define MDP_EXTER_VSYNC_TERM 0x200
+#define MDP_PRIM_RDPTR_TERM 0x400
+#endif
+#define MDP_OVERLAY2_TERM 0x80
+#define MDP_HISTOGRAM_TERM_DMA_P 0x10000
+#define MDP_HISTOGRAM_TERM_DMA_S 0x20000
+#define MDP_HISTOGRAM_TERM_VG_1 0x40000
+#define MDP_HISTOGRAM_TERM_VG_2 0x80000
+#define MDP_VSYNC_TERM 0x1000
+
+#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 MDP_PRIM_RDPTR BIT(8)
+#define TV_OUT_DMA3_START BIT(13)
+#define MDP_HIST_DONE BIT(20)
+
+/* histogram interrupts */
+#define INTR_HIST_DONE BIT(1)
+#define INTR_HIST_RESET_SEQ_DONE BIT(0)
+
+#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
+
+#define MDP_HIST_INTR_STATUS_OFF (0x0014)
+#define MDP_HIST_INTR_CLEAR_OFF (0x0018)
+#define MDP_HIST_INTR_ENABLE_OFF (0x001C)
+
+#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)
+
+#define MDP_DMA_P_HIST_INTR_STATUS (msm_mdp_base + 0x94014)
+#define MDP_DMA_P_HIST_INTR_CLEAR (msm_mdp_base + 0x94018)
+#define MDP_DMA_P_HIST_INTR_ENABLE (msm_mdp_base + 0x9401C)
+#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_clk_ctrl(int on);
+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_vsync_cfg_regs(struct msm_fb_data_type *mfd,
+ boolean first_time);
+void mdp_config_vsync(struct platform_device *pdev,
+ struct msm_fb_data_type *mfd);
+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);
+static inline int mdp4_dsi_cmd_off(struct platform_device *pdev)
+{
+ return 0;
+}
+static inline int mdp4_dsi_video_off(struct platform_device *pdev)
+{
+ return 0;
+}
+static inline int mdp4_lcdc_off(struct platform_device *pdev)
+{
+ return 0;
+}
+static inline int mdp4_dsi_cmd_on(struct platform_device *pdev)
+{
+ return 0;
+}
+static inline int mdp4_dsi_video_on(struct platform_device *pdev)
+{
+ return 0;
+}
+static inline int mdp4_lcdc_on(struct platform_device *pdev)
+{
+ return 0;
+}
+#endif
+
+void set_cont_splashScreen_status(int);
+
+int mdp_hw_cursor_update(struct fb_info *info, struct fb_cursor *cursor);
+#if defined(CONFIG_FB_MSM_OVERLAY) && defined(CONFIG_FB_MSM_MDP40)
+int mdp_hw_cursor_sync_update(struct fb_info *info, struct fb_cursor *cursor);
+#else
+static inline int mdp_hw_cursor_sync_update(struct fb_info *info,
+ struct fb_cursor *cursor)
+{
+ return 0;
+}
+#endif
+
+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(u32 rate);
+int mdp_clk_round_rate(u32 rate);
+
+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);
+#else
+static inline int mdp_bus_scale_update_request(uint32_t index)
+{
+ return 0;
+}
+#endif
+void mdp_dma_vsync_ctrl(int enable);
+void mdp_dma_video_vsync_ctrl(int enable);
+void mdp_dma_lcdc_vsync_ctrl(int enable);
+void mdp3_vsync_irq_enable(int intr, int term);
+void mdp3_vsync_irq_disable(int intr, int term);
+
+#ifdef MDP_HW_VSYNC
+void vsync_clk_prepare_enable(void);
+void vsync_clk_disable_unprepare(void);
+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_histogram_start(struct mdp_histogram_start_req *req);
+int mdp_histogram_stop(struct fb_info *info, uint32_t block);
+int mdp_histogram_ctrl(boolean en, uint32_t block);
+int mdp_histogram_ctrl_all(boolean en);
+int mdp_histogram_block2mgmt(uint32_t block, struct mdp_hist_mgmt **mgmt);
+void mdp_histogram_handle_isr(struct mdp_hist_mgmt *mgmt);
+void __mdp_histogram_kickoff(struct mdp_hist_mgmt *mgmt);
+void __mdp_histogram_reset(struct mdp_hist_mgmt *mgmt);
+unsigned int mdp_check_suspended(void);
+void mdp_footswitch_ctrl(boolean on);
+
+#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 */
+}
+static inline int mdp4_overlay_dsi_state_get(void)
+{
+ return 0;
+}
+static inline void mdp4_iommu_detach(void)
+{
+ /*empty */
+}
+#endif
+
+void mdp_vid_quant_set(void);
+#ifndef CONFIG_FB_MSM_MDP40
+static inline void mdp_dsi_cmd_overlay_suspend(struct msm_fb_data_type *mfd)
+{
+ /* empty */
+}
+static inline int msmfb_overlay_vsync_ctrl(struct fb_info *info,
+ void __user *argp)
+{
+ return 0;
+}
+#endif
+
+int mdp_ppp_v4l2_overlay_set(struct fb_info *info, struct mdp_overlay *req);
+int mdp_ppp_v4l2_overlay_clear(void);
+int mdp_ppp_v4l2_overlay_play(struct fb_info *info,
+ unsigned long srcp0_addr, unsigned long srcp0_size,
+ unsigned long srcp1_addr, unsigned long srcp1_size);
+
+#endif /* MDP_H */
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 32d9085..3e6933e 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -1,44 +1,36 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of Code Aurora nor
- * the names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
+ * 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 SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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
-/*
-#define DEBUG_OVERLAY
-*/
-
-#define MDP4_NONBLOCKING /* enable non blocking ioctl */
+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_dma_data dma_wb_data;
+extern unsigned int mdp_hist_frame_cnt;
+extern struct completion mdp_hist_comp;
+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;
+extern spinlock_t dsi_clk_lock;
+extern u32 mdp_max_clk;
#define MDP4_OVERLAYPROC0_BASE 0x10000
#define MDP4_OVERLAYPROC1_BASE 0x18000
-
-#define MDP_OVERLAY0_TERM 0x20
-#define MDP_OVERLAY1_TERM 0x40
+#define MDP4_OVERLAYPROC2_BASE 0x88000
#define MDP4_VIDEO_BASE 0x20000
#define MDP4_VIDEO_OFF 0x10000
@@ -46,12 +38,25 @@
#define MDP4_RGB_BASE 0x40000
#define MDP4_RGB_OFF 0x10000
+/* chip select controller */
+#define CS_CONTROLLER_0 0x0707ffff
+#define CS_CONTROLLER_1 0x03073f3f
+
+enum {
+ OVERLAY_PERF_LEVEL1 = 1,
+ OVERLAY_PERF_LEVEL2,
+ OVERLAY_PERF_LEVEL3,
+ OVERLAY_PERF_LEVEL4
+};
+
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,
@@ -80,6 +85,18 @@
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)
+#define MDP4_PANEL_WRITEBACK BIT(6)
+
enum {
OVERLAY_MODE_NONE,
OVERLAY_MODE_BLT
@@ -109,44 +126,48 @@
#define INTR_PRIMARY_INTF_UDERRUN BIT(8)
#define INTR_EXTERNAL_VSYNC BIT(9)
#define INTR_EXTERNAL_INTF_UDERRUN BIT(10)
+#define INTR_PRIMARY_RDPTR BIT(11) /* read pointer */
#define INTR_DMA_P_HISTOGRAM BIT(17)
-#define INTR_MDP_HIST_DONE BIT(20) /*DMA_P histogram interrupt*/
-
-/* histogram interrupts */
-#define INTR_HIST_DONE BIT(1)
-#define INTR_HIST_RESET_SEQ_DONE BIT(0)
-
+#define INTR_DMA_S_HISTOGRAM BIT(26)
+#define INTR_OVERLAY2_DONE BIT(30)
#ifdef CONFIG_FB_MSM_OVERLAY
-#define MDP4_ANY_INTR_MASK (INTR_OVERLAY0_DONE| \
- INTR_PRIMARY_INTF_UDERRUN | \
- INTR_DMA_P_HISTOGRAM)
+#define MDP4_ANY_INTR_MASK (INTR_DMA_P_HISTOGRAM | \
+ INTR_DMA_S_HISTOGRAM | \
+ INTR_VG1_HISTOGRAM | \
+ INTR_VG2_HISTOGRAM )
#else
#define MDP4_ANY_INTR_MASK (INTR_DMA_P_DONE| \
- INTR_DMA_P_HISTOGRAM)
+ INTR_DMA_P_HISTOGRAM | \
+ INTR_DMA_S_HISTOGRAM | \
+ INTR_VG1_HISTOGRAM | \
+ INTR_VG2_HISTOGRAM)
#endif
+
enum {
- OVERLAY_PIPE_RGB1,
- OVERLAY_PIPE_RGB2,
OVERLAY_PIPE_VG1, /* video/graphic */
OVERLAY_PIPE_VG2,
+ OVERLAY_PIPE_RGB1,
+ OVERLAY_PIPE_RGB2,
+ OVERLAY_PIPE_RGB3,
+ OVERLAY_PIPE_VG3,
+ OVERLAY_PIPE_VG4,
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 {
+ OVERLAY_TYPE_RGB,
+ OVERLAY_TYPE_VIDEO,
+ OVERLAY_TYPE_BF
+};
enum {
MDP4_MIXER0,
MDP4_MIXER1,
+ MDP4_MIXER2,
MDP4_MIXER_MAX
};
-#define MDP4_MAX_MIXER 2
-
enum {
OVERLAY_PLANE_INTERLEAVED,
OVERLAY_PLANE_PLANAR,
@@ -158,11 +179,11 @@
MDP4_MIXER_STAGE_BASE,
MDP4_MIXER_STAGE0, /* zorder 0 */
MDP4_MIXER_STAGE1, /* zorder 1 */
- MDP4_MIXER_STAGE2 /* zorder 2 */
+ MDP4_MIXER_STAGE2, /* zorder 2 */
+ MDP4_MIXER_STAGE3, /* zorder 3 */
+ MDP4_MIXER_STAGE_MAX
};
-#define MDP4_MAX_STAGE 4
-
enum {
MDP4_FRAME_FORMAT_LINEAR,
MDP4_FRAME_FORMAT_ARGB_TILE,
@@ -211,174 +232,708 @@
#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_SCALE_RGB_ENHANCED (1 << 4)
+#define MDP4_OP_SCALE_RGB_PIXEL_RPT (0 << 3)
+#define MDP4_OP_SCALE_RGB_BILINEAR (1 << 3)
+#define MDP4_OP_SCALE_ALPHA_PIXEL_RPT (0 << 2)
+#define MDP4_OP_SCALE_ALPHA_BILINEAR (1 << 2)
#define MDP4_OP_SCALEY_EN BIT(1)
#define MDP4_OP_SCALEX_EN BIT(0)
+#define MDP4_REV40_UP_SCALING_MAX (8)
+#define MDP4_REV41_OR_LATER_UP_SCALING_MAX (20)
+
#define MDP4_PIPE_PER_MIXER 2
#define MDP4_MAX_PLANE 4
+#define VSYNC_PERIOD 16
+struct mdp4_hsic_regs {
+ int32_t params[NUM_HSIC_PARAM];
+ int32_t conv_matrix[3][3];
+ int32_t pre_limit[6];
+ int32_t post_limit[6];
+ int32_t pre_bias[3];
+ int32_t post_bias[3];
+ int32_t dirty;
+};
+
+struct mdp4_iommu_pipe_info {
+ struct ion_handle *ihdl[MDP4_MAX_PLANE];
+ struct ion_handle *prev_ihdl[MDP4_MAX_PLANE];
+ u8 mark_unmap;
+};
+
+#define IOMMU_FREE_LIST_MAX 32
+
+struct iommu_free_list {
+ int total;
+ int fndx;
+ struct ion_handle *ihdl[IOMMU_FREE_LIST_MAX];
+};
+
+struct blend_cfg {
+ u32 op;
+ u32 bg_alpha;
+ u32 fg_alpha;
+ u32 co3_sel;
+ u32 transp_low0;
+ u32 transp_low1;
+ u32 transp_high0;
+ u32 transp_high1;
+ int solidfill;
+ struct mdp4_overlay_pipe *solidfill_pipe;
+};
struct mdp4_overlay_pipe {
- uint32_t pipe_used;
- uint32_t pipe_type; /* rgb, video/graphic */
- uint32_t pipe_num;
- uint32_t pipe_ndx;
- uint32_t mixer_num; /* which mixer used */
- uint32_t mixer_stage; /* which stage of mixer used */
- uint32_t src_format;
- uint32_t src_width; /* source img width */
- uint32_t src_height; /* source img height */
- uint32_t src_w; /* roi */
- uint32_t src_h; /* roi */
- uint32_t src_x; /* roi */
- uint32_t src_y; /* roi */
- uint32_t dst_w; /* roi */
- uint32_t dst_h; /* roi */
- uint32_t dst_x; /* roi */
- uint32_t dst_y; /* roi */
- uint32_t op_mode;
- uint32_t transp;
- uint32_t blend_op;
- uint32_t phasex_step;
- uint32_t phasey_step;
- uint32_t alpha;
- uint32_t is_fg; /* control alpha & color key */
- uint32_t srcp0_addr; /* interleave, luma */
- uint32_t srcp0_ystride;
- uint32_t srcp1_addr; /* pseudoplanar, chroma plane */
- uint32_t srcp1_ystride;
- uint32_t srcp2_addr; /* planar color 2*/
- uint32_t srcp2_ystride;
- uint32_t srcp3_addr; /* alpha/color 3 */
- uint32_t srcp3_ystride;
- uint32_t fetch_plane;
- uint32_t frame_format; /* video */
- uint32_t chroma_site; /* video */
- uint32_t chroma_sample; /* video */
- uint32_t solid_fill;
- uint32_t vc1_reduce; /* video */
- uint32_t fatch_planes; /* video */
- uint32_t unpack_align_msb;/* 0 to LSB, 1 to MSB */
- uint32_t unpack_tight;/* 0 for loose, 1 for tight */
- uint32_t unpack_count;/* 0 = 1 component, 1 = 2 component ... */
- uint32_t rotated_90; /* has been rotated 90 degree */
- uint32_t bpp; /* byte per pixel */
- uint32_t alpha_enable;/* source has alpha */
+ 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_t a_bit; /* component 3, alpha */
- uint32_t r_bit; /* component 2, R_Cr */
- uint32_t b_bit; /* component 1, B_Cb */
- uint32_t g_bit; /* component 0, G_lumz */
+ 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_t element3; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
- uint32_t element2; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
- uint32_t element1; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
- uint32_t element0; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
- struct completion comp;
-#ifdef CONFIG_FB_MSM_WRITE_BACK
- ulong blt_addr; /* blt mode addr */
- uint32_t blt_cnt;
- uint32_t blt_end;
-#endif
+ 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 */
+ ulong ov_blt_addr; /* blt mode addr */
+ ulong dma_blt_addr; /* blt mode addr */
+ ulong blt_base;
+ ulong blt_offset;
+ uint32 blt_cnt;
+ uint32 blt_changed;
+ uint32 ov_cnt;
+ uint32 dmap_cnt;
+ uint32 dmae_cnt;
+ uint32 blt_end;
+ uint32 blt_ov_koff;
+ uint32 blt_ov_done;
+ uint32 blt_dmap_koff;
+ uint32 blt_dmap_done;
+ uint32 req_clk;
+ uint32 req_bw;
+ uint32 luma_align_size;
+ struct mdp4_hsic_regs hsic_regs;
struct mdp_overlay req_data;
- struct mdp_info *mdp;
+ struct completion comp;
+ struct completion dmas_comp;
+ struct mdp4_iommu_pipe_info iommu;
};
-struct mdp4_pipe_desc {
- uint32_t ref_cnt;
- 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_overlay2;
+ ulong intr_vsync_p; /* Primary interface */
+ ulong intr_underrun_p; /* Primary interface */
+ ulong intr_vsync_e; /* external interface */
+ ulong intr_underrun_e; /* external interface */
+ ulong intr_histogram;
+ ulong intr_rdptr;
+ ulong dsi_mdp_start;
+ ulong dsi_clk_on;
+ ulong dsi_clk_off;
+ ulong intr_dsi;
+ ulong intr_dsi_mdp;
+ ulong intr_dsi_cmd;
+ ulong intr_dsi_err;
+ ulong kickoff_ov0;
+ ulong kickoff_ov1;
+ ulong kickoff_dmap;
+ ulong kickoff_dmae;
+ ulong kickoff_dmas;
+ ulong blt_dsi_cmd; /* blt */
+ ulong blt_dsi_video; /* blt */
+ ulong blt_lcdc; /* blt */
+ ulong blt_dtv; /* blt */
+ ulong blt_mddi; /* blt */
+ ulong overlay_set[MDP4_MIXER_MAX];
+ ulong overlay_unset[MDP4_MIXER_MAX];
+ ulong overlay_play[MDP4_MIXER_MAX];
+ ulong overlay_commit[MDP4_MIXER_MAX];
+ ulong pipe[OVERLAY_PIPE_MAX];
+ ulong wait4vsync0;
+ ulong wait4vsync1;
+ ulong iommu_map;
+ ulong iommu_unmap;
+ ulong iommu_drop;
+ ulong dsi_clkoff;
+ ulong err_mixer;
+ ulong err_zorder;
+ ulong err_size;
+ ulong err_scale;
+ ulong err_format;
+ ulong err_stage;
+ ulong err_play;
+ ulong err_underflow;
};
-#ifdef CONFIG_FB_MSM_WRITE_BACK
-extern spinlock_t mdp_spin_lock;
-extern uint32_t mdp_intr_mask;
-#endif
+struct vsync_update {
+ int update_cnt; /* pipes to be updated */
+ struct completion vsync_comp;
+ struct mdp4_overlay_pipe plist[OVERLAY_PIPE_MAX];
+};
-
-
+struct mdp4_overlay_pipe *mdp4_overlay_ndx2pipe(int ndx);
+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);
-void mdp4_hw_init(struct mdp_info *mdp);
+unsigned is_mdp4_hw_reset(void);
+void mdp4_overlay_cfg_init(void);
+void mdp4_hw_init(void);
void mdp4_isr_read(int);
-void mdp4_clear_lcdc(struct mdp_info *mdp);
-void mdp4_mixer_blend_init(struct mdp_info *mdp, int mixer_num);
-void mdp4_vg_qseed_init(struct mdp_info *mdp, int vg_num);
-void mdp4_vg_csc_mv_setup(struct mdp_info *mdp, int vp_num);
-void mdp4_vg_csc_pre_bv_setup(struct mdp_info *mdp, int vp_num);
-void mdp4_vg_csc_post_bv_setup(struct mdp_info *mdp, int vp_num);
-void mdp4_vg_csc_pre_lv_setup(struct mdp_info *mdp, int vp_num);
-void mdp4_vg_csc_post_lv_setup(struct mdp_info *mdp, int vp_num);
-void mdp4_mixer1_csc_mv_setup(struct mdp_info *mdp);
-void mdp4_mixer1_csc_pre_bv_setup(struct mdp_info *mdp);
-void mdp4_mixer1_csc_post_bv_setup(struct mdp_info *mdp);
-void mdp4_mixer1_csc_pre_lv_setup(struct mdp_info *mdp);
-void mdp4_mixer1_csc_post_lv_setup(struct mdp_info *mdp);
-void mdp4_overlay_format_to_pipe(uint32_t format, struct mdp4_overlay_pipe *pipe);
-uint32_t mdp4_overlay_format(struct mdp4_overlay_pipe *pipe);
-uint32_t mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe);
-uint32_t mdp4_overlay_op_mode(struct mdp4_overlay_pipe *pipe);
+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_setup(int vp_num);
+void mdp4_mixer_csc_setup(uint32 mixer);
+void mdp4_dmap_csc_setup(void);
+void mdp4_vg_csc_update(struct mdp_csc *p);
+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_base_swap(int cndx, struct mdp4_overlay_pipe *pipe);
+void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd);
+
+
+#ifdef CONFIG_FB_MSM_DTV
+void mdp4_overlay_dtv_start(void);
+void mdp4_overlay_dtv_ov_done_push(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe);
+void mdp4_overlay_dtv_wait_for_ov(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe);
+int mdp4_overlay_dtv_set(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe);
+int mdp4_overlay_dtv_unset(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe);
+void mdp4_dmae_done_dtv(void);
+void mdp4_dtv_wait4vsync(int cndx, long long *vtime);
+void mdp4_dtv_vsync_ctrl(int cndx, int enable);
+void mdp4_dtv_base_swap(int cndx, struct mdp4_overlay_pipe *pipe);
+#else
+static inline void mdp4_overlay_dtv_start(void)
+{
+ /* empty */
+}
+static inline void mdp4_overlay_dtv_ov_done_push(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ /* empty */
+}
+static inline void mdp4_overlay_dtv_wait_for_ov(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ /* empty */
+}
+static inline int mdp4_overlay_dtv_set(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ return 0;
+}
+static inline int mdp4_overlay_dtv_unset(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ return 0;
+}
+
+static inline void mdp4_dmae_done_dtv(void)
+{
+ /* empty */
+}
+static inline void mdp4_dtv_wait4vsync(int cndx, long long *vtime)
+{
+ /* empty */
+}
+static inline void mdp4_dtv_vsync_ctrl(int cndx, long long *vtime)
+{
+ /* empty */
+}
+static inline void mdp4_dtv_overlay_blt_start(struct msm_fb_data_type *mfd)
+{
+ return;
+}
+static inline void mdp4_dtv_overlay_blt_stop(struct msm_fb_data_type *mfd)
+{
+ return;
+}
+static inline void mdp4_dtv_base_swap(struct mdp4_overlay_pipe *pipe)
+{
+ /* empty */
+}
+#endif /* CONFIG_FB_MSM_DTV */
+
+void mdp4_dtv_set_black_screen(void);
+
+int mdp4_overlay_dtv_set(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe);
+int mdp4_overlay_dtv_unset(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);
+void mdp4_lcdc_vsync_ctrl(int cndx, int enable);
+void mdp4_overlay0_done_dsi_video(int cndx);
+void mdp4_overlay0_done_dsi_cmd(int cndx);
+void mdp4_primary_rdptr(void);
+void mdp4_dsi_cmd_overlay(struct msm_fb_data_type *mfd);
+int mdp4_overlay_commit(struct fb_info *info, int mixer);
+int mdp4_dsi_video_pipe_commit(void);
+int mdp4_dsi_cmd_pipe_commit(void);
+int mdp4_dsi_cmd_update_cnt(int cndx);
+int mdp4_lcdc_pipe_commit(void);
+int mdp4_dtv_pipe_commit(void);
+void mdp4_dsi_rdptr_init(int cndx);
+void mdp4_dsi_vsync_init(int cndx);
+void mdp4_lcdc_vsync_init(int cndx);
+void mdp4_dtv_vsync_init(int cndx);
+void mdp4_overlay_dsi_state_set(int state);
+int mdp4_overlay_dsi_state_get(void);
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);
+void mdp4_mixer_blend_setup(int mixer);
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);
+void mdp4_mixer_pipe_cleanup(int mixer);
int mdp4_mixer_stage_can_run(struct mdp4_overlay_pipe *pipe);
void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe);
-void mdp4_mddi_overlay(void *priv, uint32_t addr, uint32_t stride,
- uint32_t width, uint32_t height, uint32_t x,
- uint32_t y);
-int mdp4_overlay_format2type(uint32_t format);
+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 mdp_device *mdp_dev, struct fb_info *info, struct mdp_overlay *req);
-int mdp4_overlay_set(struct mdp_device *mdp_dev, struct fb_info *info, struct mdp_overlay *req);
-int mdp4_overlay_unset(struct mdp_device *mdp_dev, struct fb_info *info, int ndx);
-int mdp4_overlay_play(struct mdp_device *mdp_dev, struct fb_info *info, struct msmfb_overlay_data *req,
- struct file **pp_src_file);
-int mdp4_overlay_change_z_order_vg_pipes(struct fb_info *info);
-struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(int ptype, bool usevg);
+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_wait4vsync(struct fb_info *info, long long *vtime);
+int mdp4_overlay_vsync_ctrl(struct fb_info *info, int enable);
+int mdp4_overlay_unset(struct fb_info *info, int ndx);
+int mdp4_overlay_unset_mixer(int mixer);
+int mdp4_overlay_play_wait(struct fb_info *info,
+ struct msmfb_overlay_data *req);
+int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req);
+struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(int ptype, int mixer);
+void mdp4_overlay_dma_commit(int mixer);
+void mdp4_overlay_vsync_commit(struct mdp4_overlay_pipe *pipe);
+void mdp4_mixer_stage_commit(int mixer);
+void mdp4_dsi_cmd_do_update(int cndx, struct mdp4_overlay_pipe *pipe);
+void mdp4_lcdc_pipe_queue(int cndx, struct mdp4_overlay_pipe *pipe);
+void mdp4_dtv_pipe_queue(int cndx, struct mdp4_overlay_pipe *pipe);
void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe);
-void mdp4_overlay_dmap_cfg(struct mdp4_overlay_pipe *pipe, int lcdc);
+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 mdp4_overlay_pipe *pipe, int lcdc);
+void mdp4_overlay_dmae_cfg(struct msm_fb_data_type *mfd, int atv);
void mdp4_overlay_dmae_xy(struct mdp4_overlay_pipe *pipe);
-void mdp4_overlay_dmas_cfg(struct mdp4_overlay_pipe *pipe, int lcdc);
-void mdp4_overlay_dmas_xy(struct mdp4_overlay_pipe *pipe);
-int mdp4_overlay_active(struct mdp_info *mdp, int mixer);
-void mdp4_overlay0_done_lcdc(void);
-void mdp4_overlay0_done_mddi(void);
-void mdp4_dma_s_done_mddi(void);
-void mdp4_mddi_overlay_restore(void);
-void mdp4_mddi_dma_s_kickoff(struct mdp_info *mdp, struct mdp4_overlay_pipe *pipe);
-void mdp4_mddi_overlay_kickoff(struct mdp_info *mdp,
+int mdp4_overlay_pipe_staged(int mixer);
+void mdp4_lcdc_primary_vsyn(void);
+void mdp4_overlay0_done_lcdc(int cndx);
+void mdp4_overlay0_done_mddi(struct mdp_dma_data *dma);
+void mdp4_dma_p_done_mddi(struct mdp_dma_data *dma);
+void mdp4_dmap_done_dsi_cmd(int cndx);
+void mdp4_dmap_done_dsi_video(int cndx);
+void mdp4_dmap_done_lcdc(int cndx);
+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_lcdc_wait4vsync(int cndx, long long *vtime);
+void mdp4_overlay_lcdc_vsync_push(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe);
-void mdp4_rgb_igc_lut_setup(struct mdp_info *mdp, int num);
-void mdp4_vg_igc_lut_setup(struct mdp_info *mdp, int num);
-void mdp4_mixer_gc_lut_setup(struct mdp_info *mdp, int mixer_num);
-void mdp4_fetch_cfg(struct mdp_info *mdp, uint32_t clk, uint32_t pclk);
-uint32_t mdp4_rgb_igc_lut_cvt(uint32_t ndx);
-void mdp_pipe_kickoff(struct mdp_info *mdp, uint32_t term);
+void mdp4_mddi_overlay_dmas_restore(void);
-void mdp4_overlay_status_write(enum mdp4_overlay_status type, bool val);
-bool mdp4_overlay_status_read(enum mdp4_overlay_status type);
-
-#ifdef CONFIG_FB_MSM_WRITE_BACK
-void mdp4_dma_p_done_mddi(void);
-int mdp4_overlay_blt(struct mdp_device *mdp_dev, struct fb_info *info,
- struct msmfb_overlay_blt *req, struct file **pp_src_file);
-void mdp4_mddi_overlay_blt(ulong addr);
-void mdp4_lcdc_overlay_blt(ulong addr);
+#ifndef CONFIG_FB_MSM_MIPI_DSI
+void mdp4_mddi_dma_busy_wait(struct msm_fb_data_type *mfd);
+void mdp4_mddi_overlay_restore(void);
+#else
+static inline void mdp4_mddi_kickoff_video(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ /* empty */
+}
+static inline void mdp4_mddi_dma_busy_wait(struct msm_fb_data_type *mfd)
+{
+ /* empty */
+}
+static inline void mdp4_mddi_blt_dmap_busy_wait(struct msm_fb_data_type *mfd)
+{
+ /* empty */
+}
+static inline void mdp4_mddi_overlay_restore(void)
+{
+ /* empty */
+}
+static inline void mdp4_mddi_overlay_blt_start(struct msm_fb_data_type *mfd)
+{
+ /*empty*/
+}
+static inline void mdp4_mddi_overlay_blt_stop(struct msm_fb_data_type *mfd)
+{
+ /*empty*/
+}
+static inline void mdp4_mddi_overlay_blt_offset(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req)
+{
+ /* empty */
+}
+static inline void mdp4_mddi_overlay_blt(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req)
+{
+ /* empty*/
+}
#endif
+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);
+
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+void mdp4_dsi_cmd_blt_start(struct msm_fb_data_type *mfd);
+void mdp4_dsi_cmd_blt_stop(struct msm_fb_data_type *mfd);
+void mdp4_dsi_video_blt_start(struct msm_fb_data_type *mfd);
+void mdp4_dsi_video_blt_stop(struct msm_fb_data_type *mfd);
+void mdp4_dsi_cmd_overlay_blt(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);
+void mdp4_dsi_video_base_swap(int cndx, struct mdp4_overlay_pipe *pipe);
+
+#ifdef CONFIG_FB_MSM_MDP40
+static inline void mdp3_dsi_cmd_dma_busy_wait(struct msm_fb_data_type *mfd)
+{
+ /* empty */
+}
+#endif
+#else /* CONFIG_FB_MSM_MIPI_DSI */
+int mdp4_mddi_overlay_blt_offset(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req);
+void mdp4_mddi_overlay_blt(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req);
+int mdp4_mddi_overlay_blt_start(struct msm_fb_data_type *mfd);
+int mdp4_mddi_overlay_blt_stop(struct msm_fb_data_type *mfd);
+void mdp4_mddi_blt_dmap_busy_wait(struct msm_fb_data_type *mfd);
+static inline int mdp4_dsi_overlay_blt_start(struct msm_fb_data_type *mfd)
+{
+ return -ENODEV;
+}
+static inline int mdp4_dsi_overlay_blt_stop(struct msm_fb_data_type *mfd)
+{
+ return -ENODEV;
+}
+static inline void mdp4_dsi_video_blt_start(struct msm_fb_data_type *mfd)
+{
+}
+static inline void mdp4_dsi_video_blt_stop(struct msm_fb_data_type *mfd)
+{
+}
+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 void mdp4_dsi_cmd_overlay_blt(
+ struct msm_fb_data_type *mfd, struct msmfb_overlay_blt *req)
+{
+}
+static inline void mdp4_dsi_video_base_swap(int cndx,
+ struct mdp4_overlay_pipe *pipe)
+{
+ /* empty */
+}
+static inline void mdp4_dsi_cmd_blt_start(struct msm_fb_data_type *mfd)
+{
+ /* empty */
+}
+static inline void mdp4_dsi_cmd_blt_stop(struct msm_fb_data_type *mfd)
+{
+ /* empty */
+}
+#endif /* CONFIG_FB_MSM_MIPI_DSI */
+
+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);
+void mdp4_lcdc_overlay_blt_start(struct msm_fb_data_type *mfd);
+void mdp4_lcdc_overlay_blt_stop(struct msm_fb_data_type *mfd);
+void mdp4_dtv_overlay_blt_start(struct msm_fb_data_type *mfd);
+void mdp4_dtv_overlay_blt_stop(struct msm_fb_data_type *mfd);
+void mdp4_overlay_panel_mode(int mixer_num, uint32 mode);
+void mdp4_overlay_panel_mode_unset(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);
+
+
+
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+void mdp_dsi_cmd_overlay_suspend(struct msm_fb_data_type *mfd);
+int mdp4_dsi_cmd_on(struct platform_device *pdev);
+int mdp4_dsi_cmd_off(struct platform_device *pdev);
+int mdp4_dsi_video_off(struct platform_device *pdev);
+int mdp4_dsi_video_on(struct platform_device *pdev);
+void mdp4_primary_vsync_dsi_video(void);
+void mdp4_dsi_cmd_base_swap(int cndx, struct mdp4_overlay_pipe *pipe);
+void mdp4_dsi_cmd_wait4vsync(int cndx, long long *vtime);
+void mdp4_dsi_video_wait4vsync(int cndx, long long *vtime);
+void mdp4_dsi_cmd_pipe_queue(int cndx, struct mdp4_overlay_pipe *pipe);
+void mdp4_dsi_video_pipe_queue(int cndx, struct mdp4_overlay_pipe *pipe);
+void mdp4_dsi_cmd_vsync_ctrl(int cndx, int enable);
+void mdp4_dsi_video_vsync_ctrl(int cndx, int enable);
+#ifdef CONFIG_FB_MSM_MDP303
+static inline void mdp4_dsi_cmd_del_timer(void)
+{
+ /* empty */
+}
+#else /* CONFIG_FB_MSM_MIPI_DSI */
+void mdp4_dsi_cmd_del_timer(void);
+#endif
+#else /* CONFIG_FB_MSM_MIPI_DSI */
+
+static inline int mdp4_dsi_cmd_on(struct platform_device *pdev)
+{
+ return 0;
+}
+static inline int mdp4_dsi_cmd_off(struct platform_device *pdev)
+{
+ return 0;
+}
+static inline int mdp4_dsi_video_on(struct platform_device *pdev)
+{
+ return 0;
+}
+static inline int mdp4_dsi_video_off(struct platform_device *pdev)
+{
+ return 0;
+}
+static inline void mdp4_primary_vsync_dsi_video(void)
+{
+}
+static inline void mdp4_dsi_cmd_base_swap(int cndx,
+ struct mdp4_overlay_pipe *pipe)
+{
+}
+static inline void mdp4_dsi_cmd_wait4vsync(int cndx, long long *vtime)
+{
+}
+static inline void mdp4_dsi_video_wait4vsync(int cndx, long long *vtime)
+{
+}
+static inline void mdp4_dsi_cmd_pipe_queue(int cndx,
+ struct mdp4_overlay_pipe *pipe)
+{
+}
+static inline void mdp4_dsi_video_pipe_queue(int cndx,
+ struct mdp4_overlay_pipe *pipe)
+{
+}
+static inline void mdp4_dsi_cmd_vsync_ctrl(int cndx, int enable)
+{
+}
+static inline void mdp4_dsi_video_vsync_ctrl(int cndx, int enable)
+{
+}
+
+static inline void mdp4_overlay_dsi_video_start(void)
+{
+ /* empty */
+}
+#ifdef CONFIG_FB_MSM_MDP40
+static inline void mdp_dsi_cmd_overlay_suspend(struct msm_fb_data_type *mfd)
+{
+ /* empty */
+}
+#endif
+#endif /* CONFIG_FB_MSM_MIPI_DSI */
+
+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_overlay_panel_3d(int mixer_num, uint32 panel_3d);
+int mdp4_overlay_3d_sbys(struct fb_info *info, struct msmfb_overlay_3d *req);
+void mdp4_dsi_cmd_3d_sbys(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_3d *r3d);
+void mdp4_dsi_video_3d_sbys(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_3d *r3d);
+
+int mdp4_mixer_info(int mixer_num, struct mdp_mixer_info *info);
+
+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);
+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);
+void mdp4_overlay_borderfill_stage_down(struct mdp4_overlay_pipe *pipe);
+
+#ifdef CONFIG_FB_MSM_MDP303
+static inline int mdp4_overlay_borderfill_supported(void)
+{
+ return 0;
+}
+#else
+int mdp4_overlay_borderfill_supported(void);
+#endif
+
+int mdp4_overlay_writeback_on(struct platform_device *pdev);
+int mdp4_overlay_writeback_off(struct platform_device *pdev);
+void mdp4_writeback_overlay(struct msm_fb_data_type *mfd);
+void mdp4_writeback_kickoff_video(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe);
+void mdp4_writeback_dma_busy_wait(struct msm_fb_data_type *mfd);
+void mdp4_overlay1_done_writeback(struct mdp_dma_data *dma);
+void mdp4_dma_e_done_dtv(void);
+
+int mdp4_writeback_start(struct fb_info *info);
+int mdp4_writeback_stop(struct fb_info *info);
+int mdp4_writeback_dequeue_buffer(struct fb_info *info,
+ struct msmfb_data *data);
+int mdp4_writeback_queue_buffer(struct fb_info *info,
+ struct msmfb_data *data);
+void mdp4_writeback_dma_stop(struct msm_fb_data_type *mfd);
+int mdp4_writeback_init(struct fb_info *info);
+int mdp4_writeback_terminate(struct fb_info *info);
+
+uint32_t mdp_block2base(uint32_t block);
+int mdp_hist_lut_config(struct mdp_hist_lut_data *data);
+
+void mdp4_hsic_set(struct mdp4_overlay_pipe *pipe, struct dpp_ctrl *ctrl);
+void mdp4_hsic_update(struct mdp4_overlay_pipe *pipe);
+int mdp4_csc_config(struct mdp_csc_cfg_data *config);
+void mdp4_csc_write(struct mdp_csc_cfg *data, uint32_t base);
+int mdp4_csc_enable(struct mdp_csc_cfg_data *config);
+int mdp4_pcc_cfg(struct mdp_pcc_cfg_data *cfg_ptr);
+int mdp4_argc_cfg(struct mdp_pgc_lut_data *pgc_ptr);
+
+u32 mdp4_allocate_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num);
+void mdp4_init_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num);
+void mdp4_free_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num);
+
+int mdp4_igc_lut_config(struct mdp_igc_lut_data *cfg);
+void mdp4_overlay_iommu_pipe_free(int ndx, int all);
+void mdp4_overlay_iommu_free_list(int mixer, struct ion_handle *ihdl);
+void mdp4_overlay_iommu_unmap_freelist(int mixer);
+void mdp4_overlay_iommu_vsync_cnt(void);
+void mdp4_iommu_unmap(struct mdp4_overlay_pipe *pipe);
+void mdp4_iommu_attach(void);
+void mdp4_iommu_detach(void);
+int mdp4_v4l2_overlay_set(struct fb_info *info, struct mdp_overlay *req,
+ struct mdp4_overlay_pipe **ppipe);
+void mdp4_v4l2_overlay_clear(struct mdp4_overlay_pipe *pipe);
+int mdp4_v4l2_overlay_play(struct fb_info *info, struct mdp4_overlay_pipe *pipe,
+ unsigned long srcp0_addr, unsigned long srcp1_addr,
+ unsigned long srcp2_addr);
+
+int mdp4_overlay_mdp_pipe_req(struct mdp4_overlay_pipe *pipe,
+ struct msm_fb_data_type *mfd);
+int mdp4_overlay_mdp_perf_req(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *plist);
+void mdp4_overlay_mdp_perf_upd(struct msm_fb_data_type *mfd, int flag);
#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..bd0ce2f
--- /dev/null
+++ b/drivers/video/msm/mdp4_dtv.c
@@ -0,0 +1,327 @@
+/* Copyright (c) 2010-2012, 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 <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_unprepare(hdmi_clk);
+ if (mdp_tv_clk)
+ clk_disable_unprepare(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_unprepare(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;
+
+ if (panel_pixclock_freq > 58000000)
+ /* pm_qos_rate should be in Khz */
+ pm_qos_rate = panel_pixclock_freq / 1000 ;
+ else
+ pm_qos_rate = 58000;
+ 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_prepare_enable(ebi1_clk);
+ }
+#endif
+
+ 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);
+
+ 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);
+ mfd->panel_info.clk_rate = mfd->fbi->var.pixclock;
+ clk_prepare_enable(hdmi_clk);
+ clk_reset(hdmi_clk, CLK_RESET_ASSERT);
+ udelay(20);
+ clk_reset(hdmi_clk, CLK_RESET_DEASSERT);
+
+ if (mdp_tv_clk)
+ clk_prepare_enable(mdp_tv_clk);
+
+ 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;
+#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(&pdev->dev, "mem_clk");
+ if (IS_ERR(ebi1_clk)) {
+ ebi1_clk = NULL;
+ pr_warning("%s: Couldn't get ebi1 clock\n", __func__);
+ }
+#endif
+ tv_src_clk = clk_get(&pdev->dev, "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(&pdev->dev, "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(&pdev->dev, "mdp_clk");
+ if (IS_ERR(mdp_tv_clk))
+ mdp_tv_clk = NULL;
+
+ 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;
+ if (hdmi_prim_display)
+ 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;
+
+ /*
+ * 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)
+{
+ return dtv_register_driver();
+}
+
+module_init(dtv_driver_init);
diff --git a/drivers/video/msm/mdp4_hsic.c b/drivers/video/msm/mdp4_hsic.c
new file mode 100644
index 0000000..5735f45
--- /dev/null
+++ b/drivers/video/msm/mdp4_hsic.c
@@ -0,0 +1,534 @@
+/* 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/types.h>
+#include <linux/msm_mdp.h>
+#include "mdp.h"
+#include "mdp4.h"
+
+/* Definitions */
+#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
+#define MDP_VG1_BASE (MDP_BASE + MDP4_VIDEO_BASE)
+
+#define MDP_VG1_CSC_MVn(n) (MDP_VG1_BASE + MDP4_CSC_MV_OFF + 4 * (n))
+#define MDP_VG1_CSC_PRE_LVn(n) (MDP_VG1_BASE + MDP4_CSC_PRE_LV_OFF + 4 * (n))
+#define MDP_VG1_CSC_POST_LVn(n) (MDP_VG1_BASE + MDP4_CSC_POST_LV_OFF + 4 * (n))
+#define MDP_VG1_CSC_PRE_BVn(n) (MDP_VG1_BASE + MDP4_CSC_PRE_BV_OFF + 4 * (n))
+#define MDP_VG1_CSC_POST_BVn(n) (MDP_VG1_BASE + MDP4_CSC_POST_BV_OFF + 4 * (n))
+
+#define Q16 (16)
+#define Q16_ONE (1 << Q16)
+
+#define Q16_VALUE(x) ((int32_t)((uint32_t)x << Q16))
+#define Q16_PERCENT_VALUE(x, n) ((int32_t)( \
+ div_s64(((int64_t)x * (int64_t)Q16_ONE), n)))
+
+#define Q16_WHOLE(x) ((int32_t)(x >> 16))
+#define Q16_FRAC(x) ((int32_t)(x & 0xFFFF))
+#define Q16_S1Q16_MUL(x, y) (((x >> 1) * (y >> 1)) >> 14)
+
+#define Q16_MUL(x, y) ((int32_t)((((int64_t)x) * ((int64_t)y)) >> Q16))
+#define Q16_NEGATE(x) (0 - (x))
+
+/*
+ * HSIC Control min/max values
+ * These settings are based on the maximum/minimum allowed modifications to
+ * HSIC controls for layer and display color. Allowing too much variation in
+ * the CSC block will result in color clipping resulting in unwanted color
+ * shifts.
+ */
+#define TRIG_MAX Q16_VALUE(128)
+#define CON_SAT_MAX Q16_VALUE(128)
+#define INTENSITY_MAX (Q16_VALUE(2047) >> 12)
+
+#define HUE_MAX Q16_VALUE(100)
+#define HUE_MIN Q16_VALUE(-100)
+#define HUE_DEF Q16_VALUE(0)
+
+#define SAT_MAX Q16_VALUE(100)
+#define SAT_MIN Q16_VALUE(-100)
+#define SAT_DEF CON_SAT_MAX
+
+#define CON_MAX Q16_VALUE(100)
+#define CON_MIN Q16_VALUE(-100)
+#define CON_DEF CON_SAT_MAX
+
+#define INTEN_MAX Q16_VALUE(100)
+#define INTEN_MIN Q16_VALUE(-100)
+#define INTEN_DEF Q16_VALUE(0)
+
+enum {
+ DIRTY,
+ GENERATED,
+ CLEAN
+};
+
+/* local vars*/
+static int32_t csc_matrix_tab[3][3] = {
+ {0x00012a00, 0x00000000, 0x00019880},
+ {0x00012a00, 0xffff9b80, 0xffff3000},
+ {0x00012a00, 0x00020480, 0x00000000}
+};
+
+static int32_t csc_yuv2rgb_conv_tab[3][3] = {
+ {0x00010000, 0x00000000, 0x000123cb},
+ {0x00010000, 0xffff9af9, 0xffff6b5e},
+ {0x00010000, 0x00020838, 0x00000000}
+};
+
+static int32_t csc_rgb2yuv_conv_tab[3][3] = {
+ {0x00004c8b, 0x00009645, 0x00001d2f},
+ {0xffffda56, 0xffffb60e, 0x00006f9d},
+ {0x00009d70, 0xffff7c2a, 0xffffe666}
+};
+
+static uint32_t csc_pre_bv_tab[3] = {0xfffff800, 0xffffc000, 0xffffc000};
+static uint32_t csc_post_bv_tab[3] = {0x00000000, 0x00000000, 0x00000000};
+
+static uint32_t csc_pre_lv_tab[6] = {0x00000000, 0x00007f80, 0x00000000,
+ 0x00007f80, 0x00000000, 0x00007f80};
+static uint32_t csc_post_lv_tab[6] = {0x00000000, 0x00007f80, 0x00000000,
+ 0x00007f80, 0x00000000, 0x00007f80};
+
+/* Lookup table for Sin/Cos lookup - Q16*/
+static const int32_t trig_lut[65] = {
+ 0x00000000, /* sin((2*M_PI/256) * 0x00);*/
+ 0x00000648, /* sin((2*M_PI/256) * 0x01);*/
+ 0x00000C90, /* sin((2*M_PI/256) * 0x02);*/
+ 0x000012D5,
+ 0x00001918,
+ 0x00001F56,
+ 0x00002590,
+ 0x00002BC4,
+ 0x000031F1,
+ 0x00003817,
+ 0x00003E34,
+ 0x00004447,
+ 0x00004A50,
+ 0x0000504D,
+ 0x0000563E,
+ 0x00005C22,
+ 0x000061F8,
+ 0x000067BE,
+ 0x00006D74,
+ 0x0000731A,
+ 0x000078AD,
+ 0x00007E2F,
+ 0x0000839C,
+ 0x000088F6,
+ 0x00008E3A,
+ 0x00009368,
+ 0x00009880,
+ 0x00009D80,
+ 0x0000A268,
+ 0x0000A736,
+ 0x0000ABEB,
+ 0x0000B086,
+ 0x0000B505,
+ 0x0000B968,
+ 0x0000BDAF,
+ 0x0000C1D8,
+ 0x0000C5E4,
+ 0x0000C9D1,
+ 0x0000CD9F,
+ 0x0000D14D,
+ 0x0000D4DB,
+ 0x0000D848,
+ 0x0000DB94,
+ 0x0000DEBE,
+ 0x0000E1C6,
+ 0x0000E4AA,
+ 0x0000E768,
+ 0x0000EA0A,
+ 0x0000EC83,
+ 0x0000EED9,
+ 0x0000F109,
+ 0x0000F314,
+ 0x0000F4FA,
+ 0x0000F6BA,
+ 0x0000F854,
+ 0x0000F9C8,
+ 0x0000FB15,
+ 0x0000FC3B,
+ 0x0000FD3B,
+ 0x0000FE13,
+ 0x0000FEC4,
+ 0x0000FF4E,
+ 0x0000FFB1,
+ 0x0000FFEC,
+ 0x00010000, /* sin((2*M_PI/256) * 0x40);*/
+};
+
+void trig_values_q16(int32_t deg, int32_t *cos, int32_t *sin)
+{
+ int32_t angle;
+ int32_t quad, anglei, anglef;
+ int32_t v0 = 0, v1 = 0;
+ int32_t t1, t2;
+
+ /*
+ * Scale the angle so that 256 is one complete revolution and mask it
+ * to this domain
+ * NOTE: 0xB60B == 256/360
+ */
+ angle = Q16_MUL(deg, 0xB60B) & 0x00FFFFFF;
+
+ /* Obtain a quadrant number, integer, and fractional part */
+ quad = angle >> 22;
+ anglei = (angle >> 16) & 0x3F;
+ anglef = angle & 0xFFFF;
+
+ /*
+ * Using the integer part, obtain the lookup table entry and its
+ * complement. Using the quadrant, swap and negate these as
+ * necessary.
+ * (The values and all derivatives of sine and cosine functions
+ * can be derived from these values)
+ */
+ switch (quad) {
+ case 0x0:
+ v0 += trig_lut[anglei];
+ v1 += trig_lut[0x40-anglei];
+ break;
+
+ case 0x1:
+ v0 += trig_lut[0x40-anglei];
+ v1 -= trig_lut[anglei];
+ break;
+
+ case 0x2:
+ v0 -= trig_lut[anglei];
+ v1 -= trig_lut[0x40-anglei];
+ break;
+
+ case 0x3:
+ v0 -= trig_lut[0x40-anglei];
+ v1 += trig_lut[anglei];
+ break;
+ }
+
+ /*
+ * Multiply the fractional part by 2*PI/256 to move it from lookup
+ * table units to radians, giving us the coefficient for first
+ * derivatives.
+ */
+ t1 = Q16_S1Q16_MUL(anglef, 0x0648);
+
+ /*
+ * Square this and divide by 2 to get the coefficient for second
+ * derivatives
+ */
+ t2 = Q16_S1Q16_MUL(t1, t1) >> 1;
+
+ *sin = v0 + Q16_S1Q16_MUL(v1, t1) - Q16_S1Q16_MUL(v0, t2);
+
+ *cos = v1 - Q16_S1Q16_MUL(v0, t1) - Q16_S1Q16_MUL(v1, t2);
+}
+
+/* Convert input Q16 value to s4.9 */
+int16_t convert_q16_s49(int32_t q16Value)
+{ /* Top half is the whole number, Bottom half is fractional portion*/
+ int16_t whole = Q16_WHOLE(q16Value);
+ int32_t fraction = Q16_FRAC(q16Value);
+
+ /* Clamp whole to 3 bits */
+ if (whole > 7)
+ whole = 7;
+ else if (whole < -7)
+ whole = -7;
+
+ /* Reduce fraction to 9 bits. */
+ fraction = (fraction<<9)>>Q16;
+
+ return (int16_t) ((int16_t)whole<<9) | ((int16_t)fraction);
+}
+
+/* Convert input Q16 value to uint16 */
+int16_t convert_q16_int16(int32_t val)
+{
+ int32_t rounded;
+
+ if (val >= 0) {
+ /* Add 0.5 */
+ rounded = val + (Q16_ONE>>1);
+ } else {
+ /* Subtract 0.5 */
+ rounded = val - (Q16_ONE>>1);
+ }
+
+ /* Truncate rounded value */
+ return (int16_t)(rounded>>Q16);
+}
+
+/*
+ * norm_q16
+ * Return a Q16 value represeting a normalized value
+ *
+ * value -100% 0% +100%
+ * |-----------------|----------------|
+ * ^ ^ ^
+ * q16MinValue q16DefaultValue q16MaxValue
+ *
+ */
+int32_t norm_q16(int32_t value, int32_t min, int32_t default_val, int32_t max,
+ int32_t range)
+{
+ int32_t diff, perc, mul, result;
+
+ if (0 == value) {
+ result = default_val;
+ } else if (value > 0) {
+ /* value is between 0% and +100% represent 1.0 -> QRange Max */
+ diff = range;
+ perc = Q16_PERCENT_VALUE(value, max);
+ mul = Q16_MUL(perc, diff);
+ result = default_val + mul;
+ } else {
+ /* if (value <= 0) */
+ diff = -range;
+ perc = Q16_PERCENT_VALUE(-value, -min);
+ mul = Q16_MUL(perc, diff);
+ result = default_val + mul;
+ }
+ return result;
+}
+
+void matrix_mul_3x3(int32_t dest[][3], int32_t a[][3], int32_t b[][3])
+{
+ int32_t i, j, k;
+ int32_t tmp[3][3];
+
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j < 3; j++) {
+ tmp[i][j] = 0;
+ for (k = 0; k < 3; k++)
+ tmp[i][j] += Q16_MUL(a[i][k], b[k][j]);
+ }
+ }
+
+ /* in case dest = a or b*/
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j < 3; j++)
+ dest[i][j] = tmp[i][j];
+ }
+}
+
+#define CONVERT(x) (x)/*convert_q16_s49((x))*/
+void pr_params(struct mdp4_hsic_regs *regs)
+{
+ int i;
+ if (regs) {
+ for (i = 0; i < NUM_HSIC_PARAM; i++) {
+ pr_info("\t: hsic->params[%d] = 0x%08x [raw = 0x%08x]\n",
+ i, CONVERT(regs->params[i]), regs->params[i]);
+ }
+ }
+}
+
+void pr_3x3_matrix(int32_t in[][3])
+{
+ pr_info("\t[0x%08x\t0x%08x\t0x%08x]\n", CONVERT(in[0][0]),
+ CONVERT(in[0][1]), CONVERT(in[0][2]));
+ pr_info("\t[0x%08x\t0x%08x\t0x%08x]\n", CONVERT(in[1][0]),
+ CONVERT(in[1][1]), CONVERT(in[1][2]));
+ pr_info("\t[0x%08x\t0x%08x\t0x%08x]\n", CONVERT(in[2][0]),
+ CONVERT(in[2][1]), CONVERT(in[2][2]));
+}
+
+void _hsic_get(struct mdp4_hsic_regs *regs, int32_t type, int8_t *val)
+{
+ if (type < 0 || type >= NUM_HSIC_PARAM)
+ BUG_ON(-EINVAL);
+ *val = regs->params[type];
+ pr_info("%s: getting params[%d] = %d\n", __func__, type, *val);
+}
+
+void _hsic_set(struct mdp4_hsic_regs *regs, int32_t type, int8_t val)
+{
+ if (type < 0 || type >= NUM_HSIC_PARAM)
+ BUG_ON(-EINVAL);
+
+ if (regs->params[type] != Q16_VALUE(val)) {
+ regs->params[type] = Q16_VALUE(val);
+ regs->dirty = DIRTY;
+ }
+}
+
+void _hsic_generate_csc_matrix(struct mdp4_overlay_pipe *pipe)
+{
+ int i, j;
+ int32_t sin, cos;
+
+ int32_t hue_matrix[3][3];
+ int32_t con_sat_matrix[3][3];
+ struct mdp4_hsic_regs *regs = &(pipe->hsic_regs);
+
+ memset(con_sat_matrix, 0x0, sizeof(con_sat_matrix));
+ memset(hue_matrix, 0x0, sizeof(hue_matrix));
+
+ /*
+ * HSIC control require matrix multiplication of these two tables
+ * [T 0 0][1 0 0] T = Contrast C=Cos(Hue)
+ * [0 S 0][0 C -N] S = Saturation N=Sin(Hue)
+ * [0 0 S][0 N C]
+ */
+
+ con_sat_matrix[0][0] = norm_q16(regs->params[HSIC_CON], CON_MIN,
+ CON_DEF, CON_MAX, CON_SAT_MAX);
+ con_sat_matrix[1][1] = norm_q16(regs->params[HSIC_SAT], SAT_MIN,
+ SAT_DEF, SAT_MAX, CON_SAT_MAX);
+ con_sat_matrix[2][2] = con_sat_matrix[1][1];
+
+ hue_matrix[0][0] = TRIG_MAX;
+
+ trig_values_q16(norm_q16(regs->params[HSIC_HUE], HUE_MIN, HUE_DEF,
+ HUE_MAX, TRIG_MAX), &cos, &sin);
+
+ cos = Q16_MUL(cos, TRIG_MAX);
+ sin = Q16_MUL(sin, TRIG_MAX);
+
+ hue_matrix[1][1] = cos;
+ hue_matrix[2][2] = cos;
+ hue_matrix[2][1] = sin;
+ hue_matrix[1][2] = Q16_NEGATE(sin);
+
+ /* Generate YUV CSC matrix */
+ matrix_mul_3x3(regs->conv_matrix, con_sat_matrix, hue_matrix);
+
+ if (!(pipe->op_mode & MDP4_OP_SRC_DATA_YCBCR)) {
+ /* Convert input RGB to YUV then apply CSC matrix */
+ pr_info("Pipe %d, has RGB input\n", pipe->pipe_num);
+ matrix_mul_3x3(regs->conv_matrix, regs->conv_matrix,
+ csc_rgb2yuv_conv_tab);
+ }
+
+ /* Normalize the matrix */
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j < 3; j++)
+ regs->conv_matrix[i][j] = (regs->conv_matrix[i][j]>>14);
+ }
+
+ /* Multiply above result by current csc table */
+ matrix_mul_3x3(regs->conv_matrix, regs->conv_matrix, csc_matrix_tab);
+
+ if (!(pipe->op_mode & MDP4_OP_SRC_DATA_YCBCR)) {
+ /*HACK:only "works"for src side*/
+ /* Convert back to RGB */
+ pr_info("Pipe %d, has RGB output\n", pipe->pipe_num);
+ matrix_mul_3x3(regs->conv_matrix, csc_yuv2rgb_conv_tab,
+ regs->conv_matrix);
+ }
+
+ /* Update clamps pre and post. */
+ /* TODO: different tables for different color formats? */
+ for (i = 0; i < 6; i++) {
+ regs->pre_limit[i] = csc_pre_lv_tab[i];
+ regs->post_limit[i] = csc_post_lv_tab[i];
+ }
+
+ /* update bias values, pre and post */
+ for (i = 0; i < 3; i++) {
+ regs->pre_bias[i] = csc_pre_bv_tab[i];
+ regs->post_bias[i] = csc_post_bv_tab[i] +
+ norm_q16(regs->params[HSIC_INT],
+ INTEN_MIN, INTEN_DEF, INTEN_MAX, INTENSITY_MAX);
+ }
+
+ regs->dirty = GENERATED;
+}
+
+void _hsic_update_mdp(struct mdp4_overlay_pipe *pipe)
+{
+ struct mdp4_hsic_regs *regs = &(pipe->hsic_regs);
+ int i, j, k;
+
+ uint32_t *csc_mv;
+ uint32_t *pre_lv;
+ uint32_t *post_lv;
+ uint32_t *pre_bv;
+ uint32_t *post_bv;
+
+ switch (pipe->pipe_num) {
+ case OVERLAY_PIPE_VG2:
+ csc_mv = (uint32_t *) (MDP_VG1_CSC_MVn(0) +
+ MDP4_VIDEO_OFF);
+ pre_lv = (uint32_t *) (MDP_VG1_CSC_PRE_LVn(0) +
+ MDP4_VIDEO_OFF);
+ post_lv = (uint32_t *) (MDP_VG1_CSC_POST_LVn(0) +
+ MDP4_VIDEO_OFF);
+ pre_bv = (uint32_t *) (MDP_VG1_CSC_PRE_BVn(0) +
+ MDP4_VIDEO_OFF);
+ post_bv = (uint32_t *) (MDP_VG1_CSC_POST_BVn(0) +
+ MDP4_VIDEO_OFF);
+ break;
+ case OVERLAY_PIPE_VG1:
+ default:
+ csc_mv = (uint32_t *) MDP_VG1_CSC_MVn(0);
+ pre_lv = (uint32_t *) MDP_VG1_CSC_PRE_LVn(0);
+ post_lv = (uint32_t *) MDP_VG1_CSC_POST_LVn(0);
+ pre_bv = (uint32_t *) MDP_VG1_CSC_PRE_BVn(0);
+ post_bv = (uint32_t *) MDP_VG1_CSC_POST_BVn(0);
+ break;
+ }
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j < 3; j++) {
+ k = (3*i) + j;
+ MDP_OUTP(csc_mv + k, convert_q16_s49(
+ regs->conv_matrix[i][j]));
+ }
+ }
+
+ for (i = 0; i < 6; i++) {
+ MDP_OUTP(pre_lv + i, convert_q16_s49(regs->pre_limit[i]));
+ MDP_OUTP(post_lv + i, convert_q16_s49(regs->post_limit[i]));
+ }
+
+ for (i = 0; i < 3; i++) {
+ MDP_OUTP(pre_bv + i, convert_q16_s49(regs->pre_bias[i]));
+ MDP_OUTP(post_bv + i, convert_q16_s49(regs->post_bias[i]));
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ regs->dirty = CLEAN;
+}
+
+void mdp4_hsic_get(struct mdp4_overlay_pipe *pipe, struct dpp_ctrl *ctrl)
+{
+ int i;
+ for (i = 0; i < NUM_HSIC_PARAM; i++)
+ _hsic_get(&(pipe->hsic_regs), i, &(ctrl->hsic_params[i]));
+}
+
+void mdp4_hsic_set(struct mdp4_overlay_pipe *pipe, struct dpp_ctrl *ctrl)
+{
+ int i;
+ for (i = 0; i < NUM_HSIC_PARAM; i++)
+ _hsic_set(&(pipe->hsic_regs), i, ctrl->hsic_params[i]);
+
+ if (pipe->hsic_regs.dirty == DIRTY)
+ _hsic_generate_csc_matrix(pipe);
+}
+
+void mdp4_hsic_update(struct mdp4_overlay_pipe *pipe)
+{
+ if (pipe->hsic_regs.dirty == GENERATED)
+ _hsic_update_mdp(pipe);
+}
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 9f2c77a..b8cde41 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -1,57 +1,13 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of Code Aurora Forum nor
- * the names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
+ * 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.
*
- * Alternatively, provided that this notice is retained in full, this software
- * may be relicensed by the recipient under the terms of the GNU General Public
- * License version 2 ("GPL") and only version 2, in which case the provisions of
- * the GPL apply INSTEAD OF those given above. If the recipient relicenses the
- * software under the GPL, then the identification text in the MODULE_LICENSE
- * macro must be changed to reflect "GPLv2" instead of "Dual BSD/GPL". Once a
- * recipient changes the license terms to the GPL, subsequent recipients shall
- * not relicense under alternate licensing terms, including the BSD or dual
- * BSD/GPL terms. In addition, the following license statement immediately
- * below and between the words START and END shall also then apply when this
- * software is relicensed under the GPL:
- *
- * START
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * END
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
*
*/
@@ -65,6 +21,8 @@
#include <linux/hrtimer.h>
#include <linux/clk.h>
#include <mach/hardware.h>
+#include <mach/iommu_domains.h>
+#include <mach/iommu.h>
#include <linux/io.h>
#include <linux/debugfs.h>
#include <linux/fb.h>
@@ -77,25 +35,30 @@
#include <linux/semaphore.h>
#include <linux/uaccess.h>
#include <linux/mutex.h>
-#include <linux/syscalls.h>
-#include <mach/debug_display.h>
-#include <mach/msm_fb.h>
-
-
-#include "mdp_hw.h"
+#include <linux/msm_kgsl.h>
+#include "mdp.h"
+#include "msm_fb.h"
#include "mdp4.h"
-#define OVERLAY_UPDATE_SCREEN 6 /*Refer to user_data field in struct mdp_overlay*/
-#define OVERLAY_UPDATE_SCREEN_EN 1
-#define OVERLAY_UPDATE_SCREEN_DIS 0
-
-static int z_order_change = 0;
+#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];
+ struct mdp4_overlay_pipe plist[OVERLAY_PIPE_MAX];
+ struct mdp4_overlay_pipe *stage[MDP4_MIXER_MAX][MDP4_MIXER_STAGE_MAX];
+ struct mdp4_overlay_pipe *baselayer[MDP4_MIXER_MAX];
+ struct blend_cfg blend[MDP4_MIXER_MAX][MDP4_MIXER_STAGE_MAX];
+ uint32 mixer_cfg[MDP4_MIXER_MAX];
+ uint32 flush[MDP4_MIXER_MAX];
+ struct iommu_free_list iommu_free[MDP4_MIXER_MAX];
+ uint32 cs_controller;
+ uint32 hw_version;
+ uint32 panel_3d;
+ uint32 panel_mode;
+ uint32 mixer0_played;
+ uint32 mixer1_played;
+ uint32 mixer2_played;
} mdp4_overlay_db = {
+ .cs_controller = CS_CONTROLLER_0,
.plist = {
{
.pipe_type = OVERLAY_TYPE_RGB,
@@ -108,31 +71,236 @@
.pipe_ndx = 2,
},
{
- .pipe_type = OVERLAY_TYPE_RGB, /* shared */
+ .pipe_type = OVERLAY_TYPE_VIDEO,
.pipe_num = OVERLAY_PIPE_VG1,
.pipe_ndx = 3,
- .pipe_used = 1, /* mark used to NOT shared */
},
{
- .pipe_type = OVERLAY_TYPE_RGB, /* shared */
+ .pipe_type = OVERLAY_TYPE_VIDEO,
.pipe_num = OVERLAY_PIPE_VG2,
.pipe_ndx = 4,
},
{
- .pipe_type = OVERLAY_TYPE_VIDEO, /* shared */
- .pipe_num = OVERLAY_PIPE_VG1,
+ .pipe_type = OVERLAY_TYPE_BF,
+ .pipe_num = OVERLAY_PIPE_RGB3,
.pipe_ndx = 5,
+ .mixer_num = MDP4_MIXER0,
},
{
- .pipe_type = OVERLAY_TYPE_VIDEO, /* shared */
- .pipe_num = OVERLAY_PIPE_VG2,
+ .pipe_type = OVERLAY_TYPE_BF,
+ .pipe_num = OVERLAY_PIPE_VG3,
.pipe_ndx = 6,
- }
- }
+ .mixer_num = MDP4_MIXER1,
+ },
+ {
+ .pipe_type = OVERLAY_TYPE_BF,
+ .pipe_num = OVERLAY_PIPE_VG4,
+ .pipe_ndx = 7,
+ .mixer_num = MDP4_MIXER2,
+ },
+ },
};
+static DEFINE_MUTEX(iommu_mutex);
static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db;
+struct mdp4_overlay_perf {
+ u32 mdp_clk_rate;
+ u32 use_ov0_blt;
+ u32 use_ov1_blt;
+ u32 mdp_bw;
+};
+
+struct mdp4_overlay_perf perf_request = {
+ .mdp_bw = OVERLAY_PERF_LEVEL4,
+};
+struct mdp4_overlay_perf perf_current = {
+ .mdp_bw = OVERLAY_PERF_LEVEL4,
+};
+
+static struct ion_client *display_iclient;
+
+
+/*
+ * mdp4_overlay_iommu_unmap_freelist()
+ * mdp4_overlay_iommu_2freelist()
+ * mdp4_overlay_iommu_pipe_free()
+ * above three functiosns need to be called from same thread and
+ * in order so that no mutex are needed.
+ */
+void mdp4_overlay_iommu_unmap_freelist(int mixer)
+{
+ int i;
+ struct ion_handle *ihdl;
+ struct iommu_free_list *flist;
+
+ mutex_lock(&iommu_mutex);
+ flist = &ctrl->iommu_free[mixer];
+ if (flist->total == 0) {
+ mutex_unlock(&iommu_mutex);
+ return;
+ }
+ for (i = 0; i < IOMMU_FREE_LIST_MAX; i++) {
+ ihdl = flist->ihdl[i];
+ if (ihdl == NULL)
+ continue;
+ pr_debug("%s: mixer=%d i=%d ihdl=0x%p\n", __func__,
+ mixer, i, ihdl);
+ ion_unmap_iommu(display_iclient, ihdl, DISPLAY_DOMAIN,
+ GEN_POOL);
+ mdp4_stat.iommu_unmap++;
+ pr_debug("%s: map=%d unmap=%d drop=%d\n", __func__,
+ (int)mdp4_stat.iommu_map, (int)mdp4_stat.iommu_unmap,
+ (int)mdp4_stat.iommu_drop);
+ ion_free(display_iclient, ihdl);
+ flist->ihdl[i] = NULL;
+ }
+
+ flist->fndx = 0;
+ flist->total = 0;
+ mutex_unlock(&iommu_mutex);
+}
+
+void mdp4_overlay_iommu_2freelist(int mixer, struct ion_handle *ihdl)
+{
+ struct iommu_free_list *flist;
+
+ flist = &ctrl->iommu_free[mixer];
+ if (flist->fndx >= IOMMU_FREE_LIST_MAX) {
+ pr_err("%s: Error, mixer=%d iommu fndx=%d\n",
+ __func__, mixer, flist->fndx);
+ mdp4_stat.iommu_drop++;
+ return;
+ }
+
+ pr_debug("%s: add mixer=%d fndx=%d ihdl=0x%p\n", __func__,
+ mixer, flist->fndx, ihdl);
+
+ flist->total++;
+ flist->ihdl[flist->fndx++] = ihdl;
+}
+
+void mdp4_overlay_iommu_pipe_free(int ndx, int all)
+{
+ struct mdp4_overlay_pipe *pipe;
+ struct mdp4_iommu_pipe_info *iom;
+ int plane, mixer;
+
+ pipe = mdp4_overlay_ndx2pipe(ndx);
+ if (pipe == NULL)
+ return;
+
+ mutex_lock(&iommu_mutex);
+ mixer = pipe->mixer_num;
+ iom = &pipe->iommu;
+ pr_debug("%s: mixer=%d ndx=%d all=%d\n", __func__,
+ mixer, pipe->pipe_ndx, all);
+ for (plane = 0; plane < MDP4_MAX_PLANE; plane++) {
+ if (iom->prev_ihdl[plane]) {
+ mdp4_overlay_iommu_2freelist(mixer,
+ iom->prev_ihdl[plane]);
+ iom->prev_ihdl[plane] = NULL;
+ }
+ if (all && iom->ihdl[plane]) {
+ mdp4_overlay_iommu_2freelist(mixer, iom->ihdl[plane]);
+ iom->ihdl[plane] = NULL;
+ }
+ }
+ mutex_unlock(&iommu_mutex);
+}
+
+int mdp4_overlay_iommu_map_buf(int mem_id,
+ struct mdp4_overlay_pipe *pipe, unsigned int plane,
+ unsigned long *start, unsigned long *len,
+ struct ion_handle **srcp_ihdl)
+{
+ struct mdp4_iommu_pipe_info *iom;
+
+ if (!display_iclient)
+ return -EINVAL;
+
+ *srcp_ihdl = ion_import_fd(display_iclient, mem_id);
+ if (IS_ERR_OR_NULL(*srcp_ihdl)) {
+ pr_err("ion_import_dma_buf() failed\n");
+ return PTR_ERR(*srcp_ihdl);
+ }
+ pr_debug("%s(): ion_hdl %p, ion_buf %p\n", __func__, *srcp_ihdl,
+ ion_share(display_iclient, *srcp_ihdl));
+ pr_debug("mixer %u, pipe %u, plane %u\n", pipe->mixer_num,
+ pipe->pipe_ndx, plane);
+ if (ion_map_iommu(display_iclient, *srcp_ihdl,
+ DISPLAY_DOMAIN, GEN_POOL, SZ_4K, 0, start,
+ len, 0, ION_IOMMU_UNMAP_DELAYED)) {
+ ion_free(display_iclient, *srcp_ihdl);
+ pr_err("ion_map_iommu() failed\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&iommu_mutex);
+ iom = &pipe->iommu;
+ if (iom->prev_ihdl[plane]) {
+ mdp4_overlay_iommu_2freelist(pipe->mixer_num,
+ iom->prev_ihdl[plane]);
+ mdp4_stat.iommu_drop++;
+ pr_err("%s: dropped, ndx=%d plane=%d\n", __func__,
+ pipe->pipe_ndx, plane);
+ }
+ iom->prev_ihdl[plane] = iom->ihdl[plane];
+ iom->ihdl[plane] = *srcp_ihdl;
+ mdp4_stat.iommu_map++;
+
+ pr_debug("%s: ndx=%d plane=%d prev=0x%p cur=0x%p start=0x%lx len=%lx\n",
+ __func__, pipe->pipe_ndx, plane, iom->prev_ihdl[plane],
+ iom->ihdl[plane], *start, *len);
+ mutex_unlock(&iommu_mutex);
+ return 0;
+}
+
+static struct mdp4_iommu_pipe_info mdp_iommu[MDP4_MIXER_MAX][OVERLAY_PIPE_MAX];
+
+void mdp4_iommu_unmap(struct mdp4_overlay_pipe *pipe)
+{
+ struct mdp4_iommu_pipe_info *iom_pipe_info;
+ unsigned char i, j;
+
+ if (!display_iclient)
+ return;
+
+ for (j = 0; j < OVERLAY_PIPE_MAX; j++) {
+ iom_pipe_info = &mdp_iommu[pipe->mixer_num][j];
+ for (i = 0; i < MDP4_MAX_PLANE; i++) {
+ if (iom_pipe_info->prev_ihdl[i]) {
+ pr_debug("%s(): mixer %u, pipe %u, plane %u, "
+ "prev_ihdl %p\n", __func__,
+ pipe->mixer_num, j + 1, i,
+ iom_pipe_info->prev_ihdl[i]);
+ ion_unmap_iommu(display_iclient,
+ iom_pipe_info->prev_ihdl[i],
+ DISPLAY_DOMAIN, GEN_POOL);
+ ion_free(display_iclient,
+ iom_pipe_info->prev_ihdl[i]);
+ iom_pipe_info->prev_ihdl[i] = NULL;
+ }
+
+ if (iom_pipe_info->mark_unmap) {
+ if (iom_pipe_info->ihdl[i]) {
+ pr_debug("%s(): MARK, mixer %u, pipe %u, plane %u, "
+ "ihdl %p\n", __func__,
+ pipe->mixer_num, j + 1, i,
+ iom_pipe_info->ihdl[i]);
+ ion_unmap_iommu(display_iclient,
+ iom_pipe_info->ihdl[i],
+ DISPLAY_DOMAIN, GEN_POOL);
+ ion_free(display_iclient,
+ iom_pipe_info->ihdl[i]);
+ iom_pipe_info->ihdl[i] = NULL;
+ }
+ }
+ }
+ iom_pipe_info->mark_unmap = 0;
+ }
+}
+
/* static array with index 0 for unset status and 1 for set status */
static bool overlay_status[MDP4_OVERLAY_TYPE_MAX];
@@ -146,235 +314,272 @@
return overlay_status[type];
}
-void mdp4_overlay_dmae_cfg(struct mdp4_overlay_pipe *pipe, int atv)
+int mdp4_overlay_mixer_play(int mixer_num)
{
- uint32_t dmae_cfg_reg;
+ if (mixer_num == MDP4_MIXER2)
+ return ctrl->mixer2_played;
+ else 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;
+}
+
+void mdp4_overlay_panel_mode_unset(int mixer_num, uint32 mode)
+{
+ ctrl->panel_mode &= ~mode;
+}
+
+uint32 mdp4_overlay_panel_list(void)
+{
+ return ctrl->panel_mode;
+}
+
+void mdp4_overlay_cfg_init(void)
+{
+ if (ctrl->hw_version == 0) {
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ ctrl->hw_version = inpdw(MDP_BASE + 0x0); /* MDP_HW_VERSION */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ }
+
+ if (ctrl->hw_version >= 0x0402030b) {
+ /* MDP_LAYERMIXER_IN_CFG_UPDATE_METHOD */
+ outpdw(MDP_BASE + 0x100fc, 0x01);
+ }
+}
+
+int mdp4_overlay_borderfill_supported(void)
+{
+ return (ctrl->hw_version >= 0x0402030b);
+}
+
+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 (pipe->mdp->mdp_dev.color_format == MSM_MDP_OUT_IF_FMT_RGB565) {
- dmae_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */
- DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
- } else if (pipe->mdp->mdp_dev.color_format == MSM_MDP_OUT_IF_FMT_RGB666) {
+ 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 24BPP */
+ dmae_cfg_reg |= DMA_DSTC0G_8BITS | /* 888 16BPP */
DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
}
- dmae_cfg_reg |= DMA_PACK_PATTERN_RGB;
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
/* dma2 config register */
- mdp_writel(pipe->mdp, dmae_cfg_reg, 0xb0000);
-
+ MDP_OUTP(MDP_BASE + 0xb0000, dmae_cfg_reg);
if (atv) {
- mdp_writel(pipe->mdp, 0xeb0010, 0xb0070);
- mdp_writel(pipe->mdp, 0xf00010, 0xb0074);
- mdp_writel(pipe->mdp, 0xf00010, 0xb0078);
- mdp_writel(pipe->mdp, 0x80, 0xb3000);
- mdp_writel(pipe->mdp, 0x1800040, 0xb3010);
- mdp_writel(pipe->mdp, 0x1000080, 0xb3014);
- mdp_writel(pipe->mdp, 0x67686970, 0xb4004);
+ 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_writel(pipe->mdp, 0xff0000, 0xb0070);
- mdp_writel(pipe->mdp, 0xff0000, 0xb0074);
- mdp_writel(pipe->mdp, 0xff0000, 0xb0078);
+#ifdef CONFIG_FB_MSM_HDMI_MHL
+ mdp_vid_quant_set();
+#endif
+ 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);
}
+#ifdef CONFIG_FB_MSM_HDMI_3D
+void unfill_black_screen(void) { return; }
+#else
+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);
+ return;
+}
+#endif
+
+#ifdef CONFIG_FB_MSM_HDMI_3D
+void fill_black_screen(void) { return; }
+#else
+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);
+ return;
+}
+#endif
+
void mdp4_overlay_dmae_xy(struct mdp4_overlay_pipe *pipe)
{
- /* dma_e source */
- mdp_writel(pipe->mdp, (pipe->src_height << 16 | pipe->src_width)
- , 0xb0004);
- mdp_writel(pipe->mdp, pipe->srcp0_addr, 0xb0008);
- mdp_writel(pipe->mdp, pipe->srcp0_ystride, 0xb000c);
- /* dma_e dest */
- mdp_writel(pipe->mdp, (pipe->dst_y << 16 | pipe->dst_x), 0xb0010);
-}
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-int mdp4_overlay_parameters_check(struct mdp4_overlay_pipe *pipe)
-{
- uint32_t fb_width = 0, fb_height = 0;
-
- if (pipe == NULL || pipe->mdp == NULL)
- return 0;
-
- if (pipe->mixer_num == 0) { /* set fb0 */
- if (pipe->mdp->mdp_dev.fb0 != NULL) {
- fb_width = pipe->mdp->mdp_dev.fb0->var.xres;
- fb_height = pipe->mdp->mdp_dev.fb0->var.yres;
- } else {
- PR_DISP_ERR("%s(%d) mdp_dev fb0 is NULL\n", __func__, __LINE__);
- return -EPERM;
- }
- } else { /* set fb1 */
- if (pipe->mdp->mdp_dev.fb1 != NULL) {
- fb_width = pipe->mdp->mdp_dev.fb1->var.xres;
- fb_height = pipe->mdp->mdp_dev.fb1->var.yres;
- } else {
- PR_DISP_ERR("%s(%d) mdp_dev fb1 is NULL\n", __func__, __LINE__);
- return -EPERM;
- }
- }
- if (pipe->dst_x < 0 || pipe->dst_x >= fb_width) {
-
- PR_DISP_WARN("%s(%d) Incorrect parameter dstx=%d", __func__, __LINE__, pipe->dst_x);
- return -ERANGE;
- }
-
- if (pipe->dst_y < 0 || pipe->dst_y >= fb_height) {
-
- PR_DISP_WARN("%s(%d) Incorrect parameter dsty=%d", __func__, __LINE__, pipe->dst_y);
- return -ERANGE;
- }
-
- if (pipe->dst_w < 0 || pipe->dst_w > fb_width) {
-
- PR_DISP_WARN("%s(%d) Incorrect parameter dstw=%d", __func__, __LINE__, pipe->dst_w);
- return -ERANGE;
- }
-
- if (pipe->dst_y < 0 || pipe->dst_y > fb_height) {
-
- PR_DISP_WARN("%s(%d) Incorrect parameter2 dsty=%d", __func__, __LINE__, pipe->dst_y);
- return -ERANGE;
- }
-
- if (pipe->dst_w + pipe->dst_x > fb_width) {
-
- PR_DISP_WARN("%s(%d) Incorrect parameter dstx=%d dstw=%d found", __func__, __LINE__,
- pipe->dst_x, pipe->dst_w);
- return -ERANGE;
- }
-
- if (pipe->dst_h + pipe->dst_y > fb_height) {
-
- PR_DISP_WARN("%s(%d) Incorrect parameter dsty=%d dsth=%d found", __func__, __LINE__,
- pipe->dst_y, pipe->dst_h);
- return -ERANGE;
- }
-
- if (pipe->dst_w && (pipe->dst_w != pipe->src_w) && (pipe->src_w > pipe->dst_w * 4)) { /* dst_w too little */
-
- PR_DISP_WARN("%s(%d) Incorrect parameter dst_w=%d(too small)", __func__, __LINE__, pipe->dst_w);
- return -ERANGE;
- }
-
- if (pipe->dst_h && (pipe->dst_h != pipe->src_h) && (pipe->src_h > pipe->dst_h * 4)) { /* dst_h too little */
-
- PR_DISP_WARN("%s(%d) Incorrect parameter dst_h=%d(too small)", __func__, __LINE__, pipe->dst_h);
- return -ERANGE;
- }
- return 0;
-}
-
-
-void mdp4_overlay_dmap_cfg(struct mdp4_overlay_pipe *pipe, int lcdc)
-{
- uint32_t dmap_cfg_reg = 0;
-
- dmap_cfg_reg |= DMA_DITHER_EN;
-
-
- if (pipe->mdp->mdp_dev.color_format == MSM_MDP_OUT_IF_FMT_RGB565) {
- dmap_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */
- DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
- } else if (pipe->mdp->mdp_dev.color_format == MSM_MDP_OUT_IF_FMT_RGB666) {
- dmap_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */
- DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+ MDP_OUTP(MDP_BASE + 0xb0004,
+ (pipe->src_height << 16 | pipe->src_width));
+ if (pipe->dma_blt_addr) {
+ uint32 off, bpp;
+#ifdef BLT_RGB565
+ bpp = 2; /* overlay ouput is RGB565 */
+#else
+ bpp = 3; /* overlay ouput is RGB888 */
+#endif
+ off = 0;
+ if (pipe->ov_cnt & 0x01)
+ off = pipe->src_height * pipe->src_width * bpp;
+ MDP_OUTP(MDP_BASE + 0xb0008, pipe->dma_blt_addr + off);
+ /* RGB888, output of overlay blending */
+ MDP_OUTP(MDP_BASE + 0xb000c, pipe->src_width * bpp);
} else {
- dmap_cfg_reg |= DMA_DSTC0G_8BITS | /* 888 16BPP */
+ /* dma_e source */
+ MDP_OUTP(MDP_BASE + 0xb0008, pipe->srcp0_addr);
+ MDP_OUTP(MDP_BASE + 0xb000c, pipe->srcp0_ystride);
+ }
+ /* dma_e 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;
+ uint32 mask, curr;
+
+ 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;
}
- if (lcdc) {
- if (pipe->mdp->mdp_dev.overrides & MSM_MDP_DMA_PACK_ALIGN_LSB)
- dmap_cfg_reg |= DMA_PACK_ALIGN_LSB;
- else
- dmap_cfg_reg |= DMA_PACK_ALIGN_MSB;
- }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
- /* dmap config register */
- mdp_writel(pipe->mdp, dmap_cfg_reg, 0x90000);
-
-}
-
-void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe)
-{
-
- /* dma_p source */
- mdp_writel(pipe->mdp, (pipe->src_height << 16 | pipe->src_width), 0x90004);
-#ifdef CONFIG_FB_MSM_WRITE_BACK
- if (pipe->blt_addr) {
- /* overlay ouput is RGB565 */
- uint32_t off;
- off = 0;
- if (pipe->blt_cnt & 0x01)
- off = pipe->src_height * pipe->src_width * 2;
- mdp_writel(pipe->mdp, pipe->blt_addr+off , 0x90008);
- /* RGB888, output of overlay blending */
- mdp_writel(pipe->mdp, pipe->src_width * 2, 0x9000c);
- } else {
- mdp_writel(pipe->mdp, pipe->srcp0_addr, 0x90008);
- mdp_writel(pipe->mdp, pipe->srcp0_ystride, 0x9000c);
- }
-#else
- mdp_writel(pipe->mdp, pipe->srcp0_addr, 0x90008);
- mdp_writel(pipe->mdp, pipe->srcp0_ystride, 0x9000c);
+#ifndef CONFIG_FB_MSM_LCDC_CHIMEI_WXGA_PANEL
+ if (lcdc)
+ dma2_cfg_reg |= DMA_PACK_ALIGN_MSB;
#endif
- /* dma_p dest */
- mdp_writel(pipe->mdp, (pipe->dst_y << 16 | pipe->dst_x), 0x90010);
+ /* dma2 config register */
+ curr = inpdw(MDP_BASE + 0x90000);
+ mask = 0xBFFFFFFF;
+ dma2_cfg_reg = (dma2_cfg_reg & mask) | (curr & ~mask);
+ MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
-void mdp4_overlay_dmas_cfg(struct mdp4_overlay_pipe *pipe, int lcdc)
+/*
+ * mdp4_overlay_dmap_xy: called form baselayer only
+ */
+void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe)
{
- uint32_t dmas_cfg_reg = 0;
+ uint32 off, bpp;
- dmas_cfg_reg |= DMA_DITHER_EN;
- if (pipe->src_format == MDP_RGBA_8888) {
- dmas_cfg_reg |= DMA_PACK_PATTERN_BGR;
- dmas_cfg_reg |= (1 << 26);
+ if (!in_interrupt())
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ if (pipe->dma_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->dma_blt_addr + off);
+ /* RGB888, output of overlay blending */
+ MDP_OUTP(MDP_BASE + 0x9000c, pipe->src_width * bpp);
} else {
- dmas_cfg_reg |= DMA_PACK_PATTERN_RGB;
- dmas_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
+ MDP_OUTP(MDP_BASE + 0x90008, pipe->srcp0_addr);
+ MDP_OUTP(MDP_BASE + 0x9000c, pipe->srcp0_ystride);
}
+ /* dma_p source */
+ MDP_OUTP(MDP_BASE + 0x90004,
+ (pipe->src_height << 16 | pipe->src_width));
- dmas_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */
- DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
+ /* dma_p dest */
+ MDP_OUTP(MDP_BASE + 0x90010, (pipe->dst_y << 16 | pipe->dst_x));
- if (lcdc)
- dmas_cfg_reg |= DMA_PACK_ALIGN_MSB;
-
- /* dmas config register */
- mdp_writel(pipe->mdp, dmas_cfg_reg, 0xA0000);
-
-}
-
-void mdp4_overlay_dmas_xy(struct mdp4_overlay_pipe *pipe)
-{
-
- /* dmas source */
- mdp_writel(pipe->mdp, (pipe->dst_h << 16 | pipe->dst_w), 0xA0004);
- mdp_writel(pipe->mdp, pipe->srcp0_addr, 0xA0008);
- mdp_writel(pipe->mdp, pipe->srcp0_ystride, 0xA000c);
-
- /* dmas dest */
- mdp_writel(pipe->mdp, (pipe->dst_y << 16 | pipe->dst_x), 0xA0010);
+ if (!in_interrupt())
+ 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_t num)
+static int mdp4_leading_0(uint32 num)
{
- uint32_t bit = 0x80000000;
+ uint32 bit = 0x80000000;
int i;
for (i = 0; i < 32; i++) {
@@ -386,19 +591,20 @@
return i;
}
-static uint32_t mdp4_scale_phase_step(int f_num, uint32_t src, uint32_t dst)
+static uint32 mdp4_scale_phase_step(int f_num, uint32 src, uint32 dst)
{
- uint32_t val;
+ uint32 val, s;
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;
+ s = src << n; /* maximum to reduce lose of resolution */
+ val = s / dst;
if (n < f_num) {
n = f_num - n;
val <<= n;
+ val |= ((s % dst) << n) / dst;
}
return val;
@@ -406,20 +612,31 @@
static void mdp4_scale_setup(struct mdp4_overlay_pipe *pipe)
{
-
pipe->phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
pipe->phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
if (pipe->dst_h && pipe->src_h != pipe->dst_h) {
- if (pipe->dst_h > pipe->src_h * 8) /* too much */
+ u32 upscale_max;
+ upscale_max = (mdp_rev >= MDP_REV_41) ?
+ MDP4_REV41_OR_LATER_UP_SCALING_MAX :
+ MDP4_REV40_UP_SCALING_MAX;
+ if (pipe->dst_h > pipe->src_h * upscale_max)
return;
+
pipe->op_mode |= MDP4_OP_SCALEY_EN;
- if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {
- if (pipe->dst_h < (pipe->src_h / 4))
+ if (pipe->pipe_type == OVERLAY_TYPE_VIDEO) {
+ if (pipe->flags & MDP_BACKEND_COMPOSITION &&
+ pipe->alpha_enable && pipe->dst_h > pipe->src_h)
+ pipe->op_mode |= MDP4_OP_SCALEY_PIXEL_RPT;
+ else if (pipe->dst_h <= (pipe->src_h / 4))
pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE;
else
pipe->op_mode |= MDP4_OP_SCALEY_FIR;
+ } else { /* RGB pipe */
+ pipe->op_mode |= MDP4_OP_SCALE_RGB_ENHANCED |
+ MDP4_OP_SCALE_RGB_BILINEAR |
+ MDP4_OP_SCALE_ALPHA_BILINEAR;
}
pipe->phasey_step = mdp4_scale_phase_step(29,
@@ -427,15 +644,26 @@
}
if (pipe->dst_w && pipe->src_w != pipe->dst_w) {
- if (pipe->dst_w > pipe->src_w * 8) /* too much */
+ u32 upscale_max;
+ upscale_max = (mdp_rev >= MDP_REV_41) ?
+ MDP4_REV41_OR_LATER_UP_SCALING_MAX :
+ MDP4_REV40_UP_SCALING_MAX;
+
+ if (pipe->dst_w > pipe->src_w * upscale_max)
return;
pipe->op_mode |= MDP4_OP_SCALEX_EN;
-
- if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {
- if (pipe->dst_w < (pipe->src_w / 4))
+ if (pipe->pipe_type == OVERLAY_TYPE_VIDEO) {
+ if (pipe->flags & MDP_BACKEND_COMPOSITION &&
+ pipe->alpha_enable && pipe->dst_w > pipe->src_w)
+ pipe->op_mode |= MDP4_OP_SCALEX_PIXEL_RPT;
+ else if (pipe->dst_w <= (pipe->src_w / 4))
pipe->op_mode |= MDP4_OP_SCALEX_MN_PHASE;
else
pipe->op_mode |= MDP4_OP_SCALEX_FIR;
+ } else { /* RGB pipe */
+ pipe->op_mode |= MDP4_OP_SCALE_RGB_ENHANCED |
+ MDP4_OP_SCALE_RGB_BILINEAR |
+ MDP4_OP_SCALE_ALPHA_BILINEAR;
}
pipe->phasex_step = mdp4_scale_phase_step(29,
@@ -445,161 +673,287 @@
void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe)
{
- uint32_t rgb_base;
- uint32_t src_size, src_xy, dst_size, dst_xy;
- uint32_t format, pattern;
- uint32_t dst_newx = 0, dst_newy = 0;
+ char *rgb_base;
+ uint32 src_size, src_xy, dst_size, dst_xy;
+ uint32 format, pattern;
+ uint32 curr, mask;
+ uint32 offset = 0;
+ int pnum;
- rgb_base = MDP4_RGB_BASE;
- rgb_base += (MDP4_RGB_OFF * pipe->pipe_num);
-
- mdp4_overlay_parameters_check(pipe);
+ pnum = pipe->pipe_num - OVERLAY_PIPE_RGB1; /* start from 0 */
+ rgb_base = MDP_BASE + MDP4_RGB_BASE;
+ rgb_base += (MDP4_RGB_OFF * pnum);
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);
+
+ if ((pipe->src_x + pipe->src_w) > 0x7FF) {
+ offset += pipe->src_x * pipe->bpp;
+ src_xy &= 0xFFFF0000;
+ }
+
+ if ((pipe->src_y + pipe->src_h) > 0x7FF) {
+ offset += pipe->src_y * pipe->src_width * pipe->bpp;
+ src_xy &= 0x0000FFFF;
+ }
format = mdp4_overlay_format(pipe);
pattern = mdp4_overlay_unpack_pattern(pipe);
#ifdef MDP4_IGC_LUT_ENABLE
- pipe->op_mode = MDP4_OP_IGC_LUT_EN;
-#else
- pipe->op_mode = 0;
+ pipe->op_mode |= MDP4_OP_IGC_LUT_EN;
#endif
- /* workaroud for the panel with wrong direction */
- if (pipe->mdp->mdp_dev.overrides & MSM_MDP_PANEL_FLIP_UD) {
- pipe->op_mode ^= MDP4_OP_FLIP_UD;
-
- if (pipe->mixer_num == 0)
- dst_newy = pipe->mdp->mdp_dev.fb0->var.yres - pipe->dst_y - pipe->dst_h;
- else
- dst_newy = pipe->mdp->mdp_dev.fb1->var.yres - pipe->dst_y - pipe->dst_h;
- dst_xy = dst_newy << 16;
- } else
- dst_xy = pipe->dst_y << 16;
-
- if (pipe->mdp->mdp_dev.overrides & MSM_MDP_PANEL_FLIP_LR) {
- pipe->op_mode ^= MDP4_OP_FLIP_LR;
- if (pipe->mixer_num == 0)
- dst_newx = pipe->mdp->mdp_dev.fb0->var.xres - pipe->dst_x - pipe->dst_w;
- else
- dst_newx = pipe->mdp->mdp_dev.fb1->var.xres - pipe->dst_x - pipe->dst_w;
- dst_xy |= dst_newx;
- } else
- dst_xy |= pipe->dst_x;
-
mdp4_scale_setup(pipe);
- mdp_writel(pipe->mdp, src_size, rgb_base + 0x0000); /* MDP_RGB_SRC_SIZE */
- mdp_writel(pipe->mdp, src_xy, rgb_base + 0x0004); /* MDP_RGB_SRC_XY */
- mdp_writel(pipe->mdp, src_xy, rgb_base + 0x0008); /* MDP_RGB_DST_SIZE */
- mdp_writel(pipe->mdp, dst_xy, rgb_base + 0x000c); /* MDP_RGB_DST_XY */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
- mdp_writel(pipe->mdp, pipe->srcp0_addr, rgb_base + 0x0010);
- mdp_writel(pipe->mdp, pipe->srcp0_ystride, rgb_base + 0x0040);
+ /* Ensure proper covert matrix loaded when color space swaps */
+ curr = inpdw(rgb_base + 0x0058);
+ /* Don't touch bits you don't want to configure*/
+ mask = 0xFFFEFFFF;
+ pipe->op_mode = (pipe->op_mode & mask) | (curr & ~mask);
- mdp_writel(pipe->mdp, format, rgb_base + 0x0050);/* MDP_RGB_SRC_FORMAT */
- mdp_writel(pipe->mdp, pattern, rgb_base + 0x0054);/* MDP_RGB_SRC_UNPACK_PATTERN */
- mdp_writel(pipe->mdp, pipe->op_mode, rgb_base + 0x0058);/* MDP_RGB_OP_MODE */
- mdp_writel(pipe->mdp, pipe->phasex_step, rgb_base + 0x005c);
- mdp_writel(pipe->mdp, pipe->phasey_step, rgb_base + 0x0060);
+ 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 + offset);
+ 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 */
+ if (format & MDP4_FORMAT_SOLID_FILL) {
+ u32 op_mode = pipe->op_mode;
+ op_mode &= ~(MDP4_OP_FLIP_LR + MDP4_OP_SCALEX_EN);
+ op_mode &= ~(MDP4_OP_FLIP_UD + MDP4_OP_SCALEY_EN);
+ outpdw(rgb_base + 0x0058, op_mode);/* MDP_RGB_OP_MODE */
+ } else
+ 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]++;
}
-int mdp4_overlay_vg_setup(struct mdp4_overlay_pipe *pipe)
+
+static void mdp4_overlay_vg_get_src_offset(struct mdp4_overlay_pipe *pipe,
+ char *vg_base, uint32 *luma_off, uint32 *chroma_off)
{
- uint32_t vg_base;
- uint32_t frame_size, src_size, src_xy, dst_size, dst_xy;
- uint32_t format, pattern;
- uint32_t dst_newx = 0, dst_newy = 0;
- int pnum, ret = 0;
+ uint32 src_xy;
+ *luma_off = 0;
+ *chroma_off = 0;
+
+ if (pipe->src_x && (pipe->frame_format ==
+ MDP4_FRAME_FORMAT_LINEAR)) {
+ src_xy = (pipe->src_y << 16) | pipe->src_x;
+ src_xy &= 0xffff0000;
+ outpdw(vg_base + 0x0004, src_xy); /* MDP_RGB_SRC_XY */
+
+ switch (pipe->src_format) {
+ case MDP_Y_CR_CB_H2V2:
+ case MDP_Y_CR_CB_GH2V2:
+ case MDP_Y_CB_CR_H2V2:
+ *luma_off = pipe->src_x;
+ *chroma_off = pipe->src_x/2;
+ break;
+
+ case MDP_Y_CBCR_H2V2_TILE:
+ case MDP_Y_CRCB_H2V2_TILE:
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ case MDP_Y_CRCB_H1V1:
+ case MDP_Y_CBCR_H1V1:
+ case MDP_Y_CRCB_H2V1:
+ case MDP_Y_CBCR_H2V1:
+ *luma_off = pipe->src_x;
+ *chroma_off = pipe->src_x;
+ break;
+
+ case MDP_YCRYCB_H2V1:
+ if (pipe->src_x & 0x1)
+ pipe->src_x += 1;
+ *luma_off += pipe->src_x * 2;
+ break;
+
+ case MDP_ARGB_8888:
+ case MDP_RGBA_8888:
+ case MDP_BGRA_8888:
+ case MDP_RGBX_8888:
+ case MDP_RGB_565:
+ case MDP_BGR_565:
+ case MDP_XRGB_8888:
+ case MDP_RGB_888:
+ case MDP_YCBCR_H1V1:
+ case MDP_YCRCB_H1V1:
+ *luma_off = pipe->src_x * pipe->bpp;
+ break;
+
+ default:
+ pr_err("%s: fmt %u not supported for adjustment\n",
+ __func__, pipe->src_format);
+ break;
+ }
+ }
+}
+
+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, luma_offset, chroma_offset;
+ uint32 mask, curr, addr;
+ int pnum, ptype;
pnum = pipe->pipe_num - OVERLAY_PIPE_VG1; /* start from 0 */
- vg_base = MDP4_VIDEO_BASE;
+ vg_base = MDP_BASE + MDP4_VIDEO_BASE;
vg_base += (MDP4_VIDEO_OFF * pnum);
- ret = mdp4_overlay_parameters_check(pipe);
- if (ret)
- return ret;
-
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);
+ ptype = mdp4_overlay_format2type(pipe->src_format);
format = mdp4_overlay_format(pipe);
pattern = mdp4_overlay_unpack_pattern(pipe);
+ /* not RGB use VG pipe, pure VG pipe */
+ pipe->op_mode |= MDP4_OP_CSC_EN;
+ if (ptype != OVERLAY_TYPE_RGB)
+ pipe->op_mode |= MDP4_OP_SRC_DATA_YCBCR;
+
#ifdef MDP4_IGC_LUT_ENABLE
- pipe->op_mode = MDP4_OP_IGC_LUT_EN;
-#else
- pipe->op_mode = 0;
+ pipe->op_mode |= MDP4_OP_IGC_LUT_EN;
#endif
- /* not RGB use VG pipe */
- if (pipe->pipe_type != OVERLAY_TYPE_RGB)
- pipe->op_mode |= (MDP4_OP_CSC_EN | MDP4_OP_SRC_DATA_YCBCR);
-
-
mdp4_scale_setup(pipe);
- /* workaroud for the panel with wrong direction */
- if (pipe->mdp->mdp_dev.overrides & MSM_MDP_PANEL_FLIP_UD) {
- pipe->op_mode ^= MDP4_OP_FLIP_UD;
- if (pipe->mixer_num == 0)
- dst_newy = pipe->mdp->mdp_dev.fb0->var.yres - pipe->dst_y - pipe->dst_h;
- else
- dst_newy = pipe->mdp->mdp_dev.fb0->var.yres - pipe->dst_y - pipe->dst_h;
- dst_xy = dst_newy << 16;
- } else
- dst_xy = pipe->dst_y << 16;
+ luma_offset = 0;
+ chroma_offset = 0;
- if (pipe->mdp->mdp_dev.overrides & MSM_MDP_PANEL_FLIP_LR) {
- pipe->op_mode ^= MDP4_OP_FLIP_LR;
+ if (ptype == OVERLAY_TYPE_RGB) {
+ if ((pipe->src_y + pipe->src_h) > 0x7FF) {
+ luma_offset = pipe->src_y * pipe->src_width * pipe->bpp;
+ src_xy &= 0x0000FFFF;
+ }
- if (pipe->mixer_num == 0)
- dst_newx = pipe->mdp->mdp_dev.fb0->var.xres - pipe->dst_x - pipe->dst_w;
- else
- dst_newx = pipe->mdp->mdp_dev.fb1->var.yres - pipe->dst_x - pipe->dst_w;
- dst_xy |= dst_newx;
- } else
- dst_xy |= pipe->dst_x;
-
- if (pipe->dst_x < 0 || pipe->dst_y < 0) {
- PR_DISP_ERR("%s(%d) Incorrect overlay input pipex=%d pipey=%d newx=%d newy=%d width=%d height=%d\n",
- __func__, __LINE__, pipe->dst_x, pipe->dst_y, dst_newx, dst_newy,
- pipe->mdp->mdp_dev.width, pipe->mdp->mdp_dev.height);
+ if ((pipe->src_x + pipe->src_w) > 0x7FF) {
+ luma_offset += pipe->src_x * pipe->bpp;
+ src_xy &= 0xFFFF0000;
+ }
}
- mdp_writel(pipe->mdp, src_size, vg_base + 0x0000); /* MDP_RGB_SRC_SIZE */
- mdp_writel(pipe->mdp, src_xy, vg_base + 0x0004); /* MDP_RGB_SRC_XY */
- mdp_writel(pipe->mdp, dst_size, vg_base + 0x0008); /* MDP_RGB_DST_SIZE */
- mdp_writel(pipe->mdp, dst_xy, vg_base + 0x000c); /* MDP_RGB_DST_XY */
- mdp_writel(pipe->mdp, frame_size, vg_base + 0x0048); /* TILE frame size */
+ 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 */
+
+ if (pipe->frame_format != MDP4_FRAME_FORMAT_LINEAR)
+ outpdw(vg_base + 0x0048, frame_size); /* TILE frame size */
+
+ /*
+ * Adjust src X offset to avoid MDP from overfetching pixels
+ * present before the offset. This is required for video
+ * frames coming with unused green pixels along the left margin
+ */
+ /* not RGB use VG pipe, pure VG pipe */
+ if (ptype != OVERLAY_TYPE_RGB) {
+ mdp4_overlay_vg_get_src_offset(pipe, vg_base, &luma_offset,
+ &chroma_offset);
+ }
+
+ /* Ensure proper covert matrix loaded when color space swaps */
+ curr = inpdw(vg_base + 0x0058);
+ mask = 0x600;
+
+ if ((curr & mask) != (pipe->op_mode & mask)) {
+ addr = ((uint32_t)vg_base) + 0x4000;
+ if (ptype != OVERLAY_TYPE_RGB)
+ mdp4_csc_write(&(mdp_csc_convert[1]), addr);
+ else
+ mdp4_csc_write(&(mdp_csc_convert[0]), addr);
+
+ mask = 0xFFFCFFFF;
+ } else {
+ /* Don't touch bits you don't want to configure*/
+ mask = 0xFFFCF1FF;
+ }
+ pipe->op_mode = (pipe->op_mode & mask) | (curr & ~mask);
/* luma component plane */
- mdp_writel(pipe->mdp, pipe->srcp0_addr, vg_base + 0x0010);
+ outpdw(vg_base + 0x0010, pipe->srcp0_addr + luma_offset);
- /* chroma component plane */
- mdp_writel(pipe->mdp, pipe->srcp1_addr, vg_base + 0x0014);
+ /* chroma component plane or planar color 1 */
+ outpdw(vg_base + 0x0014, pipe->srcp1_addr + chroma_offset);
+
+ /* planar color 2 */
+ outpdw(vg_base + 0x0018, pipe->srcp2_addr + chroma_offset);
+
+ 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 */
+ if (format & MDP4_FORMAT_SOLID_FILL) {
+ u32 op_mode = pipe->op_mode;
+ op_mode &= ~(MDP4_OP_FLIP_LR + MDP4_OP_SCALEX_EN);
+ op_mode &= ~(MDP4_OP_FLIP_UD + MDP4_OP_SCALEY_EN);
+ outpdw(vg_base + 0x0058, op_mode);/* MDP_RGB_OP_MODE */
+ } else
+ 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));
+ }
+
+ if (mdp_rev > MDP_REV_41) {
+ /* mdp chip select controller */
+ mask = 0;
+ if (pipe->pipe_num == OVERLAY_PIPE_VG1)
+ mask = 0x020; /* bit 5 */
+ else if (pipe->pipe_num == OVERLAY_PIPE_VG2)
+ mask = 0x02000; /* bit 13 */
+ if (mask) {
+ if (pipe->op_mode & MDP4_OP_SCALEY_MN_PHASE)
+ ctrl->cs_controller &= ~mask;
+ else
+ ctrl->cs_controller |= mask;
+ /* NOT double buffered */
+ outpdw(MDP_BASE + 0x00c0, ctrl->cs_controller);
+ }
+ }
- mdp_writel(pipe->mdp, pipe->srcp1_ystride << 16 | pipe->srcp0_ystride, vg_base + 0x0040);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
- mdp_writel(pipe->mdp, format, vg_base + 0x0050); /* MDP_RGB_SRC_FORMAT */
- mdp_writel(pipe->mdp, pattern, vg_base + 0x0054); /* MDP_RGB_SRC_UNPACK_PATTERN */
- mdp_writel(pipe->mdp, pipe->op_mode, vg_base + 0x0058); /* MDP_RGB_OP_MODE */
- mdp_writel(pipe->mdp, pipe->phasex_step, vg_base + 0x005c);
- mdp_writel(pipe->mdp, pipe->phasey_step, vg_base + 0x0060);
-
- if (pipe->op_mode & MDP4_OP_DITHER_EN)
- mdp_writel(pipe->mdp, pipe->r_bit << 4 | pipe->b_bit << 2 | pipe->g_bit, vg_base + 0x0068);
-
- return 0;
+ mdp4_stat.pipe[pipe->pipe_num]++;
}
-int mdp4_overlay_format2type(uint32_t format)
+int mdp4_overlay_format2type(uint32 format)
{
switch (format) {
case MDP_RGB_565:
@@ -618,12 +972,21 @@
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_CR_CB_GH2V2:
+ case MDP_Y_CB_CR_H2V2:
case MDP_Y_CRCB_H1V1:
case MDP_Y_CBCR_H1V1:
+ case MDP_YCRCB_H1V1:
+ case MDP_YCBCR_H1V1:
return OVERLAY_TYPE_VIDEO;
+ case MDP_RGB_BORDERFILL:
+ return OVERLAY_TYPE_BF;
default:
+ mdp4_stat.err_format++;
return -ERANGE;
}
+
}
#define C3_ALPHA 3 /* alpha */
@@ -858,8 +1221,47 @@
}
pipe->bpp = 2; /* 2 bpp */
break;
+ case MDP_Y_CR_CB_H2V2:
+ case MDP_Y_CR_CB_GH2V2:
+ 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->chroma_sample = MDP4_CHROMA_420;
+ pipe->bpp = 2; /* 2 bpp */
+ break;
+ case MDP_YCBCR_H1V1:
+ case MDP_YCRCB_H1V1:
+ 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->element0 = C0_G_Y; /* G */
+ if (pipe->src_format == MDP_YCRCB_H1V1) {
+ pipe->element1 = C2_R_Cr; /* R */
+ pipe->element2 = C1_B_Cb; /* B */
+ } else {
+ pipe->element1 = C1_B_Cb; /* B */
+ pipe->element2 = C2_R_Cr; /* R */
+ }
+ pipe->bpp = 3; /* 3 bpp */
+ case MDP_RGB_BORDERFILL:
+ pipe->alpha_enable = 0;
+ pipe->alpha = 0;
+ break;
default:
/* not likely */
+ mdp4_stat.err_format++;
return -ERANGE;
}
@@ -869,9 +1271,9 @@
/*
* color_key_convert: output with 12 bits color key
*/
-static uint32_t color_key_convert(int start, int num, uint32_t color)
+static uint32 color_key_convert(int start, int num, uint32 color)
{
- uint32_t data;
+ uint32 data;
data = (color >> start) & ((1 << num) - 1);
@@ -887,8 +1289,8 @@
return data;
}
-void transp_color_key(int format, uint32_t transp,
- uint32_t *c0, uint32_t *c1, uint32_t *c2)
+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;
@@ -930,8 +1332,10 @@
g_num = 6;
b_num = 5;
break;
+ case MDP_Y_CB_CR_H2V2:
case MDP_Y_CBCR_H2V2:
case MDP_Y_CBCR_H2V1:
+ case MDP_YCBCR_H1V1:
b_start = 8;
g_start = 16;
r_start = 0;
@@ -939,10 +1343,13 @@
g_num = 8;
b_num = 8;
break;
+ case MDP_Y_CR_CB_H2V2:
+ case MDP_Y_CR_CB_GH2V2:
case MDP_Y_CRCB_H2V2:
case MDP_Y_CRCB_H2V1:
case MDP_Y_CRCB_H1V1:
case MDP_Y_CBCR_H1V1:
+ case MDP_YCRCB_H1V1:
b_start = 0;
g_start = 16;
r_start = 8;
@@ -965,9 +1372,9 @@
*c2 = color_key_convert(r_start, r_num, transp);
}
-uint32_t mdp4_overlay_format(struct mdp4_overlay_pipe *pipe)
+uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe)
{
- uint32_t format;
+ uint32 format;
format = 0;
@@ -983,6 +1390,8 @@
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);
@@ -992,7 +1401,8 @@
format |= (pipe->frame_format << 29);
- if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
+ 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);
@@ -1002,87 +1412,134 @@
return format;
}
-uint32_t mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe)
+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_t data;
- uint32_t overlay_base;
+ uint32 data, intf;
+ char *overlay_base;
- if (pipe->mixer_num == MDP4_MIXER1)
- overlay_base = MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
- else
- overlay_base = MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+ intf = 0;
+ if (pipe->mixer_num == MDP4_MIXER2)
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC2_BASE;
+ else 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 */
- /* MDP_OVERLAYPROC_CFG */
- mdp_writel(pipe->mdp, 0x01, overlay_base + 0x0004); /* directout */
- data = pipe->src_height;
- data <<= 16;
- data |= pipe->src_width;
- mdp_writel(pipe->mdp, data, overlay_base + 0x0008); /* ROI, height + width */
+ if (!in_interrupt())
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
/*
- * BLT only siupport at primary display
+ * BLT support both primary and external external
*/
-#ifdef CONFIG_FB_MSM_WRITE_BACK
- if (pipe->mixer_num == MDP4_MIXER0 && pipe->blt_addr) {
- int off;
- int mddi = 0;
- mddi = mdp_readl(pipe->mdp, 0x0038);
- mddi &= 0x02;
-
- if (!mddi) {
- mdp_writel(pipe->mdp, pipe->blt_addr, overlay_base + 0x000c);
- mdp_writel(pipe->mdp, pipe->src_width * 2, overlay_base + 0x0010);
- /* overlay ouput is RGB565 */
- off = pipe->src_height * pipe->src_width * 2;
- mdp_writel(pipe->mdp, pipe->blt_addr + off, overlay_base + 0x001c);
- /* LCDC - FRAME BUFFER + vsync rate */
- mdp_writel(pipe->mdp, 0x02, overlay_base + 0x0004);
- } else { /* MDDI */
+ if (pipe->ov_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 (pipe->mixer_num == MDP4_MIXER0 ||
+ pipe->mixer_num == MDP4_MIXER1) {
off = 0;
- if (pipe->blt_cnt & 0x01)
- off = pipe->src_height * pipe->src_width * 2;
+ if (pipe->ov_cnt & 0x01)
+ off = pipe->src_height * pipe->src_width * bpp;
- mdp_writel(pipe->mdp, pipe->blt_addr+off, overlay_base + 0x000c);
- /* overlay ouput is RGB565 */
- mdp_writel(pipe->mdp, pipe->src_width * 2, overlay_base + 0x0010);
- mdp_writel(pipe->mdp, pipe->blt_addr + off, overlay_base + 0x001c);
+ outpdw(overlay_base + 0x000c, pipe->ov_blt_addr + off);
+ /* overlay ouput is RGB888 */
+ outpdw(overlay_base + 0x0010, pipe->src_width * bpp);
+ outpdw(overlay_base + 0x001c, pipe->ov_blt_addr + off);
/* MDDI - BLT + on demand */
- mdp_writel(pipe->mdp, 0x02, overlay_base + 0x0004);
+ outpdw(overlay_base + 0x0004, 0x08);
+#ifdef BLT_RGB565
+ outpdw(overlay_base + 0x0014, 0x1); /* RGB565 */
+#else
+ outpdw(overlay_base + 0x0014, 0x0); /* RGB888 */
+#endif
+ } else if (pipe->mixer_num == MDP4_MIXER2) {
+ if (ctrl->panel_mode & MDP4_PANEL_WRITEBACK) {
+ off = 0;
+ bpp = 1;
+ if (pipe->ov_cnt & 0x01)
+ off = pipe->src_height *
+ pipe->src_width * bpp;
+
+ outpdw(overlay_base + 0x000c,
+ pipe->ov_blt_addr + off);
+ /* overlay ouput is RGB888 */
+ outpdw(overlay_base + 0x0010,
+ ((pipe->src_width << 16) |
+ pipe->src_width));
+ outpdw(overlay_base + 0x001c,
+ pipe->ov_blt_addr + off);
+ off = pipe->src_height * pipe->src_width;
+ /* align chroma to 2k address */
+ off = (off + 2047) & ~2047;
+ /* UV plane adress */
+ outpdw(overlay_base + 0x0020,
+ pipe->ov_blt_addr + off);
+ /* MDDI - BLT + on demand */
+ outpdw(overlay_base + 0x0004, 0x08);
+ /* pseudo planar + writeback */
+ outpdw(overlay_base + 0x0014, 0x012);
+ /* rgb->yuv */
+ outpdw(overlay_base + 0x0200, 0x05);
+ }
}
} else {
- mdp_writel(pipe->mdp, data, overlay_base + 0x0008);
- mdp_writel(pipe->mdp, pipe->srcp0_addr, overlay_base + 0x000c);
- mdp_writel(pipe->mdp, pipe->srcp0_ystride, overlay_base + 0x0010);
- mdp_writel(pipe->mdp, 0x01, overlay_base + 0x0004);
+ 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 */
}
-#else
- mdp_writel(pipe->mdp, data, overlay_base + 0x0008);/* ROI, height + width */
- mdp_writel(pipe->mdp, pipe->srcp0_addr, overlay_base + 0x000c);
- mdp_writel(pipe->mdp, pipe->srcp0_ystride, overlay_base + 0x0010);
-#endif
+ 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
- mdp_writel(pipe->mdp, 0x4, overlay_base + 0x0014); /* GC_LUT_EN, 888 */
+ outpdw(overlay_base + 0x0014, 0x4); /* GC_LUT_EN, 888 */
#endif
-#ifdef CONFIG_FB_MSM_WRITE_BACK
- mdp_writel(pipe->mdp, 0x1, overlay_base + 0x0014);
-#endif
+
+ if (!in_interrupt())
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
-int mdp4_overlay_active(struct mdp_info *mdp, int mixer)
+int mdp4_overlay_pipe_staged(int mixer)
{
- uint32_t data, mask, i;
+ uint32 data, mask, i, off;
int p1, p2;
- data = mdp_readl(mdp, 0x10100);
+ if (mixer == MDP4_MIXER2)
+ off = 0x100F0;
+ else
+ off = 0x10100;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ data = inpdw(MDP_BASE + off);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
p1 = 0;
p2 = 0;
for (i = 0; i < 8; i++) {
@@ -1102,178 +1559,498 @@
return p1;
}
-void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe)
+int mdp4_mixer_info(int mixer_num, struct mdp_mixer_info *info)
{
- uint32_t data, mask, snum, stage, mixer, pnum;
- stage = pipe->mixer_stage;
- mixer = pipe->mixer_num;
- pnum = pipe->pipe_num;
+ int ndx, cnt;
+ struct mdp4_overlay_pipe *pipe;
- /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1 */
- data = mdp_readl(pipe->mdp, 0x10100);
+ if (mixer_num > MDP4_MIXER_MAX)
+ return -ENODEV;
- if (mixer == MDP4_MIXER1)
- stage += 8;
+ cnt = 0;
+ ndx = MDP4_MIXER_STAGE_BASE;
+ for ( ; ndx < MDP4_MIXER_STAGE_MAX; ndx++) {
+ pipe = ctrl->stage[mixer_num][ndx];
+ if (pipe == NULL)
+ continue;
+ info->z_order = pipe->mixer_stage - MDP4_MIXER_STAGE0;
+ /* z_order == -1, means base layer */
+ info->ptype = pipe->pipe_type;
+ info->pnum = pipe->pipe_num;
+ info->pndx = pipe->pipe_ndx;
+ info->mixer_num = pipe->mixer_num;
+ info++;
+ cnt++;
+ }
+ return cnt;
+}
- 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 */
+void mdp4_mixer_stage_commit(int mixer)
+{
+ struct mdp4_overlay_pipe *pipe;
+ int i, num;
+ u32 data, stage;
+ int off;
+ unsigned long flags;
+
+ data = 0;
+ for (i = MDP4_MIXER_STAGE_BASE; i < MDP4_MIXER_STAGE_MAX; i++) {
+ pipe = ctrl->stage[mixer][i];
+ if (pipe == NULL)
+ continue;
+ pr_debug("%s: mixer=%d ndx=%d stage=%d\n", __func__,
+ mixer, pipe->pipe_ndx, i);
+ stage = pipe->mixer_stage;
+ if (mixer >= MDP4_MIXER1)
+ stage += 8;
+ stage <<= (4 * pipe->pipe_num);
+ data |= stage;
}
- mask = 0x0f;
- mask <<= snum;
- stage <<= snum;
- data &= ~mask; /* clear old bits */
+ mdp4_mixer_blend_setup(mixer);
- data |= stage;
+ off = 0;
+ if (data != ctrl->mixer_cfg[mixer]) {
+ ctrl->mixer_cfg[mixer] = data;
+ if (mixer >= MDP4_MIXER2) {
+ /* MDP_LAYERMIXER2_IN_CFG */
+ off = 0x100f0;
+ } else {
+ /* mixer 0 or 1 */
+ num = mixer + 1;
+ num &= 0x01;
+ data |= ctrl->mixer_cfg[num];
+ off = 0x10100;
+ }
+ pr_debug("%s: mixer=%d data=%x flush=%x pid=%d\n", __func__,
+ mixer, data, ctrl->flush[mixer], current->pid);
+ }
- mdp_writel(pipe->mdp, data, 0x10100); /* MDP_LAYERMIXER_IN_CFG */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ local_irq_save(flags);
+ if (off)
+ outpdw(MDP_BASE + off, data);
- data = mdp_readl(pipe->mdp, 0x10100);
+ if (ctrl->flush[mixer]) {
+ outpdw(MDP_BASE + 0x18000, ctrl->flush[mixer]);
+ ctrl->flush[mixer] = 0;
+ }
+ local_irq_restore(flags);
+ 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_up(struct mdp4_overlay_pipe *pipe)
+{
+ struct mdp4_overlay_pipe *pp;
+ int i, mixer;
+
+ mixer = pipe->mixer_num;
+
+ for (i = MDP4_MIXER_STAGE_BASE; i < MDP4_MIXER_STAGE_MAX; i++) {
+ pp = ctrl->stage[mixer][i];
+ if (pp && pp->pipe_ndx == pipe->pipe_ndx) {
+ ctrl->stage[mixer][i] = NULL;
+ break;
+ }
+ }
+
+ ctrl->stage[mixer][pipe->mixer_stage] = pipe; /* keep it */
}
void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe)
{
- uint32_t data, mask, snum, stage, mixer, pnum;
+ struct mdp4_overlay_pipe *pp;
+ int i, mixer;
- stage = pipe->mixer_stage;
mixer = pipe->mixer_num;
- pnum = pipe->pipe_num;
- if (pipe != ctrl->stage[mixer][stage]) /* not runing */
- return;
-
- /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1 */
- data = mdp_readl(pipe->mdp, 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 */
+ for (i = MDP4_MIXER_STAGE_BASE; i < MDP4_MIXER_STAGE_MAX; i++) {
+ pp = ctrl->stage[mixer][i];
+ if (pp && pp->pipe_ndx == pipe->pipe_ndx)
+ ctrl->stage[mixer][i] = NULL; /* clear it */
}
- mask = 0x0f;
- mask <<= snum;
- data &= ~mask; /* clear old bits */
+ mdp4_mixer_stage_commit(mixer);
+}
+/*
+ * mixer0: rgb3: border color at register 0x15004, 0x15008
+ * mixer1: vg3: border color at register 0x1D004, 0x1D008
+ * mixer2: xxx: border color at register 0x8D004, 0x8D008
+ */
+void mdp4_overlay_borderfill_stage_up(struct mdp4_overlay_pipe *pipe)
+{
+ struct mdp4_overlay_pipe *bspipe;
+ int ptype, pnum, pndx, mixer;
+ int format, alpha_enable, alpha;
- mdp_writel(pipe->mdp, data, 0x10100); /* MDP_LAYERMIXER_IN_CFG */
+ if (pipe->pipe_type != OVERLAY_TYPE_BF)
+ return;
- data = mdp_readl(pipe->mdp, 0x10100);
+ mixer = pipe->mixer_num;
- ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL; /* clear it */
+ if (ctrl->baselayer[mixer])
+ return;
+
+ bspipe = ctrl->stage[mixer][MDP4_MIXER_STAGE_BASE];
+
+ /*
+ * bspipe is clone here
+ * get real pipe
+ */
+ bspipe = mdp4_overlay_ndx2pipe(bspipe->pipe_ndx);
+
+ /* save original base layer */
+ ctrl->baselayer[mixer] = bspipe;
+
+ pipe->alpha = 0; /* make sure bf pipe has alpha 0 */
+ ptype = pipe->pipe_type;
+ pnum = pipe->pipe_num;
+ pndx = pipe->pipe_ndx;
+ format = pipe->src_format;
+ alpha_enable = pipe->alpha_enable;
+ alpha = pipe->alpha;
+ *pipe = *bspipe; /* keep base layer configuration */
+ pipe->pipe_type = ptype;
+ pipe->pipe_num = pnum;
+ pipe->pipe_ndx = pndx;
+ pipe->src_format = format;
+ pipe->alpha_enable = alpha_enable;
+ pipe->alpha = alpha;
+
+ /* free original base layer pipe to be sued as normal pipe */
+ bspipe->pipe_used = 0;
+
+ if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
+ mdp4_dsi_video_base_swap(0, pipe);
+ else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
+ mdp4_dsi_cmd_base_swap(0, pipe);
+ else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
+ mdp4_lcdc_base_swap(0, pipe);
+#ifdef CONFIG_FB_MSM_DTV
+ else if (ctrl->panel_mode & MDP4_PANEL_DTV)
+ mdp4_dtv_base_swap(0, pipe);
+#endif
+
+ mdp4_overlay_reg_flush(bspipe, 1);
+ /* borderfill pipe as base layer */
+ mdp4_mixer_stage_up(pipe);
}
-void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe)
+void mdp4_overlay_borderfill_stage_down(struct mdp4_overlay_pipe *pipe)
{
- struct mdp4_overlay_pipe *bg_pipe;
- uint32_t overlay_base;
- uint32_t c0, c1, c2, blend_op;
- int off;
+ struct mdp4_overlay_pipe *bspipe;
+ int ptype, pnum, pndx, mixer;
+ int format, alpha_enable, alpha;
- if (pipe->mixer_num) /* mixer number, /dev/fb0, /dev/fb1 */
- overlay_base = MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
- else
- overlay_base = MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+ if (pipe->pipe_type != OVERLAY_TYPE_BF)
+ return;
- /* stage 0 to stage 2 */
- off = 0x20 * (pipe->mixer_stage - MDP4_MIXER_STAGE0);
+ mixer = pipe->mixer_num;
- bg_pipe = mdp4_overlay_stage_pipe(pipe->mixer_num,
- MDP4_MIXER_STAGE_BASE);
- if (bg_pipe == NULL) {
- PR_DISP_INFO("%s: Error: no bg_pipe\n", __func__);
+ /* retrieve original base layer */
+ bspipe = ctrl->baselayer[mixer];
+ if (bspipe == NULL) {
+ pr_err("%s: no base layer at mixer=%d\n",
+ __func__, mixer);
return;
}
+ ptype = bspipe->pipe_type;
+ pnum = bspipe->pipe_num;
+ pndx = bspipe->pipe_ndx;
+ format = bspipe->src_format;
+ alpha_enable = bspipe->alpha_enable;
+ alpha = bspipe->alpha;
+ *bspipe = *pipe; /* restore base layer configuration */
+ bspipe->pipe_type = ptype;
+ bspipe->pipe_num = pnum;
+ bspipe->pipe_ndx = pndx;
+ bspipe->src_format = format;
+ bspipe->alpha_enable = alpha_enable;
+ bspipe->alpha = alpha;
- blend_op = 0;
- if (pipe->is_fg) {
- blend_op |= (MDP4_BLEND_FG_ALPHA_FG_CONST |
- MDP4_BLEND_BG_ALPHA_BG_CONST);
- mdp_writel(pipe->mdp, pipe->alpha, overlay_base + off + 0x108);
- mdp_writel(pipe->mdp, 0xff - pipe->alpha, overlay_base + off + 0x10c);
+ bspipe->pipe_used++; /* mark base layer pipe used */
+
+ ctrl->baselayer[mixer] = NULL;
+
+ /* free borderfill pipe */
+ pipe->pipe_used = 0;
+
+ if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
+ mdp4_dsi_video_base_swap(0, bspipe);
+ else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
+ mdp4_dsi_cmd_base_swap(0, bspipe);
+ else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
+ mdp4_lcdc_base_swap(0, bspipe);
+#ifdef CONFIG_FB_MSM_DTV
+ else if (ctrl->panel_mode & MDP4_PANEL_DTV)
+ mdp4_dtv_base_swap(0, bspipe);
+#endif
+
+ /* free borderfill pipe */
+ mdp4_overlay_reg_flush(pipe, 1);
+ mdp4_mixer_stage_down(pipe);
+ mdp4_overlay_pipe_free(pipe);
+
+ /* stage up base layer */
+ mdp4_overlay_reg_flush(bspipe, 1);
+ /* restore original base layer */
+ mdp4_mixer_stage_up(bspipe);
+}
+
+
+static struct mdp4_overlay_pipe *mdp4_background_layer(int mixer,
+ struct mdp4_overlay_pipe *sp)
+{
+ struct mdp4_overlay_pipe *pp;
+ struct mdp4_overlay_pipe *kp;
+ int i;
+
+ kp = ctrl->stage[mixer][MDP4_MIXER_STAGE_BASE];
+ for (i = MDP4_MIXER_STAGE_BASE; i < MDP4_MIXER_STAGE_MAX; i++) {
+ pp = ctrl->stage[mixer][i];
+ if (pp == NULL)
+ continue;
+ if (pp == sp)
+ break;
+
+ if ((pp->dst_x <= sp->dst_x) &&
+ ((pp->dst_x + pp->dst_w) >= (sp->dst_x + sp->dst_w))) {
+ if ((pp->dst_y <= sp->dst_y) &&
+ ((pp->dst_y + pp->dst_h) >=
+ (sp->dst_y + sp->dst_h))) {
+ kp = pp;
+ }
+ }
+ }
+ return kp;
+}
+
+static void mdp4_overlay_bg_solidfill(struct blend_cfg *blend)
+{
+ struct mdp4_overlay_pipe *pipe;
+ char *base;
+ u32 op_mode, format;
+ int pnum, ptype;
+
+ pipe = blend->solidfill_pipe;
+ if (pipe == NULL)
+ return;
+
+ if (pipe->pipe_type == OVERLAY_TYPE_BF)
+ return;
+
+ ptype = mdp4_overlay_format2type(pipe->src_format);
+ if (ptype == OVERLAY_TYPE_RGB) {
+ pnum = pipe->pipe_num - OVERLAY_PIPE_RGB1;
+ base = MDP_BASE + MDP4_RGB_BASE;
+ base += MDP4_RGB_OFF * pnum;
} 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) {
- blend_op = (MDP4_BLEND_BG_ALPHA_BG_PIXEL |
- MDP4_BLEND_FG_ALPHA_BG_PIXEL |
- MDP4_BLEND_FG_INV_ALPHA);
- }
+ pnum = pipe->pipe_num - OVERLAY_PIPE_VG1;
+ base = MDP_BASE + MDP4_VIDEO_BASE;
+ base += MDP4_VIDEO_OFF * pnum;
}
- if (pipe->transp != MDP_TRANSP_NOP) {
- if (pipe->is_fg) {
- transp_color_key(pipe->src_format, pipe->transp,
- &c0, &c1, &c2);
-#if 0
- /* FIXME: We don't enable this function until framework can support color keying. */
- blend_op |= MDP4_BLEND_FG_TRANSP_EN; /* Fg blocked */
-#endif
- /* lower limit */
- mdp_writel(pipe->mdp, (c1 << 16 | c0), overlay_base + off + 0x110); /* low */
- mdp_writel(pipe->mdp, c2, overlay_base + off + 0x114);/* low */
- /* upper limit */
- mdp_writel(pipe->mdp, (c1 << 16 | c0), overlay_base + off + 0x118);/* high */
- mdp_writel(pipe->mdp, c2, overlay_base + off + 0x11c);/* high */
- } else {
- transp_color_key(bg_pipe->src_format, pipe->transp,
- &c0, &c1, &c2);
-#if 0
- blend_op |= MDP4_BLEND_BG_TRANSP_EN; /* bg blocked */
-#endif
- /* lower limit */
- mdp_writel(pipe->mdp, (c1 << 16 | c0), overlay_base + off + 0x180);/* low */
- mdp_writel(pipe->mdp, c2, overlay_base + off + 0x184);/* low */
- /* upper limit */
- mdp_writel(pipe->mdp, (c1 << 16 | c0), overlay_base + off + 0x188);/* high */
- mdp_writel(pipe->mdp, c2, overlay_base + off + 0x18c);/* high */
- }
+ format = inpdw(base + 0x50);
+ if (blend->solidfill) {
+ format |= MDP4_FORMAT_SOLID_FILL;
+ /*
+ * If solid fill is enabled, flip and scale
+ * have to be disabled. otherwise, h/w
+ * underruns.
+ */
+ op_mode = inpdw(base + 0x0058);
+ op_mode &= ~(MDP4_OP_FLIP_LR + MDP4_OP_SCALEX_EN);
+ op_mode &= ~(MDP4_OP_FLIP_UD + MDP4_OP_SCALEY_EN);
+ outpdw(base + 0x0058, op_mode);
+ outpdw(base + 0x1008, 0); /* black */
+ /*
+ * Set src size and dst size same to avoid underruns
+ */
+ outpdw(base + 0x0000, inpdw(base + 0x0008));
+ } else {
+ u32 src_size = ((pipe->src_h << 16) | pipe->src_w);
+ outpdw(base + 0x0000, src_size);
+ format &= ~MDP4_FORMAT_SOLID_FILL;
+ blend->solidfill_pipe = NULL;
}
- mdp_writel(pipe->mdp, blend_op, overlay_base + off + 0x104);
+ outpdw(base + 0x50, format);
+
+ mdp4_overlay_reg_flush(pipe, 0);
+}
+
+/*
+ * D(i+1) = Ks * S + Kd * D(i)
+ */
+void mdp4_mixer_blend_setup(int mixer)
+{
+ struct mdp4_overlay_pipe *d_pipe;
+ struct mdp4_overlay_pipe *s_pipe;
+ struct blend_cfg *blend;
+ int i, off, ptype;
+ int d_alpha, s_alpha;
+ unsigned char *overlay_base;
+ uint32 c0, c1, c2;
+
+
+ d_pipe = ctrl->stage[mixer][MDP4_MIXER_STAGE_BASE];
+ if (d_pipe == NULL) {
+ pr_err("%s: Error: no bg_pipe at mixer=%d\n", __func__, mixer);
+ return;
+ }
+
+ blend = &ctrl->blend[mixer][MDP4_MIXER_STAGE0];
+ for (i = MDP4_MIXER_STAGE0; i < MDP4_MIXER_STAGE_MAX; i++) {
+ blend->solidfill = 0;
+ blend->op = (MDP4_BLEND_FG_ALPHA_FG_CONST |
+ MDP4_BLEND_BG_ALPHA_BG_CONST);
+ s_pipe = ctrl->stage[mixer][i];
+ if (s_pipe == NULL) {
+ blend++;
+ d_pipe = NULL;
+ d_alpha = 0;
+ continue;
+ }
+ d_pipe = mdp4_background_layer(mixer, s_pipe);
+ d_alpha = d_pipe->alpha_enable;
+ s_alpha = s_pipe->alpha_enable;
+ pr_debug("%s: stage=%d: bg: ndx=%d da=%d dalpha=%x "
+ "fg: ndx=%d sa=%d salpha=%x is_fg=%d\n",
+ __func__, i-2, d_pipe->pipe_ndx, d_alpha, d_pipe->alpha,
+ s_pipe->pipe_ndx, s_alpha, s_pipe->alpha, s_pipe->is_fg);
+
+ /* base on fg's alpha */
+ blend->bg_alpha = 0x0ff - s_pipe->alpha;
+ blend->fg_alpha = s_pipe->alpha;
+ blend->co3_sel = 1; /* use fg alpha */
+
+ if (s_pipe->is_fg) {
+ if (s_pipe->alpha == 0xff) {
+ blend->solidfill = 1;
+ blend->solidfill_pipe = d_pipe;
+ }
+ } else if (s_alpha) {
+ blend->op = (MDP4_BLEND_BG_ALPHA_FG_PIXEL |
+ MDP4_BLEND_BG_INV_ALPHA);
+ } else if (d_alpha) {
+ ptype = mdp4_overlay_format2type(s_pipe->src_format);
+ if (ptype == OVERLAY_TYPE_VIDEO) {
+ blend->op = (MDP4_BLEND_BG_ALPHA_BG_PIXEL |
+ MDP4_BLEND_FG_ALPHA_BG_PIXEL |
+ MDP4_BLEND_FG_INV_ALPHA);
+ blend->co3_sel = 0; /* use bg alpha */
+ } else {
+ /* s_pipe is rgb without alpha */
+ blend->op = (MDP4_BLEND_FG_ALPHA_FG_CONST |
+ MDP4_BLEND_BG_ALPHA_BG_CONST);
+ blend->bg_alpha = 0;
+ }
+ }
+
+ if (s_pipe->transp != MDP_TRANSP_NOP) {
+ if (s_pipe->is_fg) {
+ transp_color_key(s_pipe->src_format,
+ s_pipe->transp, &c0, &c1, &c2);
+ /* Fg blocked */
+ blend->op |= MDP4_BLEND_FG_TRANSP_EN;
+ /* lower limit */
+ blend->transp_low0 = (c1 << 16 | c0);
+ blend->transp_low1 = c2;
+ /* upper limit */
+ blend->transp_high0 = (c1 << 16 | c0);
+ blend->transp_high1 = c2;
+ } else {
+ transp_color_key(d_pipe->src_format,
+ s_pipe->transp, &c0, &c1, &c2);
+ /* Fg blocked */
+ blend->op |= MDP4_BLEND_BG_TRANSP_EN;
+ blend--; /* one stage back */
+ /* lower limit */
+ blend->transp_low0 = (c1 << 16 | c0);
+ blend->transp_low1 = c2;
+ /* upper limit */
+ blend->transp_high0 = (c1 << 16 | c0);
+ blend->transp_high1 = c2;
+ blend++; /* back to original stage */
+ }
+ }
+ blend++;
+ }
+
+ /* mixer numer, /dev/fb0, /dev/fb1, /dev/fb2 */
+ if (mixer == MDP4_MIXER2)
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC2_BASE;/* 0x88000 */
+ else if (mixer == MDP4_MIXER1)
+ 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);
+ blend = &ctrl->blend[mixer][MDP4_MIXER_STAGE_BASE];
+ /* lower limit */
+ outpdw(overlay_base + 0x180, blend->transp_low0);
+ outpdw(overlay_base + 0x184, blend->transp_low1);
+ /* upper limit */
+ outpdw(overlay_base + 0x188, blend->transp_high0);
+ outpdw(overlay_base + 0x18c, blend->transp_high1);
+ blend++; /* stage0 */
+ for (i = MDP4_MIXER_STAGE0; i < MDP4_MIXER_STAGE_MAX; i++) {
+ off = 20 * i;
+ off = 0x20 * (i - MDP4_MIXER_STAGE0);
+ if (i == MDP4_MIXER_STAGE3)
+ off -= 4;
+
+ if (blend->solidfill_pipe)
+ mdp4_overlay_bg_solidfill(blend);
+
+ outpdw(overlay_base + off + 0x108, blend->fg_alpha);
+ outpdw(overlay_base + off + 0x10c, blend->bg_alpha);
+ outpdw(overlay_base + off + 0x104, blend->op);
+ outpdw(overlay_base + (off << 5) + 0x1004, blend->co3_sel);
+ outpdw(overlay_base + off + 0x110, blend->transp_low0);/* low */
+ outpdw(overlay_base + off + 0x114, blend->transp_low1);/* low */
+ /* upper limit */
+ outpdw(overlay_base + off + 0x118, blend->transp_high0);
+ outpdw(overlay_base + off + 0x11c, blend->transp_high1);
+ blend++;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all)
{
- uint32_t bits = 0;
+ int mixer;
+ uint32 *reg;
- if (pipe->mixer_num == MDP4_MIXER1)
- bits |= 0x02;
- else
- bits |= 0x01;
+ mixer = pipe->mixer_num;
+ reg = &ctrl->flush[mixer];
+ *reg |= (1 << (2 + pipe->pipe_num));
if (all) {
- if (pipe->pipe_num <= OVERLAY_PIPE_RGB2) {
- if (pipe->pipe_num == OVERLAY_PIPE_RGB2)
- bits |= 0x20;
- else
- bits |= 0x10;
- } else {
- if (pipe->pipe_num == OVERLAY_PIPE_VG2)
- bits |= 0x08;
- else
- bits |= 0x04;
- }
+ if (mixer == MDP4_MIXER0)
+ *reg |= 0x01;
+ else
+ *reg |= 0x02;
}
+}
- mdp_writel(pipe->mdp, bits, 0x18000); /* MDP_OVERLAY_REG_FLUSH */
+void mdp4_overlay_flush_piggyback(int m0, int m1)
+{
+ u32 data;
+
+ data = ctrl->flush[m0] | ctrl->flush[m1];
+ ctrl->flush[m0] = data;
+}
+
+void mdp4_overlay_reg_flush_reset(struct mdp4_overlay_pipe *pipe)
+{
+ int mixer;
+
+ mixer = pipe->mixer_num;
+ ctrl->flush[mixer] = 0;
}
struct mdp4_overlay_pipe *mdp4_overlay_stage_pipe(int mixer, int stage)
@@ -1285,7 +2062,7 @@
{
struct mdp4_overlay_pipe *pipe;
- if (ndx <= 0 || ndx > MDP4_MAX_PIPE)
+ if (ndx <= 0 || ndx > OVERLAY_PIPE_MAX)
return NULL;
pipe = &ctrl->plist[ndx - 1]; /* ndx start from 1 */
@@ -1296,25 +2073,33 @@
return pipe;
}
-struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(int ptype, bool usevg)
+struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(int ptype, int mixer)
{
- int i = 0;
+ int i;
struct mdp4_overlay_pipe *pipe;
- if (usevg)
- i = 2;
- pipe = &ctrl->plist[i];
- for (; i < MDP4_MAX_PIPE; i++) {
- if (pipe->pipe_type == ptype && pipe->pipe_used == 0) {
- init_completion(&pipe->comp);
- PR_DISP_INFO("mdp4_overlay_pipe_alloc: pipe=%x ndx=%d\n",
- (int)pipe, pipe->pipe_ndx);
- return pipe;
- }
- pipe++;
+ if (ptype == OVERLAY_TYPE_BF) {
+ if (!mdp4_overlay_borderfill_supported())
+ return NULL;
}
- PR_DISP_INFO("mdp4_overlay_pipe_alloc: ptype=%d FAILED\n", ptype);
+ for (i = 0; i < OVERLAY_PIPE_MAX; i++) {
+ pipe = &ctrl->plist[i];
+ if ((pipe->pipe_used == 0) && ((pipe->pipe_type == ptype) ||
+ (ptype == OVERLAY_TYPE_RGB &&
+ pipe->pipe_type == OVERLAY_TYPE_VIDEO))) {
+ if (ptype == OVERLAY_TYPE_BF &&
+ mixer != pipe->mixer_num)
+ continue;
+ init_completion(&pipe->comp);
+ init_completion(&pipe->dmas_comp);
+ pr_debug("%s: pipe=%x ndx=%d num=%d\n", __func__,
+ (int)pipe, pipe->pipe_ndx, pipe->pipe_num);
+ return pipe;
+ }
+ }
+
+ pr_err("%s: ptype=%d FAILED\n", __func__, ptype);
return NULL;
}
@@ -1322,138 +2107,220 @@
void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe)
{
- uint32_t ptype, num, ndx;
- struct mdp4_pipe_desc *pd;
+ uint32 ptype, num, ndx, mixer;
+ struct mdp4_iommu_pipe_info iom;
- PR_DISP_INFO("mdp4_overlay_pipe_free: pipe=%x ndx=%d\n",
- (int)pipe, pipe->pipe_ndx);
- pd = &ctrl->ov_pipe[pipe->pipe_num];
- if (pd->ref_cnt)
- pd->ref_cnt--;
-
- pd->player = NULL;
+ pr_debug("%s: pipe=%x ndx=%d\n", __func__, (int)pipe, pipe->pipe_ndx);
ptype = pipe->pipe_type;
num = pipe->pipe_num;
ndx = pipe->pipe_ndx;
+ mixer = pipe->mixer_num;
+ mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 0);
+
+ iom = pipe->iommu;
memset(pipe, 0, sizeof(*pipe));
-
pipe->pipe_type = ptype;
pipe->pipe_num = num;
pipe->pipe_ndx = ndx;
-}
+ pipe->mixer_num = mixer;
+ pipe->iommu = iom;
-int mdp4_overlay_req_check(uint32_t id, uint32_t z_order, uint32_t mixer)
-{
- struct mdp4_overlay_pipe *pipe;
- /* HTC to support multiple overlays, correct stage array mapping
- *
- * base layer == 1, reserved for frame buffer
- * zorder 0 == stage 0 == 2
- * zorder 1 == stage 1 == 3
- * zorder 2 == stage 2 == 4
- */
- /* FIXME: original design has problem, therefore, prevent query out of range stage array here */
- if (z_order + MDP4_MIXER_STAGE0 >= MDP4_MAX_STAGE) {
- PR_DISP_ERR("%s(%d) zorder=%d out of stage arry range\n", __func__, __LINE__, z_order);
- return -EPERM;
- }
-
- pipe = ctrl->stage[mixer][z_order+MDP4_MIXER_STAGE0];
-
- 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_req2pipe(struct mdp_overlay *req, int mixer,
- struct mdp4_overlay_pipe **ppipe)
+ struct mdp4_overlay_pipe **ppipe,
+ struct msm_fb_data_type *mfd)
{
struct mdp4_overlay_pipe *pipe;
- struct mdp4_pipe_desc *pd;
int ret, ptype;
- if (mixer >= MDP4_MAX_MIXER) {
- PR_DISP_ERR("mpd_overlay_req2pipe: mixer out of range!\n");
+ u32 upscale_max;
+ upscale_max = (mdp_rev >= MDP_REV_41) ?
+ MDP4_REV41_OR_LATER_UP_SCALING_MAX :
+ MDP4_REV40_UP_SCALING_MAX;
+
+ if (mfd == NULL) {
+ pr_err("%s: mfd == NULL, -ENODEV\n", __func__);
+ return -ENODEV;
+ }
+
+ if (mixer >= MDP4_MIXER_MAX) {
+ 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_DISP_ERR("mpd_overlay_req2pipe: z_order=%d out of range!\n",
+ if (req->z_order < 0 || req->z_order > 3) {
+ 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_DISP_ERR("mpd_overlay_req2pipe: src img of zero size!\n");
+ if (req->src_rect.h > 0xFFF) {
+ pr_err("%s: src_h is out of range: 0X%x!\n",
+ __func__, req->src_rect.h);
+ mdp4_stat.err_size++;
return -EINVAL;
}
+ if (req->src_rect.w > 0xFFF) {
+ pr_err("%s: src_w is out of range: 0X%x!\n",
+ __func__, req->src_rect.w);
+ mdp4_stat.err_size++;
+ return -EINVAL;
+ }
- if (req->dst_rect.h > (req->src_rect.h * 8)) { /* too much */
- PR_DISP_ERR("mpd_overlay_req2pipe: too much (h)!\n");
+ if (req->src_rect.x > 0xFFF) {
+ pr_err("%s: src_x is out of range: 0X%x!\n",
+ __func__, req->src_rect.x);
+ mdp4_stat.err_size++;
+ return -EINVAL;
+ }
+
+ if (req->src_rect.y > 0xFFF) {
+ pr_err("%s: src_y is out of range: 0X%x!\n",
+ __func__, req->src_rect.y);
+ mdp4_stat.err_size++;
+ return -EINVAL;
+ }
+
+ if (req->dst_rect.h > 0xFFF) {
+ pr_err("%s: dst_h is out of range: 0X%x!\n",
+ __func__, req->dst_rect.h);
+ mdp4_stat.err_size++;
+ return -EINVAL;
+ }
+
+ if (req->dst_rect.w > 0xFFF) {
+ pr_err("%s: dst_w is out of range: 0X%x!\n",
+ __func__, req->dst_rect.w);
+ mdp4_stat.err_size++;
+ return -EINVAL;
+ }
+
+ if (req->dst_rect.x > 0xFFF) {
+ pr_err("%s: dst_x is out of range: 0X%x!\n",
+ __func__, req->dst_rect.x);
+ mdp4_stat.err_size++;
+ return -EINVAL;
+ }
+
+ if (req->dst_rect.y > 0xFFF) {
+ pr_err("%s: dst_y is out of range: 0X%x!\n",
+ __func__, req->dst_rect.y);
+ mdp4_stat.err_size++;
+ return -EINVAL;
+ }
+
+ 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 * upscale_max)) {
+ 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 */
- PR_DISP_ERR("mpd_overlay_req2pipe: too little (h)!\n");
+ 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 */
- PR_DISP_ERR("mpd_overlay_req2pipe: too much (w)!\n");
+ if (req->dst_rect.w > (req->src_rect.w * upscale_max)) {
+ 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 */
- PR_DISP_ERR("mpd_overlay_req2pipe: too little (w)!\n");
+ mdp4_stat.err_scale++;
+ pr_err("%s: scale down, too little (w)!\n", __func__);
return -ERANGE;
}
- /* Current mdp only support the maximum 1/4 downscaling */
- if (req->src_rect.w > req->dst_rect.w * 4 || req->src_rect.h > req->dst_rect.h * 4) {
- PR_DISP_ERR("mdp_overlay_req2pipe: Don't support this kind of downscalig srcw=%d srch=%d dstw=%d dsth=%d\n",
- req->src_rect.w, req->src_rect.h, req->dst_rect.w, req->dst_rect.h);
- return -EINVAL;
+ 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)
+ if (ptype < 0) {
+ pr_err("%s: mdp4_overlay_format2type!\n", __func__);
return ptype;
+ }
- if (req->id == MSMFB_NEW_REQUEST) /* new request */
- pipe = mdp4_overlay_pipe_alloc(ptype, true);
+ if (req->flags & MDP_OV_PIPE_SHARE)
+ ptype = OVERLAY_TYPE_VIDEO; /* VG pipe supports both RGB+YUV */
+
+ if (req->id == MSMFB_NEW_REQUEST) /* new request */
+ pipe = mdp4_overlay_pipe_alloc(ptype, mixer);
else
pipe = mdp4_overlay_ndx2pipe(req->id);
- if (pipe == NULL)
+ 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_DISP_ERR("mpd_overlay_req2pipe: h>h || w>w!\n");
- return -ERANGE;
- }
+ if (!display_iclient && !IS_ERR_OR_NULL(mfd->iclient)) {
+ display_iclient = mfd->iclient;
+ pr_debug("%s(): display_iclient %p\n", __func__,
+ display_iclient);
}
pipe->src_format = req->src.format;
ret = mdp4_overlay_format2pipe(pipe);
- if (ret < 0)
+ if (ret < 0) {
+ pr_err("%s: mdp4_overlay_format2pipe!\n", __func__);
return ret;
+ }
/*
* base layer == 1, reserved for frame buffer
@@ -1462,18 +2329,16 @@
* zorder 2 == stage 2 == 4
*/
if (req->id == MSMFB_NEW_REQUEST) { /* new request */
- pd = &ctrl->ov_pipe[pipe->pipe_num];
- pd->ref_cnt++;
pipe->pipe_used++;
pipe->mixer_num = mixer;
- PR_DISP_INFO("mpd4_overlay_req2pipe: zorder=%d pipe_num=%d\n",
- req->z_order, pipe->pipe_num);
+ pr_debug("%s: zorder=%d pipe ndx=%d num=%d\n", __func__,
+ req->z_order, pipe->pipe_ndx, pipe->pipe_num);
+
}
pipe->mixer_stage = req->z_order + MDP4_MIXER_STAGE0;
-
- pipe->src_width = req->src.width & 0x07ff; /* source img width */
- pipe->src_height = req->src.height & 0x07ff; /* source img height */
+ pipe->src_width = req->src.width & 0x1fff; /* source img width */
+ pipe->src_height = req->src.height & 0x1fff; /* 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;
@@ -1483,9 +2348,6 @@
pipe->dst_y = req->dst_rect.y & 0x07ff;
pipe->dst_x = req->dst_rect.x & 0x07ff;
- if (mdp4_overlay_parameters_check(pipe))
- return -ERANGE;
-
pipe->op_mode = 0;
if (req->flags & MDP_FLIP_LR)
@@ -1500,137 +2362,563 @@
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;
+ pipe->flags = req->flags;
+
*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)
+static int mdp4_calc_pipe_mdp_clk(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
{
- int put_needed, ret = 0, fb_num;
- struct file *file;
-#ifdef CONFIG_ANDROID_PMEM
- unsigned long vstart;
-#endif
+ u32 pclk;
+ u32 xscale, yscale;
+ u32 hsync = 0;
+ u32 shift = 16;
+ u64 rst;
+ int ret = -EINVAL;
-#ifdef CONFIG_ANDROID_PMEM
- if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file))
+ if (!pipe) {
+ pr_err("%s: pipe is null!\n", __func__);
+ pipe->req_bw = OVERLAY_PERF_LEVEL4;
+ return ret;
+ }
+ if (!mfd) {
+ pr_err("%s: mfd is null!\n", __func__);
+ pipe->req_bw = OVERLAY_PERF_LEVEL4;
+ return ret;
+ }
+
+ /*
+ * Serveral special cases require the max mdp clk but cannot
+ * be explained by mdp clk equation.
+ */
+ if (pipe->flags & MDP_DEINTERLACE) {
+ pr_info("%s deinterlace requires max mdp clk.\n",
+ __func__);
+ pipe->req_clk = mdp_max_clk;
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);
+ pr_debug("%s: pipe sets: panel res(x,y)=(%d,%d)\n",
+ __func__, mfd->panel_info.xres, mfd->panel_info.yres);
+ pr_debug("%s: src(w,h)(%d,%d),src(x,y)(%d,%d)\n",
+ __func__, pipe->src_w, pipe->src_h, pipe->src_x, pipe->src_y);
+ pr_debug("%s: dst(w,h)(%d,%d),dst(x,y)(%d,%d)\n",
+ __func__, pipe->dst_w, pipe->dst_h, pipe->dst_x, pipe->dst_y);
+
+ pclk = (mfd->panel_info.type == MIPI_VIDEO_PANEL ||
+ mfd->panel_info.type == MIPI_CMD_PANEL) ?
+ mfd->panel_info.mipi.dsi_pclk_rate :
+ mfd->panel_info.clk_rate;
+ if (!pclk) {
+ pipe->req_clk = mdp_max_clk;
+ pr_err("%s panel pixel clk is zero!\n", __func__);
+ return ret;
+ }
+ pr_debug("%s: mdp panel pixel clk is %d.\n",
+ __func__, pclk);
+
+ if (!pipe->dst_h) {
+ pr_err("%s: pipe dst_h is zero!\n", __func__);
+ pipe->req_clk = mdp_max_clk;
+ return ret;
+ }
+
+ if (!pipe->src_h) {
+ pr_err("%s: pipe src_h is zero!\n", __func__);
+ pipe->req_clk = mdp_max_clk;
+ return ret;
+ }
+
+ if (!pipe->dst_w) {
+ pr_err("%s: pipe dst_w is zero!\n", __func__);
+ pipe->req_clk = mdp_max_clk;
+ return ret;
+ }
+
+ if (!pipe->dst_h) {
+ pr_err("%s: pipe dst_h is zero!\n", __func__);
+ pipe->req_clk = mdp_max_clk;
+ return ret;
+ }
+
+ /*
+ * For the scaling cases, make more margin by removing porch
+ * values and adding extra 20%.
+ */
+ if ((pipe->src_h != pipe->dst_h) ||
+ (pipe->src_w != pipe->dst_w)) {
+ hsync = mfd->panel_info.xres;
+ hsync *= 100;
+ hsync /= 120;
+ pr_debug("%s: panel hsync is %d. with scaling\n",
+ __func__, hsync);
+
+ } else {
+ hsync = 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;
+ pr_debug("%s: panel hsync is %d.\n",
+ __func__, hsync);
+ }
+
+ if (!hsync) {
+ pipe->req_clk = mdp_max_clk;
+ pr_err("%s: panel hsync is zero!\n", __func__);
+ return 0;
+ }
+
+ xscale = mfd->panel_info.xres;
+ xscale += pipe->src_w;
+
+ if (xscale < pipe->dst_w) {
+ pipe->req_clk = mdp_max_clk;
+ pr_err("%s: xres+src_w cannot be less than dst_w!\n",
+ __func__);
+ return ret;
+ }
+
+ xscale -= pipe->dst_w;
+ xscale <<= shift;
+ xscale /= hsync;
+ pr_debug("%s: the right %d shifted xscale is %d.\n",
+ __func__, shift, xscale);
+
+ if (pipe->src_h > pipe->dst_h) {
+ yscale = pipe->src_h;
+ yscale <<= shift;
+ yscale /= pipe->dst_h;
+ } else { /* upscale */
+ yscale = pipe->dst_h;
+ yscale <<= shift;
+ yscale /= pipe->src_h;
+ }
+
+ yscale *= pipe->src_w;
+ yscale /= hsync;
+
+ pr_debug("%s: the right %d shifted yscale is %d.\n",
+ __func__, shift, yscale);
+
+ rst = pclk;
+ if (yscale > xscale)
+ rst *= yscale;
+ else
+ rst *= xscale;
+
+ rst >>= shift;
+
+ /*
+ * If the calculated mdp clk is less than panel pixel clk,
+ * most likely due to upscaling, mdp clk rate will be set to
+ * greater than pclk. Now the driver uses 1.15 as the
+ * factor. Ideally this factor is passed from board file.
+ */
+ if (rst < pclk) {
+ rst = ((pclk >> shift) * 23 / 20) << shift;
+ pr_debug("%s calculated mdp clk is less than pclk.\n",
+ __func__);
+ }
+
+ pipe->req_clk = (u32) rst;
+
+ pr_debug("%s: required mdp clk %d mixer %d pipe ndx %d\n",
+ __func__, pipe->req_clk, pipe->mixer_num, pipe->pipe_ndx);
+
+ 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_BUS_SCALE_TABLE_BASE 6
+
+
+static int mdp4_calc_pipe_mdp_bw(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ u32 res;
+ int ret = -EINVAL;
+
+ if (!pipe) {
+ pr_err("%s: pipe is null!\n", __func__);
+ return ret;
+ }
+ if (!mfd) {
+ pr_err("%s: mfd is null!\n", __func__);
+ return ret;
+ }
+
+ if (pipe->flags & MDP_DEINTERLACE) {
+ pr_info("%s deinterlace requires max mdp bw.\n",
+ __func__);
+ pipe->req_bw = OVERLAY_PERF_LEVEL1;
+ return 0;
+ }
+
+ if (pipe->pipe_type == OVERLAY_TYPE_BF) {
+ pipe->req_bw = OVERLAY_PERF_LEVEL4;
+ return 0;
+ }
+
+ res = pipe->src_w * pipe->src_h;
+
+ if (res <= OVERLAY_WSVGA_SIZE)
+ pipe->req_bw = OVERLAY_PERF_LEVEL4;
+ else if (res <= OVERLAY_VGA_SIZE)
+ pipe->req_bw = OVERLAY_PERF_LEVEL3;
+ else if (res <= OVERLAY_720P_TILE_SIZE)
+ pipe->req_bw = OVERLAY_PERF_LEVEL2;
+ else
+ pipe->req_bw = OVERLAY_PERF_LEVEL1;
+
+ return 0;
+}
+
+int mdp4_overlay_mdp_perf_req(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *plist)
+{
+ u32 worst_mdp_clk = 0;
+ u32 worst_mdp_bw = OVERLAY_PERF_LEVEL4;
+ int i;
+ struct mdp4_overlay_perf *perf_req = &perf_request;
+ struct mdp4_overlay_pipe *pipe = plist;
+ u32 cnt = 0;
+ int ret = -EINVAL;
+
+ if (!mfd) {
+ pr_err("%s: mfd is null!\n", __func__);
+ return ret;
+ }
+
+ if (!plist) {
+ pr_err("%s: plist is null!\n", __func__);
+ return ret;
+ }
+
+ perf_req->use_ov0_blt = 0;
+ perf_req->use_ov1_blt = 0;
+
+ for (i = 0; i < OVERLAY_PIPE_MAX; i++, pipe++) {
+
+ if (!pipe)
+ return ret;
+
+ if (!pipe->pipe_used)
+ continue;
+ cnt++;
+ if (worst_mdp_clk < pipe->req_clk)
+ worst_mdp_clk = pipe->req_clk;
+ if (pipe->req_clk > mdp_max_clk) {
+ if (pipe->mixer_num == MDP4_MIXER0)
+ perf_req->use_ov0_blt = 1;
+ if (pipe->mixer_num == MDP4_MIXER1)
+ perf_req->use_ov1_blt = 1;
+ }
+
+ if (!pipe->req_bw) {
+ pr_err("%s mdp pipe bw request should not be zero!\n",
+ __func__);
+ pr_debug("%s %d pid %d num %d idx %d mix %d bw %d\n",
+ __func__, __LINE__, current->pid,
+ pipe->pipe_num, pipe->pipe_ndx,
+ pipe->mixer_num, pipe->req_bw);
+ pipe->req_bw = OVERLAY_PERF_LEVEL4;
+ }
+
+ if (pipe->req_bw < worst_mdp_bw)
+ worst_mdp_bw = pipe->req_bw;
+
+ if (mfd->mdp_rev == MDP_REV_41) {
+ /*
+ * writeback (blt) mode to provide work around
+ * for dsi cmd mode interface hardware bug.
+ */
+ if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
+ if (pipe->dst_x != 0)
+ perf_req->use_ov0_blt = 1;
+ }
+ if ((mfd->panel_info.xres > 1280) &&
+ (mfd->panel_info.type != DTV_PANEL)) {
+ perf_req->use_ov0_blt = 1;
+ }
+ }
+ }
+
+ perf_req->mdp_clk_rate = worst_mdp_clk;
+ if (perf_req->mdp_clk_rate > mdp_max_clk)
+ perf_req->mdp_clk_rate = mdp_max_clk;
+
+ perf_req->mdp_clk_rate = mdp_clk_round_rate(perf_req->mdp_clk_rate);
+
+ perf_req->mdp_bw = worst_mdp_bw;
+
+ if (cnt >= 3)
+ perf_req->mdp_bw = OVERLAY_PERF_LEVEL1;
+
+ pr_debug("%s %d pid %d cnt %d clk %d ov0_blt %d, ov1_blt %d bw %d\n",
+ __func__, __LINE__, current->pid, cnt,
+ perf_req->mdp_clk_rate,
+ perf_req->use_ov0_blt,
+ perf_req->use_ov1_blt,
+ perf_req->mdp_bw);
+
+ return 0;
+}
+
+int mdp4_overlay_mdp_pipe_req(struct mdp4_overlay_pipe *pipe,
+ struct msm_fb_data_type *mfd)
+{
+ int ret = 0;
+
+ if (mdp4_calc_pipe_mdp_clk(mfd, pipe)) {
+ pr_err("%s unable to calc mdp pipe clk rate ret=%d\n",
+ __func__, ret);
+ ret = -EINVAL;
+ }
+ if (mdp4_calc_pipe_mdp_bw(mfd, pipe)) {
+ pr_err("%s unable to calc mdp pipe bandwidth ret=%d\n",
+ __func__, ret);
+ ret = -EINVAL;
+ }
return ret;
}
-#ifdef CONFIG_FB_MSM_WRITE_BACK
-int mdp4_overlay_blt(struct mdp_device *mdp_dev, struct fb_info *info, struct msmfb_overlay_blt *req,
- struct file **pp_src_file)
+void mdp4_overlay_mdp_perf_upd(struct msm_fb_data_type *mfd,
+ int flag)
{
- struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
- int lcdc = 0;
- ulong addr;
- addr = get_pmem_id_addr(0);
- lcdc = mdp_readl(mdp, 0xc0000);
- if (mfd == NULL)
- return -ENODEV;
- if (req->enable) {
- if (lcdc)
- mdp4_lcdc_overlay_blt(addr); /* enable */
- else
- mdp4_mddi_overlay_blt(addr); /* enable */
- } else {
- if (lcdc)
- mdp4_lcdc_overlay_blt(0); /* disable */
- else
- mdp4_mddi_overlay_blt(0); /* disable */
+ struct mdp4_overlay_perf *perf_req = &perf_request;
+ struct mdp4_overlay_perf *perf_cur = &perf_current;
- PR_DISP_INFO("mdp4_overlay_blt: END\n");
+ pr_debug("%s %d: req mdp clk %d, cur mdp clk %d flag %d\n",
+ __func__, __LINE__,
+ perf_req->mdp_clk_rate,
+ perf_cur->mdp_clk_rate,
+ flag);
+
+ if (!mdp4_extn_disp)
+ perf_cur->use_ov1_blt = 0;
+
+ if (flag) {
+ if (perf_req->mdp_clk_rate > perf_cur->mdp_clk_rate) {
+ mdp_set_core_clk(perf_req->mdp_clk_rate);
+ pr_info("%s mdp clk is changed [%d] from %d to %d\n",
+ __func__,
+ flag,
+ perf_cur->mdp_clk_rate,
+ perf_req->mdp_clk_rate);
+ perf_cur->mdp_clk_rate =
+ perf_req->mdp_clk_rate;
+ }
+ if (perf_req->mdp_bw < perf_cur->mdp_bw) {
+ mdp_bus_scale_update_request
+ (OVERLAY_BUS_SCALE_TABLE_BASE -
+ perf_req->mdp_bw);
+ pr_info("%s mdp bw is changed [%d] from %d to %d\n",
+ __func__,
+ flag,
+ perf_cur->mdp_bw,
+ perf_req->mdp_bw);
+ perf_cur->mdp_bw = perf_req->mdp_bw;
+ }
+ if (mfd->panel_info.pdest == DISPLAY_1 &&
+ perf_req->use_ov0_blt && !perf_cur->use_ov0_blt) {
+ if (mfd->panel_info.type == LCDC_PANEL ||
+ mfd->panel_info.type == LVDS_PANEL)
+ mdp4_lcdc_overlay_blt_start(mfd);
+ else if (mfd->panel_info.type == MIPI_VIDEO_PANEL)
+ mdp4_dsi_video_blt_start(mfd);
+ else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
+ mdp4_dsi_cmd_blt_start(mfd);
+ pr_info("%s mixer0 start blt [%d] from %d to %d.\n",
+ __func__,
+ flag,
+ perf_cur->use_ov0_blt,
+ perf_req->use_ov0_blt);
+ perf_cur->use_ov0_blt = perf_req->use_ov0_blt;
+ }
+ if (mfd->panel_info.pdest == DISPLAY_2 &&
+ perf_req->use_ov1_blt && !perf_cur->use_ov1_blt) {
+ mdp4_dtv_overlay_blt_start(mfd);
+ pr_info("%s mixer1 start blt [%d] from %d to %d.\n",
+ __func__,
+ flag,
+ perf_cur->use_ov1_blt,
+ perf_req->use_ov1_blt);
+ perf_cur->use_ov1_blt = perf_req->use_ov1_blt;
+ }
+ } else {
+ if (perf_req->mdp_clk_rate < perf_cur->mdp_clk_rate) {
+ pr_info("%s mdp clk is changed [%d] from %d to %d\n",
+ __func__,
+ flag,
+ perf_cur->mdp_clk_rate,
+ perf_req->mdp_clk_rate);
+ mdp_set_core_clk(perf_req->mdp_clk_rate);
+ perf_cur->mdp_clk_rate =
+ perf_req->mdp_clk_rate;
+ }
+ if (perf_req->mdp_bw > perf_cur->mdp_bw) {
+ pr_info("%s mdp bw is changed [%d] from %d to %d\n",
+ __func__,
+ flag,
+ perf_cur->mdp_bw,
+ perf_req->mdp_bw);
+ mdp_bus_scale_update_request
+ (OVERLAY_BUS_SCALE_TABLE_BASE -
+ perf_req->mdp_bw);
+ perf_cur->mdp_bw = perf_req->mdp_bw;
+ }
+ if (mfd->panel_info.pdest == DISPLAY_1 &&
+ !perf_req->use_ov0_blt && perf_cur->use_ov0_blt) {
+ if (mfd->panel_info.type == LCDC_PANEL ||
+ mfd->panel_info.type == LVDS_PANEL)
+ mdp4_lcdc_overlay_blt_stop(mfd);
+ else if (mfd->panel_info.type == MIPI_VIDEO_PANEL)
+ mdp4_dsi_video_blt_stop(mfd);
+ else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
+ mdp4_dsi_cmd_blt_stop(mfd);
+ pr_info("%s mixer0 stop blt [%d] from %d to %d.\n",
+ __func__,
+ flag,
+ perf_cur->use_ov0_blt,
+ perf_req->use_ov0_blt);
+ perf_cur->use_ov0_blt = perf_req->use_ov0_blt;
+ }
+ if (mfd->panel_info.pdest == DISPLAY_2 &&
+ !perf_req->use_ov1_blt && perf_cur->use_ov1_blt) {
+ mdp4_dtv_overlay_blt_stop(mfd);
+ pr_info("%s mixer1 stop blt [%d] from %d to %d.\n",
+ __func__,
+ flag,
+ perf_cur->use_ov1_blt,
+ perf_req->use_ov1_blt);
+ perf_cur->use_ov1_blt = perf_req->use_ov1_blt;
+ }
+ }
+ return;
+}
+
+static int get_img(struct msmfb_data *img, struct fb_info *info,
+ struct mdp4_overlay_pipe *pipe, unsigned int plane,
+ unsigned long *start, unsigned long *len, struct file **srcp_file,
+ int *p_need, struct ion_handle **srcp_ihdl)
+{
+ struct file *file;
+ int put_needed, ret = 0, fb_num;
+#ifdef CONFIG_ANDROID_PMEM
+ unsigned long vstart;
+#endif
+ *p_need = 0;
+
+ if (img->flags & MDP_BLIT_SRC_GEM) {
+ *srcp_file = NULL;
+ return kgsl_gem_obj_addr(img->memory_id, (int) img->priv,
+ start, len);
}
- return 0;
+ if (img->flags & MDP_MEMORY_ID_TYPE_FB) {
+ file = fget_light(img->memory_id, &put_needed);
+ if (file == NULL)
+ return -EINVAL;
+
+ 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,
+ DISPLAY_SUBSYSTEM_ID)) {
+ ret = -1;
+ } else {
+ pr_warn("%s: mdp4_overlay play with FB memory\n",
+ __func__);
+ *srcp_file = file;
+ *p_need = put_needed;
+ }
+ } else
+ ret = -1;
+ if (ret)
+ fput_light(file, put_needed);
+ return ret;
+ }
+
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ return mdp4_overlay_iommu_map_buf(img->memory_id, pipe, plane,
+ start, len, srcp_ihdl);
+#endif
+#ifdef CONFIG_ANDROID_PMEM
+ if (!get_pmem_file(img->memory_id, start, &vstart,
+ len, srcp_file))
+ return 0;
+ else
+ return -EINVAL;
+#endif
+}
+
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+int mdp4_overlay_3d_sbys(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;
+
+ if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
+ mdp4_dsi_cmd_3d_sbys(mfd, req);
+ ret = 0;
+ } else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
+ mdp4_dsi_video_3d_sbys(mfd, req);
+ ret = 0;
+ }
+ mutex_unlock(&mfd->dma->ov_mutex);
+
+ return ret;
+}
+#else
+int mdp4_overlay_3d_sbys(struct fb_info *info, struct msmfb_overlay_3d *req)
+{
+ /* do nothing */
+ return -EPERM;
}
#endif
-int mdp4_overlay_change_z_order_vg_pipes(struct fb_info *info)
+int mdp4_overlay_blt(struct fb_info *info, struct msmfb_overlay_blt *req)
{
- struct mdp4_overlay_pipe *pipeS1, *pipeS2;
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
- pipeS1 = &ctrl->plist[4]; /* ndx start from 1 */
- pipeS2 = &ctrl->plist[5]; /* ndx start from 1 */
-
- if (ctrl->stage[pipeS1->mixer_num][pipeS1->mixer_stage] == NULL ||
- ctrl->stage[pipeS2->mixer_num][pipeS2->mixer_stage] == NULL) {
- PR_DISP_ERR("mdp4_overlay_change_z_order_vg_pipes: less than two VG pipes are active \n");
- z_order_change = 0;
+ if (mfd == NULL)
return -ENODEV;
- } else {
- z_order_change = 1;
- }
+
+ if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
+ return -EINTR;
+
+ if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
+ mdp4_dsi_cmd_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);
+ else if (ctrl->panel_mode & MDP4_PANEL_MDDI)
+ mdp4_mddi_overlay_blt(mfd, req);
+
+ mutex_unlock(&mfd->dma->ov_mutex);
+
return 0;
}
-static int mdp4_overlay_change_z_order_vg_pipes_actual(struct mdp4_overlay_pipe *pipe)
-{
- int data;
- int pipe1 = 0, pipe2 = 0;
- int temp;
- struct mdp4_overlay_pipe *pipeS1, *pipeS2;
-
- pipeS1 = &ctrl->plist[4]; /* ndx start from 1 */
- pipeS2 = &ctrl->plist[5]; /* ndx start from 1 */
-
- z_order_change = 0;
- if (ctrl->stage[pipeS1->mixer_num][pipeS1->mixer_stage] == NULL ||
- ctrl->stage[pipeS2->mixer_num][pipeS2->mixer_stage] == NULL) {
- PR_DISP_ERR("mdp4_overlay_change_z_order_vg_pipes: less than two VG pipes are active \n");
- mdp4_mixer_stage_up(pipe);
- return -ENODEV;
- }
-
- temp = pipeS1->mixer_stage;
- pipeS1->mixer_stage = pipeS2->mixer_stage;
- pipeS2->mixer_stage = temp;
-
- pipeS1->req_data.z_order = pipeS1->mixer_stage - MDP4_MIXER_STAGE0;
- pipeS2->req_data.z_order = pipeS2->mixer_stage - MDP4_MIXER_STAGE0;
-
- PR_DISP_INFO("mdp4_overlay_change_z_order_vg_pipes\n");
- data = mdp_readl(pipeS1->mdp, 0x10100);
- PR_DISP_INFO("mdp4_overlay_change_z_order_vg_pipes data = 0x%x\n", data);
- pipe1 = (data & 0xf) << 4;
- PR_DISP_INFO("mdp4_overlay_change_z_order_vg_pipes pipe1 = 0x%x\n", pipe1);
- pipe2 = (data & 0xf0) >> 4;
- PR_DISP_INFO("mdp4_overlay_change_z_order_vg_pipes pipe2 = 0x%x\n", pipe2);
- data &= 0xffffff00;
- data |= pipe1;
- data |= pipe2;
- PR_DISP_INFO("mdp4_overlay_change_z_order_vg_pipes data = 0x%x\n", data);
- mdp_writel(pipeS1->mdp, data, 0x10100);
- return 0;
- }
-
-int mdp4_overlay_get(struct mdp_device *mdp_dev, struct fb_info *info, struct mdp_overlay *req)
+int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req)
{
struct mdp4_overlay_pipe *pipe;
@@ -1640,174 +2928,223 @@
*req = pipe->req_data;
+ if (mdp4_overlay_borderfill_supported())
+ req->flags |= MDP_BORDERFILL_SUPPORTED;
+
return 0;
}
-
-static int mdp4_pull_mode(struct mdp4_overlay_pipe *pipe)
+int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req)
{
- uint32_t lcdc;
- if (pipe->mixer_num == MDP4_MIXER1) { /* DTV */
- lcdc = mdp_readl(pipe->mdp, 0xd0000);
- lcdc &= 0x01;
- } else { /* LCDC */
- lcdc = mdp_readl(pipe->mdp, 0x0038);
- lcdc &= 0x08;
- }
- return lcdc;
-}
-
-#ifdef CONFIG_MACH_VISION
-/* Temporary workaround before QCT release formal fix. */
-int mdp4_overlay_alter_req(struct mdp_overlay *req)
-{
- if (req->src.format == MDP_Y_CRCB_H2V2 &&
- req->src.width == 1280 && req->src.height == 720 &&
- req->dst_rect.w == 480) {
- pr_info("%s: alter req due to down-scaling issue of 720p.",
- __func__);
- req->src_rect.x = 60;
- req->src_rect.y = 90;
- req->src_rect.w = 960;
- req->src_rect.h = 540;
- }
- return 0;
-}
-#endif
-
-void mdp4_dump_ov(struct mdp_overlay *ov);
-
-int mdp4_overlay_set(struct mdp_device *mdp_dev, struct fb_info *info, struct mdp_overlay *req)
-{
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
int ret, mixer;
struct mdp4_overlay_pipe *pipe;
- int lcdc, mddi = 0;
-#ifdef CONFIG_PANEL_SELF_REFRESH
- unsigned long irq_flags = 0;
-#endif
- if (req->src.format == MDP_FB_FORMAT)
- req->src.format = MDP_RGB_565; /* mfd->fb_imgType; */
-#ifdef DEBUG_OVERLAY
- mdp4_dump_ov(req);
-#endif
-
-#ifdef CONFIG_MACH_VISION
- mdp4_overlay_alter_req(req);
-#endif
-
-#ifdef CONFIG_PANEL_SELF_REFRESH
- if (mdp->mdp_dev.overrides & MSM_MDP_RGB_PANEL_SELE_REFRESH) {
- panel_icm->force_leave();
- spin_lock_irqsave(&panel_icm->lock, irq_flags);
- panel_icm->panel_update = 1;
- spin_unlock_irqrestore(&panel_icm->lock, irq_flags);
- wake_up(&panel_update_wait_queue);
- mutex_lock(&panel_icm->icm_lock);
- panel_icm->icm_doable = false;
- mutex_unlock(&panel_icm->icm_lock);
+ if (mfd == NULL) {
+ pr_err("%s: mfd == NULL, -ENODEV\n", __func__);
+ return -ENODEV;
}
-#endif
- mixer = info->node; /* minor number of char device */
+ if (info->node != 0 || mfd->cont_splash_done) /* primary */
+ if (!mfd->panel_power_on) /* suspended */
+ return -EPERM;
- ret = mdp4_overlay_req2pipe(req, mixer, &pipe);
- if (ret < 0)
+ 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;
+ }
+
+ 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;
-
- pipe->mdp = mdp;
+ }
/* return id back to user */
req->id = pipe->pipe_ndx; /* pipe_ndx start from 1 */
pipe->req_data = *req; /* keep original req */
- if (req->user_data[OVERLAY_UPDATE_SCREEN] == OVERLAY_UPDATE_SCREEN_EN
- && pipe->srcp0_addr) {
- clk_enable(mdp->clk);
- if (pipe->pipe_num >= OVERLAY_PIPE_VG1)
- mdp4_overlay_vg_setup(pipe); /* video/graphic pipe */
- else
- mdp4_overlay_rgb_setup(pipe); /* rgb pipe */
-
- pipe->req_data.user_data[OVERLAY_UPDATE_SCREEN] = OVERLAY_UPDATE_SCREEN_DIS;
-
- mdp4_mixer_blend_setup(pipe);
- mdp4_mixer_stage_up(pipe);
-
- lcdc = mdp_readl(mdp, 0xc0000);
- if (lcdc) /* LCDC mode */
- mdp4_overlay_reg_flush(pipe, 1);
- clk_disable(mdp->clk);
+ if (!IS_ERR_OR_NULL(mfd->iclient)) {
+ pr_debug("pipe->flags 0x%x\n", pipe->flags);
+ if (pipe->flags & MDP_SECURE_OVERLAY_SESSION) {
+ mfd->mem_hid &= ~BIT(ION_IOMMU_HEAP_ID);
+ mfd->mem_hid |= ION_SECURE;
+ } else {
+ mfd->mem_hid |= BIT(ION_IOMMU_HEAP_ID);
+ mfd->mem_hid &= ~ION_SECURE;
+ }
}
- mddi = mdp_readl(pipe->mdp, 0x0038);
- mddi &= 0x02;
- if (mddi) {
- if (mdp->hw_version == MDP4_REVISION_V2_1 &&
+ 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_debug("%s: No sharpening while downscaling.\n",
+ __func__);
+ pipe->flags &= ~MDP_SHARPENING;
+ }
+ }
+
+ /* precompute HSIC matrices */
+ if (req->flags & MDP_DPP_HSIC)
+ mdp4_hsic_set(pipe, &(req->dpp));
+
+ 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);
- /* clean the UNSET flag to false */
- mdp4_overlay_status_write(MDP4_OVERLAY_TYPE_UNSET, false);
}
+
+ mdp4_overlay_mdp_pipe_req(pipe, mfd);
+
+ mutex_unlock(&mfd->dma->ov_mutex);
+
return 0;
}
-int mdp4_overlay_unset(struct mdp_device *mdp_dev, struct fb_info *info, int ndx)
+int mdp4_overlay_unset_mixer(int mixer)
{
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
struct mdp4_overlay_pipe *pipe;
- int pull;
+ int i, cnt = 0;
+
+ /* free pipe besides base layer pipe */
+ for (i = MDP4_MIXER_STAGE3; i > MDP4_MIXER_STAGE_BASE; i--) {
+ pipe = ctrl->stage[mixer][i];
+ if (pipe == NULL)
+ continue;
+ pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
+ mdp4_overlay_reg_flush(pipe, 1);
+ mdp4_mixer_stage_down(pipe);
+ mdp4_overlay_pipe_free(pipe);
+ cnt++;
+ }
+
+ return cnt;
+}
+
+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;
+ struct dpp_ctrl dpp;
+ int i;
+
+ if (mfd == NULL)
+ return -ENODEV;
+
+ if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
+ return -EINTR;
pipe = mdp4_overlay_ndx2pipe(ndx);
- if (pipe == NULL)
+ if (pipe == NULL) {
+ mutex_unlock(&mfd->dma->ov_mutex);
return -ENODEV;
+ }
- pipe->mdp = mdp;
- clk_enable(mdp->clk);
+ if (pipe->pipe_type == OVERLAY_TYPE_BF) {
+ mdp4_overlay_borderfill_stage_down(pipe);
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return 0;
+ }
- pull = mdp4_pull_mode(pipe);
-
+ if (pipe->mixer_num == MDP4_MIXER2)
+ ctrl->mixer2_played = 0;
+ else if (pipe->mixer_num == MDP4_MIXER1)
+ ctrl->mixer1_played = 0;
+ else {
+ /* mixer 0 */
+ ctrl->mixer0_played = 0;
+ if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
+ if (mfd->panel_power_on)
+ mdp4_mddi_blt_dmap_busy_wait(mfd);
+ }
+ }
+ mdp4_overlay_reg_flush(pipe, 1);
mdp4_mixer_stage_down(pipe);
- if (pull) /* LCDC or DTV mode */
- mdp4_overlay_reg_flush(pipe, 0);
-#ifdef CONFIG_FB_MSM_WRITE_BACK
- else
- mdp4_overlay0_done_mddi();
-#endif
+ if (pipe->mixer_num == MDP4_MIXER0) {
+ if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
+ if (mfd->panel_power_on)
+ mdp4_mddi_overlay_restore();
+ }
+ } else { /* mixer1, DTV, ATV */
+ if (ctrl->panel_mode & MDP4_PANEL_DTV)
+ mdp4_overlay_dtv_unset(mfd, pipe);
+ }
+
+ /* Reset any HSIC settings to default */
+ if (pipe->flags & MDP_DPP_HSIC) {
+ for (i = 0; i < NUM_HSIC_PARAM; i++)
+ dpp.hsic_params[i] = 0;
+
+ mdp4_hsic_set(pipe, &dpp);
+ mdp4_hsic_update(pipe);
+ }
+
+ 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)) {
- if ((pipe->mixer_num == MDP4_MIXER0) &&
- (mdp->hw_version == MDP4_REVISION_V2_1))
- mdp4_overlay_status_write(MDP4_OVERLAY_TYPE_UNSET, true);
- /* clean the SET flag to false */
- mdp4_overlay_status_write(MDP4_OVERLAY_TYPE_SET, false);
- }
-
-#ifdef CONFIG_PANEL_SELF_REFRESH
- if (mdp->mdp_dev.overrides & MSM_MDP_RGB_PANEL_SELE_REFRESH) {
- mutex_lock(&panel_icm->icm_lock);
- if (panel_icm->icm_suspend == false)
- panel_icm->icm_doable = true;
- mutex_unlock(&panel_icm->icm_lock);
- }
-#endif
-
- clk_disable(mdp->clk);
+ mutex_unlock(&mfd->dma->ov_mutex);
return 0;
}
+int mdp4_overlay_wait4vsync(struct fb_info *info, long long *vtime)
+{
+ if (!hdmi_prim_display && info->node == 0) {
+ if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
+ mdp4_dsi_video_wait4vsync(0, vtime);
+ else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
+ mdp4_dsi_cmd_wait4vsync(0, vtime);
+ else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
+ mdp4_lcdc_wait4vsync(0, vtime);
+ } else if (hdmi_prim_display || info->node == 1) {
+ mdp4_dtv_wait4vsync(0, vtime);
+ }
+
+ return 0;
+}
+
+int mdp4_overlay_vsync_ctrl(struct fb_info *info, int enable)
+{
+ int cmd;
+
+ if (enable)
+ cmd = 1;
+ else
+ cmd = 0;
+
+ if (!hdmi_prim_display && info->node == 0) {
+ if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
+ mdp4_dsi_video_vsync_ctrl(0, cmd);
+ else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
+ mdp4_dsi_cmd_vsync_ctrl(0, cmd);
+ else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
+ mdp4_lcdc_vsync_ctrl(0, cmd);
+ } else if (hdmi_prim_display || info->node == 1) {
+ mdp4_dtv_vsync_ctrl(0, cmd);
+ }
+
+ return 0;
+}
+
+
struct tile_desc {
- uint32_t width; /* tile's width */
- uint32_t height; /* tile's height */
- uint32_t row_tile_w; /* tiles per row's width */
- uint32_t row_tile_h; /* tiles per row's height */
+ 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)
@@ -1825,10 +3162,10 @@
tp->row_tile_h = 1; /* 1 tiles per row's height */
}
-uint32_t tile_mem_size(struct mdp4_overlay_pipe *pipe, struct tile_desc *tp)
+uint32 tile_mem_size(struct mdp4_overlay_pipe *pipe, struct tile_desc *tp)
{
- uint32_t tile_w, tile_h;
- uint32_t row_num_w, row_num_h;
+ uint32 tile_w, tile_h;
+ uint32 row_num_w, row_num_h;
tile_w = tp->width * tp->row_tile_w;
@@ -1839,136 +3176,117 @@
return ((row_num_w * row_num_h * tile_w * tile_h) + 8191) & ~8191;
}
-#ifdef DEBUG_OVERLAY
-
-static char snapshot_filename[2048];
-static bool is_demanding_snapshot = false;
-static DEFINE_MUTEX(snapshot_lock);
-
-/*
-TODO: file header to brife the image content
-*/
-int mdp4_overlay_snapshot(struct msmfb_overlay_data *req, uint32_t phy_addr,
- int w, int h, int bpp, char *filename)
+int mdp4_overlay_play_wait(struct fb_info *info, struct msmfb_overlay_data *req)
{
- int retval, size;
- uint8_t *vir_addr;
- struct file *dstf;
- mm_segment_t orgfs;
-
- /* Save FS register and set FS register to kernel space, needed
- * for read and write to accept buffer in kernel space.
- */
- orgfs = get_fs();
- set_fs(KERNEL_DS);
-
- dstf = filp_open(filename, O_WRONLY | O_TRUNC | O_CREAT , 0644);
- if (IS_ERR(dstf)) {
- pr_err("%s: Error %ld opening %s\n", __func__,
- -PTR_ERR(dstf), filename);
- is_demanding_snapshot = false;
- return -EIO;
- }
-
- if (!(dstf->f_op && dstf->f_op->write)) {
- pr_err("file doesn't have a write method\n");
- return -EFAULT;
- }
-
- size = w * h * bpp;
- vir_addr = (uint8_t *)ioremap(phy_addr, size);
- pr_info("%s: w=%d, h=%d, size=%d, vir=%08x\n", __func__,
- w, h, size, (uint32_t)vir_addr);
- retval = dstf->f_op->write(dstf, vir_addr, size, &dstf->f_pos);
- iounmap(vir_addr);
-
- retval = filp_close(dstf, NULL);
- if (retval)
- pr_err("%s: Error %d closing %s\n", __func__,
- -retval, filename);
-
- set_fs(orgfs);
- is_demanding_snapshot = false;
-
return 0;
}
-#endif
-int mdp4_overlay_play(struct mdp_device *mdp_dev, struct fb_info *info, struct msmfb_overlay_data *req,
- struct file **pp_src_file)
+/*
+ * mdp4_overlay_dma_commit: called from dma_done isr
+ * No mutex/sleep allowed
+ */
+void mdp4_overlay_dma_commit(int mixer)
{
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
- struct msmfb_info *msmfb = (struct msmfb_info *)info->par;
- struct msm_panel_data *panel = msmfb->panel;
+ /*
+ * non double buffer register update here
+ * perf level, new clock rate should be done here
+ */
+}
+
+/*
+ * mdp4_overlay_vsync_commit: called from tasklet context
+ * No mutex/sleep allowed
+ */
+void mdp4_overlay_vsync_commit(struct mdp4_overlay_pipe *pipe)
+{
+ if (pipe->pipe_type == OVERLAY_TYPE_VIDEO)
+ mdp4_overlay_vg_setup(pipe); /* video/graphic pipe */
+ else
+ mdp4_overlay_rgb_setup(pipe); /* rgb pipe */
+
+ pr_debug("%s: pipe=%x ndx=%d num=%d used=%d\n", __func__,
+ (int) pipe, pipe->pipe_ndx, pipe->pipe_num, pipe->pipe_used);
+ mdp4_overlay_reg_flush(pipe, 1);
+ mdp4_mixer_stage_up(pipe);
+}
+
+int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req)
+{
+ 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;
- int pull;
-#ifdef CONFIG_PANEL_SELF_REFRESH
- unsigned long irq_flags = 0;
-#endif
+ struct file *srcp0_file = NULL;
+ struct file *srcp1_file = NULL, *srcp2_file = NULL;
+ struct ion_handle *srcp0_ihdl = NULL;
+ struct ion_handle *srcp1_ihdl = NULL, *srcp2_ihdl = NULL;
+ int ps0_need, p_need;
+ uint32_t overlay_version = 0;
+ int ret = 0;
- pipe = mdp4_overlay_ndx2pipe(req->id);
- if (pipe == NULL)
+ if (mfd == NULL)
return -ENODEV;
-#ifdef CONFIG_PANEL_SELF_REFRESH
- if (mdp->mdp_dev.overrides & MSM_MDP_RGB_PANEL_SELE_REFRESH) {
- panel_icm->force_leave();
- spin_lock_irqsave(&panel_icm->lock, irq_flags);
- panel_icm->panel_update = 1;
- spin_unlock_irqrestore(&panel_icm->lock, irq_flags);
- wake_up(&panel_update_wait_queue);
- }
-#endif
+ if (!mfd->panel_power_on) /* suspended */
+ return -EPERM;
- pd = &ctrl->ov_pipe[pipe->pipe_num];
- if (pd->player && pipe != pd->player) {
- if (pipe->pipe_type == OVERLAY_TYPE_RGB)
- return 0; /* ignore it, kicked out already */
+ pipe = mdp4_overlay_ndx2pipe(req->id);
+ if (pipe == NULL) {
+ mdp4_stat.err_play++;
+ return -ENODEV;
}
- pd->player = pipe; /* keep */
+ if (pipe->pipe_type == OVERLAY_TYPE_BF) {
+ mdp4_overlay_borderfill_stage_up(pipe);
+ mdp4_mixer_stage_commit(pipe->mixer_num);
+ return 0;
+ }
+
+ mutex_lock(&mfd->dma->ov_mutex);
img = &req->data;
- get_img(img, info, &start, &len, &p_src_file);
+ get_img(img, info, pipe, 0, &start, &len, &srcp0_file,
+ &ps0_need, &srcp0_ihdl);
if (len == 0) {
- PR_DISP_ERR("mdp_overlay_play: could not retrieve"
- " image from memory\n");
- return -1;
+ pr_err("%s: pmem Error\n", __func__);
+ ret = -1;
+ goto end;
}
- *pp_src_file = p_src_file;
addr = start + img->offset;
pipe->srcp0_addr = addr;
pipe->srcp0_ystride = pipe->src_width * pipe->bpp;
- pipe->mdp = mdp;
-#ifdef DEBUG_OVERLAY
- mutex_lock(&snapshot_lock);
- if (is_demanding_snapshot) {
- mdp4_overlay_snapshot(req, addr, pipe->src_width,
- pipe->src_height, pipe->bpp, snapshot_filename);
- }
- mutex_unlock(&snapshot_lock);
-#endif
- clk_set_rate(mdp->ebi1_clk, 153000000);
- clk_enable(mdp->clk);
+ pr_debug("%s: mixer=%d ndx=%x addr=%x flags=%x pid=%d\n", __func__,
+ pipe->mixer_num, pipe->pipe_ndx, (int)addr, pipe->flags,
+ current->pid);
+
+ 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 (pipe->frame_format == MDP4_FRAME_FORMAT_VIDEO_SUPERTILE) {
+ if (overlay_version > 0) {
+ img = &req->plane1_data;
+ get_img(img, info, pipe, 1, &start, &len, &srcp1_file,
+ &p_need, &srcp1_ihdl);
+ if (len == 0) {
+ pr_err("%s: Error to get plane1\n", __func__);
+ ret = -EINVAL;
+ goto end;
+ }
+ pipe->srcp1_addr = start + img->offset;
+ } 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;
-
+ } 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)) {
@@ -1978,193 +3296,341 @@
pipe->srcp1_ystride = pipe->src_width << 1;
} else
pipe->srcp1_ystride = pipe->src_width;
- }
- if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {
- int ret = 0;
- ret = mdp4_overlay_vg_setup(pipe);/* video/graphic pipe */
- if (ret) {
- clk_disable(mdp->clk);
- mod_timer(&mdp->standby_timer,
- jiffies + msecs_to_jiffies(1000));
- return ret;
+ } else if (pipe->fetch_plane == OVERLAY_PLANE_PLANAR) {
+ if (overlay_version > 0) {
+ img = &req->plane1_data;
+ get_img(img, info, pipe, 1, &start, &len, &srcp1_file,
+ &p_need, &srcp1_ihdl);
+ if (len == 0) {
+ pr_err("%s: Error to get plane1\n", __func__);
+ ret = -EINVAL;
+ goto end;
+ }
+ pipe->srcp1_addr = start + img->offset;
+
+ img = &req->plane2_data;
+ get_img(img, info, pipe, 2, &start, &len, &srcp2_file,
+ &p_need, &srcp2_ihdl);
+ if (len == 0) {
+ pr_err("%s: Error to get plane2\n", __func__);
+ ret = -EINVAL;
+ goto end;
+ }
+ pipe->srcp2_addr = start + img->offset;
+ } else {
+ if (pipe->src_format == MDP_Y_CR_CB_GH2V2) {
+ addr += (ALIGN(pipe->src_width, 16) *
+ pipe->src_height);
+ pipe->srcp1_addr = addr;
+ addr += ((ALIGN((pipe->src_width / 2), 16)) *
+ (pipe->src_height / 2));
+ pipe->srcp2_addr = addr;
+ } 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;
+ }
}
- } else
- mdp4_overlay_rgb_setup(pipe); /* rgb pipe */
+ /* mdp planar format expects Cb in srcp1 and Cr in p2 */
+ if ((pipe->src_format == MDP_Y_CR_CB_H2V2) ||
+ (pipe->src_format == MDP_Y_CR_CB_GH2V2))
+ swap(pipe->srcp1_addr, pipe->srcp2_addr);
- mdp4_mixer_blend_setup(pipe);
- if (z_order_change == 1)
- mdp4_overlay_change_z_order_vg_pipes_actual(pipe);
- else
- mdp4_mixer_stage_up(pipe);
-
- pull = mdp4_pull_mode(pipe);
-
-
- if (pull) { /* LCDC or DTV mode */
- mdp4_overlay_reg_flush(pipe, 1);
- if (pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) { /* done */
- clk_disable(mdp->clk);
- mod_timer(&mdp->standby_timer,
- jiffies + msecs_to_jiffies(1000));
- return 0;
+ if (pipe->src_format == MDP_Y_CR_CB_GH2V2) {
+ pipe->srcp0_ystride = ALIGN(pipe->src_width, 16);
+ pipe->srcp1_ystride = ALIGN(pipe->src_width / 2, 16);
+ pipe->srcp2_ystride = ALIGN(pipe->src_width / 2, 16);
+ } else {
+ pipe->srcp0_ystride = pipe->src_width;
+ pipe->srcp1_ystride = pipe->src_width / 2;
+ pipe->srcp2_ystride = pipe->src_width / 2;
}
- } else
- mdp_dev->dma_wait(mdp_dev, panel->interface_type);
-
- clk_disable(mdp->clk);
- mod_timer(&mdp->standby_timer,
- jiffies + msecs_to_jiffies(1000));
-
- return 0;
-}
-
-/*---------------------------------------------------------------------------*/
-#ifdef DEBUG_OVERLAY
-static char debug_buf[2048];
-int ov_dump_req(struct mdp_overlay *ov, char *buff)
-{
- int len = 0;
- char *bp = buff;
- struct mdp_rect *r;
- uint32_t *p = ov->user_data;
-
- len = snprintf(buff, sizeof(debug_buf),
- "[OV]src: width=%d, height=%d, format=%d\n",
- ov->src.width, ov->src.height, ov->src.format);
- r = &ov->src_rect;
- bp += len;
- len = snprintf(bp, sizeof(debug_buf),
- "[OV]src_rect: x=%d, y=%d, w=%d, h=%d\n",
- r->x, r->y, r->w, r->h);
- r = &ov->dst_rect;
- bp += len;
- len = snprintf(bp, sizeof(debug_buf),
- "[OV]dst_rect: x=%d, y=%d, w=%d, h=%d\n",
- r->x, r->y, r->w, r->h);
- bp += len;
- len = snprintf(bp, sizeof(debug_buf),
- "[OV]z_order=%d, is_fg=%d, alpha=0x%08x\n",
- ov->z_order, ov->is_fg, ov->alpha);
- bp += len;
- len = snprintf(bp, sizeof(debug_buf),
- "[OV]transp_mask=0x%08x, flags=0x%08x, id=%d\n",
- ov->transp_mask, ov->flags, ov->id);
- bp += len;
- len = snprintf(bp, sizeof(debug_buf),
- "[OV]user_data={%08x, %08x, %08x, %08x,\n"
- "[OV]\t%08x, %08x, %08x, %08x}\n",
- p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
-
- return (bp - buff + len);
-}
-
-static int ov_requests_open(struct inode *inode, struct file *file)
-{
- /* non-seekable */
- file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
- return 0;
-}
-
-static int ov_requests_release(struct inode *inode, struct file *file)
-{
- return 0;
-}
-
-static ssize_t ov_requests_read(struct file *file, char __user *buff,
- size_t count, loff_t *ppos)
-{
- int i, len = 0;
-
- pr_info("%s\n", __func__);
- if (*ppos)
- return 0; /* the end */
-
- for (i = 0 ; i < MDP4_MAX_PIPE; i++) {
- len += snprintf(debug_buf+len, sizeof(debug_buf),
- "Pipe-%d\n", i);
- len += ov_dump_req(&(ctrl->plist[i].req_data), debug_buf+len);
}
- if (copy_to_user(buff, debug_buf, len))
- return -EFAULT;
+ mdp4_overlay_mdp_perf_req(mfd, ctrl->plist);
- *ppos += len; /* increase offset */
+ if (pipe->mixer_num == MDP4_MIXER2 || ctrl->panel_mode & MDP4_PANEL_MDDI)
+ goto mddi;
- return len;
-}
-
-static const struct file_operations ov_requests_fops = {
- .open = ov_requests_open,
- .release = ov_requests_release,
- .read = ov_requests_read,
-};
-
-static int ov_snapshot_open(struct inode *inode, struct file *file)
-{
- /* non-seekable */
- file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
- return 0;
-}
-
-static int ov_snapshot_release(struct inode *inode, struct file *file)
-{
- return 0;
-}
-
-static ssize_t ov_snapshot_write(struct file *file, const char __user *buff, size_t count, loff_t *ppos)
-{
- if (count >= sizeof(snapshot_filename))
- return -EFAULT;
- if (copy_from_user(snapshot_filename, buff, count))
- return -EFAULT;
- snapshot_filename[count] = 0; /* end of string */
- pr_info("%s: snapshot to: %s\n", __func__, snapshot_filename);
-
- mutex_lock(&snapshot_lock);
- is_demanding_snapshot = true;
- mutex_unlock(&snapshot_lock);
-
- return 0;
-}
-
-static const struct file_operations ov_snapshot_fops = {
- .open = ov_snapshot_open,
- .release = ov_snapshot_release,
- .write = ov_snapshot_write,
-};
-
-void mdp4_dump_ov(struct mdp_overlay *ov)
-{
- ov_dump_req(ov, debug_buf);
- pr_info("%s\n", debug_buf);
-}
-
-int mdp4_overlay_debugfs_init(void)
-{
- struct dentry *dent = debugfs_create_dir("overlay", 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("requests", 0444, dent, 0, &ov_requests_fops)
- == NULL) {
- printk(KERN_ERR "%s(%d): debugfs_create_file: index fail\n",
- __FILE__, __LINE__);
- return -1;
- }
-
- if (debugfs_create_file("snapshot", 0222, dent, 0, &ov_snapshot_fops)
- == NULL) {
- printk(KERN_ERR "%s(%d): debugfs_create_file: index fail\n",
- __FILE__, __LINE__);
- return -1;
- }
-
-
- return 0;
-}
+ if (pipe->mixer_num == MDP4_MIXER0) {
+ if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
+ /* cndx = 0 */
+ mdp4_dsi_cmd_pipe_queue(0, pipe);
+ }
+ if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
+ /* cndx = 0 */
+ mdp4_dsi_video_pipe_queue(0, pipe);
+ } else if (ctrl->panel_mode & MDP4_PANEL_LCDC) {
+ /* cndx = 0 */
+ mdp4_lcdc_pipe_queue(0, pipe);
+ }
+ } else if (pipe->mixer_num == MDP4_MIXER1) {
+#ifdef CONFIG_FB_MSM_DTV
+ if (ctrl->panel_mode & MDP4_PANEL_DTV)
+ mdp4_dtv_pipe_queue(0, pipe);/* cndx = 0 */
#endif
+ }
+
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return ret;
+
+mddi:
+ if (pipe->pipe_type == OVERLAY_TYPE_VIDEO) {
+ mdp4_overlay_vg_setup(pipe); /* video/graphic pipe */
+ } else {
+ mdp4_overlay_rgb_setup(pipe); /* rgb pipe */
+ }
+
+ mdp4_mixer_stage_up(pipe);
+
+ if (pipe->mixer_num == MDP4_MIXER2) {
+ ctrl->mixer2_played++;
+#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
+ if (ctrl->panel_mode & MDP4_PANEL_WRITEBACK) {
+ mdp4_writeback_dma_busy_wait(mfd);
+ mdp4_writeback_kickoff_video(mfd, pipe);
+ }
+#endif
+ } else if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
+ if (pipe->flags & MDP_OV_PLAY_NOWAIT) {
+ mdp4_stat.overlay_play[pipe->mixer_num]++;
+ mutex_unlock(&mfd->dma->ov_mutex);
+ goto end;
+ }
+ mdp4_mixer_stage_commit(pipe->mixer_num);
+ mdp4_mddi_dma_busy_wait(mfd);
+ mdp4_mddi_kickoff_video(mfd, pipe);
+ }
+
+ if (!(pipe->flags & MDP_OV_PLAY_NOWAIT))
+ mdp4_iommu_unmap(pipe);
+ mdp4_stat.overlay_play[pipe->mixer_num]++;
+
+end:
+ mutex_unlock(&mfd->dma->ov_mutex);
+
+#ifdef CONFIG_ANDROID_PMEM
+ if (srcp0_file)
+ put_pmem_file(srcp0_file);
+ if (srcp1_file)
+ put_pmem_file(srcp1_file);
+ if (srcp2_file)
+ put_pmem_file(srcp2_file);
+#endif
+ /* only source may use frame buffer */
+ if (img->flags & MDP_MEMORY_ID_TYPE_FB)
+ fput_light(srcp0_file, ps0_need);
+ return ret;
+}
+
+static struct {
+ char *name;
+ int domain;
+} msm_iommu_ctx_names[] = {
+ /* Display */
+ {
+ .name = "mdp_port0_cb0",
+ .domain = DISPLAY_DOMAIN,
+ },
+ /* Display */
+ {
+ .name = "mdp_port0_cb1",
+ .domain = DISPLAY_DOMAIN,
+ },
+ /* Display */
+ {
+ .name = "mdp_port1_cb0",
+ .domain = DISPLAY_DOMAIN,
+ },
+ /* Display */
+ {
+ .name = "mdp_port1_cb1",
+ .domain = DISPLAY_DOMAIN,
+ },
+};
+
+static int iommu_enabled;
+
+void mdp4_iommu_attach(void)
+{
+ struct iommu_domain *domain;
+ int i;
+
+ if (!iommu_enabled) {
+ for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_names); i++) {
+ int domain_idx;
+ struct device *ctx = msm_iommu_get_ctx(
+ msm_iommu_ctx_names[i].name);
+
+ if (!ctx)
+ continue;
+
+ domain_idx = msm_iommu_ctx_names[i].domain;
+
+ domain = msm_get_iommu_domain(domain_idx);
+ if (!domain)
+ continue;
+
+ if (iommu_attach_device(domain, ctx)) {
+ WARN(1, "%s: could not attach domain %d to context %s."
+ " iommu programming will not occur.\n",
+ __func__, domain_idx,
+ msm_iommu_ctx_names[i].name);
+ continue;
+ }
+ }
+ pr_debug("Attached MDP IOMMU device\n");
+ iommu_enabled = 1;
+ }
+}
+
+void mdp4_iommu_detach(void)
+{
+ struct iommu_domain *domain;
+ int i;
+
+ if (!mdp_check_suspended() || mdp4_extn_disp)
+ return;
+
+ if (iommu_enabled) {
+ for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_names); i++) {
+ int domain_idx;
+ struct device *ctx = msm_iommu_get_ctx(
+ msm_iommu_ctx_names[i].name);
+
+ if (!ctx)
+ continue;
+
+ domain_idx = msm_iommu_ctx_names[i].domain;
+
+ domain = msm_get_iommu_domain(domain_idx);
+ if (!domain)
+ continue;
+
+ iommu_detach_device(domain, ctx);
+ }
+ pr_debug("Detached MDP IOMMU device\n");
+ iommu_enabled = 0;
+ }
+}
+
+int mdp4_v4l2_overlay_set(struct fb_info *info, struct mdp_overlay *req,
+ struct mdp4_overlay_pipe **ppipe)
+{
+ struct mdp4_overlay_pipe *pipe;
+ int err;
+ struct msm_fb_data_type *mfb = info->par;
+
+ req->z_order = 0;
+ req->id = MSMFB_NEW_REQUEST;
+ req->is_fg = false;
+ req->alpha = 0xff;
+ err = mdp4_overlay_req2pipe(req, MDP4_MIXER0, &pipe, mfb);
+ if (err < 0) {
+ pr_err("%s:Could not allocate MDP overlay pipe\n", __func__);
+ return err;
+ }
+
+ mdp4_mixer_blend_setup(pipe->mixer_num);
+ *ppipe = pipe;
+
+ return 0;
+}
+
+void mdp4_v4l2_overlay_clear(struct mdp4_overlay_pipe *pipe)
+{
+ mdp4_overlay_reg_flush(pipe, 1);
+ mdp4_mixer_stage_down(pipe);
+ mdp4_overlay_pipe_free(pipe);
+}
+
+int mdp4_v4l2_overlay_play(struct fb_info *info, struct mdp4_overlay_pipe *pipe,
+ unsigned long srcp0_addr, unsigned long srcp1_addr,
+ unsigned long srcp2_addr)
+{
+ struct msm_fb_data_type *mfd = info->par;
+ int err;
+
+ if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
+ return -EINTR;
+
+ switch (pipe->src_format) {
+ case MDP_Y_CR_CB_H2V2:
+ /* YUV420 */
+ pipe->srcp0_addr = srcp0_addr;
+ pipe->srcp0_ystride = pipe->src_width;
+ /*
+ * For YUV420, the luma plane is 1 byte per pixel times
+ * num of pixels in the image Also, the planes are
+ * switched in MDP, srcp2 is actually first chroma plane
+ */
+ pipe->srcp2_addr = srcp1_addr ? srcp1_addr :
+ pipe->srcp0_addr + (pipe->src_width * pipe->src_height);
+ pipe->srcp2_ystride = pipe->src_width/2;
+ /*
+ * The chroma planes are half the size of the luma
+ * planes
+ */
+ pipe->srcp1_addr = srcp2_addr ? srcp2_addr :
+ pipe->srcp2_addr +
+ (pipe->src_width * pipe->src_height / 4);
+ pipe->srcp1_ystride = pipe->src_width/2;
+ break;
+ case MDP_Y_CRCB_H2V2:
+ /* NV12 */
+ pipe->srcp0_addr = srcp0_addr;
+ pipe->srcp0_ystride = pipe->src_width;
+ pipe->srcp1_addr = srcp1_addr ? srcp1_addr :
+ pipe->srcp0_addr +
+ (pipe->src_width * pipe->src_height);
+ pipe->srcp1_ystride = pipe->src_width;
+ break;
+ default:
+ pr_err("%s: format (%u) is not supported\n", __func__,
+ pipe->src_format);
+ err = -EINVAL;
+ goto done;
+ }
+
+ pr_debug("%s: pipe ndx=%d stage=%d format=%x\n", __func__,
+ pipe->pipe_ndx, pipe->mixer_stage, pipe->src_format);
+
+ if (pipe->pipe_type == OVERLAY_TYPE_VIDEO)
+ mdp4_overlay_vg_setup(pipe);
+ else
+ mdp4_overlay_rgb_setup(pipe);
+
+ if (ctrl->panel_mode & MDP4_PANEL_LCDC)
+ mdp4_overlay_reg_flush(pipe, 1);
+
+ mdp4_mixer_stage_up(pipe);
+ mdp4_mixer_stage_commit(pipe->mixer_num);
+#ifdef V4L2_VSYNC
+ /*
+ * TODO: incorporate v4l2 into vsycn driven mechanism
+ */
+ if (ctrl->panel_mode & MDP4_PANEL_LCDC) {
+ mdp4_overlay_lcdc_vsync_push(mfd, pipe);
+ } else {
+#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
+ }
+#endif
+
+done:
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return err;
+}
+
diff --git a/drivers/video/msm/mdp4_overlay_atv.c b/drivers/video/msm/mdp4_overlay_atv.c
new file mode 100644
index 0000000..c133831
--- /dev/null
+++ b/drivers/video/msm/mdp4_overlay_atv.c
@@ -0,0 +1,208 @@
+/* Copyright (c) 2010, 2012 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;
+ unsigned int buf_offset;
+ 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_offset = calc_fb_offset(mfd, fbi, bpp);
+
+ if (atv_pipe == NULL) {
+ ptype = mdp4_overlay_format2type(mfd->fb_imgType);
+ pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER1);
+ 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;
+ if (mfd->map_buffer) {
+ pipe->srcp0_addr = (unsigned int)mfd->map_buffer->iova[0] + \
+ buf_offset;
+ pr_debug("start 0x%lx srcp0_addr 0x%x\n", mfd->
+ map_buffer->iova[0], pipe->srcp0_addr);
+ } else {
+ pipe->srcp0_addr = (uint32)(buf + buf_offset);
+ }
+
+ 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_overlayproc_cfg(pipe);
+
+ mdp4_overlay_reg_flush(pipe, 1);
+ mdp4_mixer_stage_up(pipe);
+ mdp4_mixer_stage_commit(pipe->mixer_num);
+ 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);
+ mdp4_iommu_unmap(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;
+ unsigned int buf_offset;
+ 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_offset = calc_fb_offset(mfd, fbi, bpp);
+
+ mutex_lock(&mfd->dma->ov_mutex);
+
+ pipe = atv_pipe;
+ if (mfd->map_buffer) {
+ pipe->srcp0_addr = (unsigned int)mfd->map_buffer->iova[0] + \
+ buf_offset;
+ pr_debug("start 0x%lx srcp0_addr 0x%x\n", mfd->
+ map_buffer->iova[0], pipe->srcp0_addr);
+ } else {
+ pipe->srcp0_addr = (uint32)(buf + buf_offset);
+ }
+ mdp4_overlay_mdp_perf_req(pipe, mfd);
+ mdp4_overlay_mdp_perf_upd(mfd, 1);
+ mdp4_overlay_rgb_setup(pipe);
+ mdp4_overlay_reg_flush(pipe, 0);
+ mdp4_mixer_stage_up(pipe);
+ mdp4_mixer_stage_commit(pipe->mixer_num);
+ 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_overlay_mdp_perf_upd(mfd, 0);
+ mdp4_stat.kickoff_atv++;
+ 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..334f600
--- /dev/null
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -0,0 +1,1058 @@
+/* Copyright (c) 2011-2012, 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 <asm/mach-types.h>
+#include <mach/hardware.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mdp4.h"
+
+static int dsi_state;
+
+#define TOUT_PERIOD HZ /* 1 second */
+#define MS_100 (HZ/10) /* 100 ms */
+
+static int vsync_start_y_adjust = 4;
+
+#define MAX_CONTROLLER 1
+#define VSYNC_EXPIRE_TICK 4
+
+static struct vsycn_ctrl {
+ struct device *dev;
+ int inited;
+ int update_ndx;
+ int expire_tick;
+ int blt_wait;
+ u32 ov_koff;
+ u32 ov_done;
+ u32 dmap_koff;
+ u32 dmap_done;
+ uint32 rdptr_intr_tot;
+ uint32 rdptr_sirq_tot;
+ atomic_t suspend;
+ int wait_vsync_cnt;
+ int blt_change;
+ int blt_free;
+ int blt_end;
+ int fake_vsync;
+ struct mutex update_lock;
+ struct completion ov_comp;
+ struct completion dmap_comp;
+ struct completion vsync_comp;
+ spinlock_t spin_lock;
+ struct msm_fb_data_type *mfd;
+ struct mdp4_overlay_pipe *base_pipe;
+ struct vsync_update vlist[2];
+ int vsync_enabled;
+ int clk_enabled;
+ int clk_control;
+ ktime_t vsync_time;
+ struct work_struct vsync_work;
+ struct work_struct clk_work;
+} vsync_ctrl_db[MAX_CONTROLLER];
+
+static void vsync_irq_enable(int intr, int term)
+{
+ unsigned long flag;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ /* no need to clrear other interrupts for comamnd mode */
+ mdp_intr_mask |= intr;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ mdp_enable_irq(term);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+}
+
+static void vsync_irq_disable(int intr, int term)
+{
+ unsigned long flag;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ /* no need to clrear other interrupts for comamnd mode */
+ mdp_intr_mask &= ~intr;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ mdp_disable_irq_nosync(term);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+}
+
+static void mdp4_dsi_cmd_blt_ov_update(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 off, addr;
+ int bpp;
+ char *overlay_base;
+
+ if (pipe->ov_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->ov_cnt & 0x01)
+ off = pipe->src_height * pipe->src_width * bpp;
+ addr = pipe->ov_blt_addr + off;
+ /* overlay 0 */
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+ outpdw(overlay_base + 0x000c, addr);
+ outpdw(overlay_base + 0x001c, addr);
+}
+
+static void mdp4_dsi_cmd_blt_dmap_update(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 off, addr;
+ int bpp;
+
+ if (pipe->ov_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->dma_blt_addr + off;
+
+ /* dmap */
+ MDP_OUTP(MDP_BASE + 0x90008, addr);
+}
+
+static void mdp4_dsi_cmd_wait4dmap(int cndx);
+static void mdp4_dsi_cmd_wait4ov(int cndx);
+
+static void mdp4_dsi_cmd_do_blt(struct msm_fb_data_type *mfd, int enable)
+{
+ unsigned long flags;
+ int cndx = 0;
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+ int need_wait;
+
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+
+ mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0);
+
+ if (mfd->ov0_wb_buf->write_addr == 0) {
+ pr_info("%s: no blt_base assigned\n", __func__);
+ return;
+ }
+
+ spin_lock_irqsave(&vctrl->spin_lock, flags);
+ if (enable && pipe->ov_blt_addr == 0) {
+ vctrl->blt_change++;
+ if (vctrl->dmap_koff != vctrl->dmap_done) {
+ INIT_COMPLETION(vctrl->dmap_comp);
+ need_wait = 1;
+ }
+ } else if (enable == 0 && pipe->ov_blt_addr) {
+ vctrl->blt_change++;
+ if (vctrl->ov_koff != vctrl->dmap_done) {
+ INIT_COMPLETION(vctrl->dmap_comp);
+ need_wait = 1;
+ }
+ }
+ spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+
+ if (need_wait)
+ mdp4_dsi_cmd_wait4dmap(0);
+
+ spin_lock_irqsave(&vctrl->spin_lock, flags);
+ if (enable && pipe->ov_blt_addr == 0) {
+ pipe->ov_blt_addr = mfd->ov0_wb_buf->write_addr;
+ pipe->dma_blt_addr = mfd->ov0_wb_buf->read_addr;
+ pipe->ov_cnt = 0;
+ pipe->dmap_cnt = 0;
+ vctrl->ov_koff = vctrl->dmap_koff;
+ vctrl->ov_done = vctrl->dmap_done;
+ vctrl->blt_free = 0;
+ vctrl->blt_wait = 0;
+ vctrl->blt_end = 0;
+ mdp4_stat.blt_dsi_video++;
+ } else if (enable == 0 && pipe->ov_blt_addr) {
+ pipe->ov_blt_addr = 0;
+ pipe->dma_blt_addr = 0;
+ vctrl->blt_end = 1;
+ vctrl->blt_free = 4; /* 4 commits to free wb buf */
+ }
+
+ pr_info("%s: changed=%d enable=%d ov_blt_addr=%x\n", __func__,
+ vctrl->blt_change, enable, (int)pipe->ov_blt_addr);
+
+ spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+}
+
+/*
+ * mdp4_dsi_cmd_do_update:
+ * called from thread context
+ */
+void mdp4_dsi_cmd_pipe_queue(int cndx, struct mdp4_overlay_pipe *pipe)
+{
+ struct vsycn_ctrl *vctrl;
+ struct vsync_update *vp;
+ struct mdp4_overlay_pipe *pp;
+ int undx;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+
+ if (atomic_read(&vctrl->suspend) > 0)
+ return;
+
+ mutex_lock(&vctrl->update_lock);
+ undx = vctrl->update_ndx;
+ vp = &vctrl->vlist[undx];
+
+ pp = &vp->plist[pipe->pipe_ndx - 1]; /* ndx start form 1 */
+
+ pr_debug("%s: vndx=%d pipe_ndx=%d expire=%x pid=%d\n", __func__,
+ undx, pipe->pipe_ndx, vctrl->expire_tick, current->pid);
+
+ *pp = *pipe; /* clone it */
+ vp->update_cnt++;
+
+ mutex_unlock(&vctrl->update_lock);
+ mdp4_stat.overlay_play[pipe->mixer_num]++;
+}
+
+static void mdp4_dsi_cmd_blt_ov_update(struct mdp4_overlay_pipe *pipe);
+
+int mdp4_dsi_cmd_pipe_commit(void)
+{
+ int i, undx;
+ int mixer = 0;
+ struct vsycn_ctrl *vctrl;
+ struct vsync_update *vp;
+ struct mdp4_overlay_pipe *pipe;
+ struct mdp4_overlay_pipe *real_pipe;
+ unsigned long flags;
+ int need_dmap_wait = 0;
+ int need_ov_wait = 0;
+ int cnt = 0;
+
+ vctrl = &vsync_ctrl_db[0];
+
+ mutex_lock(&vctrl->update_lock);
+ undx = vctrl->update_ndx;
+ vp = &vctrl->vlist[undx];
+ pipe = vctrl->base_pipe;
+ mixer = pipe->mixer_num;
+
+ if (vp->update_cnt == 0) {
+ mutex_unlock(&vctrl->update_lock);
+ return cnt;
+ }
+
+ vctrl->update_ndx++;
+ vctrl->update_ndx &= 0x01;
+ vp->update_cnt = 0; /* reset */
+ if (vctrl->blt_free) {
+ vctrl->blt_free--;
+ if (vctrl->blt_free == 0)
+ mdp4_free_writeback_buf(vctrl->mfd, mixer);
+ }
+ mutex_unlock(&vctrl->update_lock);
+
+ /* free previous committed iommu back to pool */
+ mdp4_overlay_iommu_unmap_freelist(mixer);
+
+ spin_lock_irqsave(&vctrl->spin_lock, flags);
+ if (pipe->ov_blt_addr) {
+ /* Blt */
+ if (vctrl->blt_wait)
+ need_dmap_wait = 1;
+ else if (vctrl->ov_koff != vctrl->ov_done) {
+ INIT_COMPLETION(vctrl->ov_comp);
+ need_ov_wait = 1;
+ }
+ } else {
+ /* direct out */
+ if (vctrl->dmap_koff != vctrl->dmap_done) {
+ INIT_COMPLETION(vctrl->dmap_comp);
+ pr_debug("%s: wait, ok=%d od=%d dk=%d dd=%d cpu=%d\n",
+ __func__, vctrl->ov_koff, vctrl->ov_done,
+ vctrl->dmap_koff, vctrl->dmap_done, smp_processor_id());
+ need_dmap_wait = 1;
+ }
+ }
+ spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+
+ if (need_dmap_wait) {
+ pr_debug("%s: wait4dmap\n", __func__);
+ mdp4_dsi_cmd_wait4dmap(0);
+ }
+
+ if (need_ov_wait) {
+ pr_debug("%s: wait4ov\n", __func__);
+ mdp4_dsi_cmd_wait4ov(0);
+ }
+
+ if (pipe->ov_blt_addr) {
+ if (vctrl->blt_end) {
+ vctrl->blt_end = 0;
+ pipe->ov_blt_addr = 0;
+ pipe->dma_blt_addr = 0;
+ }
+ }
+
+ if (vctrl->blt_change) {
+ mdp4_overlayproc_cfg(pipe);
+ mdp4_overlay_dmap_xy(pipe);
+ vctrl->blt_change = 0;
+ }
+
+ pipe = vp->plist;
+ for (i = 0; i < OVERLAY_PIPE_MAX; i++, pipe++) {
+ if (pipe->pipe_used) {
+ cnt++;
+ real_pipe = mdp4_overlay_ndx2pipe(pipe->pipe_ndx);
+ if (real_pipe && real_pipe->pipe_used) {
+ /* pipe not unset */
+ mdp4_overlay_vsync_commit(pipe);
+ }
+ /* free previous iommu to freelist
+ * which will be freed at next
+ * pipe_commit
+ */
+ mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 0);
+ pipe->pipe_used = 0; /* clear */
+ }
+ }
+
+ /* tx dcs command if had any */
+ mipi_dsi_cmdlist_commit(1);
+
+ mdp4_mixer_stage_commit(mixer);
+
+ pipe = vctrl->base_pipe;
+ spin_lock_irqsave(&vctrl->spin_lock, flags);
+ if (pipe->ov_blt_addr) {
+ mdp4_dsi_cmd_blt_ov_update(pipe);
+ pipe->ov_cnt++;
+ vctrl->ov_koff++;
+ vsync_irq_enable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
+ } else {
+ vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+ vctrl->dmap_koff++;
+ }
+ pr_debug("%s: kickoff\n", __func__);
+ /* kickoff overlay engine */
+ mdp4_stat.kickoff_ov0++;
+ outpdw(MDP_BASE + 0x0004, 0);
+ mb();
+ spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+
+ mdp4_stat.overlay_commit[pipe->mixer_num]++;
+
+ return cnt;
+}
+
+void mdp4_dsi_cmd_vsync_ctrl(int cndx, int enable)
+{
+ struct vsycn_ctrl *vctrl;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+
+ if (enable && vctrl->fake_vsync) {
+ vctrl->fake_vsync = 0;
+ schedule_work(&vctrl->vsync_work);
+ }
+
+ if (vctrl->vsync_enabled == enable)
+ return;
+
+ vctrl->vsync_enabled = enable;
+
+#ifdef CLOCK_CONTROL
+ mutex_lock(&vctrl->update_lock);
+ if (enable) {
+ vsync_irq_enable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM);
+ } else {
+ vsync_irq_disable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM);
+ }
+ mutex_unlock(&vctrl->update_lock);
+#endif
+}
+
+void mdp4_dsi_cmd_wait4vsync(int cndx, long long *vtime)
+{
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+ unsigned long flags;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+
+ if (atomic_read(&vctrl->suspend) > 0) {
+ *vtime = -1;
+ return;
+ }
+
+ spin_lock_irqsave(&vctrl->spin_lock, flags);
+ if (vctrl->wait_vsync_cnt == 0)
+ INIT_COMPLETION(vctrl->vsync_comp);
+ vctrl->wait_vsync_cnt++;
+ spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+
+ wait_for_completion(&vctrl->vsync_comp);
+ mdp4_stat.wait4vsync0++;
+
+ *vtime = ktime_to_ns(vctrl->vsync_time);
+}
+
+static void mdp4_dsi_cmd_wait4dmap(int cndx)
+{
+ struct vsycn_ctrl *vctrl;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+
+ if (atomic_read(&vctrl->suspend) > 0)
+ return;
+
+ wait_for_completion(&vctrl->dmap_comp);
+}
+
+static void mdp4_dsi_cmd_wait4ov(int cndx)
+{
+ struct vsycn_ctrl *vctrl;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+
+ if (atomic_read(&vctrl->suspend) > 0)
+ return;
+
+ wait_for_completion(&vctrl->ov_comp);
+}
+
+/*
+ * primary_rdptr_isr:
+ * called from interrupt context
+ */
+
+static void primary_rdptr_isr(int cndx)
+{
+ struct vsycn_ctrl *vctrl;
+
+ vctrl = &vsync_ctrl_db[cndx];
+ pr_debug("%s: ISR, cpu=%d\n", __func__, smp_processor_id());
+ vctrl->rdptr_intr_tot++;
+ vctrl->vsync_time = ktime_get();
+ schedule_work(&vctrl->vsync_work);
+
+ spin_lock(&vctrl->spin_lock);
+ if (vctrl->wait_vsync_cnt) {
+ complete(&vctrl->vsync_comp);
+ vctrl->wait_vsync_cnt = 0;
+ }
+ spin_unlock(&vctrl->spin_lock);
+}
+
+void mdp4_dmap_done_dsi_cmd(int cndx)
+{
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+ int diff;
+
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+
+ /* blt enabled */
+ spin_lock(&vctrl->spin_lock);
+ vsync_irq_disable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+ vctrl->dmap_done++;
+ diff = vctrl->ov_done - vctrl->dmap_done;
+ pr_debug("%s: ov_koff=%d ov_done=%d dmap_koff=%d dmap_done=%d cpu=%d\n",
+ __func__, vctrl->ov_koff, vctrl->ov_done, vctrl->dmap_koff,
+ vctrl->dmap_done, smp_processor_id());
+ complete_all(&vctrl->dmap_comp);
+ if (diff <= 0) {
+ if (vctrl->blt_wait)
+ vctrl->blt_wait = 0;
+ spin_unlock(&vctrl->spin_lock);
+ return;
+ }
+
+ /* kick dmap */
+ mdp4_dsi_cmd_blt_dmap_update(pipe);
+ pipe->dmap_cnt++;
+ mdp4_stat.kickoff_dmap++;
+ vctrl->dmap_koff++;
+ vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+ outpdw(MDP_BASE + 0x000c, 0); /* kickoff dmap engine */
+ mb();
+ spin_unlock(&vctrl->spin_lock);
+}
+
+/*
+ * mdp4_overlay0_done_dsi_cmd: called from isr
+ */
+void mdp4_overlay0_done_dsi_cmd(int cndx)
+{
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+ int diff;
+
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+
+ spin_lock(&vctrl->spin_lock);
+ vsync_irq_disable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
+ vctrl->ov_done++;
+ complete_all(&vctrl->ov_comp);
+ diff = vctrl->ov_done - vctrl->dmap_done;
+
+ pr_debug("%s: ov_koff=%d ov_done=%d dmap_koff=%d dmap_done=%d cpu=%d\n",
+ __func__, vctrl->ov_koff, vctrl->ov_done, vctrl->dmap_koff,
+ vctrl->dmap_done, smp_processor_id());
+
+ if (pipe->ov_blt_addr == 0) {
+ /* blt disabled */
+ spin_unlock(&vctrl->spin_lock);
+ return;
+ }
+
+ if (diff > 1) {
+ /*
+ * two overlay_done and none dmap_done yet
+ * let dmap_done kickoff dmap
+ * and put pipe_commit to wait
+ */
+ vctrl->blt_wait = 1;
+ pr_debug("%s: blt_wait set\n", __func__);
+ spin_unlock(&vctrl->spin_lock);
+ return;
+ }
+ mdp4_dsi_cmd_blt_dmap_update(pipe);
+ pipe->dmap_cnt++;
+ mdp4_stat.kickoff_dmap++;
+ vctrl->dmap_koff++;
+ vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+ outpdw(MDP_BASE + 0x000c, 0); /* kickoff dmap engine */
+ mb();
+ spin_unlock(&vctrl->spin_lock);
+}
+
+static void clk_ctrl_work(struct work_struct *work)
+{
+ struct vsycn_ctrl *vctrl =
+ container_of(work, typeof(*vctrl), clk_work);
+
+ mutex_lock(&vctrl->update_lock);
+ if (vctrl->clk_control) {
+ if (vctrl->clk_enabled) {
+ mdp_clk_ctrl(0);
+ vctrl->clk_enabled = 0;
+ vctrl->fake_vsync = 1;
+ }
+ }
+
+ mutex_unlock(&vctrl->update_lock);
+}
+
+static void send_vsync_work(struct work_struct *work)
+{
+ struct vsycn_ctrl *vctrl =
+ container_of(work, typeof(*vctrl), vsync_work);
+ char buf[64];
+ char *envp[2];
+
+ snprintf(buf, sizeof(buf), "VSYNC=%llu",
+ ktime_to_ns(vctrl->vsync_time));
+ envp[0] = buf;
+ envp[1] = NULL;
+ kobject_uevent_env(&vctrl->dev->kobj, KOBJ_CHANGE, envp);
+}
+
+
+void mdp4_dsi_rdptr_init(int cndx)
+{
+ struct vsycn_ctrl *vctrl;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+ if (vctrl->inited)
+ return;
+
+ vctrl->inited = 1;
+ vctrl->update_ndx = 0;
+ mutex_init(&vctrl->update_lock);
+ init_completion(&vctrl->ov_comp);
+ init_completion(&vctrl->dmap_comp);
+ init_completion(&vctrl->vsync_comp);
+ spin_lock_init(&vctrl->spin_lock);
+ INIT_WORK(&vctrl->vsync_work, send_vsync_work);
+ INIT_WORK(&vctrl->clk_work, clk_ctrl_work);
+}
+
+void mdp4_primary_rdptr(void)
+{
+ primary_rdptr_isr(0);
+}
+
+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);
+}
+
+int mdp4_overlay_dsi_state_get(void)
+{
+ return dsi_state;
+}
+
+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_dsi_cmd_base_swap(int cndx, struct mdp4_overlay_pipe *pipe)
+{
+ struct vsycn_ctrl *vctrl;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+ vctrl->base_pipe = pipe;
+}
+
+static void mdp4_overlay_setup_pipe_addr(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ MDPIBUF *iBuf = &mfd->ibuf;
+ struct fb_info *fbi;
+ int bpp;
+ uint8 *src;
+
+ /* whole screen for base layer */
+ src = (uint8 *) iBuf->buf;
+ 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;
+}
+
+void mdp4_overlay_update_dsi_cmd(struct msm_fb_data_type *mfd)
+{
+ int ptype;
+ struct mdp4_overlay_pipe *pipe;
+ int ret;
+ int cndx = 0;
+ struct vsycn_ctrl *vctrl;
+
+
+ if (mfd->key != MFD_KEY)
+ return;
+
+ vctrl = &vsync_ctrl_db[cndx];
+
+ /* MDP cmd block enable */
+ mdp_clk_ctrl(1);
+
+ 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);
+ if (pipe == NULL) {
+ printk(KERN_INFO "%s: pipe_alloc failed\n", __func__);
+ return;
+ }
+ 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__);
+
+ vctrl->base_pipe = pipe; /* keep it */
+ mdp4_init_writeback_buf(mfd, MDP4_MIXER0);
+ pipe->ov_blt_addr = 0;
+ pipe->dma_blt_addr = 0;
+
+ MDP_OUTP(MDP_BASE + 0x021c, 10); /* read pointer */
+
+ /*
+ * configure dsi stream id
+ * dma_p = 0, dma_s = 1
+ */
+ MDP_OUTP(MDP_BASE + 0x000a0, 0x10);
+ /* disable dsi trigger */
+ MDP_OUTP(MDP_BASE + 0x000a4, 0x00);
+
+
+ mdp4_overlay_setup_pipe_addr(mfd, pipe);
+
+ mdp4_overlay_rgb_setup(pipe);
+
+ mdp4_overlay_reg_flush(pipe, 1);
+
+ mdp4_mixer_stage_up(pipe);
+
+ mdp4_overlayproc_cfg(pipe);
+
+ mdp4_overlay_dmap_xy(pipe);
+
+ mdp4_overlay_dmap_cfg(mfd, 0);
+
+ mdp4_mixer_stage_commit(pipe->mixer_num);
+ /* MDP cmd block disable */
+ mdp_clk_ctrl(0);
+
+ wmb();
+}
+
+/* 3D side by side */
+void mdp4_dsi_cmd_3d_sbys(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_3d *r3d)
+{
+ struct fb_info *fbi;
+ int bpp;
+ uint8 *src = NULL;
+ int cndx = 0;
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+
+ if (pipe == NULL)
+ return;
+
+ if (pipe->pipe_used == 0 ||
+ pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) {
+ pr_err("%s: NOT baselayer\n", __func__);
+ return;
+ }
+
+ pipe->is_3d = r3d->is_3d;
+ pipe->src_height_3d = r3d->height;
+ pipe->src_width_3d = r3d->width;
+
+ 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);
+
+ 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_overlay_reg_flush(pipe, 1);
+
+ mdp4_mixer_stage_up(pipe);
+
+ mdp4_overlayproc_cfg(pipe);
+
+ mdp4_overlay_dmap_xy(pipe);
+
+ mdp4_overlay_dmap_cfg(mfd, 0);
+
+ mdp4_mixer_stage_commit(pipe->mixer_num);
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_dsi_cmd_blt_start(struct msm_fb_data_type *mfd)
+{
+ mdp4_dsi_cmd_do_blt(mfd, 1);
+}
+
+void mdp4_dsi_cmd_blt_stop(struct msm_fb_data_type *mfd)
+{
+ mdp4_dsi_cmd_do_blt(mfd, 0);
+}
+
+void mdp4_dsi_cmd_overlay_blt(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req)
+{
+ mdp4_dsi_cmd_do_blt(mfd, req->enable);
+}
+
+int mdp4_dsi_cmd_on(struct platform_device *pdev)
+{
+ int ret = 0;
+ int cndx = 0;
+ struct msm_fb_data_type *mfd;
+ struct vsycn_ctrl *vctrl;
+
+ pr_info("%s+:\n", __func__);
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ vctrl = &vsync_ctrl_db[cndx];
+ vctrl->mfd = mfd;
+ vctrl->dev = mfd->fbi->dev;
+
+ mdp_clk_ctrl(1);
+ vsync_irq_enable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM);
+
+ if (vctrl->base_pipe == NULL)
+ mdp4_overlay_update_dsi_cmd(mfd);
+
+ mdp4_iommu_attach();
+
+ atomic_set(&vctrl->suspend, 0);
+ pr_info("%s-:\n", __func__);
+
+
+ return ret;
+}
+
+int mdp4_dsi_cmd_off(struct platform_device *pdev)
+{
+ int ret = 0;
+ int cndx = 0;
+ struct msm_fb_data_type *mfd;
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+
+ pr_info("%s+:\n", __func__);
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+ if (pipe == NULL) {
+ pr_err("%s: NO base pipe\n", __func__);
+ return ret;
+ }
+
+ atomic_set(&vctrl->suspend, 1);
+
+ /* sanity check, free pipes besides base layer */
+ mdp4_overlay_unset_mixer(pipe->mixer_num);
+ mdp4_mixer_stage_down(pipe);
+ mdp4_overlay_pipe_free(pipe);
+ vctrl->base_pipe = NULL;
+
+ vctrl->fake_vsync = 1;
+
+ vsync_irq_disable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM);
+
+ pr_info("%s-:\n", __func__);
+
+ /*
+ * footswitch off
+ * this will casue all mdp register
+ * to be reset to default
+ * after footswitch on later
+ */
+
+ return ret;
+}
+
+void mdp_dsi_cmd_overlay_suspend(struct msm_fb_data_type *mfd)
+{
+ int cndx = 0;
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+ /* dis-engage rgb0 from mixer0 */
+ if (pipe) {
+ if (mfd->ref_cnt == 0) {
+ /* adb stop */
+ if (pipe->pipe_type == OVERLAY_TYPE_BF)
+ mdp4_overlay_borderfill_stage_down(pipe);
+
+ /* pipe == rgb1 */
+ mdp4_overlay_unset_mixer(pipe->mixer_num);
+ vctrl->base_pipe = NULL;
+ } else {
+ mdp4_mixer_stage_down(pipe);
+ mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 1);
+ }
+ }
+}
+
+void mdp4_dsi_cmd_overlay(struct msm_fb_data_type *mfd)
+{
+ int cndx = 0;
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+ long long xx;
+
+ vctrl = &vsync_ctrl_db[cndx];
+
+ if (!mfd->panel_power_on)
+ return;
+
+ vctrl->clk_control = 0;
+ pipe = vctrl->base_pipe;
+ if (pipe == NULL) {
+ pr_err("%s: NO base pipe\n", __func__);
+ return;
+ }
+
+ if (pipe->mixer_stage == MDP4_MIXER_STAGE_BASE) {
+ mdp4_mipi_vsync_enable(mfd, pipe, 0);
+ mdp4_overlay_setup_pipe_addr(mfd, pipe);
+ mdp4_dsi_cmd_pipe_queue(0, pipe);
+ }
+
+ mdp4_overlay_mdp_perf_upd(mfd, 1);
+
+ mutex_lock(&mfd->dma->ov_mutex);
+ mdp4_dsi_cmd_pipe_commit();
+ mutex_unlock(&mfd->dma->ov_mutex);
+
+ mdp4_dsi_cmd_wait4vsync(0, &xx);
+ vctrl->expire_tick = VSYNC_EXPIRE_TICK;
+ vctrl->clk_control = 1;
+
+ mdp4_overlay_mdp_perf_upd(mfd, 0);
+}
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..7afa8d7
--- /dev/null
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -0,0 +1,1041 @@
+/* Copyright (c) 2010-2012, 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 <linux/ktime.h>
+#include <linux/wakelock.h>
+#include <linux/time.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"
+
+#include <mach/iommu_domains.h>
+
+#define DSI_VIDEO_BASE 0xE0000
+
+static int first_pixel_start_x;
+static int first_pixel_start_y;
+static int dsi_video_enabled;
+
+#define MAX_CONTROLLER 1
+
+static struct vsycn_ctrl {
+ struct device *dev;
+ int inited;
+ int update_ndx;
+ int ov_koff;
+ int ov_done;
+ atomic_t suspend;
+ int wait_vsync_cnt;
+ int blt_change;
+ int blt_free;
+ int fake_vsync;
+ struct mutex update_lock;
+ struct completion ov_comp;
+ struct completion dmap_comp;
+ struct completion vsync_comp;
+ spinlock_t spin_lock;
+ struct msm_fb_data_type *mfd;
+ struct mdp4_overlay_pipe *base_pipe;
+ struct vsync_update vlist[2];
+ int vsync_irq_enabled;
+ ktime_t vsync_time;
+ struct work_struct vsync_work;
+} vsync_ctrl_db[MAX_CONTROLLER];
+
+static void vsync_irq_enable(int intr, int term)
+{
+ unsigned long flag;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ outp32(MDP_INTR_CLEAR, intr);
+ mdp_intr_mask |= intr;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ mdp_enable_irq(term);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ pr_debug("%s: IRQ-en done, term=%x\n", __func__, term);
+}
+
+static void vsync_irq_disable(int intr, int term)
+{
+ unsigned long flag;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ outp32(MDP_INTR_CLEAR, intr);
+ mdp_intr_mask &= ~intr;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ mdp_disable_irq_nosync(term);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ pr_debug("%s: IRQ-dis done, term=%x\n", __func__, term);
+}
+
+static void mdp4_overlay_dsi_video_start(void)
+{
+ if (!dsi_video_enabled) {
+ /* enable DSI block */
+ mdp4_iommu_attach();
+ mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 1);
+ dsi_video_enabled = 1;
+ }
+}
+
+/*
+ * mdp4_dsi_video_pipe_queue:
+ * called from thread context
+ */
+void mdp4_dsi_video_pipe_queue(int cndx, struct mdp4_overlay_pipe *pipe)
+{
+ struct vsycn_ctrl *vctrl;
+ struct vsync_update *vp;
+ struct mdp4_overlay_pipe *pp;
+ int undx;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+
+ if (atomic_read(&vctrl->suspend) > 0)
+ return;
+
+ mutex_lock(&vctrl->update_lock);
+ undx = vctrl->update_ndx;
+ vp = &vctrl->vlist[undx];
+
+ pp = &vp->plist[pipe->pipe_ndx - 1]; /* ndx start form 1 */
+
+ pr_debug("%s: vndx=%d pipe=%x ndx=%d num=%d pid=%d\n",
+ __func__, undx, (int)pipe, pipe->pipe_ndx, pipe->pipe_num,
+ current->pid);
+
+ *pp = *pipe; /* clone it */
+ vp->update_cnt++;
+ mutex_unlock(&vctrl->update_lock);
+ mdp4_stat.overlay_play[pipe->mixer_num]++;
+}
+
+static void mdp4_dsi_video_blt_ov_update(struct mdp4_overlay_pipe *pipe);
+static void mdp4_dsi_video_wait4dmap(int cndx);
+static void mdp4_dsi_video_wait4ov(int cndx);
+
+int mdp4_dsi_video_pipe_commit(void)
+{
+
+ int i, undx;
+ int mixer = 0;
+ struct vsycn_ctrl *vctrl;
+ struct vsync_update *vp;
+ struct mdp4_overlay_pipe *pipe;
+ struct mdp4_overlay_pipe *real_pipe;
+ unsigned long flags;
+ int cnt = 0;
+
+ vctrl = &vsync_ctrl_db[0];
+
+ mutex_lock(&vctrl->update_lock);
+ undx = vctrl->update_ndx;
+ vp = &vctrl->vlist[undx];
+ pipe = vctrl->base_pipe;
+ mixer = pipe->mixer_num;
+
+ if (vp->update_cnt == 0) {
+ mutex_unlock(&vctrl->update_lock);
+ return cnt;
+ }
+
+ vctrl->update_ndx++;
+ vctrl->update_ndx &= 0x01;
+ vp->update_cnt = 0; /* reset */
+ if (vctrl->blt_free) {
+ vctrl->blt_free--;
+ if (vctrl->blt_free == 0)
+ mdp4_free_writeback_buf(vctrl->mfd, mixer);
+ }
+ mutex_unlock(&vctrl->update_lock);
+
+ /* free previous committed iommu back to pool */
+ mdp4_overlay_iommu_unmap_freelist(mixer);
+
+ spin_lock_irqsave(&vctrl->spin_lock, flags);
+ if (vctrl->ov_koff != vctrl->ov_done) {
+ spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+ pr_err("%s: Error, frame dropped %d %d\n", __func__,
+ vctrl->ov_koff, vctrl->ov_done);
+ return 0;
+ }
+ spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+
+ mdp4_overlay_mdp_perf_upd(vctrl->mfd, 1);
+
+ if (vctrl->blt_change) {
+ pipe = vctrl->base_pipe;
+ spin_lock_irqsave(&vctrl->spin_lock, flags);
+ INIT_COMPLETION(vctrl->dmap_comp);
+ INIT_COMPLETION(vctrl->ov_comp);
+ vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+ spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+ mdp4_dsi_video_wait4dmap(0);
+ if (pipe->ov_blt_addr)
+ mdp4_dsi_video_wait4ov(0);
+ }
+
+ pipe = vp->plist;
+
+ for (i = 0; i < OVERLAY_PIPE_MAX; i++, pipe++) {
+ if (pipe->pipe_used) {
+ cnt++;
+ real_pipe = mdp4_overlay_ndx2pipe(pipe->pipe_ndx);
+ if (real_pipe && real_pipe->pipe_used) {
+ /* pipe not unset */
+ mdp4_overlay_vsync_commit(pipe);
+ }
+ /* free previous iommu to freelist
+ * which will be freed at next
+ * pipe_commit
+ */
+ mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 0);
+ pipe->pipe_used = 0; /* clear */
+ }
+ }
+
+ mdp4_mixer_stage_commit(mixer);
+
+ /* start timing generator & mmu if they are not started yet */
+ mdp4_overlay_dsi_video_start();
+
+ pipe = vctrl->base_pipe;
+ spin_lock_irqsave(&vctrl->spin_lock, flags);
+ if (pipe->ov_blt_addr) {
+ mdp4_dsi_video_blt_ov_update(pipe);
+ pipe->ov_cnt++;
+ INIT_COMPLETION(vctrl->ov_comp);
+ vsync_irq_enable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
+ mb();
+ vctrl->ov_koff++;
+ /* kickoff overlay engine */
+ mdp4_stat.kickoff_ov0++;
+ outpdw(MDP_BASE + 0x0004, 0);
+ } else {
+ /* schedule second phase update at dmap */
+ INIT_COMPLETION(vctrl->dmap_comp);
+ vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+ }
+ spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+
+ mdp4_stat.overlay_commit[pipe->mixer_num]++;
+
+ return cnt;
+}
+
+void mdp4_dsi_video_vsync_ctrl(int cndx, int enable)
+{
+ struct vsycn_ctrl *vctrl;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+
+ if (vctrl->fake_vsync) {
+ vctrl->fake_vsync = 0;
+ schedule_work(&vctrl->vsync_work);
+ }
+
+ if (vctrl->vsync_irq_enabled == enable)
+ return;
+
+ pr_debug("%s: vsync enable=%d\n", __func__, enable);
+
+ vctrl->vsync_irq_enabled = enable;
+
+ if (enable)
+ vsync_irq_enable(INTR_PRIMARY_VSYNC, MDP_PRIM_VSYNC_TERM);
+ else
+ vsync_irq_disable(INTR_PRIMARY_VSYNC, MDP_PRIM_VSYNC_TERM);
+}
+
+void mdp4_dsi_video_wait4vsync(int cndx, long long *vtime)
+{
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+ unsigned long flags;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+
+ if (atomic_read(&vctrl->suspend) > 0) {
+ *vtime = -1;
+ return;
+ }
+
+ /* start timing generator & mmu if they are not started yet */
+ mdp4_overlay_dsi_video_start();
+
+ spin_lock_irqsave(&vctrl->spin_lock, flags);
+ if (vctrl->wait_vsync_cnt == 0)
+ INIT_COMPLETION(vctrl->vsync_comp);
+
+ vctrl->wait_vsync_cnt++;
+ spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+
+ wait_for_completion(&vctrl->vsync_comp);
+ mdp4_stat.wait4vsync0++;
+
+ *vtime = ktime_to_ns(vctrl->vsync_time);
+}
+
+static void mdp4_dsi_video_wait4dmap(int cndx)
+{
+ struct vsycn_ctrl *vctrl;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+
+ if (atomic_read(&vctrl->suspend) > 0)
+ return;
+
+ wait_for_completion(&vctrl->dmap_comp);
+}
+
+
+static void mdp4_dsi_video_wait4dmap_done(int cndx)
+{
+ unsigned long flags;
+ struct vsycn_ctrl *vctrl;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+ vctrl = &vsync_ctrl_db[cndx];
+
+ spin_lock_irqsave(&vctrl->spin_lock, flags);
+ INIT_COMPLETION(vctrl->dmap_comp);
+ vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+ spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+ mdp4_dsi_video_wait4dmap(cndx);
+ vsync_irq_disable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+}
+
+
+static void mdp4_dsi_video_wait4ov(int cndx)
+{
+ struct vsycn_ctrl *vctrl;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+
+ if (atomic_read(&vctrl->suspend) > 0)
+ return;
+
+ wait_for_completion(&vctrl->ov_comp);
+}
+
+static void send_vsync_work(struct work_struct *work)
+{
+ struct vsycn_ctrl *vctrl =
+ container_of(work, typeof(*vctrl), vsync_work);
+ char buf[64];
+ char *envp[2];
+
+ snprintf(buf, sizeof(buf), "VSYNC=%llu",
+ ktime_to_ns(vctrl->vsync_time));
+ envp[0] = buf;
+ envp[1] = NULL;
+ kobject_uevent_env(&vctrl->dev->kobj, KOBJ_CHANGE, envp);
+}
+
+void mdp4_dsi_vsync_init(int cndx)
+{
+ struct vsycn_ctrl *vctrl;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ pr_info("%s: ndx=%d\n", __func__, cndx);
+
+ vctrl = &vsync_ctrl_db[cndx];
+ if (vctrl->inited)
+ return;
+
+ vctrl->inited = 1;
+ vctrl->update_ndx = 0;
+ mutex_init(&vctrl->update_lock);
+ init_completion(&vctrl->vsync_comp);
+ init_completion(&vctrl->dmap_comp);
+ init_completion(&vctrl->ov_comp);
+ atomic_set(&vctrl->suspend, 0);
+ spin_lock_init(&vctrl->spin_lock);
+ INIT_WORK(&vctrl->vsync_work, send_vsync_work);
+}
+
+void mdp4_dsi_video_base_swap(int cndx, struct mdp4_overlay_pipe *pipe)
+{
+ struct vsycn_ctrl *vctrl;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+ vctrl->base_pipe = pipe;
+}
+
+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;
+ unsigned int buf_offset;
+ 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 = 0;
+ int cndx = 0;
+ struct vsycn_ctrl *vctrl;
+
+ vctrl = &vsync_ctrl_db[cndx];
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ vctrl->mfd = mfd;
+ vctrl->dev = mfd->fbi->dev;
+ vctrl->fake_vsync = 1;
+
+ /* mdp clock on */
+ mdp_clk_ctrl(1);
+
+ fbi = mfd->fbi;
+ var = &fbi->var;
+
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf_offset = calc_fb_offset(mfd, fbi, bpp);
+
+ if (vctrl->base_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);
+ 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__);
+
+ pipe->ov_blt_addr = 0;
+ pipe->dma_blt_addr = 0;
+ vctrl->base_pipe = pipe; /* keep it */
+ mdp4_init_writeback_buf(mfd, MDP4_MIXER0);
+
+ } else {
+ pipe = vctrl->base_pipe;
+ }
+
+ if (!(mfd->cont_splash_done)) {
+ mfd->cont_splash_done = 1;
+ mdp4_dsi_video_wait4dmap_done(0);
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0);
+ mipi_dsi_controller_cfg(0);
+ }
+
+ 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->srcp0_ystride = fbi->fix.line_length;
+ pipe->bpp = bpp;
+
+ if (mfd->map_buffer) {
+ pipe->srcp0_addr = (unsigned int)mfd->map_buffer->iova[0] + \
+ buf_offset;
+ pr_debug("start 0x%lx srcp0_addr 0x%x\n", mfd->
+ map_buffer->iova[0], pipe->srcp0_addr);
+ } else {
+ pipe->srcp0_addr = (uint32)(buf + buf_offset);
+ }
+
+ pipe->dst_h = fbi->var.yres;
+ pipe->dst_w = fbi->var.xres;
+
+ mdp4_overlay_mdp_pipe_req(pipe, mfd);
+
+ atomic_set(&vctrl->suspend, 0);
+
+ mdp4_overlay_dmap_xy(pipe); /* dma_p */
+ mdp4_overlay_dmap_cfg(mfd, 1);
+ mdp4_overlay_rgb_setup(pipe);
+ mdp4_overlayproc_cfg(pipe);
+
+ mdp4_overlay_reg_flush(pipe, 1);
+ mdp4_mixer_stage_up(pipe);
+ mdp4_mixer_stage_commit(pipe->mixer_num);
+ /*
+ * 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.lcdc.xres_pad;
+ dsi_height = mfd->panel_info.yres +
+ mfd->panel_info.lcdc.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_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ 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);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ mdp_histogram_ctrl_all(TRUE);
+ return ret;
+}
+
+int mdp4_dsi_video_off(struct platform_device *pdev)
+{
+ int ret = 0;
+ int cndx = 0;
+ struct msm_fb_data_type *mfd;
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+
+ atomic_set(&vctrl->suspend, 1);
+
+ while (vctrl->wait_vsync_cnt)
+ msleep(20); /* >= 17 ms */
+
+ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0);
+
+ dsi_video_enabled = 0;
+
+ mdp_histogram_ctrl_all(FALSE);
+
+
+ if (pipe) {
+ /* sanity check, free pipes besides base layer */
+ mdp4_overlay_unset_mixer(pipe->mixer_num);
+ if (mfd->ref_cnt == 0) {
+ /* adb stop */
+ if (pipe->pipe_type == OVERLAY_TYPE_BF)
+ mdp4_overlay_borderfill_stage_down(pipe);
+ vctrl->base_pipe = NULL;
+ } else {
+ /* system suspending */
+ mdp4_mixer_stage_down(vctrl->base_pipe);
+ mdp4_overlay_iommu_pipe_free(
+ vctrl->base_pipe->pipe_ndx, 1);
+ }
+ }
+
+ vctrl->fake_vsync = 1;
+
+ /* mdp clock off */
+ mdp_clk_ctrl(0);
+ mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ return ret;
+}
+
+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;
+}
+
+/* 3D side by side */
+void mdp4_dsi_video_3d_sbys(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_3d *r3d)
+{
+ struct fb_info *fbi;
+ unsigned int buf_offset;
+ int bpp;
+ uint8 *buf = NULL;
+ int cndx = 0;
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+
+ if (vctrl->base_pipe == NULL)
+ return;
+
+ pipe = vctrl->base_pipe;
+ pipe->is_3d = r3d->is_3d;
+ pipe->src_height_3d = r3d->height;
+ pipe->src_width_3d = r3d->width;
+
+ 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);
+
+ fbi = mfd->fbi;
+
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf_offset = calc_fb_offset(mfd, fbi, bpp);
+
+ if (pipe->is_3d) {
+ 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;
+
+ if (mfd->map_buffer) {
+ pipe->srcp0_addr = (unsigned int)mfd->map_buffer->iova[0] + \
+ buf_offset;
+ pr_debug("start 0x%lx srcp0_addr 0x%x\n", mfd->
+ map_buffer->iova[0], pipe->srcp0_addr);
+ } else {
+ pipe->srcp0_addr = (uint32)(buf + buf_offset);
+ }
+
+ mdp4_overlay_rgb_setup(pipe);
+
+ mdp4_overlayproc_cfg(pipe);
+
+ mdp4_overlay_dmap_xy(pipe);
+
+ mdp4_overlay_dmap_cfg(mfd, 1);
+
+ mdp4_overlay_reg_flush(pipe, 1);
+
+ mdp4_mixer_stage_up(pipe);
+
+ mdp4_mixer_stage_commit(pipe->mixer_num);
+
+ mb();
+}
+
+static void mdp4_dsi_video_blt_ov_update(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 off, addr;
+ int bpp;
+ char *overlay_base;
+
+ if (pipe->ov_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->ov_cnt & 0x01)
+ off = pipe->src_height * pipe->src_width * bpp;
+ addr = pipe->ov_blt_addr + off;
+
+ /* overlay 0 */
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+ outpdw(overlay_base + 0x000c, addr);
+ outpdw(overlay_base + 0x001c, addr);
+}
+
+static void mdp4_dsi_video_blt_dmap_update(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 off, addr;
+ int bpp;
+
+ if (pipe->ov_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->dma_blt_addr + off;
+
+ /* dmap */
+ MDP_OUTP(MDP_BASE + 0x90008, addr);
+}
+
+/*
+ * mdp4_primary_vsync_dsi_video: called from isr
+ */
+void mdp4_primary_vsync_dsi_video(void)
+{
+ int cndx;
+ struct vsycn_ctrl *vctrl;
+
+
+ cndx = 0;
+ vctrl = &vsync_ctrl_db[cndx];
+ pr_debug("%s: cpu=%d\n", __func__, smp_processor_id());
+ vctrl->vsync_time = ktime_get();
+ schedule_work(&vctrl->vsync_work);
+
+ spin_lock(&vctrl->spin_lock);
+ if (vctrl->wait_vsync_cnt) {
+ complete_all(&vctrl->vsync_comp);
+ vctrl->wait_vsync_cnt = 0;
+ }
+ spin_unlock(&vctrl->spin_lock);
+}
+
+ /*
+ * mdp4_dmap_done_dsi_video: called from isr
+ */
+void mdp4_dmap_done_dsi_video(int cndx)
+{
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+
+ spin_lock(&vctrl->spin_lock);
+ vsync_irq_disable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+ if (vctrl->blt_change) {
+ mdp4_overlayproc_cfg(pipe);
+ mdp4_overlay_dmap_xy(pipe);
+ if (pipe->ov_blt_addr) {
+ mdp4_dsi_video_blt_ov_update(pipe);
+ pipe->ov_cnt++;
+ /* Prefill one frame */
+ vsync_irq_enable(INTR_OVERLAY0_DONE,
+ MDP_OVERLAY0_TERM);
+ /* kickoff overlay0 engine */
+ mdp4_stat.kickoff_ov0++;
+ vctrl->ov_koff++; /* make up for prefill */
+ outpdw(MDP_BASE + 0x0004, 0);
+ }
+ vctrl->blt_change = 0;
+ }
+
+ complete_all(&vctrl->dmap_comp);
+ mdp4_overlay_dma_commit(cndx);
+ spin_unlock(&vctrl->spin_lock);
+}
+
+/*
+ * mdp4_overlay0_done_dsi: called from isr
+ */
+void mdp4_overlay0_done_dsi_video(int cndx)
+{
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+
+ spin_lock(&vctrl->spin_lock);
+ vsync_irq_disable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
+ vctrl->ov_done++;
+ complete_all(&vctrl->ov_comp);
+ if (pipe->ov_blt_addr == 0) {
+ spin_unlock(&vctrl->spin_lock);
+ return;
+ }
+
+ mdp4_dsi_video_blt_dmap_update(pipe);
+ pipe->dmap_cnt++;
+ spin_unlock(&vctrl->spin_lock);
+}
+
+/*
+ * make sure the MIPI_DSI_WRITEBACK_SIZE defined at boardfile
+ * has enough space h * w * 3 * 2
+ */
+static void mdp4_dsi_video_do_blt(struct msm_fb_data_type *mfd, int enable)
+{
+ unsigned long flag;
+ int cndx = 0;
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+
+ mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0);
+
+ if (mfd->ov0_wb_buf->write_addr == 0) {
+ pr_info("%s: no blt_base assigned\n", __func__);
+ return;
+ }
+
+ spin_lock_irqsave(&vctrl->spin_lock, flag);
+ if (enable && pipe->ov_blt_addr == 0) {
+ pipe->ov_blt_addr = mfd->ov0_wb_buf->write_addr;
+ pipe->dma_blt_addr = mfd->ov0_wb_buf->read_addr;
+ pipe->ov_cnt = 0;
+ pipe->dmap_cnt = 0;
+ vctrl->ov_koff = 0;
+ vctrl->ov_done = 0;
+ vctrl->blt_free = 0;
+ mdp4_stat.blt_dsi_video++;
+ vctrl->blt_change++;
+ } else if (enable == 0 && pipe->ov_blt_addr) {
+ pipe->ov_blt_addr = 0;
+ pipe->dma_blt_addr = 0;
+ vctrl->blt_free = 4; /* 4 commits to free wb buf */
+ vctrl->blt_change++;
+ }
+
+ pr_info("%s: changed=%d enable=%d ov_blt_addr=%x\n", __func__,
+ vctrl->blt_change, enable, (int)pipe->ov_blt_addr);
+
+ if (!vctrl->blt_change) {
+ spin_unlock_irqrestore(&vctrl->spin_lock, flag);
+ return;
+ }
+
+ spin_unlock_irqrestore(&vctrl->spin_lock, flag);
+}
+
+void mdp4_dsi_video_overlay_blt(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req)
+{
+ mdp4_dsi_video_do_blt(mfd, req->enable);
+}
+
+void mdp4_dsi_video_blt_start(struct msm_fb_data_type *mfd)
+{
+ mdp4_dsi_video_do_blt(mfd, 1);
+}
+
+void mdp4_dsi_video_blt_stop(struct msm_fb_data_type *mfd)
+{
+ mdp4_dsi_video_do_blt(mfd, 0);
+}
+
+void mdp4_dsi_video_overlay(struct msm_fb_data_type *mfd)
+{
+ struct fb_info *fbi = mfd->fbi;
+ uint8 *buf;
+ unsigned int buf_offset;
+ int bpp;
+ int cndx = 0;
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+
+ if (!pipe || !mfd->panel_power_on)
+ return;
+
+ pr_debug("%s: cpu=%d pid=%d\n", __func__,
+ smp_processor_id(), current->pid);
+ if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf_offset = calc_fb_offset(mfd, fbi, bpp);
+
+ if (mfd->map_buffer->iova[0]) {
+ pipe->srcp0_addr = mfd->map_buffer->iova[0]
+ + buf_offset;
+ } else
+ pipe->srcp0_addr = (uint32)(buf + buf_offset);
+
+ mdp4_dsi_video_pipe_queue(0, pipe);
+ }
+
+ mdp4_overlay_mdp_perf_upd(mfd, 1);
+
+ mutex_lock(&mfd->dma->ov_mutex);
+ mdp4_dsi_video_pipe_commit();
+ mutex_unlock(&mfd->dma->ov_mutex);
+
+ if (pipe->ov_blt_addr)
+ mdp4_dsi_video_wait4ov(0);
+ else
+ mdp4_dsi_video_wait4dmap(0);
+
+ mdp4_overlay_mdp_perf_upd(mfd, 0);
+}
+
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
new file mode 100644
index 0000000..0bd4ced
--- /dev/null
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -0,0 +1,1011 @@
+/* Copyright (c) 2011-2012, 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
+
+static int dtv_enabled;
+
+/*#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;
+
+void mdp4_dtv_base_swap(int cndx, struct mdp4_overlay_pipe *pipe)
+{
+#ifdef BYPASS4
+ if (hdmi_prim_display)
+ dtv_pipe = pipe;
+#endif
+}
+
+#define MAX_CONTROLLER 1
+
+static struct vsycn_ctrl {
+ struct device *dev;
+ int inited;
+ int update_ndx;
+ int dmae_intr_cnt;
+ atomic_t suspend;
+ int wait_vsync_cnt;
+ int blt_change;
+ int fake_vsync;
+ struct mutex update_lock;
+ struct completion ov_comp;
+ struct completion dmae_comp;
+ struct completion vsync_comp;
+ spinlock_t spin_lock;
+ struct mdp4_overlay_pipe *base_pipe;
+ struct vsync_update vlist[2];
+ int vsync_irq_enabled;
+ ktime_t vsync_time;
+ struct work_struct vsync_work;
+} vsync_ctrl_db[MAX_CONTROLLER];
+
+static void vsync_irq_enable(int intr, int term)
+{
+ unsigned long flag;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ outp32(MDP_INTR_CLEAR, intr);
+ mdp_intr_mask |= intr;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ mdp_enable_irq(term);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ pr_debug("%s: IRQ-en done, term=%x\n", __func__, term);
+}
+
+static void vsync_irq_disable(int intr, int term)
+{
+ unsigned long flag;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ outp32(MDP_INTR_CLEAR, intr);
+ mdp_intr_mask &= ~intr;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ mdp_disable_irq_nosync(term);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ pr_debug("%s: IRQ-dis done, term=%x\n", __func__, term);
+}
+
+void mdp4_overlay_dtv_start(void)
+{
+ if (!dtv_enabled) {
+ /* enable DTV block */
+ mdp4_iommu_attach();
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ MDP_OUTP(MDP_BASE + DTV_BASE, 1);
+ mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ dtv_enabled = 1;
+ }
+}
+
+/*
+ * mdp4_dtv_vsync_do_update:
+ * called from thread context
+ */
+void mdp4_dtv_pipe_queue(int cndx, struct mdp4_overlay_pipe *pipe)
+{
+ struct vsycn_ctrl *vctrl;
+ struct vsync_update *vp;
+ struct mdp4_overlay_pipe *pp;
+ int undx;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+
+ if (atomic_read(&vctrl->suspend) > 0)
+ return;
+
+ mutex_lock(&vctrl->update_lock);
+ undx = vctrl->update_ndx;
+ vp = &vctrl->vlist[undx];
+
+ pp = &vp->plist[pipe->pipe_ndx - 1]; /* ndx start form 1 */
+
+ pr_debug("%s: vndx=%d pipe_ndx=%d flags=%x pid=%d\n",
+ __func__, undx, pipe->pipe_ndx, pipe->flags, current->pid);
+
+ *pp = *pipe; /* clone it */
+ vp->update_cnt++;
+ mutex_unlock(&vctrl->update_lock);
+ mdp4_stat.overlay_play[pipe->mixer_num]++;
+}
+
+static void mdp4_dtv_blt_ov_update(struct mdp4_overlay_pipe *pipe);
+static void mdp4_dtv_wait4dmae(int cndx);
+
+int mdp4_dtv_pipe_commit(void)
+{
+
+ int i, undx;
+ int mixer = 0;
+ struct vsycn_ctrl *vctrl;
+ struct vsync_update *vp;
+ struct mdp4_overlay_pipe *pipe;
+ struct mdp4_overlay_pipe *real_pipe;
+ unsigned long flags;
+ int cnt = 0;
+
+ vctrl = &vsync_ctrl_db[0];
+ mutex_lock(&vctrl->update_lock);
+ undx = vctrl->update_ndx;
+ vp = &vctrl->vlist[undx];
+ pipe = vctrl->base_pipe;
+ mixer = pipe->mixer_num;
+ mdp4_overlay_iommu_unmap_freelist(mixer);
+
+ if (vp->update_cnt == 0) {
+ mutex_unlock(&vctrl->update_lock);
+ return 0;
+ }
+
+ vctrl->update_ndx++;
+ vctrl->update_ndx &= 0x01;
+ vp->update_cnt = 0; /* reset */
+ mutex_unlock(&vctrl->update_lock);
+
+ pipe = vp->plist;
+ for (i = 0; i < OVERLAY_PIPE_MAX; i++, pipe++) {
+ if (pipe->pipe_used) {
+ cnt++;
+ real_pipe = mdp4_overlay_ndx2pipe(pipe->pipe_ndx);
+ if (real_pipe && real_pipe->pipe_used) {
+ /* pipe not unset */
+ mdp4_overlay_vsync_commit(pipe);
+ }
+ /* free previous iommu to freelist
+ * which will be freed at next
+ * pipe_commit
+ */
+ mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 0);
+ pipe->pipe_used = 0; /* clear */
+ }
+ }
+ mdp4_mixer_stage_commit(mixer);
+
+ /* start timing generator & mmu if they are not started yet */
+ mdp4_overlay_dtv_start();
+
+ pipe = vctrl->base_pipe;
+ spin_lock_irqsave(&vctrl->spin_lock, flags);
+ if (pipe->ov_blt_addr) {
+ mdp4_dtv_blt_ov_update(pipe);
+ pipe->blt_ov_done++;
+ vsync_irq_enable(INTR_OVERLAY1_DONE, MDP_OVERLAY1_TERM);
+ mb();
+ pipe->blt_ov_koff++;
+ /* kickoff overlay1 engine */
+ mdp4_stat.kickoff_ov1++;
+ outpdw(MDP_BASE + 0x0008, 0);
+ } else {
+ /* schedule second phase update at dmap */
+ INIT_COMPLETION(vctrl->dmae_comp);
+ vsync_irq_enable(INTR_DMA_E_DONE, MDP_DMA_E_TERM);
+ }
+ spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+ mdp4_stat.overlay_commit[pipe->mixer_num]++;
+
+ return cnt;
+}
+
+void mdp4_dtv_vsync_ctrl(int cndx, int enable)
+{
+ struct vsycn_ctrl *vctrl;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+
+ if (vctrl->fake_vsync) {
+ vctrl->fake_vsync = 0;
+ schedule_work(&vctrl->vsync_work);
+ }
+
+ if (vctrl->vsync_irq_enabled == enable)
+ return;
+
+ pr_debug("%s: vsync enable=%d\n", __func__, enable);
+
+ vctrl->vsync_irq_enabled = enable;
+
+ if (enable)
+ vsync_irq_enable(INTR_EXTERNAL_VSYNC, MDP_EXTER_VSYNC_TERM);
+ else
+ vsync_irq_disable(INTR_EXTERNAL_VSYNC, MDP_EXTER_VSYNC_TERM);
+}
+
+void mdp4_dtv_wait4vsync(int cndx, long long *vtime)
+{
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+ unsigned long flags;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+
+ if (atomic_read(&vctrl->suspend) > 0)
+ return;
+
+ spin_lock_irqsave(&vctrl->spin_lock, flags);
+
+ if (vctrl->wait_vsync_cnt == 0)
+ INIT_COMPLETION(vctrl->vsync_comp);
+ vctrl->wait_vsync_cnt++;
+ spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+
+ wait_for_completion(&vctrl->vsync_comp);
+ mdp4_stat.wait4vsync1++;
+
+ *vtime = ktime_to_ns(vctrl->vsync_time);
+}
+
+static void mdp4_dtv_wait4dmae(int cndx)
+{
+ struct vsycn_ctrl *vctrl;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+
+ if (atomic_read(&vctrl->suspend) > 0)
+ return;
+
+ wait_for_completion(&vctrl->dmae_comp);
+}
+
+static void send_vsync_work(struct work_struct *work)
+{
+ struct vsycn_ctrl *vctrl =
+ container_of(work, typeof(*vctrl), vsync_work);
+ char buf[64];
+ char *envp[2];
+
+ snprintf(buf, sizeof(buf), "VSYNC=%llu",
+ ktime_to_ns(vctrl->vsync_time));
+ envp[0] = buf;
+ envp[1] = NULL;
+ kobject_uevent_env(&vctrl->dev->kobj, KOBJ_CHANGE, envp);
+}
+
+void mdp4_dtv_vsync_init(int cndx)
+{
+ struct vsycn_ctrl *vctrl;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ pr_info("%s: ndx=%d\n", __func__, cndx);
+
+ vctrl = &vsync_ctrl_db[cndx];
+ if (vctrl->inited)
+ return;
+
+ vctrl->inited = 1;
+ vctrl->update_ndx = 0;
+ mutex_init(&vctrl->update_lock);
+ init_completion(&vctrl->vsync_comp);
+ init_completion(&vctrl->ov_comp);
+ init_completion(&vctrl->dmae_comp);
+ atomic_set(&vctrl->suspend, 0);
+ spin_lock_init(&vctrl->spin_lock);
+ INIT_WORK(&vctrl->vsync_work, send_vsync_work);
+}
+
+static int mdp4_dtv_start(struct msm_fb_data_type *mfd)
+{
+ 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;
+ struct fb_info *fbi;
+ struct fb_var_screeninfo *var;
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ fbi = mfd->fbi;
+ var = &fbi->var;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ if (hdmi_prim_display) {
+ if (is_mdp4_hw_reset()) {
+ mdp4_hw_init();
+ outpdw(MDP_BASE + 0x0038, mdp4_display_intf);
+ }
+ }
+ mdp4_overlay_dmae_cfg(mfd, 0);
+
+ /*
+ * 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); */
+
+ /* enable DTV block */
+ MDP_OUTP(MDP_BASE + DTV_BASE, 1);
+
+ return 0;
+}
+
+static int mdp4_dtv_stop(struct msm_fb_data_type *mfd)
+{
+ int cndx = 0;
+ struct vsycn_ctrl *vctrl;
+
+ vctrl = &vsync_ctrl_db[cndx];
+ if (vctrl->base_pipe == NULL)
+ return -EINVAL;
+
+ MDP_OUTP(MDP_BASE + DTV_BASE, 0);
+
+ return 0;
+}
+
+int mdp4_dtv_on(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ int ret = 0;
+ int cndx = 0;
+ struct vsycn_ctrl *vctrl;
+
+ vctrl = &vsync_ctrl_db[cndx];
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ vctrl->dev = mfd->fbi->dev;
+ vctrl->fake_vsync = 1;
+
+ mdp_footswitch_ctrl(TRUE);
+ /* Mdp clock enable */
+ mdp_clk_ctrl(1);
+
+ mdp4_overlay_panel_mode(MDP4_MIXER1, MDP4_PANEL_DTV);
+
+ /* Allocate dtv_pipe at dtv_on*/
+ if (vctrl->base_pipe == NULL) {
+ if (mdp4_overlay_dtv_set(mfd, NULL)) {
+ pr_warn("%s: dtv_pipe is NULL, dtv_set failed\n",
+ __func__);
+ return -EINVAL;
+ }
+ }
+
+ ret = panel_next_on(pdev);
+ if (ret != 0)
+ pr_warn("%s: panel_next_on failed", __func__);
+
+ atomic_set(&vctrl->suspend, 0);
+
+ pr_info("%s:\n", __func__);
+
+ return ret;
+}
+
+int mdp4_dtv_off(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ int ret = 0;
+ int cndx = 0;
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ vctrl = &vsync_ctrl_db[cndx];
+
+ atomic_set(&vctrl->suspend, 1);
+
+ while (vctrl->wait_vsync_cnt)
+ msleep(20); /* >= 17 ms */
+
+ pipe = vctrl->base_pipe;
+ if (pipe != NULL) {
+ mdp4_dtv_stop(mfd);
+ /* sanity check, free pipes besides base layer */
+ mdp4_overlay_unset_mixer(pipe->mixer_num);
+ if (hdmi_prim_display && mfd->ref_cnt == 0) {
+ /* adb stop */
+ if (pipe->pipe_type == OVERLAY_TYPE_BF)
+ mdp4_overlay_borderfill_stage_down(pipe);
+
+ /* pipe == rgb2 */
+ vctrl->base_pipe = NULL;
+ } else {
+ mdp4_mixer_stage_down(pipe);
+ mdp4_overlay_pipe_free(pipe);
+ vctrl->base_pipe = NULL;
+ }
+ }
+
+ mdp4_overlay_panel_mode_unset(MDP4_MIXER1, MDP4_PANEL_DTV);
+
+ ret = panel_next_off(pdev);
+ mdp_footswitch_ctrl(FALSE);
+ vctrl->fake_vsync = 1;
+
+ /* Mdp clock disable */
+ mdp_clk_ctrl(0);
+
+ pr_info("%s:\n", __func__);
+ return ret;
+}
+
+static void mdp4_dtv_blt_ov_update(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 off, addr;
+ int bpp;
+ char *overlay_base;
+
+ if (pipe->ov_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->blt_ov_done & 0x01)
+ off = pipe->src_height * pipe->src_width * bpp;
+ addr = pipe->ov_blt_addr + off;
+
+ /* overlay 1 */
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x10000 */
+ outpdw(overlay_base + 0x000c, addr);
+ outpdw(overlay_base + 0x001c, addr);
+}
+
+static void mdp4_dtv_blt_dmae_update(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 off, addr;
+ int bpp;
+
+ if (pipe->ov_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->blt_dmap_done & 0x01)
+ off = pipe->src_height * pipe->src_width * bpp;
+ addr = pipe->dma_blt_addr + off;
+
+ /* dmae */
+ MDP_OUTP(MDP_BASE + 0xb0008, addr);
+}
+
+void mdp4_overlay_dtv_set_perf(struct msm_fb_data_type *mfd)
+{
+
+}
+
+static void mdp4_overlay_dtv_alloc_pipe(struct msm_fb_data_type *mfd,
+ int32 ptype, struct vsycn_ctrl *vctrl)
+{
+ int ret = 0;
+ struct fb_info *fbi = mfd->fbi;
+ struct mdp4_overlay_pipe *pipe;
+
+ if (vctrl->base_pipe != NULL)
+ return;
+
+ pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER1);
+ if (pipe == NULL) {
+ pr_err("%s: pipe_alloc failed\n", __func__);
+ return;
+ }
+ pipe->pipe_used++;
+ pipe->mixer_stage = MDP4_MIXER_STAGE_BASE;
+ pipe->mixer_num = MDP4_MIXER1;
+
+ if (ptype == OVERLAY_TYPE_BF) {
+ /* LSP_BORDER_COLOR */
+ MDP_OUTP(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x5004,
+ ((0x0 & 0xFFF) << 16) | /* 12-bit B */
+ (0x0 & 0xFFF)); /* 12-bit G */
+ /* MSP_BORDER_COLOR */
+ MDP_OUTP(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x5008,
+ (0x0 & 0xFFF)); /* 12-bit R */
+ pipe->src_format = MDP_ARGB_8888;
+ } else {
+ switch (mfd->ibuf.bpp) {
+ case 2:
+ pipe->src_format = MDP_RGB_565;
+ break;
+ case 3:
+ pipe->src_format = MDP_RGB_888;
+ break;
+ case 4:
+ default:
+ if (hdmi_prim_display)
+ pipe->src_format = MSMFB_DEFAULT_TYPE;
+ else
+ pipe->src_format = MDP_ARGB_8888;
+ break;
+ }
+ }
+
+ 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->src_y = 0;
+ pipe->src_x = 0;
+ pipe->dst_h = fbi->var.yres;
+ pipe->dst_w = fbi->var.xres;
+ pipe->srcp0_ystride = fbi->fix.line_length;
+
+ mdp4_overlay_mdp_pipe_req(pipe, mfd);
+
+ ret = mdp4_overlay_format2pipe(pipe);
+ if (ret < 0)
+ pr_warn("%s: format2type failed\n", __func__);
+
+ mdp4_overlay_dmae_xy(pipe); /* dma_e */
+ mdp4_overlayproc_cfg(pipe);
+
+ if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
+ pipe->srcp0_addr = (uint32) mfd->ibuf.buf;
+ mdp4_overlay_rgb_setup(pipe);
+ }
+
+ mdp4_overlay_reg_flush(pipe, 1);
+ mdp4_mixer_stage_up(pipe);
+ mdp4_mixer_stage_commit(pipe->mixer_num);
+ vctrl->base_pipe = pipe; /* keep it */
+}
+
+int mdp4_overlay_dtv_set(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ int cndx = 0;
+ struct vsycn_ctrl *vctrl;
+
+ vctrl = &vsync_ctrl_db[cndx];
+ if (vctrl->base_pipe != NULL)
+ return 0;
+
+ if (pipe != NULL && pipe->mixer_stage == MDP4_MIXER_STAGE_BASE &&
+ pipe->pipe_type == OVERLAY_TYPE_RGB)
+ vctrl->base_pipe = pipe; /* keep it */
+ else if (!hdmi_prim_display && mdp4_overlay_borderfill_supported())
+ mdp4_overlay_dtv_alloc_pipe(mfd, OVERLAY_TYPE_BF, vctrl);
+ else
+ mdp4_overlay_dtv_alloc_pipe(mfd, OVERLAY_TYPE_RGB, vctrl);
+
+
+ if (vctrl->base_pipe == NULL)
+ return -ENODEV;
+
+ mdp4_init_writeback_buf(mfd, MDP4_MIXER1);
+ vctrl->base_pipe->ov_blt_addr = 0;
+ vctrl->base_pipe->dma_blt_addr = 0;
+
+ return mdp4_dtv_start(mfd);
+}
+
+int mdp4_overlay_dtv_unset(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ int result = 0;
+ int cndx = 0;
+ struct vsycn_ctrl *vctrl;
+
+ vctrl = &vsync_ctrl_db[cndx];
+ if (vctrl->base_pipe != NULL)
+ return 0;
+
+ if (pipe->mixer_stage == MDP4_MIXER_STAGE_BASE &&
+ pipe->pipe_type == OVERLAY_TYPE_RGB) {
+ result = mdp4_dtv_stop(mfd);
+ vctrl->base_pipe = NULL;
+ }
+ return result;
+}
+
+/* TODO: dtv writeback need to be added later */
+
+void mdp4_external_vsync_dtv(void)
+{
+ int cndx;
+ struct vsycn_ctrl *vctrl;
+
+ cndx = 0;
+ vctrl = &vsync_ctrl_db[cndx];
+ pr_debug("%s: cpu=%d\n", __func__, smp_processor_id());
+ vctrl->vsync_time = ktime_get();
+ schedule_work(&vctrl->vsync_work);
+
+ spin_lock(&vctrl->spin_lock);
+ if (vctrl->wait_vsync_cnt) {
+ complete_all(&vctrl->vsync_comp);
+ vctrl->wait_vsync_cnt = 0;
+ }
+ spin_unlock(&vctrl->spin_lock);
+}
+
+/*
+ * mdp4_dmae_done_dtv: called from isr
+ */
+void mdp4_dmae_done_dtv(void)
+{
+ int cndx;
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+
+ cndx = 0;
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+ pr_debug("%s: cpu=%d\n", __func__, smp_processor_id());
+
+ spin_lock(&vctrl->spin_lock);
+ if (vctrl->blt_change) {
+ if (pipe->ov_blt_addr) {
+ mdp4_overlayproc_cfg(pipe);
+ mdp4_overlay_dmae_xy(pipe);
+ mdp4_dtv_blt_ov_update(pipe);
+ pipe->blt_ov_done++;
+
+ /* Prefill one frame */
+ vsync_irq_enable(INTR_OVERLAY1_DONE, MDP_OVERLAY1_TERM);
+ /* kickoff overlay1 engine */
+ mdp4_stat.kickoff_ov1++;
+ outpdw(MDP_BASE + 0x0008, 0);
+ }
+ vctrl->blt_change = 0;
+ }
+
+ complete_all(&vctrl->dmae_comp);
+ mdp4_overlay_dma_commit(MDP4_MIXER1);
+ vsync_irq_disable(INTR_DMA_E_DONE, MDP_DMA_E_TERM);
+ spin_unlock(&vctrl->spin_lock);
+}
+
+/*
+ * mdp4_overlay1_done_dtv: called from isr
+ */
+void mdp4_overlay1_done_dtv(void)
+{
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+ int cndx = 0;
+
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+
+ spin_lock(&vctrl->spin_lock);
+ if (pipe->ov_blt_addr == 0) {
+ spin_unlock(&vctrl->spin_lock);
+ return;
+ }
+
+ mdp4_dtv_blt_dmae_update(pipe);
+ pipe->blt_dmap_done++;
+ vsync_irq_disable(INTR_OVERLAY1_DONE, MDP_OVERLAY1_TERM);
+ spin_unlock(&vctrl->spin_lock);
+}
+
+void mdp4_dtv_set_black_screen(void)
+{
+ char *rgb_base;
+ /*Black color*/
+ uint32 color = 0x00000000;
+ uint32 temp_src_format;
+ int cndx = 0;
+ struct vsycn_ctrl *vctrl;
+
+ vctrl = &vsync_ctrl_db[cndx];
+ if (vctrl->base_pipe == NULL || !hdmi_prim_display) {
+ pr_err("dtv_pipe is not configured yet\n");
+ return;
+ }
+ rgb_base = MDP_BASE + MDP4_RGB_BASE;
+ rgb_base += (MDP4_RGB_OFF * vctrl->base_pipe->pipe_num);
+
+ /*
+ * RGB Constant Color
+ */
+ MDP_OUTP(rgb_base + 0x1008, color);
+ /*
+ * MDP_RGB_SRC_FORMAT
+ */
+ temp_src_format = inpdw(rgb_base + 0x0050);
+ MDP_OUTP(rgb_base + 0x0050, temp_src_format | BIT(22));
+ mdp4_overlay_reg_flush(vctrl->base_pipe, 1);
+ mdp4_mixer_stage_up(vctrl->base_pipe);
+ mdp4_mixer_stage_commit(vctrl->base_pipe->mixer_num);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+static void mdp4_dtv_do_blt(struct msm_fb_data_type *mfd, int enable)
+{
+ unsigned long flag;
+ int data;
+ int cndx = 0;
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+
+ mdp4_allocate_writeback_buf(mfd, MDP4_MIXER1);
+
+ if (!mfd->ov1_wb_buf->write_addr) {
+ pr_info("%s: ctrl=%d blt_base NOT assigned\n", __func__, cndx);
+ return;
+ }
+
+ spin_lock_irqsave(&vctrl->spin_lock, flag);
+ if (enable && pipe->ov_blt_addr == 0) {
+ pipe->ov_blt_addr = mfd->ov1_wb_buf->write_addr;
+ pipe->dma_blt_addr = mfd->ov1_wb_buf->read_addr;
+ pipe->blt_cnt = 0;
+ pipe->ov_cnt = 0;
+ pipe->blt_dmap_done = 0;
+ pipe->blt_ov_koff = 0;
+ pipe->blt_ov_done = 0;
+ mdp4_stat.blt_dtv++;
+ vctrl->blt_change++;
+ } else if (enable == 0 && pipe->ov_blt_addr) {
+ pipe->ov_blt_addr = 0;
+ pipe->dma_blt_addr = 0;
+ vctrl->blt_change++;
+ }
+
+ pr_info("%s: enable=%d change=%d blt_addr=%x\n", __func__,
+ enable, vctrl->blt_change, (int)pipe->ov_blt_addr);
+
+ if (!vctrl->blt_change) {
+ spin_unlock_irqrestore(&vctrl->spin_lock, flag);
+ return;
+ }
+
+ atomic_set(&vctrl->suspend, 1);
+ spin_unlock_irqrestore(&vctrl->spin_lock, flag);
+
+ data = inpdw(MDP_BASE + DTV_BASE);
+ data &= 0x01;
+ if (data) /* timing generator enabled */
+ mdp4_dtv_wait4dmae(0);
+
+ if (pipe->ov_blt_addr == 0) {
+ MDP_OUTP(MDP_BASE + DTV_BASE, 0); /* stop dtv */
+ msleep(20);
+ mdp4_overlayproc_cfg(pipe);
+ mdp4_overlay_dmae_xy(pipe);
+ MDP_OUTP(MDP_BASE + DTV_BASE, 1); /* start dtv */
+ }
+
+ atomic_set(&vctrl->suspend, 0);
+}
+
+void mdp4_dtv_overlay_blt_start(struct msm_fb_data_type *mfd)
+{
+ mdp4_dtv_do_blt(mfd, 1);
+}
+
+void mdp4_dtv_overlay_blt_stop(struct msm_fb_data_type *mfd)
+{
+ mdp4_dtv_do_blt(mfd, 0);
+}
+
+void mdp4_dtv_overlay(struct msm_fb_data_type *mfd)
+{
+ int cndx = 0;
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+
+ if (!mfd->panel_power_on)
+ return;
+
+ vctrl = &vsync_ctrl_db[cndx];
+ if (vctrl->base_pipe == NULL)
+ mdp4_overlay_dtv_set(mfd, NULL);
+
+ pipe = vctrl->base_pipe;
+
+ if (pipe == NULL) {
+ pr_warn("%s: dtv_pipe == NULL\n", __func__);
+ return;
+ }
+
+ if (hdmi_prim_display && (pipe->pipe_used == 0 ||
+ pipe->mixer_stage != MDP4_MIXER_STAGE_BASE)) {
+ pr_err("%s: NOT baselayer\n", __func__);
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return;
+ }
+
+ if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
+ pipe->srcp0_addr = (uint32)mfd->ibuf.buf;
+ mdp4_dtv_pipe_queue(0, pipe);
+ }
+
+ mutex_lock(&mfd->dma->ov_mutex);
+ mdp4_dtv_pipe_commit();
+ 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..dd5b67e
--- /dev/null
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -0,0 +1,911 @@
+/* Copyright (c) 2009-2012, 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 lcdc_enabled;
+
+#define MAX_CONTROLLER 1
+
+static struct vsycn_ctrl {
+ struct device *dev;
+ int inited;
+ int update_ndx;
+ int ov_koff;
+ int ov_done;
+ atomic_t suspend;
+ int wait_vsync_cnt;
+ int blt_change;
+ int blt_free;
+ int fake_vsync;
+ struct mutex update_lock;
+ struct completion ov_comp;
+ struct completion dmap_comp;
+ struct completion vsync_comp;
+ spinlock_t spin_lock;
+ struct msm_fb_data_type *mfd;
+ struct mdp4_overlay_pipe *base_pipe;
+ struct vsync_update vlist[2];
+ int vsync_irq_enabled;
+ ktime_t vsync_time;
+ struct work_struct vsync_work;
+} vsync_ctrl_db[MAX_CONTROLLER];
+
+
+/*******************************************************
+to do:
+1) move vsync_irq_enable/vsync_irq_disable to mdp.c to be shared
+*******************************************************/
+static void vsync_irq_enable(int intr, int term)
+{
+ unsigned long flag;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ outp32(MDP_INTR_CLEAR, intr);
+ mdp_intr_mask |= intr;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ mdp_enable_irq(term);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ pr_debug("%s: IRQ-en done, term=%x\n", __func__, term);
+}
+
+static void vsync_irq_disable(int intr, int term)
+{
+ unsigned long flag;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ outp32(MDP_INTR_CLEAR, intr);
+ mdp_intr_mask &= ~intr;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ mdp_disable_irq_nosync(term);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ pr_debug("%s: IRQ-dis done, term=%x\n", __func__, term);
+}
+
+static void mdp4_overlay_lcdc_start(void)
+{
+ if (!lcdc_enabled) {
+ /* enable DSI block */
+ mdp4_iommu_attach();
+ mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ MDP_OUTP(MDP_BASE + LCDC_BASE, 1);
+ lcdc_enabled = 1;
+ }
+}
+
+/*
+ * mdp4_lcdc_pipe_queue:
+ * called from thread context
+ */
+void mdp4_lcdc_pipe_queue(int cndx, struct mdp4_overlay_pipe *pipe)
+{
+ struct vsycn_ctrl *vctrl;
+ struct vsync_update *vp;
+ struct mdp4_overlay_pipe *pp;
+ int undx;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+
+ if (atomic_read(&vctrl->suspend) > 0)
+ return;
+
+ mutex_lock(&vctrl->update_lock);
+ undx = vctrl->update_ndx;
+ vp = &vctrl->vlist[undx];
+
+ pp = &vp->plist[pipe->pipe_ndx - 1]; /* ndx start form 1 */
+
+ pr_debug("%s: vndx=%d pipe_ndx=%d pid=%d\n", __func__,
+ undx, pipe->pipe_ndx, current->pid);
+
+ *pp = *pipe; /* clone it */
+ vp->update_cnt++;
+ mutex_unlock(&vctrl->update_lock);
+ mdp4_stat.overlay_play[pipe->mixer_num]++;
+}
+
+static void mdp4_lcdc_blt_ov_update(struct mdp4_overlay_pipe *pipe);
+static void mdp4_lcdc_wait4dmap(int cndx);
+static void mdp4_lcdc_wait4ov(int cndx);
+
+int mdp4_lcdc_pipe_commit(void)
+{
+
+ int i, undx;
+ int mixer = 0;
+ struct vsycn_ctrl *vctrl;
+ struct vsync_update *vp;
+ struct mdp4_overlay_pipe *pipe;
+ struct mdp4_overlay_pipe *real_pipe;
+ unsigned long flags;
+ int cnt = 0;
+
+ vctrl = &vsync_ctrl_db[0];
+
+ mutex_lock(&vctrl->update_lock);
+ undx = vctrl->update_ndx;
+ vp = &vctrl->vlist[undx];
+ pipe = vctrl->base_pipe;
+ mixer = pipe->mixer_num;
+
+ if (vp->update_cnt == 0) {
+ mutex_unlock(&vctrl->update_lock);
+ return 0;
+ }
+
+ vctrl->update_ndx++;
+ vctrl->update_ndx &= 0x01;
+ vp->update_cnt = 0; /* reset */
+ if (vctrl->blt_free) {
+ vctrl->blt_free--;
+ if (vctrl->blt_free == 0)
+ mdp4_free_writeback_buf(vctrl->mfd, mixer);
+ }
+ mutex_unlock(&vctrl->update_lock);
+
+ /* free previous committed iommu back to pool */
+ mdp4_overlay_iommu_unmap_freelist(mixer);
+
+ spin_lock_irqsave(&vctrl->spin_lock, flags);
+ if (vctrl->ov_koff != vctrl->ov_done) {
+ spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+ pr_err("%s: Error, frame dropped %d %d\n", __func__,
+ vctrl->ov_koff, vctrl->ov_done);
+ return 0;
+ }
+ spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+
+ mdp4_overlay_mdp_perf_upd(vctrl->mfd, 1);
+
+ if (vctrl->blt_change) {
+ pipe = vctrl->base_pipe;
+ spin_lock_irqsave(&vctrl->spin_lock, flags);
+ INIT_COMPLETION(vctrl->dmap_comp);
+ INIT_COMPLETION(vctrl->ov_comp);
+ vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+ spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+ mdp4_lcdc_wait4dmap(0);
+ if (pipe->ov_blt_addr)
+ mdp4_lcdc_wait4ov(0);
+ }
+
+ pipe = vp->plist;
+ for (i = 0; i < OVERLAY_PIPE_MAX; i++, pipe++) {
+ if (pipe->pipe_used) {
+ cnt++;
+ real_pipe = mdp4_overlay_ndx2pipe(pipe->pipe_ndx);
+ if (real_pipe && real_pipe->pipe_used) {
+ /* pipe not unset */
+ mdp4_overlay_vsync_commit(pipe);
+ }
+ /* free previous iommu to freelist
+ * which will be freed at next
+ * pipe_commit
+ */
+ mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 0);
+ pipe->pipe_used = 0; /* clear */
+ }
+ }
+
+ mdp4_mixer_stage_commit(mixer);
+
+ /* start timing generator & mmu if they are not started yet */
+ mdp4_overlay_lcdc_start();
+
+ pipe = vctrl->base_pipe;
+ spin_lock_irqsave(&vctrl->spin_lock, flags);
+ if (pipe->ov_blt_addr) {
+ mdp4_lcdc_blt_ov_update(pipe);
+ pipe->ov_cnt++;
+ INIT_COMPLETION(vctrl->ov_comp);
+ vsync_irq_enable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
+ mb();
+ vctrl->ov_koff++;
+ /* kickoff overlay engine */
+ mdp4_stat.kickoff_ov0++;
+ outpdw(MDP_BASE + 0x0004, 0);
+ } else {
+ /* schedule second phase update at dmap */
+ INIT_COMPLETION(vctrl->dmap_comp);
+ vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+ }
+ spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+
+ mdp4_stat.overlay_commit[pipe->mixer_num]++;
+
+ return cnt;
+}
+
+void mdp4_lcdc_vsync_ctrl(int cndx, int enable)
+{
+ struct vsycn_ctrl *vctrl;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+
+ if (vctrl->fake_vsync) {
+ vctrl->fake_vsync = 0;
+ schedule_work(&vctrl->vsync_work);
+ }
+
+ if (vctrl->vsync_irq_enabled == enable)
+ return;
+
+ pr_debug("%s: vsync enable=%d\n", __func__, enable);
+
+ vctrl->vsync_irq_enabled = enable;
+
+ if (enable)
+ vsync_irq_enable(INTR_PRIMARY_VSYNC, MDP_PRIM_VSYNC_TERM);
+ else
+ vsync_irq_disable(INTR_PRIMARY_VSYNC, MDP_PRIM_VSYNC_TERM);
+}
+
+void mdp4_lcdc_wait4vsync(int cndx, long long *vtime)
+{
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+ unsigned long flags;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+
+ if (atomic_read(&vctrl->suspend) > 0) {
+ *vtime = -1;
+ return;
+ }
+
+ /* start timing generator & mmu if they are not started yet */
+ mdp4_overlay_lcdc_start();
+
+ spin_lock_irqsave(&vctrl->spin_lock, flags);
+
+ if (vctrl->wait_vsync_cnt == 0)
+ INIT_COMPLETION(vctrl->vsync_comp);
+ vctrl->wait_vsync_cnt++;
+ spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+
+ wait_for_completion(&vctrl->vsync_comp);
+ mdp4_stat.wait4vsync0++;
+
+ *vtime = vctrl->vsync_time.tv64;
+}
+
+static void mdp4_lcdc_wait4dmap(int cndx)
+{
+ struct vsycn_ctrl *vctrl;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+
+ if (atomic_read(&vctrl->suspend) > 0)
+ return;
+
+ wait_for_completion(&vctrl->dmap_comp);
+}
+
+static void mdp4_lcdc_wait4ov(int cndx)
+{
+ struct vsycn_ctrl *vctrl;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+
+ if (atomic_read(&vctrl->suspend) > 0)
+ return;
+
+ wait_for_completion(&vctrl->ov_comp);
+}
+
+static void send_vsync_work(struct work_struct *work)
+{
+ struct vsycn_ctrl *vctrl =
+ container_of(work, typeof(*vctrl), vsync_work);
+ char buf[64];
+ char *envp[2];
+
+ snprintf(buf, sizeof(buf), "VSYNC=%llu",
+ ktime_to_ns(vctrl->vsync_time));
+ envp[0] = buf;
+ envp[1] = NULL;
+ kobject_uevent_env(&vctrl->dev->kobj, KOBJ_CHANGE, envp);
+}
+
+void mdp4_lcdc_vsync_init(int cndx)
+{
+ struct vsycn_ctrl *vctrl;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ pr_info("%s: ndx=%d\n", __func__, cndx);
+
+ vctrl = &vsync_ctrl_db[cndx];
+ if (vctrl->inited)
+ return;
+
+ vctrl->inited = 1;
+ vctrl->update_ndx = 0;
+ mutex_init(&vctrl->update_lock);
+ init_completion(&vctrl->vsync_comp);
+ init_completion(&vctrl->dmap_comp);
+ init_completion(&vctrl->ov_comp);
+ atomic_set(&vctrl->suspend, 0);
+ spin_lock_init(&vctrl->spin_lock);
+ INIT_WORK(&vctrl->vsync_work, send_vsync_work);
+}
+
+void mdp4_lcdc_base_swap(int cndx, struct mdp4_overlay_pipe *pipe)
+{
+ struct vsycn_ctrl *vctrl;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+ vctrl->base_pipe = pipe;
+}
+
+int mdp4_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;
+ unsigned int buf_offset;
+ 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 = 0;
+ int cndx = 0;
+ struct vsycn_ctrl *vctrl;
+
+ vctrl = &vsync_ctrl_db[cndx];
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ vctrl->mfd = mfd;
+ vctrl->dev = mfd->fbi->dev;
+ vctrl->fake_vsync = 1;
+
+ /* mdp clock on */
+ mdp_clk_ctrl(1);
+
+ fbi = mfd->fbi;
+ var = &fbi->var;
+
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf_offset = calc_fb_offset(mfd, fbi, bpp);
+
+ if (vctrl->base_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);
+ 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__);
+
+ mdp4_init_writeback_buf(mfd, MDP4_MIXER0);
+ pipe->ov_blt_addr = 0;
+ pipe->dma_blt_addr = 0;
+
+ vctrl->base_pipe = pipe; /* keep it */
+ } else {
+ pipe = vctrl->base_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->dst_h = fbi->var.yres;
+ pipe->dst_w = fbi->var.xres;
+ if (mfd->map_buffer) {
+ pipe->srcp0_addr = (unsigned int)mfd->map_buffer->iova[0] + \
+ buf_offset;
+ pr_debug("start 0x%lx srcp0_addr 0x%x\n", mfd->
+ map_buffer->iova[0], pipe->srcp0_addr);
+ } else {
+ pipe->srcp0_addr = (uint32)(buf + buf_offset);
+ }
+
+ pipe->srcp0_ystride = fbi->fix.line_length;
+ pipe->bpp = bpp;
+
+ mdp4_overlay_mdp_pipe_req(pipe, mfd);
+
+ atomic_set(&vctrl->suspend, 0);
+
+ mdp4_overlay_dmap_xy(pipe);
+ mdp4_overlay_dmap_cfg(mfd, 1);
+ mdp4_overlay_rgb_setup(pipe);
+ mdp4_overlayproc_cfg(pipe);
+
+ mdp4_overlay_reg_flush(pipe, 1);
+ mdp4_mixer_stage_up(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 + mfd->panel_info.lcdc.xres_pad;
+ lcdc_height = var->yres + mfd->panel_info.lcdc.yres_pad;
+ 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_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ 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);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ mdp_histogram_ctrl_all(TRUE);
+ return ret;
+}
+
+int mdp4_lcdc_off(struct platform_device *pdev)
+{
+ int ret = 0;
+ int cndx = 0;
+ struct msm_fb_data_type *mfd;
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+
+ atomic_set(&vctrl->suspend, 1);
+
+ while (vctrl->wait_vsync_cnt)
+ msleep(20); /* >= 17 ms */
+
+ MDP_OUTP(MDP_BASE + LCDC_BASE, 0);
+
+ lcdc_enabled = 0;
+
+ mdp_histogram_ctrl_all(FALSE);
+
+
+ if (pipe) {
+ /* sanity check, free pipes besides base layer */
+ mdp4_overlay_unset_mixer(pipe->mixer_num);
+ if (mfd->ref_cnt == 0) {
+ /* adb stop */
+ if (pipe->pipe_type == OVERLAY_TYPE_BF)
+ mdp4_overlay_borderfill_stage_down(pipe);
+ vctrl->base_pipe = NULL;
+ } else {
+ /* system suspending */
+ mdp4_mixer_stage_down(vctrl->base_pipe);
+ mdp4_overlay_iommu_pipe_free(
+ vctrl->base_pipe->pipe_ndx, 1);
+ }
+ }
+
+ vctrl->fake_vsync = 1;
+
+ /* MDP clock disable */
+ mdp_clk_ctrl(0);
+ mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ return ret;
+}
+
+static void mdp4_lcdc_blt_ov_update(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 off, addr;
+ int bpp;
+ char *overlay_base;
+
+ if (pipe->ov_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->ov_cnt & 0x01)
+ off = pipe->src_height * pipe->src_width * bpp;
+ addr = pipe->ov_blt_addr + off;
+
+ /* overlay 0 */
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+ outpdw(overlay_base + 0x000c, addr);
+ outpdw(overlay_base + 0x001c, addr);
+}
+
+static void mdp4_lcdc_blt_dmap_update(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 off, addr;
+ int bpp;
+
+ if (pipe->ov_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->dma_blt_addr + off;
+
+ /* dmap */
+ MDP_OUTP(MDP_BASE + 0x90008, addr);
+}
+
+/*
+ * mdp4_primary_vsync_lcdc: called from isr
+ */
+void mdp4_primary_vsync_lcdc(void)
+{
+ int cndx;
+ struct vsycn_ctrl *vctrl;
+
+ cndx = 0;
+ vctrl = &vsync_ctrl_db[cndx];
+ pr_debug("%s: cpu=%d\n", __func__, smp_processor_id());
+ vctrl->vsync_time = ktime_get();
+ schedule_work(&vctrl->vsync_work);
+
+ spin_lock(&vctrl->spin_lock);
+ if (vctrl->wait_vsync_cnt) {
+ complete_all(&vctrl->vsync_comp);
+ vctrl->wait_vsync_cnt = 0;
+ }
+
+ spin_unlock(&vctrl->spin_lock);
+}
+
+/*
+ * mdp4_dma_p_done_lcdc: called from isr
+ */
+void mdp4_dmap_done_lcdc(int cndx)
+{
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+
+ spin_lock(&vctrl->spin_lock);
+ vsync_irq_disable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+ if (vctrl->blt_change) {
+ mdp4_overlayproc_cfg(pipe);
+ mdp4_overlay_dmap_xy(pipe);
+ if (pipe->ov_blt_addr) {
+ mdp4_lcdc_blt_ov_update(pipe);
+ pipe->ov_cnt++;
+ /* Prefill one frame */
+ vsync_irq_enable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
+ /* kickoff overlay0 engine */
+ mdp4_stat.kickoff_ov0++;
+ vctrl->ov_koff++; /* make up for prefill */
+ outpdw(MDP_BASE + 0x0004, 0);
+ }
+ vctrl->blt_change = 0;
+ }
+
+ complete_all(&vctrl->dmap_comp);
+ mdp4_overlay_dma_commit(cndx);
+ spin_unlock(&vctrl->spin_lock);
+}
+
+/*
+ * mdp4_overlay0_done_lcdc: called from isr
+ */
+void mdp4_overlay0_done_lcdc(int cndx)
+{
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+
+ spin_lock(&vctrl->spin_lock);
+ vsync_irq_disable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
+ vctrl->ov_done++;
+ complete_all(&vctrl->ov_comp);
+ if (pipe->ov_blt_addr == 0) {
+ spin_unlock(&vctrl->spin_lock);
+ return;
+ }
+
+ mdp4_lcdc_blt_dmap_update(pipe);
+ pipe->dmap_cnt++;
+ spin_unlock(&vctrl->spin_lock);
+}
+
+static void mdp4_lcdc_do_blt(struct msm_fb_data_type *mfd, int enable)
+{
+ unsigned long flag;
+ int cndx = 0;
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+
+ mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0);
+
+ if (mfd->ov0_wb_buf->write_addr == 0) {
+ pr_info("%s: no blt_base assigned\n", __func__);
+ return;
+ }
+
+ spin_lock_irqsave(&vctrl->spin_lock, flag);
+ if (enable && pipe->ov_blt_addr == 0) {
+ pipe->ov_blt_addr = mfd->ov0_wb_buf->write_addr;
+ pipe->dma_blt_addr = mfd->ov0_wb_buf->read_addr;
+ pipe->ov_cnt = 0;
+ pipe->dmap_cnt = 0;
+ vctrl->ov_koff = 0;
+ vctrl->ov_done = 0;
+ vctrl->blt_free = 0;
+ mdp4_stat.blt_lcdc++;
+ vctrl->blt_change++;
+ } else if (enable == 0 && pipe->ov_blt_addr) {
+ pipe->ov_blt_addr = 0;
+ pipe->dma_blt_addr = 0;
+ vctrl->blt_free = 4; /* 4 commits to free wb buf */
+ vctrl->blt_change++;
+ }
+
+ pr_info("%s: enable=%d change=%d blt_addr=%x\n", __func__,
+ vctrl->blt_change, enable, (int)pipe->ov_blt_addr);
+
+ if (!vctrl->blt_change) {
+ spin_unlock_irqrestore(&vctrl->spin_lock, flag);
+ return;
+ }
+
+ spin_unlock_irqrestore(&vctrl->spin_lock, flag);
+}
+
+void mdp4_lcdc_overlay_blt(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req)
+{
+ mdp4_lcdc_do_blt(mfd, req->enable);
+}
+
+void mdp4_lcdc_overlay_blt_start(struct msm_fb_data_type *mfd)
+{
+ mdp4_lcdc_do_blt(mfd, 1);
+}
+
+void mdp4_lcdc_overlay_blt_stop(struct msm_fb_data_type *mfd)
+{
+ mdp4_lcdc_do_blt(mfd, 0);
+}
+
+void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd)
+{
+ struct fb_info *fbi = mfd->fbi;
+ uint8 *buf;
+ unsigned int buf_offset;
+ int bpp;
+ int cndx = 0;
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+
+
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
+
+ if (!pipe || !mfd->panel_power_on)
+ return;
+
+ pr_debug("%s: cpu=%d pid=%d\n", __func__,
+ smp_processor_id(), current->pid);
+ if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf_offset = calc_fb_offset(mfd, fbi, bpp);
+
+ if (mfd->map_buffer->iova[0]) {
+ pipe->srcp0_addr = mfd->map_buffer->iova[0]
+ + buf_offset;
+ } else
+ pipe->srcp0_addr = (uint32)(buf + buf_offset);
+
+ mdp4_lcdc_pipe_queue(0, pipe);
+ }
+
+ mdp4_overlay_mdp_perf_upd(mfd, 1);
+
+ mdp4_lcdc_pipe_commit();
+ mutex_unlock(&mfd->dma->ov_mutex);
+
+ if (pipe->ov_blt_addr)
+ mdp4_lcdc_wait4ov(0);
+ else
+ mdp4_lcdc_wait4dmap(0);
+
+ mdp4_overlay_mdp_perf_upd(mfd, 0);
+}
diff --git a/drivers/video/msm/mdp4_overlay_mddi.c b/drivers/video/msm/mdp4_overlay_mddi.c
index 1f62f79..c4e144e 100644
--- a/drivers/video/msm/mdp4_overlay_mddi.c
+++ b/drivers/video/msm/mdp4_overlay_mddi.c
@@ -1,57 +1,13 @@
-/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of Code Aurora Forum nor
- * the names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
+ * 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.
*
- * Alternatively, provided that this notice is retained in full, this software
- * may be relicensed by the recipient under the terms of the GNU General Public
- * License version 2 ("GPL") and only version 2, in which case the provisions of
- * the GPL apply INSTEAD OF those given above. If the recipient relicenses the
- * software under the GPL, then the identification text in the MODULE_LICENSE
- * macro must be changed to reflect "GPLv2" instead of "Dual BSD/GPL". Once a
- * recipient changes the license terms to the GPL, subsequent recipients shall
- * not relicense under alternate licensing terms, including the BSD or dual
- * BSD/GPL terms. In addition, the following license statement immediately
- * below and between the words START and END shall also then apply when this
- * software is relicensed under the GPL:
- *
- * START
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * END
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
*
*/
@@ -73,170 +29,117 @@
#include <linux/fb.h>
-#include <linux/msm_mdp.h>
-#include <mach/msm_fb.h>
-#include <mach/debug_display.h>
-
-#include "mdp_hw.h"
+#include "mdp.h"
+#include "msm_fb.h"
#include "mdp4.h"
-static struct mdp4_overlay_pipe *mddi_pipe = NULL;
-static struct mdp_info *mddi_mdp;
-#ifdef CONFIG_FB_MSM_WRITE_BACK
-static struct completion mddi_comp;
-static ulong blt_addr;
-#endif
+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
-#ifdef CONFIG_FB_MSM_WRITE_BACK
-void mdp4_mddi_overlay_blt(ulong addr)
+void mdp4_overlay_update_lcd(struct msm_fb_data_type *mfd)
{
- unsigned long flag;
-
- spin_lock_irqsave(&mdp_spin_lock, flag);
- if (addr) {
- mdp_intr_mask |= INTR_DMA_P_DONE;
- if (mddi_pipe != NULL) {
- mdp_writel(mddi_pipe->mdp, mdp_intr_mask, MDP_INTR_ENABLE);
- mddi_pipe->blt_cnt = 0;
- mddi_pipe->blt_end = 0;
- mddi_pipe->blt_addr = addr;
- }
- blt_addr = addr;
- } else {
- mddi_pipe->blt_end = 1; /* mark as end */
- mdp4_dma_p_done_mddi();
- }
- spin_unlock_irqrestore(&mdp_spin_lock, flag);
-}
-void mdp4_blt_xy_update(struct mdp4_overlay_pipe *pipe)
-{
- uint32_t off, addr;
-
- if (pipe->blt_addr == 0)
- return;
-
- /* overlay ouput is RG565 */
- off = 0;
- if (pipe->blt_cnt & 0x01)
- off = pipe->src_height * pipe->src_width * 2;
-
- addr = pipe->blt_addr + off;
-
- /* dmap */
- mdp_writel(pipe->mdp, addr, 0x90008);
- /* overlay 0 */
- mdp_writel(pipe->mdp, addr, MDP4_OVERLAYPROC0_BASE + 0x000c);
- mdp_writel(pipe->mdp, addr, MDP4_OVERLAYPROC0_BASE + 0x001c);
-}
-
-/*
- * 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;
- mdp_writel(mddi_pipe->mdp, mdp_intr_mask, MDP_INTR_ENABLE);
- mdp4_overlayproc_cfg(mddi_pipe);
- mdp4_overlay_dmap_xy(mddi_pipe);
- return;
- }
-}
-/*
- * mdp4_overlay0_done_mddi: called from isr
- */
-void mdp4_overlay0_done_mddi(void)
-{
- if (mddi_pipe->blt_addr) {
- if (mddi_pipe->blt_cnt == 0) {
- mdp4_overlayproc_cfg(mddi_pipe);
- mdp4_overlay_dmap_xy(mddi_pipe);
- mddi_pipe->blt_cnt++;
- /* BLT start from next frame */
- } else {
- mdp4_blt_xy_update(mddi_pipe);
- mddi_pipe->blt_cnt++;
-
- /* start DMAP */
- mdp_writel(mddi_pipe->mdp, 0x0, 0x000c);
- }
- }
-
-}
-#endif
-
-#ifdef CONFIG_MDP4_HW_VSYNC
-void mdp4_mddi_vsync_enable(struct mdp_info *mdp,
- struct mdp4_overlay_pipe *pipe)
-{
- uint32_t start_y, data;
- int vsync_start_y_adjust = 4;
-
- if (vsync_start_y_adjust <= pipe->dst_y)
- start_y = pipe->dst_y - vsync_start_y_adjust;
- else
- start_y = (mdp->total_lcd_line - 1) -
- (vsync_start_y_adjust - pipe->dst_y);
-
- mdp_writel(mdp, start_y, 0x210); /* primary */
-
- data = mdp_readl(mdp, 0x20c);
- data |= 1;
- mdp_writel(mdp, data, 0x20c);
-}
-#endif
-
-void mdp4_overlay_update_lcd(struct mdp_info *mdp, uint32_t addr, uint32_t stride,
- uint32_t width, uint32_t height, uint32_t x,
- uint32_t y)
-{
+ MDPIBUF *iBuf = &mfd->ibuf;
+ uint8 *src;
int ptype;
- uint32_t mddi_ld_param;
- uint16_t mddi_vdo_packet_reg;
- struct mdp4_overlay_pipe *pipe = NULL;
- int data;
+ uint32 mddi_ld_param;
+ uint16 mddi_vdo_packet_reg;
+ struct mdp4_overlay_pipe *pipe;
+ int ret;
- mddi_mdp = mdp; /* keep it */
+ 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(MDP_RGB_565);
- pipe = mdp4_overlay_pipe_alloc(ptype, false);
-
- pipe->pipe_type = ptype;
- pipe->pipe_used = 1;
- pipe->mdp = mdp;
+ 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);
+ if (pipe == NULL)
+ printk(KERN_INFO "%s: pipe_alloc failed\n", __func__);
+ pipe->pipe_used++;
pipe->mixer_num = MDP4_MIXER0;
- pipe->src_format = MDP_RGB_565;
- mdp4_overlay_format2pipe(pipe);
+ 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 */
-#ifdef CONFIG_FB_MSM_WRITE_BACK
- init_completion(&mddi_comp);
- mddi_pipe->blt_cnt = 0;
- mddi_pipe->blt_end = 0;
- mddi_pipe->blt_addr = blt_addr;
-#endif
-
mddi_ld_param = 0;
+ mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt;
- mddi_vdo_packet_reg = MDDI_VDO_PACKET_PRIM;
- if (mdp->hw_version >= MDP4_REVISION_V2_1) {
- data = mdp_readl(mdp, MDP_AXI_RDMASTER_CONFIG);
- data &= ~0x0300; /* bit 8, 9, MASTER4 */
- if (width == 540) /* qHD, 540x960 */
+ 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_writel(mdp, data, MDP_AXI_RDMASTER_CONFIG);
+ MDP_OUTP(MDP_BASE + 0x00028, data);
}
-/* FIXME: currently we use only one display
-
if (mfd->panel_info.type == MDDI_PANEL) {
if (mfd->panel_info.pdest == DISPLAY_1)
mddi_ld_param = 0;
@@ -245,65 +148,91 @@
} else {
mddi_ld_param = 2;
}
-*/
- mdp_writel(mdp, mddi_ld_param, 0x00090);
- if (mdp->mdp_dev.color_format == MSM_MDP_OUT_IF_FMT_RGB888)
- mdp_writel(mdp, (MDDI_VDO_PACKET_DESC_RGB888 << 16) | mddi_vdo_packet_reg, 0x00094);
+
+ 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_writel(mdp, (MDDI_VDO_PACKET_DESC_RGB565 << 16) | mddi_vdo_packet_reg, 0x00094);
- mdp_writel(mdp, 0x01, 0x00098);
+ MDP_OUTP(MDP_BASE + 0x00094,
+ (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg);
+
+ MDP_OUTP(MDP_BASE + 0x00098, 0x01);
+ mdp4_init_writeback_buf(mfd, MDP4_MIXER0);
+ pipe->ov_blt_addr = 0;
} else {
pipe = mddi_pipe;
- if (mdp->hw_version >= MDP4_REVISION_V2_1 &&
- mdp4_overlay_status_read(MDP4_OVERLAY_TYPE_UNSET)) {
- data = mdp_readl(mdp, MDP_AXI_RDMASTER_CONFIG);
- data &= ~0x0300; /* bit 8, 9, MASTER4 */
- if (width == 540) /* qHD, 540x960 */
- data |= 0x0200;
- else
- data |= 0x0100;
- mdp_writel(mdp, data, MDP_AXI_RDMASTER_CONFIG);
- mdp4_overlay_status_write(MDP4_OVERLAY_TYPE_UNSET, false);
- }
- if (mdp->hw_version >= MDP4_REVISION_V2_1 &&
- mdp4_overlay_status_read(MDP4_OVERLAY_TYPE_SET)) {
- data = mdp_readl(mdp, MDP_AXI_RDMASTER_CONFIG);
- if (data & 0x0300) {
- data &= ~0x0300; /* bit 8, 9, MASTER4 */
- mdp_writel(mdp, data, MDP_AXI_RDMASTER_CONFIG);
- }
- mdp4_overlay_status_write(MDP4_OVERLAY_TYPE_SET, false);
- }
}
- pipe->src_height = height;
- pipe->src_width = width;
- pipe->src_h = height;
- pipe->src_w = width;
- pipe->src_y = 0;
- pipe->src_x = 0;
- pipe->dst_h = height;
- pipe->dst_w = width;
- pipe->dst_y = 0;
- pipe->dst_x = 0;
- pipe->srcp0_addr = (uint32_t)addr;
- pipe->srcp0_ystride = (stride + 31) & ~31;
+ /* 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;
- /* 16/32 bits framebuffer */
- if (mddi_mdp->dma_config_dirty) {
- if (mddi_mdp->dma_format == DMA_IBUF_FORMAT_RGB565) {
- pipe->src_format = MDP_RGB_565;
- pipe->srcp0_ystride = pipe->src_width * 2;
- } else if (mddi_mdp->dma_format == DMA_IBUF_FORMAT_XRGB8888) {
- pipe->src_format = MDP_RGBA_8888;
- pipe->srcp0_ystride = pipe->src_width * 4;
- }
- mdp4_overlay_format2pipe(pipe);
- mddi_mdp->dma_config_dirty = false;
- }
-
mdp4_overlay_rgb_setup(pipe);
mdp4_mixer_stage_up(pipe);
@@ -312,91 +241,507 @@
mdp4_overlay_dmap_xy(pipe);
- mdp4_overlay_dmap_cfg(pipe, 0);
-#ifdef CONFIG_MDP4_HW_VSYNC
- mdp4_mddi_vsync_enable(mdp, pipe);
-#endif
+ mdp4_overlay_dmap_cfg(mfd, 0);
+ mdp4_mixer_stage_commit(pipe->mixer_num);
+ mdp4_mddi_vsync_enable(mfd, pipe, 0);
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
-void mdp4_mddi_overlay_kickoff(struct mdp_info *mdp,
- struct mdp4_overlay_pipe *pipe)
+int mdp4_mddi_overlay_blt_start(struct msm_fb_data_type *mfd)
{
+ unsigned long flag;
-#ifdef MDP4_NONBLOCKING
- mdp_writel(mdp, 0, 0x0004);
-#endif
-}
-void mdp4_dma_s_update_lcd(struct mdp_info *mdp)
-{
- uint32_t mddi_ld_param = 1;
- uint16_t mddi_vdo_packet_reg = MDDI_VDO_PACKET_PRIM;
- struct mdp4_overlay_pipe *pipe = NULL;
+ pr_debug("%s: blt_end=%d ov_blt_addr=%x pid=%d\n",
+ __func__, mddi_pipe->blt_end, (int)mddi_pipe->ov_blt_addr, current->pid);
- mddi_mdp = mdp; /* keep it */
+ mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0);
- pipe = mddi_pipe;
-
- /*config PIXELSIZE*/
- mdp4_overlay_dmas_xy(pipe);
-
- /*config for dma_s_cfg_reg*/
- mdp4_overlay_dmas_cfg(pipe, 0);
-
- mdp_writel(mdp, mddi_ld_param, 0x00090);
- mdp_writel(mdp, (MDDI_VDO_PACKET_DESC_RGB565 << 16) | mddi_vdo_packet_reg, 0x00094);
- mdp_writel(mdp, 1, 0x00098);
-}
-
-
-void mdp4_mddi_dma_s_kickoff(struct mdp_info *mdp,
- struct mdp4_overlay_pipe *pipe)
-{
- mdp_writel(mdp, 0, 0x00010);
-}
-
-void mdp4_mddi_overlay(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;
-
-#ifdef CONFIG_FB_MSM_WRITE_BACK
- if (mdp->hw_version < MDP4_REVISION_V2_1 &&
- mdp->mdp_dev.overrides & MSM_MDP4_MDDI_DMA_SWITCH) {
- mdp4_overlay_update_lcd(mdp, addr, stride, width, height, x, y);
-
- if (mdp4_overlay_active(mdp, MDP4_MIXER0) > 1) {
- mdp4_overlay0_done_mddi();
- mdp4_mddi_overlay_kickoff(mdp, mddi_pipe);
- } else {
- if (mddi_pipe->blt_addr) {
- mdp4_overlay0_done_mddi();
- mdp4_mddi_overlay_kickoff(mdp, mddi_pipe);
- } else {
- mdp4_dma_s_update_lcd(mdp);
- mdp4_mddi_dma_s_kickoff(mdp, mddi_pipe);
- }
- }
- } else {
- mdp4_overlay_update_lcd(mdp, addr, stride, width, height, x, y);
- mdp4_overlay0_done_mddi();
- mdp4_mddi_overlay_kickoff(mdp, mddi_pipe);
+ if (mfd->ov0_wb_buf->write_addr == 0) {
+ pr_info("%s: no blt_base assigned\n", __func__);
+ return -EBUSY;
}
+
+ if (mddi_pipe->ov_blt_addr == 0) {
+ mdp4_mddi_dma_busy_wait(mfd);
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mddi_pipe->blt_end = 0;
+ mddi_pipe->blt_cnt = 0;
+ mddi_pipe->ov_cnt = 0;
+ mddi_pipe->dmap_cnt = 0;
+ mddi_pipe->ov_blt_addr = mfd->ov0_wb_buf->write_addr;
+ mdp4_stat.blt_mddi++;
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ return 0;
+}
+
+ return -EBUSY;
+}
+
+int mdp4_mddi_overlay_blt_stop(struct msm_fb_data_type *mfd)
+{
+ unsigned long flag;
+
+ pr_debug("%s: blt_end=%d ov_blt_addr=%x\n",
+ __func__, mddi_pipe->blt_end, (int)mddi_pipe->ov_blt_addr);
+
+ if ((mddi_pipe->blt_end == 0) && mddi_pipe->ov_blt_addr) {
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mddi_pipe->blt_end = 1; /* mark as end */
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ return 0;
+ }
+
+ return -EBUSY;
+}
+
+int mdp4_mddi_overlay_blt_offset(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req)
+{
+ req->offset = 0;
+ req->width = mddi_pipe->src_width;
+ req->height = mddi_pipe->src_height;
+ req->bpp = mddi_pipe->bpp;
+
+ return sizeof(*req);
+}
+
+void mdp4_mddi_overlay_blt(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_blt *req)
+{
+ if (req->enable)
+ mdp4_mddi_overlay_blt_start(mfd);
+ else if (req->enable == 0)
+ mdp4_mddi_overlay_blt_stop(mfd);
+
+}
+
+void mdp4_blt_xy_update(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 off, addr, addr2;
+ int bpp;
+ char *overlay_base;
+
+ if (pipe->ov_blt_addr == 0)
+ return;
+
+
+#ifdef BLT_RGB565
+ bpp = 2; /* overlay ouput is RGB565 */
#else
- if (mdp->hw_version < MDP4_REVISION_V2_1 &&
- mdp->mdp_dev.overrides & MSM_MDP4_MDDI_DMA_SWITCH) {
- mdp4_overlay_update_lcd(mdp, addr, stride, width, height, x, y);
- if (mdp4_overlay_active(mdp, MDP4_MIXER0) > 1)
- mdp4_mddi_overlay_kickoff(mdp, mddi_pipe);
- else {
- mdp4_dma_s_update_lcd(mdp);
- mdp4_mddi_dma_s_kickoff(mdp, mddi_pipe);
- }
- } else {
- mdp4_overlay_update_lcd(mdp, addr, stride, width, height, x, y);
- mdp4_mddi_overlay_kickoff(mdp, mddi_pipe);
- }
+ bpp = 3; /* overlay ouput is RGB888 */
#endif
+ off = 0;
+ if (pipe->dmap_cnt & 0x01)
+ off = pipe->src_height * pipe->src_width * bpp;
+
+ addr = pipe->ov_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->ov_blt_addr + off;
+ /* overlay 0 */
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+ outpdw(overlay_base + 0x000c, addr2);
+ outpdw(overlay_base + 0x001c, addr2);
}
+void mdp4_primary_rdptr(void)
+{
+}
+
+/*
+ * mdp4_dmap_done_mddi: called from isr
+ */
+void mdp4_dma_p_done_mddi(struct mdp_dma_data *dma)
+{
+ int diff;
+
+ mddi_pipe->dmap_cnt++;
+ diff = mddi_pipe->ov_cnt - mddi_pipe->dmap_cnt;
+ pr_debug("%s: ov_cnt=%d dmap_cnt=%d\n",
+ __func__, mddi_pipe->ov_cnt, mddi_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 (mddi_pipe->blt_end) {
+ mddi_pipe->blt_end = 0;
+ mddi_pipe->ov_blt_addr = 0;
+ pr_debug("%s: END, ov_cnt=%d dmap_cnt=%d\n", __func__,
+ mddi_pipe->ov_cnt, mddi_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(mddi_pipe);
+ /* kick off dmap */
+ outpdw(MDP_BASE + 0x000c, 0x0);
+ mdp4_stat.kickoff_dmap++;
+ mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+}
+
+/*
+ * mdp4_overlay0_done_mddi: called from isr
+ */
+void mdp4_overlay0_done_mddi(struct mdp_dma_data *dma)
+{
+ int diff;
+
+ if (mddi_pipe->ov_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 (mddi_pipe->blt_end == 0)
+ mddi_pipe->ov_cnt++;
+
+ pr_debug("%s: ov_cnt=%d dmap_cnt=%d\n",
+ __func__, mddi_pipe->ov_cnt, mddi_pipe->dmap_cnt);
+
+ if (mddi_pipe->blt_cnt == 0) {
+ /* first kickoff since blt enabled */
+ mdp_intr_mask |= INTR_DMA_P_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ }
+
+ mddi_pipe->blt_cnt++;
+
+ diff = mddi_pipe->ov_cnt - mddi_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(mddi_pipe);
+ mdp_enable_irq(MDP_DMA2_TERM); /* enable intr */
+ /* kick off dmap */
+ outpdw(MDP_BASE + 0x000c, 0x0);
+ mdp4_stat.kickoff_dmap++;
+ mdp_disable_irq_nosync(MDP_OVERLAY0_TERM);
+}
+
+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);
+
+ if (mddi_pipe->ov_blt_addr)
+ mdp4_mddi_blt_dmap_busy_wait(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();
+}
+
+void mdp4_mddi_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_mddi_cmd_dma_busy_wait: check mddi link activity
+ * mddi 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)
+{
+ /*
+ * a video kickoff may happen before UI kickoff after
+ * blt enabled. mdp4_overlay_update_lcd() need
+ * to be called before kickoff.
+ * vice versa for blt disabled.
+ */
+ if (mddi_pipe->ov_blt_addr && mddi_pipe->blt_cnt == 0)
+ mdp4_overlay_update_lcd(mfd); /* first time */
+ else if (mddi_pipe->ov_blt_addr == 0 && mddi_pipe->blt_cnt) {
+ mdp4_overlay_update_lcd(mfd); /* last time */
+ mddi_pipe->blt_cnt = 0;
+ }
+
+ pr_debug("%s: ov_blt_addr=%d blt_cnt=%d\n",
+ __func__, (int)mddi_pipe->ov_blt_addr, mddi_pipe->blt_cnt);
+
+ if (mddi_pipe->ov_blt_addr)
+ mdp4_mddi_blt_dmap_busy_wait(mddi_mfd);
+ 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)
+{
+ unsigned long flag;
+
+ 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);
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mfd->dma->busy = TRUE;
+ if (mddi_pipe->ov_blt_addr)
+ mfd->dma->dmap_busy = TRUE;
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ /* start OVERLAY pipe */
+ mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
+ mdp4_stat.kickoff_ov0++;
+}
+
+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);
+
+ if (mddi_pipe->ov_blt_addr == 0)
+ mfd->dma->busy = TRUE;
+
+ mfd->ibuf_flushed = TRUE;
+ /* start dma_s pipe */
+ mdp_pipe_kickoff(MDP_DMA_S_TERM, mfd);
+ mdp4_stat.kickoff_dmas++;
+
+ /* 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);
+
+ if (mddi_pipe && mddi_pipe->ov_blt_addr)
+ mdp4_mddi_blt_dmap_busy_wait(mfd);
+ mdp4_overlay_mdp_perf_upd(mfd, 0);
+ mdp4_overlay_update_lcd(mfd);
+
+ mdp4_overlay_mdp_perf_upd(mfd, 1);
+ 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);
+
+ /* signal if pan function is waiting for the update completion */
+ if (mfd->pan_waiting) {
+ mfd->pan_waiting = FALSE;
+ complete(&mfd->pan_comp);
+ }
+ }
+ 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_overlay_writeback.c b/drivers/video/msm/mdp4_overlay_writeback.c
new file mode 100644
index 0000000..2e76134
--- /dev/null
+++ b/drivers/video/msm/mdp4_overlay_writeback.c
@@ -0,0 +1,620 @@
+/* Copyright (c) 2011-2012, 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 <mach/iommu_domains.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"
+enum {
+ WB_OPEN,
+ WB_START,
+ WB_STOPING,
+ WB_STOP
+};
+enum {
+ REGISTERED,
+ IN_FREE_QUEUE,
+ IN_BUSY_QUEUE,
+ WITH_CLIENT
+};
+
+static struct mdp4_overlay_pipe *writeback_pipe;
+static struct msm_fb_data_type *writeback_mfd;
+static int busy_wait_cnt;
+
+int mdp4_overlay_writeback_on(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct fb_info *fbi;
+ uint8 *buf;
+ struct mdp4_overlay_pipe *pipe;
+ int bpp;
+ int ret;
+ uint32 data;
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ writeback_mfd = mfd; /* keep it */
+
+ fbi = mfd->fbi;
+
+ 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 cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ if (writeback_pipe == NULL) {
+ pipe = mdp4_overlay_pipe_alloc(OVERLAY_TYPE_BF, MDP4_MIXER2);
+ if (pipe == NULL)
+ pr_info("%s: pipe_alloc failed\n", __func__);
+ pipe->pipe_used++;
+ pipe->mixer_stage = MDP4_MIXER_STAGE_BASE;
+ pipe->mixer_num = MDP4_MIXER2;
+ pipe->src_format = MDP_ARGB_8888;
+ mdp4_overlay_panel_mode(pipe->mixer_num, MDP4_PANEL_WRITEBACK);
+ ret = mdp4_overlay_format2pipe(pipe);
+ if (ret < 0)
+ pr_info("%s: format2type failed\n", __func__);
+
+ writeback_pipe = pipe; /* keep it */
+
+ } else {
+ pipe = writeback_pipe;
+ }
+ ret = panel_next_on(pdev);
+
+ /* MDP_LAYERMIXER_WB_MUX_SEL to use mixer1 axi for mixer2 writeback */
+ if (hdmi_prim_display)
+ data = 0x01;
+ else
+ data = 0x02;
+ outpdw(MDP_BASE + 0x100F4, data);
+
+ MDP_OUTP(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x5004,
+ ((0x0 & 0xFFF) << 16) | /* 12-bit B */
+ (0x0 & 0xFFF)); /* 12-bit G */
+ /* MSP_BORDER_COLOR */
+ MDP_OUTP(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x5008,
+ (0x0 & 0xFFF)); /* 12-bit R */
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ return ret;
+}
+
+int mdp4_overlay_writeback_off(struct platform_device *pdev)
+{
+ int ret;
+ struct msm_fb_data_type *mfd =
+ (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+ if (mfd && writeback_pipe) {
+ mdp4_writeback_dma_busy_wait(mfd);
+ mdp4_overlay_pipe_free(writeback_pipe);
+ mdp4_overlay_panel_mode_unset(writeback_pipe->mixer_num,
+ MDP4_PANEL_WRITEBACK);
+ writeback_pipe = NULL;
+ }
+ ret = panel_next_off(pdev);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ /* MDP_LAYERMIXER_WB_MUX_SEL to restore to default cfg*/
+ outpdw(MDP_BASE + 0x100F4, 0x0);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ return ret;
+}
+int mdp4_overlay_writeback_update(struct msm_fb_data_type *mfd)
+{
+ struct fb_info *fbi;
+ uint8 *buf;
+ unsigned int buf_offset;
+ struct mdp4_overlay_pipe *pipe;
+ int bpp;
+
+ if (mfd->key != MFD_KEY)
+ return -ENODEV;
+
+ if (!writeback_pipe)
+ return -EINVAL;
+
+ fbi = mfd->fbi;
+
+ pipe = writeback_pipe;
+
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf_offset = fbi->var.xoffset * bpp +
+ fbi->var.yoffset * fbi->fix.line_length;
+
+ /* 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->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;
+
+ mdp4_overlay_mdp_pipe_req(pipe, mfd);
+ if (mfd->map_buffer) {
+ pipe->srcp0_addr = (unsigned int)mfd->map_buffer->iova[0] + \
+ buf_offset;
+ pr_debug("start 0x%lx srcp0_addr 0x%x\n", mfd->
+ map_buffer->iova[0], pipe->srcp0_addr);
+ } else {
+ pipe->srcp0_addr = (uint32)(buf + buf_offset);
+ }
+
+ mdp4_mixer_stage_up(pipe);
+
+ mdp4_overlayproc_cfg(pipe);
+ mdp4_mixer_stage_commit(pipe->mixer_num);
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ wmb();
+ return 0;
+}
+void mdp4_writeback_dma_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->busy == TRUE) {
+ if (busy_wait_cnt == 0)
+ INIT_COMPLETION(mfd->dma->comp);
+ busy_wait_cnt = 1;
+ 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);
+ }
+}
+
+void mdp4_overlay1_done_writeback(struct mdp_dma_data *dma)
+{
+ spin_lock(&mdp_spin_lock);
+ dma->busy = FALSE;
+ if (busy_wait_cnt)
+ busy_wait_cnt = 0;
+ mdp_disable_irq_nosync(MDP_OVERLAY2_TERM);
+ spin_unlock(&mdp_spin_lock);
+ complete_all(&dma->comp);
+ pr_debug("%s ovdone interrupt\n", __func__);
+
+}
+void mdp4_writeback_overlay_kickoff(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ unsigned long flag;
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_enable_irq(MDP_OVERLAY2_TERM);
+
+ mfd->dma->busy = TRUE;
+ outp32(MDP_INTR_CLEAR, INTR_OVERLAY2_DONE);
+ mdp_intr_mask |= INTR_OVERLAY2_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+
+ wmb(); /* make sure all registers updated */
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ /* start OVERLAY pipe */
+ mdp_pipe_kickoff(MDP_OVERLAY2_TERM, mfd);
+ wmb();
+ pr_debug("%s: before ov done interrupt\n", __func__);
+}
+void mdp4_writeback_dma_stop(struct msm_fb_data_type *mfd)
+{
+ /* mutex holded by caller */
+ if (mfd && writeback_pipe) {
+ mdp4_writeback_dma_busy_wait(mfd);
+ mdp4_overlay_writeback_update(mfd);
+
+ mdp4_writeback_overlay_kickoff(mfd, writeback_pipe);
+ }
+}
+
+void mdp4_writeback_kickoff_video(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ struct msmfb_writeback_data_list *node = NULL;
+ mutex_lock(&mfd->unregister_mutex);
+ mutex_lock(&mfd->writeback_mutex);
+ if (!list_empty(&mfd->writeback_free_queue)
+ && mfd->writeback_state != WB_STOPING
+ && mfd->writeback_state != WB_STOP) {
+ node = list_first_entry(&mfd->writeback_free_queue,
+ struct msmfb_writeback_data_list, active_entry);
+ }
+ if (node) {
+ list_del(&(node->active_entry));
+ node->state = IN_BUSY_QUEUE;
+ mfd->writeback_active_cnt++;
+ }
+ mutex_unlock(&mfd->writeback_mutex);
+
+ writeback_pipe->ov_blt_addr = (ulong) (node ? node->addr : NULL);
+
+ if (!writeback_pipe->ov_blt_addr) {
+ pr_err("%s: no writeback buffer 0x%x, %p\n", __func__,
+ (unsigned int)writeback_pipe->ov_blt_addr, node);
+ mutex_unlock(&mfd->unregister_mutex);
+ return;
+ }
+
+ if (writeback_pipe->blt_cnt == 0)
+ mdp4_overlay_writeback_update(mfd);
+
+ pr_debug("%s: pid=%d\n", __func__, current->pid);
+
+ mdp4_mixer_stage_commit(pipe->mixer_num);
+
+ mdp4_writeback_overlay_kickoff(mfd, pipe);
+
+ mutex_lock(&mfd->writeback_mutex);
+ list_add_tail(&node->active_entry, &mfd->writeback_busy_queue);
+ mutex_unlock(&mfd->writeback_mutex);
+ mfd->writeback_active_cnt--;
+ mutex_unlock(&mfd->unregister_mutex);
+ wake_up(&mfd->wait_q);
+}
+
+void mdp4_writeback_kickoff_ui(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ mdp4_mixer_stage_commit(pipe->mixer_num);
+
+ pr_debug("%s: pid=%d\n", __func__, current->pid);
+ mdp4_writeback_overlay_kickoff(mfd, pipe);
+}
+
+void mdp4_writeback_overlay(struct msm_fb_data_type *mfd)
+{
+ int ret = 0;
+ struct msmfb_writeback_data_list *node = NULL;
+
+ mutex_lock(&mfd->unregister_mutex);
+ mutex_lock(&mfd->writeback_mutex);
+ if (!list_empty(&mfd->writeback_free_queue)
+ && mfd->writeback_state != WB_STOPING
+ && mfd->writeback_state != WB_STOP) {
+ node = list_first_entry(&mfd->writeback_free_queue,
+ struct msmfb_writeback_data_list, active_entry);
+ }
+ if (node) {
+ list_del(&(node->active_entry));
+ node->state = IN_BUSY_QUEUE;
+ mfd->writeback_active_cnt++;
+ }
+ mutex_unlock(&mfd->writeback_mutex);
+
+ writeback_pipe->ov_blt_addr = (ulong) (node ? node->addr : NULL);
+
+ mutex_lock(&mfd->dma->ov_mutex);
+ pr_debug("%s in writeback\n", __func__);
+ if (writeback_pipe && !writeback_pipe->ov_blt_addr) {
+ pr_err("%s: no writeback buffer 0x%x\n", __func__,
+ (unsigned int)writeback_pipe->ov_blt_addr);
+ ret = mdp4_overlay_writeback_update(mfd);
+ if (ret)
+ pr_err("%s: update failed writeback pipe NULL\n",
+ __func__);
+ goto fail_no_blt_addr;
+ }
+
+ if (mfd && mfd->panel_power_on) {
+ pr_debug("%s in before busy wait\n", __func__);
+ mdp4_writeback_dma_busy_wait(mfd);
+
+ pr_debug("%s in before update\n", __func__);
+ ret = mdp4_overlay_writeback_update(mfd);
+ if (ret) {
+ pr_err("%s: update failed writeback pipe NULL\n",
+ __func__);
+ goto fail_no_blt_addr;
+ }
+
+ pr_debug("%s: in writeback pan display 0x%x\n", __func__,
+ (unsigned int)writeback_pipe->ov_blt_addr);
+ mdp4_writeback_kickoff_ui(mfd, writeback_pipe);
+ mdp4_iommu_unmap(writeback_pipe);
+
+ /* signal if pan function is waiting for the
+ * update completion */
+ if (mfd->pan_waiting) {
+ mfd->pan_waiting = FALSE;
+ complete(&mfd->pan_comp);
+ }
+ }
+
+ mutex_lock(&mfd->writeback_mutex);
+ list_add_tail(&node->active_entry, &mfd->writeback_busy_queue);
+ mfd->writeback_active_cnt--;
+ mutex_unlock(&mfd->writeback_mutex);
+ wake_up(&mfd->wait_q);
+fail_no_blt_addr:
+ /*NOTE: This api was removed
+ mdp4_overlay_resource_release();*/
+ mutex_unlock(&mfd->dma->ov_mutex);
+ mutex_unlock(&mfd->unregister_mutex);
+}
+static int mdp4_overlay_writeback_register_buffer(
+ struct msm_fb_data_type *mfd, struct msmfb_writeback_data_list *node)
+{
+ if (!node) {
+ pr_err("Cannot register a NULL node\n");
+ return -EINVAL;
+ }
+ node->state = REGISTERED;
+ list_add_tail(&node->registered_entry, &mfd->writeback_register_queue);
+ return 0;
+}
+static struct msmfb_writeback_data_list *get_if_registered(
+ struct msm_fb_data_type *mfd, struct msmfb_data *data)
+{
+ struct msmfb_writeback_data_list *temp;
+ bool found = false;
+ if (!list_empty(&mfd->writeback_register_queue)) {
+ list_for_each_entry(temp,
+ &mfd->writeback_register_queue,
+ registered_entry) {
+ if (temp && temp->buf_info.iova == data->iova) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ temp = kzalloc(sizeof(struct msmfb_writeback_data_list),
+ GFP_KERNEL);
+ if (temp == NULL) {
+ pr_err("%s: out of memory\n", __func__);
+ goto register_alloc_fail;
+ }
+ temp->ihdl = NULL;
+ if (data->iova)
+ temp->addr = (void *)(data->iova + data->offset);
+ else if (mfd->iclient) {
+ struct ion_handle *srcp_ihdl;
+ ulong len;
+ srcp_ihdl = ion_import_fd(mfd->iclient,
+ data->memory_id);
+ if (IS_ERR_OR_NULL(srcp_ihdl)) {
+ pr_err("%s: ion import fd failed\n", __func__);
+ goto register_ion_fail;
+ }
+
+ if (ion_map_iommu(mfd->iclient,
+ srcp_ihdl,
+ DISPLAY_DOMAIN,
+ GEN_POOL,
+ SZ_4K,
+ 0,
+ (ulong *)&temp->addr,
+ (ulong *)&len,
+ 0,
+ ION_IOMMU_UNMAP_DELAYED)) {
+ ion_free(mfd->iclient, srcp_ihdl);
+ pr_err("%s: unable to get ion mapping addr\n",
+ __func__);
+ goto register_ion_fail;
+ }
+ temp->addr += data->offset;
+ temp->ihdl = srcp_ihdl;
+ }
+ else {
+ pr_err("%s: only support ion memory\n", __func__);
+ goto register_ion_fail;
+ }
+
+ memcpy(&temp->buf_info, data, sizeof(struct msmfb_data));
+ if (mdp4_overlay_writeback_register_buffer(mfd, temp)) {
+ pr_err("%s: error registering node\n", __func__);
+ goto register_ion_fail;
+ }
+ }
+ return temp;
+ register_ion_fail:
+ kfree(temp);
+ register_alloc_fail:
+ return NULL;
+}
+int mdp4_writeback_start(
+ struct fb_info *info)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ mutex_lock(&mfd->writeback_mutex);
+ mfd->writeback_state = WB_START;
+ mutex_unlock(&mfd->writeback_mutex);
+ wake_up(&mfd->wait_q);
+ return 0;
+}
+
+int mdp4_writeback_queue_buffer(struct fb_info *info, struct msmfb_data *data)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct msmfb_writeback_data_list *node = NULL;
+ int rv = 0;
+
+ mutex_lock(&mfd->writeback_mutex);
+ node = get_if_registered(mfd, data);
+ if (!node || node->state == IN_BUSY_QUEUE ||
+ node->state == IN_FREE_QUEUE) {
+ pr_err("memory not registered or Buffer already with us\n");
+ rv = -EINVAL;
+ goto exit;
+ }
+
+ list_add_tail(&node->active_entry, &mfd->writeback_free_queue);
+ node->state = IN_FREE_QUEUE;
+
+exit:
+ mutex_unlock(&mfd->writeback_mutex);
+ return rv;
+}
+static int is_buffer_ready(struct msm_fb_data_type *mfd)
+{
+ int rc;
+ mutex_lock(&mfd->writeback_mutex);
+ rc = !list_empty(&mfd->writeback_busy_queue) ||
+ (mfd->writeback_state == WB_STOPING);
+ mutex_unlock(&mfd->writeback_mutex);
+ return rc;
+}
+int mdp4_writeback_dequeue_buffer(struct fb_info *info, struct msmfb_data *data)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct msmfb_writeback_data_list *node = NULL;
+ int rc = 0;
+
+ rc = wait_event_interruptible(mfd->wait_q, is_buffer_ready(mfd));
+ if (rc) {
+ pr_err("failed to get dequeued buffer\n");
+ return -ENOBUFS;
+ }
+ mutex_lock(&mfd->writeback_mutex);
+ if (mfd->writeback_state == WB_STOPING) {
+ mfd->writeback_state = WB_STOP;
+ mutex_unlock(&mfd->writeback_mutex);
+ return -ENOBUFS;
+ } else if (!list_empty(&mfd->writeback_busy_queue)) {
+ node = list_first_entry(&mfd->writeback_busy_queue,
+ struct msmfb_writeback_data_list, active_entry);
+ }
+ if (node) {
+ list_del(&node->active_entry);
+ node->state = WITH_CLIENT;
+ memcpy(data, &node->buf_info, sizeof(struct msmfb_data));
+ if (!data->iova)
+ if (mfd->iclient && node->ihdl) {
+ ion_unmap_iommu(mfd->iclient,
+ node->ihdl,
+ DISPLAY_DOMAIN,
+ GEN_POOL);
+ ion_free(mfd->iclient,
+ node->ihdl);
+ }
+ } else {
+ pr_err("node is NULL. Somebody else dequeued?\n");
+ rc = -ENOBUFS;
+ }
+ mutex_unlock(&mfd->writeback_mutex);
+ return rc;
+}
+
+static bool is_writeback_inactive(struct msm_fb_data_type *mfd)
+{
+ bool active;
+ mutex_lock(&mfd->writeback_mutex);
+ active = !mfd->writeback_active_cnt;
+ mutex_unlock(&mfd->writeback_mutex);
+ return active;
+}
+int mdp4_writeback_stop(struct fb_info *info)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ mutex_lock(&mfd->writeback_mutex);
+ mfd->writeback_state = WB_STOPING;
+ mutex_unlock(&mfd->writeback_mutex);
+ /* Wait for all pending writebacks to finish */
+ wait_event_interruptible(mfd->wait_q, is_writeback_inactive(mfd));
+
+ /* Wake up dequeue thread in case of no UI update*/
+ wake_up(&mfd->wait_q);
+
+ return 0;
+}
+int mdp4_writeback_init(struct fb_info *info)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ mutex_init(&mfd->writeback_mutex);
+ mutex_init(&mfd->unregister_mutex);
+ INIT_LIST_HEAD(&mfd->writeback_free_queue);
+ INIT_LIST_HEAD(&mfd->writeback_busy_queue);
+ INIT_LIST_HEAD(&mfd->writeback_register_queue);
+ mfd->writeback_state = WB_OPEN;
+ init_waitqueue_head(&mfd->wait_q);
+ return 0;
+}
+int mdp4_writeback_terminate(struct fb_info *info)
+{
+ struct list_head *ptr, *next;
+ struct msmfb_writeback_data_list *temp;
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ int rc = 0;
+
+ mutex_lock(&mfd->unregister_mutex);
+ mutex_lock(&mfd->writeback_mutex);
+
+ if (mfd->writeback_state != WB_STOPING &&
+ mfd->writeback_state != WB_STOP) {
+ pr_err("%s called without stopping\n", __func__);
+ rc = -EPERM;
+ goto terminate_err;
+
+ }
+
+ if (!list_empty(&mfd->writeback_register_queue)) {
+ list_for_each_safe(ptr, next,
+ &mfd->writeback_register_queue) {
+ temp = list_entry(ptr,
+ struct msmfb_writeback_data_list,
+ registered_entry);
+ list_del(&temp->registered_entry);
+ kfree(temp);
+ }
+ }
+ INIT_LIST_HEAD(&mfd->writeback_register_queue);
+ INIT_LIST_HEAD(&mfd->writeback_busy_queue);
+ INIT_LIST_HEAD(&mfd->writeback_free_queue);
+
+
+terminate_err:
+ mutex_unlock(&mfd->writeback_mutex);
+ mutex_unlock(&mfd->unregister_mutex);
+ return rc;
+}
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index 00e8acf..2ad7d36 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -1,58 +1,13 @@
-
-/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of Code Aurora Forum nor
- * the names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
+ * 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.
*
- * Alternatively, provided that this notice is retained in full, this software
- * may be relicensed by the recipient under the terms of the GNU General Public
- * License version 2 ("GPL") and only version 2, in which case the provisions of
- * the GPL apply INSTEAD OF those given above. If the recipient relicenses the
- * software under the GPL, then the identification text in the MODULE_LICENSE
- * macro must be changed to reflect "GPLv2" instead of "Dual BSD/GPL". Once a
- * recipient changes the license terms to the GPL, subsequent recipients shall
- * not relicense under alternate licensing terms, including the BSD or dual
- * BSD/GPL terms. In addition, the following license statement immediately
- * below and between the words START and END shall also then apply when this
- * software is relicensed under the GPL:
- *
- * START
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * END
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
*
*/
@@ -65,32 +20,52 @@
#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/msm_mdp.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
#include <linux/semaphore.h>
#include <linux/uaccess.h>
-#include <mach/debug_display.h>
-
-#include "mdp_hw.h"
+#include <linux/msm_mdp.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/iommu_domains.h>
+#include "mdp.h"
+#include "msm_fb.h"
#include "mdp4.h"
+struct mdp4_statistic mdp4_stat;
-void mdp4_sw_reset(struct mdp_info *mdp, ulong bits)
+unsigned is_mdp4_hw_reset(void)
{
- bits &= 0x1f; /* 5 bits */
- mdp_writel(mdp, bits, 0x001c); /* MDP_SW_RESET */
+ unsigned hw_reset = 0;
- while (mdp_readl(mdp, 0x001c) & bits) /* self clear when complete */
- ;
- PR_DISP_WARN("mdp4_sw_reset: 0x%x\n", (int)bits);
+ /* 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_overlay_cfg(struct mdp_info *mdp, int overlayer, int blt_mode, int refresh, int direct_out)
+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;
@@ -100,33 +75,41 @@
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)
- mdp_writel(mdp, bits, 0x10004); /* MDP_OVERLAY0_CFG */
- else
- mdp_writel(mdp, bits, 0x18004); /* MDP_OVERLAY1_CFG */
+ outpdw(MDP_BASE + 0x10004, bits); /* MDP_OVERLAY0_CFG */
+ else if (overlayer == MDP4_MIXER1)
+ outpdw(MDP_BASE + 0x18004, bits); /* MDP_OVERLAY1_CFG */
- PR_DISP_WARN("mdp4_overlay_cfg: 0x%x\n", (int)mdp_readl(mdp, 0x10004));
+ 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(struct mdp_info *mdp, int output, ulong intf)
+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 = mdp_readl(mdp, 0x0038); /* MDP_DISP_INTF_SEL */
+ 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) {
- PR_DISP_INFO("%s: Illegal INTF selected, output=%d \
+ 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) {
- PR_DISP_INFO("%s: Illegal INTF selected, output=%d \
+ MSM_FB_INFO("%s: Illegal INTF selected, output=%d \
intf=%d\n", __func__, output, (int)intf);
}
} else
@@ -155,30 +138,45 @@
bits &= ~mask;
bits |= intf;
- mdp_writel(mdp, bits, 0x0038); /* MDP_DISP_INTF_SEL */
+ outpdw(MDP_BASE + 0x0038, bits); /* MDP_DISP_INTF_SEL */
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
- PR_DISP_WARN("mdp4_display_intf_sel: 0x%x\n", (int)mdp_readl(mdp, 0x0038));
+ MSM_FB_DEBUG("mdp4_display_intf_sel: 0x%x\n", (int)inpdw(MDP_BASE + 0x0038));
}
-unsigned long mdp4_display_status(struct mdp_info *mdp)
+unsigned long mdp4_display_status(void)
{
- return mdp_readl(mdp, 0x0018) & 0x3ff; /* MDP_DISPLAY_STATUS */
+ 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(struct mdp_info *mdp, int lcd, ulong base, int ystride)
+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) {
- mdp_writel(mdp, base, 0x0060);/* MDP_EBI2_LCD0 */
- mdp_writel(mdp, ystride, 0x0068);/* MDP_EBI2_LCD0_YSTRIDE */
+ outpdw(MDP_BASE + 0x0060, base);/* MDP_EBI2_LCD0 */
+ outpdw(MDP_BASE + 0x0068, ystride);/* MDP_EBI2_LCD0_YSTRIDE */
} else {
- mdp_writel(mdp, base, 0x0064);/* MDP_EBI2_LCD1 */
- mdp_writel(mdp, ystride, 0x006c);/* MDP_EBI2_LCD1_YSTRIDE */
+ 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(struct mdp_info *mdp, int mddi, unsigned long id)
+void mdp4_mddi_setup(int mddi, unsigned long id)
{
ulong bits;
@@ -192,413 +190,392 @@
id <<= 16;
bits |= id;
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
- mdp_writel(mdp, bits, 0x0090); /* MDP_MDDI_PARAM_WR_SEL */
-
+ 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);
}
-
-
-void mdp4_fetch_cfg(struct mdp_info *mdp, uint32_t clk, uint32_t pclk)
+int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req)
{
- uint32_t dmap_data, vg_data;
- uint32_t base;
+ /* 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 (clk <= pclk)
- PR_DISP_INFO("mdp4_fetch_cfg: ERROR!! mdp_clk=%d \
- <= mdp_pclk=%d\n", (int)clk, (int)pclk);
-
- if (clk >= 90000000) { /* 90 Mhz */
+ if (mdp_rev >= MDP_REV_41 || core_clk >= 90000000) { /* 90 Mhz */
dmap_data = 0x47; /* 16 bytes-burst x 8 req */
- vg_data = 0xc7; /* 16 bytes-burs x 8 req */
+ vg_data = 0x47; /* 16 bytes-burs x 8 req */
} else {
dmap_data = 0x27; /* 8 bytes-burst x 8 req */
- vg_data = 0xc3; /* 16 bytes-burst x 4 req */
+ vg_data = 0x43; /* 16 bytes-burst x 4 req */
}
- PR_DISP_INFO("mdp4_fetch_cfg: dmap=%x vg=%x\n",
+ MSM_FB_DEBUG("mdp4_fetch_cfg: dmap=%x vg=%x\n",
dmap_data, vg_data);
/* dma_p fetch config */
- mdp_writel(mdp, dmap_data, 0x91004);
+ outpdw(MDP_BASE + 0x91004, dmap_data);
/* dma_e fetch config */
- mdp_writel(mdp, dmap_data, 0xB1004);
+ outpdw(MDP_BASE + 0xB1004, dmap_data);
/*
* set up two vg pipes and two rgb pipes
*/
- base = MDP4_VIDEO_BASE;
+ base = MDP_BASE + MDP4_VIDEO_BASE;
for (i = 0; i < 4; i++) {
- mdp_writel(mdp, vg_data, base + 0x1004);
+ 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(struct mdp_info *mdp)
+void mdp4_hw_init(void)
{
ulong bits;
+ uint32 clk_rate;
- PR_DISP_WARN("%s\n", __func__);
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ mdp_bus_scale_update_request(5);
+
#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(mdp, 0x17);
+ mdp4_sw_reset(0x17);
#endif
- mdp4_clear_lcdc(mdp);
+ if (mdp_rev > MDP_REV_41) {
+ /* mdp chip select controller */
+ outpdw(MDP_BASE + 0x00c0, CS_CONTROLLER_0);
+ outpdw(MDP_BASE + 0x00c4, CS_CONTROLLER_1);
+ }
- mdp4_mixer_blend_init(mdp, 0);
- mdp4_mixer_blend_init(mdp, 1);
- mdp4_vg_qseed_init(mdp, 0);
- mdp4_vg_qseed_init(mdp, 1);
+ mdp4_clear_lcdc();
- /* yuv2rgb */
- mdp4_vg_qseed_init(mdp, 0);
- mdp4_vg_qseed_init(mdp, 1);
- mdp4_vg_csc_mv_setup(mdp, 0);
- mdp4_vg_csc_mv_setup(mdp, 1);
- mdp4_vg_csc_pre_bv_setup(mdp, 0);
- mdp4_vg_csc_pre_bv_setup(mdp, 1);
- mdp4_vg_csc_post_bv_setup(mdp, 0);
- mdp4_vg_csc_post_bv_setup(mdp, 1);
- mdp4_vg_csc_pre_lv_setup(mdp, 0);
- mdp4_vg_csc_pre_lv_setup(mdp, 1);
- mdp4_vg_csc_post_lv_setup(mdp, 0);
- mdp4_vg_csc_post_lv_setup(mdp, 1);
+ mdp4_mixer_blend_init(0);
+ mdp4_mixer_blend_init(1);
+ mdp4_vg_qseed_init(0);
+ mdp4_vg_qseed_init(1);
- /* rgb2yuv */
- mdp4_mixer1_csc_mv_setup(mdp);
- mdp4_mixer1_csc_pre_bv_setup(mdp);
- mdp4_mixer1_csc_post_bv_setup(mdp);
- mdp4_mixer1_csc_pre_lv_setup(mdp);
- mdp4_mixer1_csc_post_lv_setup(mdp);
+ mdp4_vg_csc_setup(0);
+ mdp4_vg_csc_setup(1);
+ mdp4_mixer_csc_setup(1);
+ mdp4_mixer_csc_setup(2);
+ mdp4_dmap_csc_setup();
- mdp4_mixer_gc_lut_setup(mdp, 0);
- mdp4_mixer_gc_lut_setup(mdp, 1);
+ if (mdp_rev <= MDP_REV_41) {
+ mdp4_mixer_gc_lut_setup(0);
+ mdp4_mixer_gc_lut_setup(1);
+ }
- mdp4_vg_igc_lut_setup(mdp, 0);
- mdp4_vg_igc_lut_setup(mdp, 1);
+ mdp4_vg_igc_lut_setup(0);
+ mdp4_vg_igc_lut_setup(1);
- mdp4_rgb_igc_lut_setup(mdp, 0);
- mdp4_rgb_igc_lut_setup(mdp, 1);
+ mdp4_rgb_igc_lut_setup(0);
+ mdp4_rgb_igc_lut_setup(1);
-
- mdp_writel(mdp, 0x3, MDP_EBI2_PORTMAP_MODE);
+ outp32(MDP_EBI2_PORTMAP_MODE, 0x3);
/* system interrupts */
- bits = MDP4_ANY_INTR_MASK;
- mdp_writel(mdp, bits, 0x0050);/* enable specififed interrupts */
- /* histogram */
- mdp_writel(mdp, 1, 0x95010); /* auto clear HIST */
+ bits = mdp_intr_mask;
+ outpdw(MDP_BASE + 0x0050, bits);/* enable specififed interrupts */
- /* enable histogram interrupts */
- mdp_writel(mdp, INTR_HIST_DONE, 0x9501c);
-#if defined(CONFIG_FB_MSM_MDP_ABL)
- mdp_writel(mdp, MDP_HIST_DONE, MDP_INTR_ENABLE);
-#endif
/* 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 */
- mdp_writel(mdp, 0x02222, 0x004c); /* 3 pending requests */
+ 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(mdp, MDP4_MIXER0, OVERLAY_MODE_BLT, 0, 0);
- mdp4_overlay_cfg(mdp, MDP4_MIXER1, OVERLAY_MODE_BLT, 0, 0);
+ mdp4_overlay_cfg(MDP4_MIXER0, OVERLAY_MODE_BLT, 0, 0);
+ mdp4_overlay_cfg(MDP4_MIXER1, OVERLAY_MODE_BLT, 0, 0);
#endif
+ clk_rate = mdp_get_core_clk();
+ mdp4_fetch_cfg(clk_rate);
+
+ mdp4_overlay_cfg_init();
+
+ /* 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);
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
-void mdp4_clear_lcdc(struct mdp_info *mdp)
+void mdp4_clear_lcdc(void)
{
- uint32_t bits;
+ uint32 bits;
- bits = mdp_readl(mdp, 0xc0000);
- if (bits & 0x01) /* enabled already */
+ 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;
+ }
- mdp_writel(mdp, 0, 0xc0004); /* vsync ctrl out */
- mdp_writel(mdp, 0, 0xc0008); /* vsync period */
- mdp_writel(mdp, 0, 0xc000c); /* vsync pusle width */
- mdp_writel(mdp, 0, 0xc0010); /* lcdc display HCTL */
- mdp_writel(mdp, 0, 0xc0014); /* lcdc display v start */
- mdp_writel(mdp, 0, 0xc0018); /* lcdc display v end */
- mdp_writel(mdp, 0, 0xc001c); /* lcdc active hctl */
- mdp_writel(mdp, 0, 0xc0020); /* lcdc active v start */
- mdp_writel(mdp, 0, 0xc0024); /* lcdc active v end */
- mdp_writel(mdp, 0, 0xc0028); /* lcdc board color */
- mdp_writel(mdp, 0, 0xc002c); /* lcdc underflow ctrl */
- mdp_writel(mdp, 0, 0xc0030); /* lcdc hsync skew */
- mdp_writel(mdp, 0, 0xc0034); /* lcdc test ctl */
- mdp_writel(mdp, 0, 0xc0038); /* lcdc ctl polarity */
+ 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;
+ struct mdp_hist_mgmt *mgmt = NULL;
+ char *base_addr;
+ int i, ret;
+ 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) {
+ pr_debug("%s: UNDERRUN -- primary\n", __func__);
+ 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.*/
+ for (i = 0; i < MDP_HIST_MGMT_MAX; i++) {
+ mgmt = mdp_hist_mgmt_array[i];
+ if (!mgmt)
+ continue;
+ base_addr = MDP_BASE + mgmt->base;
+ MDP_OUTP(base_addr + 0x010, 1);
+ outpdw(base_addr + 0x01c, INTR_HIST_DONE |
+ INTR_HIST_RESET_SEQ_DONE);
+ mgmt->mdp_is_hist_valid = FALSE;
+ __mdp_histogram_reset(mgmt);
+ }
+ }
+
+ if (isr & INTR_EXTERNAL_INTF_UDERRUN) {
+ pr_debug("%s: UNDERRUN -- external\n", __func__);
+ mdp4_stat.intr_underrun_e++;
+ }
+
+ isr &= mask;
+
+ if (isr == 0)
+ goto out;
+
+ panel = mdp4_overlay_panel_list();
+
+ if (isr & INTR_DMA_P_DONE) {
+ mdp4_stat.intr_dma_p++;
+ dma = &dma2_data;
+ if (panel & MDP4_PANEL_LCDC)
+ mdp4_dmap_done_lcdc(0);
+#ifdef CONFIG_FB_MSM_OVERLAY
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+ else if (panel & MDP4_PANEL_DSI_VIDEO)
+ mdp4_dmap_done_dsi_video(0);
+ else if (panel & MDP4_PANEL_DSI_CMD)
+ mdp4_dmap_done_dsi_cmd(0);
+#else
+ else { /* MDDI */
+ mdp4_dma_p_done_mddi(dma);
+ mdp_pipe_ctrl(MDP_DMA2_BLOCK,
+ MDP_BLOCK_POWER_OFF, TRUE);
+ complete(&dma->comp);
+ }
+#endif
+#else
+ else {
+ spin_lock(&mdp_spin_lock);
+ dma->busy = FALSE;
+ spin_unlock(&mdp_spin_lock);
+ 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++;
+ if (panel & MDP4_PANEL_DTV)
+ mdp4_dmae_done_dtv();
+ }
+#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 */
+ if (panel & MDP4_PANEL_LCDC)
+ mdp4_overlay0_done_lcdc(0);
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+ else if (panel & MDP4_PANEL_DSI_VIDEO)
+ mdp4_overlay0_done_dsi_video(0);
+#endif
+ } else { /* MDDI, DSI_CMD */
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+ if (panel & MDP4_PANEL_DSI_CMD)
+ mdp4_overlay0_done_dsi_cmd(0);
+#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
+ }
+#if defined(CONFIG_FB_MSM_WRITEBACK_MSM_PANEL)
+ if (isr & INTR_OVERLAY2_DONE) {
+ mdp4_stat.intr_overlay2++;
+ /* disable DTV interrupt */
+ dma = &dma_wb_data;
+ spin_lock(&mdp_spin_lock);
+ mdp_intr_mask &= ~INTR_OVERLAY2_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ dma->waiting = FALSE;
+ spin_unlock(&mdp_spin_lock);
+ if (panel & MDP4_PANEL_WRITEBACK)
+ mdp4_overlay1_done_writeback(dma);
+ }
+#endif
+#endif /* OVERLAY */
+
+ if (isr & INTR_PRIMARY_VSYNC) {
+ mdp4_stat.intr_vsync_p++;
+ if (panel & MDP4_PANEL_LCDC)
+ mdp4_primary_vsync_lcdc();
+ else if (panel & MDP4_PANEL_DSI_VIDEO)
+ mdp4_primary_vsync_dsi_video();
+ }
+#ifdef CONFIG_FB_MSM_DTV
+ if (isr & INTR_EXTERNAL_VSYNC) {
+ mdp4_stat.intr_vsync_e++;
+ if (panel & MDP4_PANEL_DTV)
+ mdp4_external_vsync_dtv();
+ }
+#endif
+ if (isr & INTR_DMA_P_HISTOGRAM) {
+ mdp4_stat.intr_histogram++;
+ ret = mdp_histogram_block2mgmt(MDP_BLOCK_DMA_P, &mgmt);
+ if (!ret)
+ mdp_histogram_handle_isr(mgmt);
+ }
+ if (isr & INTR_DMA_S_HISTOGRAM) {
+ mdp4_stat.intr_histogram++;
+ ret = mdp_histogram_block2mgmt(MDP_BLOCK_DMA_S, &mgmt);
+ if (!ret)
+ mdp_histogram_handle_isr(mgmt);
+ }
+ if (isr & INTR_VG1_HISTOGRAM) {
+ mdp4_stat.intr_histogram++;
+ ret = mdp_histogram_block2mgmt(MDP_BLOCK_VG_1, &mgmt);
+ if (!ret)
+ mdp_histogram_handle_isr(mgmt);
+ }
+ if (isr & INTR_VG2_HISTOGRAM) {
+ mdp4_stat.intr_histogram++;
+ ret = mdp_histogram_block2mgmt(MDP_BLOCK_VG_2, &mgmt);
+ if (!ret)
+ mdp_histogram_handle_isr(mgmt);
+ }
+ if (isr & INTR_PRIMARY_RDPTR) {
+ mdp4_stat.intr_rdptr++;
+ mdp4_primary_rdptr();
+ }
+
+out:
+ mdp_is_in_isr = FALSE;
+
+ return IRQ_HANDLED;
+}
/*
* QSEED tables
*/
-static uint32_t vg_qseed_table0[] = {
+static uint32 vg_qseed_table0[] = {
0x5556aaff, 0x00000000, 0x00000000, 0x00000000
};
-static uint32_t vg_qseed_table1[] = {
- 0x76543210, 0xfedcba98
+static uint32 vg_qseed_table1[] = {
+ 0x00000000, 0x20000000,
};
-static uint32_t vg_qseed_table2[] = {
- 0x02000000, 0x00000000, 0x02060ff2, 0x00000008,
- 0x02090fe4, 0x00000013, 0x020a0fd9, 0x0ffc0021,
- 0x02080fce, 0x0ffa0030, 0x02030fc5, 0x0ff60042,
- 0x01fd0fbe, 0x0ff10054, 0x01f50fb6, 0x0fed0068,
- 0x01e90fb1, 0x0fe60080, 0x01dc0fae, 0x0fe10095,
- 0x01ca0fae, 0x0fda00ae, 0x01b70fad, 0x0fd600c6,
- 0x01a40fad, 0x0fcf00e0, 0x018f0faf, 0x0fc800fa,
- 0x01780fb1, 0x0fc30114, 0x015f0fb5, 0x0fbf012d,
- 0x01490fb7, 0x0fb70149, 0x012d0fbf, 0x0fb5015f,
- 0x01140fc3, 0x0fb10178, 0x00fa0fc8, 0x0faf018f,
- 0x00e00fcf, 0x0fad01a4, 0x00c60fd6, 0x0fad01b7,
- 0x00ae0fda, 0x0fae01ca, 0x00950fe1, 0x0fae01dc,
- 0x00800fe6, 0x0fb101e9, 0x00680fed, 0x0fb601f5,
- 0x00540ff1, 0x0fbe01fd, 0x00420ff6, 0x0fc50203,
- 0x00300ffa, 0x0fce0208, 0x00210ffc, 0x0fd9020a,
- 0x00130000, 0x0fe40209, 0x00080000, 0x0ff20206,
- 0x02000000, 0x00000000, 0x02040ff2, 0x0000000a,
- 0x02040fe4, 0x00000018, 0x02010fda, 0x0ffc0029,
- 0x01fc0fcf, 0x0ffa003b, 0x01f30fc7, 0x0ff60050,
- 0x01e90fc0, 0x0ff20065, 0x01dc0fba, 0x0fee007c,
- 0x01cc0fb6, 0x0fe80096, 0x01ba0fb4, 0x0fe400ae,
- 0x01a70fb4, 0x0fdd00c8, 0x018f0fb5, 0x0fda00e2,
- 0x017a0fb5, 0x0fd400fd, 0x01630fb8, 0x0fce0117,
- 0x014c0fba, 0x0fca0130, 0x01320fbf, 0x0fc70148,
- 0x011b0fc1, 0x0fc10163, 0x01010fc8, 0x0fc00177,
- 0x00e90fcd, 0x0fbd018d, 0x00d10fd1, 0x0fbc01a2,
- 0x00ba0fd7, 0x0fbb01b4, 0x00a30fdd, 0x0fbc01c4,
- 0x008e0fe1, 0x0fbd01d4, 0x00790fe7, 0x0fbe01e2,
- 0x00670feb, 0x0fc001ee, 0x00540ff1, 0x0fc501f6,
- 0x00430ff4, 0x0fcb01fe, 0x00340ff8, 0x0fd10203,
- 0x00260ffb, 0x0fd80207, 0x001a0ffd, 0x0fe10208,
- 0x000f0000, 0x0fea0207, 0x00060000, 0x0ff50205,
- 0x02000000, 0x00000000, 0x02020ff2, 0x0000000c,
- 0x02000fe4, 0x0000001c, 0x01fa0fda, 0x0ffc0030,
- 0x01f10fd0, 0x0ffa0045, 0x01e50fc8, 0x0ff6005d,
- 0x01d60fc3, 0x0ff30074, 0x01c60fbd, 0x0fef008e,
- 0x01b30fba, 0x0fe900aa, 0x019e0fb9, 0x0fe500c4,
- 0x01870fba, 0x0fe000df, 0x016f0fbb, 0x0fdd00f9,
- 0x01580fbc, 0x0fd80114, 0x01400fbf, 0x0fd3012e,
- 0x01280fc2, 0x0fd00146, 0x010f0fc6, 0x0fce015d,
- 0x00f90fc9, 0x0fc90175, 0x00e00fcf, 0x0fc90188,
- 0x00ca0fd4, 0x0fc6019c, 0x00b40fd8, 0x0fc601ae,
- 0x009f0fdd, 0x0fc501bf, 0x008b0fe3, 0x0fc601cc,
- 0x00780fe6, 0x0fc701db, 0x00660feb, 0x0fc801e7,
- 0x00560fef, 0x0fcb01f0, 0x00460ff3, 0x0fcf01f8,
- 0x00380ff6, 0x0fd401fe, 0x002c0ff9, 0x0fd90202,
- 0x00200ffc, 0x0fdf0205, 0x00160ffe, 0x0fe60206,
- 0x000c0000, 0x0fed0207, 0x00050000, 0x0ff70204,
- 0x02000000, 0x00000000, 0x01fe0ff3, 0x0000000f,
- 0x01f60fe5, 0x00000025, 0x01ea0fdb, 0x0ffd003e,
- 0x01db0fd2, 0x0ffb0058, 0x01c80fcc, 0x0ff70075,
- 0x01b50fc7, 0x0ff40090, 0x01a00fc3, 0x0ff000ad,
- 0x01880fc1, 0x0feb00cc, 0x01700fc1, 0x0fe800e7,
- 0x01550fc3, 0x0fe40104, 0x013b0fc5, 0x0fe2011e,
- 0x01240fc6, 0x0fde0138, 0x010c0fca, 0x0fda0150,
- 0x00f40fcd, 0x0fd90166, 0x00dd0fd1, 0x0fd7017b,
- 0x00c80fd4, 0x0fd40190, 0x00b20fd9, 0x0fd401a1,
- 0x009f0fdd, 0x0fd301b1, 0x008c0fe1, 0x0fd301c0,
- 0x007b0fe5, 0x0fd301cd, 0x006a0fea, 0x0fd401d8,
- 0x005c0fec, 0x0fd501e3, 0x004d0ff0, 0x0fd601ed,
- 0x00410ff3, 0x0fd801f4, 0x00340ff7, 0x0fdb01fa,
- 0x002a0ff9, 0x0fdf01fe, 0x00200ffb, 0x0fe30202,
- 0x00180ffd, 0x0fe70204, 0x00100ffe, 0x0fed0205,
- 0x00090000, 0x0ff20205, 0x00040000, 0x0ff90203,
- 0x02000000, 0x00000000, 0x02050ff5, 0x00000006,
- 0x02070fea, 0x0000000f, 0x02080fe1, 0x0ffd001a,
- 0x02070fd8, 0x0ffb0026, 0x02030fd1, 0x0ff80034,
- 0x01fe0fcb, 0x0ff40043, 0x01f60fc5, 0x0ff10054,
- 0x01ee0fc0, 0x0feb0067, 0x01e20fbe, 0x0fe70079,
- 0x01d40fbd, 0x0fe1008e, 0x01c40fbc, 0x0fdd00a3,
- 0x01b40fbb, 0x0fd700ba, 0x01a20fbc, 0x0fd100d1,
- 0x018d0fbd, 0x0fcd00e9, 0x01770fc0, 0x0fc80101,
- 0x01630fc1, 0x0fc1011b, 0x01480fc7, 0x0fbf0132,
- 0x01300fca, 0x0fba014c, 0x01170fce, 0x0fb80163,
- 0x00fd0fd4, 0x0fb5017a, 0x00e20fda, 0x0fb5018f,
- 0x00c80fdd, 0x0fb401a7, 0x00ae0fe4, 0x0fb401ba,
- 0x00960fe8, 0x0fb601cc, 0x007c0fee, 0x0fba01dc,
- 0x00650ff2, 0x0fc001e9, 0x00500ff6, 0x0fc701f3,
- 0x003b0ffa, 0x0fcf01fc, 0x00290ffc, 0x0fda0201,
- 0x00180000, 0x0fe40204, 0x000a0000, 0x0ff20204,
- 0x02000000, 0x00000000, 0x02030ff5, 0x00000008,
- 0x02030fea, 0x00000013, 0x02020fe1, 0x0ffd0020,
- 0x01fc0fd9, 0x0ffc002f, 0x01f60fd2, 0x0ff80040,
- 0x01ed0fcd, 0x0ff50051, 0x01e30fc7, 0x0ff10065,
- 0x01d70fc3, 0x0fec007a, 0x01c60fc2, 0x0fe9008f,
- 0x01b60fc1, 0x0fe300a6, 0x01a20fc1, 0x0fe000bd,
- 0x018f0fc1, 0x0fdb00d5, 0x017b0fc2, 0x0fd500ee,
- 0x01640fc4, 0x0fd20106, 0x014d0fc8, 0x0fce011d,
- 0x01370fc9, 0x0fc90137, 0x011d0fce, 0x0fc8014d,
- 0x01060fd2, 0x0fc40164, 0x00ee0fd5, 0x0fc2017b,
- 0x00d50fdb, 0x0fc1018f, 0x00bd0fe0, 0x0fc101a2,
- 0x00a60fe3, 0x0fc101b6, 0x008f0fe9, 0x0fc201c6,
- 0x007a0fec, 0x0fc301d7, 0x00650ff1, 0x0fc701e3,
- 0x00510ff5, 0x0fcd01ed, 0x00400ff8, 0x0fd201f6,
- 0x002f0ffc, 0x0fd901fc, 0x00200ffd, 0x0fe10202,
- 0x00130000, 0x0fea0203, 0x00080000, 0x0ff50203,
- 0x02000000, 0x00000000, 0x02020ff5, 0x00000009,
- 0x01ff0fea, 0x00000017, 0x01fb0fe2, 0x0ffd0026,
- 0x01f30fda, 0x0ffc0037, 0x01ea0fd3, 0x0ff8004b,
- 0x01df0fce, 0x0ff5005e, 0x01d10fc9, 0x0ff20074,
- 0x01c10fc6, 0x0fed008c, 0x01ae0fc5, 0x0fea00a3,
- 0x019b0fc5, 0x0fe500bb, 0x01850fc6, 0x0fe200d3,
- 0x01700fc6, 0x0fde00ec, 0x015a0fc8, 0x0fd90105,
- 0x01430fca, 0x0fd6011d, 0x012b0fcd, 0x0fd30135,
- 0x01150fcf, 0x0fcf014d, 0x00fc0fd4, 0x0fce0162,
- 0x00e50fd8, 0x0fcc0177, 0x00cf0fdb, 0x0fca018c,
- 0x00b80fe0, 0x0fc9019f, 0x00a20fe5, 0x0fca01af,
- 0x008e0fe8, 0x0fcb01bf, 0x00790fec, 0x0fcb01d0,
- 0x00670fef, 0x0fcd01dd, 0x00550ff4, 0x0fd001e7,
- 0x00440ff7, 0x0fd501f0, 0x00350ffa, 0x0fda01f7,
- 0x00270ffc, 0x0fdf01fe, 0x001b0ffe, 0x0fe70200,
- 0x00100000, 0x0fee0202, 0x00060000, 0x0ff70203,
- 0x02000000, 0x00000000, 0x01ff0ff5, 0x0000000c,
- 0x01f80fea, 0x0000001e, 0x01ef0fe2, 0x0ffd0032,
- 0x01e20fdb, 0x0ffc0047, 0x01d30fd5, 0x0ff9005f,
- 0x01c20fd1, 0x0ff60077, 0x01b00fcd, 0x0ff30090,
- 0x019b0fcb, 0x0fef00ab, 0x01850fcb, 0x0fec00c4,
- 0x016e0fcc, 0x0fe800de, 0x01550fcd, 0x0fe600f8,
- 0x013f0fce, 0x0fe20111, 0x01280fd0, 0x0fdf0129,
- 0x01110fd2, 0x0fdd0140, 0x00f90fd6, 0x0fdb0156,
- 0x00e40fd8, 0x0fd8016c, 0x00cd0fdd, 0x0fd8017e,
- 0x00b80fe0, 0x0fd60192, 0x00a40fe3, 0x0fd601a3,
- 0x00910fe7, 0x0fd501b3, 0x007f0feb, 0x0fd601c0,
- 0x006e0fed, 0x0fd701ce, 0x005d0ff1, 0x0fd701db,
- 0x004f0ff3, 0x0fd901e5, 0x00400ff7, 0x0fdc01ed,
- 0x00330ff9, 0x0fe001f4, 0x00280ffb, 0x0fe301fa,
- 0x001d0ffd, 0x0fe801fe, 0x00140ffe, 0x0fed0201,
- 0x000c0000, 0x0ff20202, 0x00050000, 0x0ff90202,
- 0x02000000, 0x00000000, 0x02040ff7, 0x00000005,
- 0x02070fed, 0x0000000c, 0x02060fe6, 0x0ffe0016,
- 0x02050fdf, 0x0ffc0020, 0x02020fd9, 0x0ff9002c,
- 0x01fe0fd4, 0x0ff60038, 0x01f80fcf, 0x0ff30046,
- 0x01f00fcb, 0x0fef0056, 0x01e70fc8, 0x0feb0066,
- 0x01db0fc7, 0x0fe60078, 0x01cc0fc6, 0x0fe3008b,
- 0x01bf0fc5, 0x0fdd009f, 0x01ae0fc6, 0x0fd800b4,
- 0x019c0fc6, 0x0fd400ca, 0x01880fc9, 0x0fcf00e0,
- 0x01750fc9, 0x0fc900f9, 0x015d0fce, 0x0fc6010f,
- 0x01460fd0, 0x0fc20128, 0x012e0fd3, 0x0fbf0140,
- 0x01140fd8, 0x0fbc0158, 0x00f90fdd, 0x0fbb016f,
- 0x00df0fe0, 0x0fba0187, 0x00c40fe5, 0x0fb9019e,
- 0x00aa0fe9, 0x0fba01b3, 0x008e0fef, 0x0fbd01c6,
- 0x00740ff3, 0x0fc301d6, 0x005d0ff6, 0x0fc801e5,
- 0x00450ffa, 0x0fd001f1, 0x00300ffc, 0x0fda01fa,
- 0x001c0000, 0x0fe40200, 0x000c0000, 0x0ff20202,
- 0x02000000, 0x00000000, 0x02030ff7, 0x00000006,
- 0x02020fee, 0x00000010, 0x02000fe7, 0x0ffe001b,
- 0x01fe0fdf, 0x0ffc0027, 0x01f70fda, 0x0ffa0035,
- 0x01f00fd5, 0x0ff70044, 0x01e70fd0, 0x0ff40055,
- 0x01dd0fcd, 0x0fef0067, 0x01d00fcb, 0x0fec0079,
- 0x01bf0fcb, 0x0fe8008e, 0x01af0fca, 0x0fe500a2,
- 0x019f0fc9, 0x0fe000b8, 0x018c0fca, 0x0fdb00cf,
- 0x01770fcc, 0x0fd800e5, 0x01620fce, 0x0fd400fc,
- 0x014d0fcf, 0x0fcf0115, 0x01350fd3, 0x0fcd012b,
- 0x011d0fd6, 0x0fca0143, 0x01050fd9, 0x0fc8015a,
- 0x00ec0fde, 0x0fc60170, 0x00d30fe2, 0x0fc60185,
- 0x00bb0fe5, 0x0fc5019b, 0x00a30fea, 0x0fc501ae,
- 0x008c0fed, 0x0fc601c1, 0x00740ff2, 0x0fc901d1,
- 0x005e0ff5, 0x0fce01df, 0x004b0ff8, 0x0fd301ea,
- 0x00370ffc, 0x0fda01f3, 0x00260ffd, 0x0fe201fb,
- 0x00170000, 0x0fea01ff, 0x00090000, 0x0ff50202,
- 0x02000000, 0x00000000, 0x02010ff7, 0x00000008,
- 0x01ff0fee, 0x00000013, 0x01fb0fe7, 0x0ffe0020,
- 0x01f60fe0, 0x0ffc002e, 0x01ed0fda, 0x0ffa003f,
- 0x01e40fd6, 0x0ff7004f, 0x01d80fd2, 0x0ff40062,
- 0x01ca0fcf, 0x0ff00077, 0x01bb0fcd, 0x0fed008b,
- 0x01a90fcd, 0x0fe900a1, 0x01960fcd, 0x0fe600b7,
- 0x01830fcd, 0x0fe200ce, 0x016d0fcf, 0x0fde00e6,
- 0x01580fd0, 0x0fdb00fd, 0x01410fd3, 0x0fd80114,
- 0x012c0fd4, 0x0fd4012c, 0x01140fd8, 0x0fd30141,
- 0x00fd0fdb, 0x0fd00158, 0x00e60fde, 0x0fcf016d,
- 0x00ce0fe2, 0x0fcd0183, 0x00b70fe6, 0x0fcd0196,
- 0x00a10fe9, 0x0fcd01a9, 0x008b0fed, 0x0fcd01bb,
- 0x00770ff0, 0x0fcf01ca, 0x00620ff4, 0x0fd201d8,
- 0x004f0ff7, 0x0fd601e4, 0x003f0ffa, 0x0fda01ed,
- 0x002e0ffc, 0x0fe001f6, 0x00200ffe, 0x0fe701fb,
- 0x00130000, 0x0fee01ff, 0x00080000, 0x0ff70201,
- 0x02000000, 0x00000000, 0x01ff0ff7, 0x0000000a,
- 0x01f90fee, 0x00000019, 0x01f10fe7, 0x0ffe002a,
- 0x01e60fe1, 0x0ffd003c, 0x01d90fdc, 0x0ffa0051,
- 0x01cc0fd8, 0x0ff70065, 0x01bb0fd5, 0x0ff5007b,
- 0x01a80fd3, 0x0ff10094, 0x01950fd2, 0x0fef00aa,
- 0x01800fd2, 0x0feb00c3, 0x016a0fd3, 0x0fe900da,
- 0x01540fd3, 0x0fe600f3, 0x013f0fd5, 0x0fe2010a,
- 0x01280fd7, 0x0fe00121, 0x01100fda, 0x0fde0138,
- 0x00fb0fdb, 0x0fdb014f, 0x00e40fdf, 0x0fdb0162,
- 0x00ce0fe2, 0x0fd90177, 0x00b90fe4, 0x0fd8018b,
- 0x00a50fe8, 0x0fd8019b, 0x00910fec, 0x0fd801ab,
- 0x007e0fee, 0x0fd801bc, 0x006c0ff2, 0x0fd901c9,
- 0x005c0ff4, 0x0fda01d6, 0x004b0ff7, 0x0fdd01e1,
- 0x003c0ff9, 0x0fe001eb, 0x002f0ffb, 0x0fe401f2,
- 0x00230ffd, 0x0fe801f8, 0x00180ffe, 0x0fed01fd,
- 0x000e0000, 0x0ff20200, 0x00060000, 0x0ff90201,
- 0x02000000, 0x00000000, 0x02030ff9, 0x00000004,
- 0x02050ff2, 0x00000009, 0x02050fed, 0x0ffe0010,
- 0x02040fe7, 0x0ffd0018, 0x02020fe3, 0x0ffb0020,
- 0x01fe0fdf, 0x0ff9002a, 0x01fa0fdb, 0x0ff70034,
- 0x01f40fd8, 0x0ff30041, 0x01ed0fd6, 0x0ff0004d,
- 0x01e30fd5, 0x0fec005c, 0x01d80fd4, 0x0fea006a,
- 0x01cd0fd3, 0x0fe5007b, 0x01c00fd3, 0x0fe1008c,
- 0x01b10fd3, 0x0fdd009f, 0x01a10fd4, 0x0fd900b2,
- 0x01900fd4, 0x0fd400c8, 0x017b0fd7, 0x0fd100dd,
- 0x01660fd9, 0x0fcd00f4, 0x01500fda, 0x0fca010c,
- 0x01380fde, 0x0fc60124, 0x011e0fe2, 0x0fc5013b,
- 0x01040fe4, 0x0fc30155, 0x00e70fe8, 0x0fc10170,
- 0x00cc0feb, 0x0fc10188, 0x00ad0ff0, 0x0fc301a0,
- 0x00900ff4, 0x0fc701b5, 0x00750ff7, 0x0fcc01c8,
- 0x00580ffb, 0x0fd201db, 0x003e0ffd, 0x0fdb01ea,
- 0x00250000, 0x0fe501f6, 0x000f0000, 0x0ff301fe,
- 0x02000000, 0x00000000, 0x02020ff9, 0x00000005,
- 0x02020ff2, 0x0000000c, 0x02010fed, 0x0ffe0014,
- 0x01fe0fe8, 0x0ffd001d, 0x01fa0fe3, 0x0ffb0028,
- 0x01f40fe0, 0x0ff90033, 0x01ed0fdc, 0x0ff70040,
- 0x01e50fd9, 0x0ff3004f, 0x01db0fd7, 0x0ff1005d,
- 0x01ce0fd7, 0x0fed006e, 0x01c00fd6, 0x0feb007f,
- 0x01b30fd5, 0x0fe70091, 0x01a30fd6, 0x0fe300a4,
- 0x01920fd6, 0x0fe000b8, 0x017e0fd8, 0x0fdd00cd,
- 0x016c0fd8, 0x0fd800e4, 0x01560fdb, 0x0fd600f9,
- 0x01400fdd, 0x0fd20111, 0x01290fdf, 0x0fd00128,
- 0x01110fe2, 0x0fce013f, 0x00f80fe6, 0x0fcd0155,
- 0x00de0fe8, 0x0fcc016e, 0x00c40fec, 0x0fcb0185,
- 0x00ab0fef, 0x0fcb019b, 0x00900ff3, 0x0fcd01b0,
- 0x00770ff6, 0x0fd101c2, 0x005f0ff9, 0x0fd501d3,
- 0x00470ffc, 0x0fdb01e2, 0x00320ffd, 0x0fe201ef,
- 0x001e0000, 0x0fea01f8, 0x000c0000, 0x0ff501ff,
- 0x02000000, 0x00000000, 0x02010ff9, 0x00000006,
- 0x02000ff2, 0x0000000e, 0x01fd0fed, 0x0ffe0018,
- 0x01f80fe8, 0x0ffd0023, 0x01f20fe4, 0x0ffb002f,
- 0x01eb0fe0, 0x0ff9003c, 0x01e10fdd, 0x0ff7004b,
- 0x01d60fda, 0x0ff4005c, 0x01c90fd9, 0x0ff2006c,
- 0x01bc0fd8, 0x0fee007e, 0x01ab0fd8, 0x0fec0091,
- 0x019b0fd8, 0x0fe800a5, 0x018b0fd8, 0x0fe400b9,
- 0x01770fd9, 0x0fe200ce, 0x01620fdb, 0x0fdf00e4,
- 0x014f0fdb, 0x0fdb00fb, 0x01380fde, 0x0fda0110,
- 0x01210fe0, 0x0fd70128, 0x010a0fe2, 0x0fd5013f,
- 0x00f30fe6, 0x0fd30154, 0x00da0fe9, 0x0fd3016a,
- 0x00c30feb, 0x0fd20180, 0x00aa0fef, 0x0fd20195,
- 0x00940ff1, 0x0fd301a8, 0x007b0ff5, 0x0fd501bb,
- 0x00650ff7, 0x0fd801cc, 0x00510ffa, 0x0fdc01d9,
- 0x003c0ffd, 0x0fe101e6, 0x002a0ffe, 0x0fe701f1,
- 0x00190000, 0x0fee01f9, 0x000a0000, 0x0ff701ff,
+static uint32 vg_qseed_table2[] = {
0x02000000, 0x00000000, 0x01ff0ff9, 0x00000008,
0x01fb0ff2, 0x00000013, 0x01f50fed, 0x0ffe0020,
0x01ed0fe8, 0x0ffd002e, 0x01e30fe4, 0x0ffb003e,
@@ -615,246 +592,262 @@
0x004e0ff9, 0x0fe101d8, 0x003e0ffb, 0x0fe401e3,
0x002e0ffd, 0x0fe801ed, 0x00200ffe, 0x0fed01f5,
0x00130000, 0x0ff201fb, 0x00080000, 0x0ff901ff,
- 0x02000000, 0x00000000, 0x02060ff2, 0x00000008,
- 0x02090fe4, 0x00000013, 0x020a0fd9, 0x0ffc0021,
- 0x02080fce, 0x0ffa0030, 0x02030fc5, 0x0ff60042,
- 0x01fd0fbe, 0x0ff10054, 0x01f50fb6, 0x0fed0068,
- 0x01e90fb1, 0x0fe60080, 0x01dc0fae, 0x0fe10095,
- 0x01ca0fae, 0x0fda00ae, 0x01b70fad, 0x0fd600c6,
- 0x01a40fad, 0x0fcf00e0, 0x018f0faf, 0x0fc800fa,
- 0x01780fb1, 0x0fc30114, 0x015f0fb5, 0x0fbf012d,
- 0x01490fb7, 0x0fb70149, 0x012d0fbf, 0x0fb5015f,
- 0x01140fc3, 0x0fb10178, 0x00fa0fc8, 0x0faf018f,
- 0x00e00fcf, 0x0fad01a4, 0x00c60fd6, 0x0fad01b7,
- 0x00ae0fda, 0x0fae01ca, 0x00950fe1, 0x0fae01dc,
- 0x00800fe6, 0x0fb101e9, 0x00680fed, 0x0fb601f5,
- 0x00540ff1, 0x0fbe01fd, 0x00420ff6, 0x0fc50203,
- 0x00300ffa, 0x0fce0208, 0x00210ffc, 0x0fd9020a,
- 0x00130000, 0x0fe40209, 0x00080000, 0x0ff20206,
- 0x02000000, 0x00000000, 0x02040ff2, 0x0000000a,
- 0x02040fe4, 0x00000018, 0x02010fda, 0x0ffc0029,
- 0x01fc0fcf, 0x0ffa003b, 0x01f30fc7, 0x0ff60050,
- 0x01e90fc0, 0x0ff20065, 0x01dc0fba, 0x0fee007c,
- 0x01cc0fb6, 0x0fe80096, 0x01ba0fb4, 0x0fe400ae,
- 0x01a70fb4, 0x0fdd00c8, 0x018f0fb5, 0x0fda00e2,
- 0x017a0fb5, 0x0fd400fd, 0x01630fb8, 0x0fce0117,
- 0x014c0fba, 0x0fca0130, 0x01320fbf, 0x0fc70148,
- 0x011b0fc1, 0x0fc10163, 0x01010fc8, 0x0fc00177,
- 0x00e90fcd, 0x0fbd018d, 0x00d10fd1, 0x0fbc01a2,
- 0x00ba0fd7, 0x0fbb01b4, 0x00a30fdd, 0x0fbc01c4,
- 0x008e0fe1, 0x0fbd01d4, 0x00790fe7, 0x0fbe01e2,
- 0x00670feb, 0x0fc001ee, 0x00540ff1, 0x0fc501f6,
- 0x00430ff4, 0x0fcb01fe, 0x00340ff8, 0x0fd10203,
- 0x00260ffb, 0x0fd80207, 0x001a0ffd, 0x0fe10208,
- 0x000f0000, 0x0fea0207, 0x00060000, 0x0ff50205,
- 0x02000000, 0x00000000, 0x02020ff2, 0x0000000c,
- 0x02000fe4, 0x0000001c, 0x01fa0fda, 0x0ffc0030,
- 0x01f10fd0, 0x0ffa0045, 0x01e50fc8, 0x0ff6005d,
- 0x01d60fc3, 0x0ff30074, 0x01c60fbd, 0x0fef008e,
- 0x01b30fba, 0x0fe900aa, 0x019e0fb9, 0x0fe500c4,
- 0x01870fba, 0x0fe000df, 0x016f0fbb, 0x0fdd00f9,
- 0x01580fbc, 0x0fd80114, 0x01400fbf, 0x0fd3012e,
- 0x01280fc2, 0x0fd00146, 0x010f0fc6, 0x0fce015d,
- 0x00f90fc9, 0x0fc90175, 0x00e00fcf, 0x0fc90188,
- 0x00ca0fd4, 0x0fc6019c, 0x00b40fd8, 0x0fc601ae,
- 0x009f0fdd, 0x0fc501bf, 0x008b0fe3, 0x0fc601cc,
- 0x00780fe6, 0x0fc701db, 0x00660feb, 0x0fc801e7,
- 0x00560fef, 0x0fcb01f0, 0x00460ff3, 0x0fcf01f8,
- 0x00380ff6, 0x0fd401fe, 0x002c0ff9, 0x0fd90202,
- 0x00200ffc, 0x0fdf0205, 0x00160ffe, 0x0fe60206,
- 0x000c0000, 0x0fed0207, 0x00050000, 0x0ff70204,
- 0x02000000, 0x00000000, 0x01fe0ff3, 0x0000000f,
- 0x01f60fe5, 0x00000025, 0x01ea0fdb, 0x0ffd003e,
- 0x01db0fd2, 0x0ffb0058, 0x01c80fcc, 0x0ff70075,
- 0x01b50fc7, 0x0ff40090, 0x01a00fc3, 0x0ff000ad,
- 0x01880fc1, 0x0feb00cc, 0x01700fc1, 0x0fe800e7,
- 0x01550fc3, 0x0fe40104, 0x013b0fc5, 0x0fe2011e,
- 0x01240fc6, 0x0fde0138, 0x010c0fca, 0x0fda0150,
- 0x00f40fcd, 0x0fd90166, 0x00dd0fd1, 0x0fd7017b,
- 0x00c80fd4, 0x0fd40190, 0x00b20fd9, 0x0fd401a1,
- 0x009f0fdd, 0x0fd301b1, 0x008c0fe1, 0x0fd301c0,
- 0x007b0fe5, 0x0fd301cd, 0x006a0fea, 0x0fd401d8,
- 0x005c0fec, 0x0fd501e3, 0x004d0ff0, 0x0fd601ed,
- 0x00410ff3, 0x0fd801f4, 0x00340ff7, 0x0fdb01fa,
- 0x002a0ff9, 0x0fdf01fe, 0x00200ffb, 0x0fe30202,
- 0x00180ffd, 0x0fe70204, 0x00100ffe, 0x0fed0205,
- 0x00090000, 0x0ff20205, 0x00040000, 0x0ff90203,
- 0x02000000, 0x00000000, 0x02050ff5, 0x00000006,
- 0x02070fea, 0x0000000f, 0x02080fe1, 0x0ffd001a,
- 0x02070fd8, 0x0ffb0026, 0x02030fd1, 0x0ff80034,
- 0x01fe0fcb, 0x0ff40043, 0x01f60fc5, 0x0ff10054,
- 0x01ee0fc0, 0x0feb0067, 0x01e20fbe, 0x0fe70079,
- 0x01d40fbd, 0x0fe1008e, 0x01c40fbc, 0x0fdd00a3,
- 0x01b40fbb, 0x0fd700ba, 0x01a20fbc, 0x0fd100d1,
- 0x018d0fbd, 0x0fcd00e9, 0x01770fc0, 0x0fc80101,
- 0x01630fc1, 0x0fc1011b, 0x01480fc7, 0x0fbf0132,
- 0x01300fca, 0x0fba014c, 0x01170fce, 0x0fb80163,
- 0x00fd0fd4, 0x0fb5017a, 0x00e20fda, 0x0fb5018f,
- 0x00c80fdd, 0x0fb401a7, 0x00ae0fe4, 0x0fb401ba,
- 0x00960fe8, 0x0fb601cc, 0x007c0fee, 0x0fba01dc,
- 0x00650ff2, 0x0fc001e9, 0x00500ff6, 0x0fc701f3,
- 0x003b0ffa, 0x0fcf01fc, 0x00290ffc, 0x0fda0201,
- 0x00180000, 0x0fe40204, 0x000a0000, 0x0ff20204,
- 0x02000000, 0x00000000, 0x02030ff5, 0x00000008,
- 0x02030fea, 0x00000013, 0x02020fe1, 0x0ffd0020,
- 0x01fc0fd9, 0x0ffc002f, 0x01f60fd2, 0x0ff80040,
- 0x01ed0fcd, 0x0ff50051, 0x01e30fc7, 0x0ff10065,
- 0x01d70fc3, 0x0fec007a, 0x01c60fc2, 0x0fe9008f,
- 0x01b60fc1, 0x0fe300a6, 0x01a20fc1, 0x0fe000bd,
- 0x018f0fc1, 0x0fdb00d5, 0x017b0fc2, 0x0fd500ee,
- 0x01640fc4, 0x0fd20106, 0x014d0fc8, 0x0fce011d,
- 0x01370fc9, 0x0fc90137, 0x011d0fce, 0x0fc8014d,
- 0x01060fd2, 0x0fc40164, 0x00ee0fd5, 0x0fc2017b,
- 0x00d50fdb, 0x0fc1018f, 0x00bd0fe0, 0x0fc101a2,
- 0x00a60fe3, 0x0fc101b6, 0x008f0fe9, 0x0fc201c6,
- 0x007a0fec, 0x0fc301d7, 0x00650ff1, 0x0fc701e3,
- 0x00510ff5, 0x0fcd01ed, 0x00400ff8, 0x0fd201f6,
- 0x002f0ffc, 0x0fd901fc, 0x00200ffd, 0x0fe10202,
- 0x00130000, 0x0fea0203, 0x00080000, 0x0ff50203,
- 0x02000000, 0x00000000, 0x02020ff5, 0x00000009,
- 0x01ff0fea, 0x00000017, 0x01fb0fe2, 0x0ffd0026,
- 0x01f30fda, 0x0ffc0037, 0x01ea0fd3, 0x0ff8004b,
- 0x01df0fce, 0x0ff5005e, 0x01d10fc9, 0x0ff20074,
- 0x01c10fc6, 0x0fed008c, 0x01ae0fc5, 0x0fea00a3,
- 0x019b0fc5, 0x0fe500bb, 0x01850fc6, 0x0fe200d3,
- 0x01700fc6, 0x0fde00ec, 0x015a0fc8, 0x0fd90105,
- 0x01430fca, 0x0fd6011d, 0x012b0fcd, 0x0fd30135,
- 0x01150fcf, 0x0fcf014d, 0x00fc0fd4, 0x0fce0162,
- 0x00e50fd8, 0x0fcc0177, 0x00cf0fdb, 0x0fca018c,
- 0x00b80fe0, 0x0fc9019f, 0x00a20fe5, 0x0fca01af,
- 0x008e0fe8, 0x0fcb01bf, 0x00790fec, 0x0fcb01d0,
- 0x00670fef, 0x0fcd01dd, 0x00550ff4, 0x0fd001e7,
- 0x00440ff7, 0x0fd501f0, 0x00350ffa, 0x0fda01f7,
- 0x00270ffc, 0x0fdf01fe, 0x001b0ffe, 0x0fe70200,
- 0x00100000, 0x0fee0202, 0x00060000, 0x0ff70203,
- 0x02000000, 0x00000000, 0x01ff0ff5, 0x0000000c,
- 0x01f80fea, 0x0000001e, 0x01ef0fe2, 0x0ffd0032,
- 0x01e20fdb, 0x0ffc0047, 0x01d30fd5, 0x0ff9005f,
- 0x01c20fd1, 0x0ff60077, 0x01b00fcd, 0x0ff30090,
- 0x019b0fcb, 0x0fef00ab, 0x01850fcb, 0x0fec00c4,
- 0x016e0fcc, 0x0fe800de, 0x01550fcd, 0x0fe600f8,
- 0x013f0fce, 0x0fe20111, 0x01280fd0, 0x0fdf0129,
- 0x01110fd2, 0x0fdd0140, 0x00f90fd6, 0x0fdb0156,
- 0x00e40fd8, 0x0fd8016c, 0x00cd0fdd, 0x0fd8017e,
- 0x00b80fe0, 0x0fd60192, 0x00a40fe3, 0x0fd601a3,
- 0x00910fe7, 0x0fd501b3, 0x007f0feb, 0x0fd601c0,
- 0x006e0fed, 0x0fd701ce, 0x005d0ff1, 0x0fd701db,
- 0x004f0ff3, 0x0fd901e5, 0x00400ff7, 0x0fdc01ed,
- 0x00330ff9, 0x0fe001f4, 0x00280ffb, 0x0fe301fa,
- 0x001d0ffd, 0x0fe801fe, 0x00140ffe, 0x0fed0201,
- 0x000c0000, 0x0ff20202, 0x00050000, 0x0ff90202,
- 0x02000000, 0x00000000, 0x02040ff7, 0x00000005,
- 0x02070fed, 0x0000000c, 0x02060fe6, 0x0ffe0016,
- 0x02050fdf, 0x0ffc0020, 0x02020fd9, 0x0ff9002c,
- 0x01fe0fd4, 0x0ff60038, 0x01f80fcf, 0x0ff30046,
- 0x01f00fcb, 0x0fef0056, 0x01e70fc8, 0x0feb0066,
- 0x01db0fc7, 0x0fe60078, 0x01cc0fc6, 0x0fe3008b,
- 0x01bf0fc5, 0x0fdd009f, 0x01ae0fc6, 0x0fd800b4,
- 0x019c0fc6, 0x0fd400ca, 0x01880fc9, 0x0fcf00e0,
- 0x01750fc9, 0x0fc900f9, 0x015d0fce, 0x0fc6010f,
- 0x01460fd0, 0x0fc20128, 0x012e0fd3, 0x0fbf0140,
- 0x01140fd8, 0x0fbc0158, 0x00f90fdd, 0x0fbb016f,
- 0x00df0fe0, 0x0fba0187, 0x00c40fe5, 0x0fb9019e,
- 0x00aa0fe9, 0x0fba01b3, 0x008e0fef, 0x0fbd01c6,
- 0x00740ff3, 0x0fc301d6, 0x005d0ff6, 0x0fc801e5,
- 0x00450ffa, 0x0fd001f1, 0x00300ffc, 0x0fda01fa,
- 0x001c0000, 0x0fe40200, 0x000c0000, 0x0ff20202,
- 0x02000000, 0x00000000, 0x02030ff7, 0x00000006,
- 0x02020fee, 0x00000010, 0x02000fe7, 0x0ffe001b,
- 0x01fe0fdf, 0x0ffc0027, 0x01f70fda, 0x0ffa0035,
- 0x01f00fd5, 0x0ff70044, 0x01e70fd0, 0x0ff40055,
- 0x01dd0fcd, 0x0fef0067, 0x01d00fcb, 0x0fec0079,
- 0x01bf0fcb, 0x0fe8008e, 0x01af0fca, 0x0fe500a2,
- 0x019f0fc9, 0x0fe000b8, 0x018c0fca, 0x0fdb00cf,
- 0x01770fcc, 0x0fd800e5, 0x01620fce, 0x0fd400fc,
- 0x014d0fcf, 0x0fcf0115, 0x01350fd3, 0x0fcd012b,
- 0x011d0fd6, 0x0fca0143, 0x01050fd9, 0x0fc8015a,
- 0x00ec0fde, 0x0fc60170, 0x00d30fe2, 0x0fc60185,
- 0x00bb0fe5, 0x0fc5019b, 0x00a30fea, 0x0fc501ae,
- 0x008c0fed, 0x0fc601c1, 0x00740ff2, 0x0fc901d1,
- 0x005e0ff5, 0x0fce01df, 0x004b0ff8, 0x0fd301ea,
- 0x00370ffc, 0x0fda01f3, 0x00260ffd, 0x0fe201fb,
- 0x00170000, 0x0fea01ff, 0x00090000, 0x0ff50202,
- 0x02000000, 0x00000000, 0x02010ff7, 0x00000008,
- 0x01ff0fee, 0x00000013, 0x01fb0fe7, 0x0ffe0020,
- 0x01f60fe0, 0x0ffc002e, 0x01ed0fda, 0x0ffa003f,
- 0x01e40fd6, 0x0ff7004f, 0x01d80fd2, 0x0ff40062,
- 0x01ca0fcf, 0x0ff00077, 0x01bb0fcd, 0x0fed008b,
- 0x01a90fcd, 0x0fe900a1, 0x01960fcd, 0x0fe600b7,
- 0x01830fcd, 0x0fe200ce, 0x016d0fcf, 0x0fde00e6,
- 0x01580fd0, 0x0fdb00fd, 0x01410fd3, 0x0fd80114,
- 0x012c0fd4, 0x0fd4012c, 0x01140fd8, 0x0fd30141,
- 0x00fd0fdb, 0x0fd00158, 0x00e60fde, 0x0fcf016d,
- 0x00ce0fe2, 0x0fcd0183, 0x00b70fe6, 0x0fcd0196,
- 0x00a10fe9, 0x0fcd01a9, 0x008b0fed, 0x0fcd01bb,
- 0x00770ff0, 0x0fcf01ca, 0x00620ff4, 0x0fd201d8,
- 0x004f0ff7, 0x0fd601e4, 0x003f0ffa, 0x0fda01ed,
- 0x002e0ffc, 0x0fe001f6, 0x00200ffe, 0x0fe701fb,
- 0x00130000, 0x0fee01ff, 0x00080000, 0x0ff70201,
- 0x02000000, 0x00000000, 0x01ff0ff7, 0x0000000a,
- 0x01f90fee, 0x00000019, 0x01f10fe7, 0x0ffe002a,
- 0x01e60fe1, 0x0ffd003c, 0x01d90fdc, 0x0ffa0051,
- 0x01cc0fd8, 0x0ff70065, 0x01bb0fd5, 0x0ff5007b,
- 0x01a80fd3, 0x0ff10094, 0x01950fd2, 0x0fef00aa,
- 0x01800fd2, 0x0feb00c3, 0x016a0fd3, 0x0fe900da,
- 0x01540fd3, 0x0fe600f3, 0x013f0fd5, 0x0fe2010a,
- 0x01280fd7, 0x0fe00121, 0x01100fda, 0x0fde0138,
- 0x00fb0fdb, 0x0fdb014f, 0x00e40fdf, 0x0fdb0162,
- 0x00ce0fe2, 0x0fd90177, 0x00b90fe4, 0x0fd8018b,
- 0x00a50fe8, 0x0fd8019b, 0x00910fec, 0x0fd801ab,
- 0x007e0fee, 0x0fd801bc, 0x006c0ff2, 0x0fd901c9,
- 0x005c0ff4, 0x0fda01d6, 0x004b0ff7, 0x0fdd01e1,
- 0x003c0ff9, 0x0fe001eb, 0x002f0ffb, 0x0fe401f2,
- 0x00230ffd, 0x0fe801f8, 0x00180ffe, 0x0fed01fd,
- 0x000e0000, 0x0ff20200, 0x00060000, 0x0ff90201,
- 0x02000000, 0x00000000, 0x02030ff9, 0x00000004,
- 0x02050ff2, 0x00000009, 0x02050fed, 0x0ffe0010,
- 0x02040fe7, 0x0ffd0018, 0x02020fe3, 0x0ffb0020,
- 0x01fe0fdf, 0x0ff9002a, 0x01fa0fdb, 0x0ff70034,
- 0x01f40fd8, 0x0ff30041, 0x01ed0fd6, 0x0ff0004d,
- 0x01e30fd5, 0x0fec005c, 0x01d80fd4, 0x0fea006a,
- 0x01cd0fd3, 0x0fe5007b, 0x01c00fd3, 0x0fe1008c,
- 0x01b10fd3, 0x0fdd009f, 0x01a10fd4, 0x0fd900b2,
- 0x01900fd4, 0x0fd400c8, 0x017b0fd7, 0x0fd100dd,
- 0x01660fd9, 0x0fcd00f4, 0x01500fda, 0x0fca010c,
- 0x01380fde, 0x0fc60124, 0x011e0fe2, 0x0fc5013b,
- 0x01040fe4, 0x0fc30155, 0x00e70fe8, 0x0fc10170,
- 0x00cc0feb, 0x0fc10188, 0x00ad0ff0, 0x0fc301a0,
- 0x00900ff4, 0x0fc701b5, 0x00750ff7, 0x0fcc01c8,
- 0x00580ffb, 0x0fd201db, 0x003e0ffd, 0x0fdb01ea,
- 0x00250000, 0x0fe501f6, 0x000f0000, 0x0ff301fe,
- 0x02000000, 0x00000000, 0x02020ff9, 0x00000005,
- 0x02020ff2, 0x0000000c, 0x02010fed, 0x0ffe0014,
- 0x01fe0fe8, 0x0ffd001d, 0x01fa0fe3, 0x0ffb0028,
- 0x01f40fe0, 0x0ff90033, 0x01ed0fdc, 0x0ff70040,
- 0x01e50fd9, 0x0ff3004f, 0x01db0fd7, 0x0ff1005d,
- 0x01ce0fd7, 0x0fed006e, 0x01c00fd6, 0x0feb007f,
- 0x01b30fd5, 0x0fe70091, 0x01a30fd6, 0x0fe300a4,
- 0x01920fd6, 0x0fe000b8, 0x017e0fd8, 0x0fdd00cd,
- 0x016c0fd8, 0x0fd800e4, 0x01560fdb, 0x0fd600f9,
- 0x01400fdd, 0x0fd20111, 0x01290fdf, 0x0fd00128,
- 0x01110fe2, 0x0fce013f, 0x00f80fe6, 0x0fcd0155,
- 0x00de0fe8, 0x0fcc016e, 0x00c40fec, 0x0fcb0185,
- 0x00ab0fef, 0x0fcb019b, 0x00900ff3, 0x0fcd01b0,
- 0x00770ff6, 0x0fd101c2, 0x005f0ff9, 0x0fd501d3,
- 0x00470ffc, 0x0fdb01e2, 0x00320ffd, 0x0fe201ef,
- 0x001e0000, 0x0fea01f8, 0x000c0000, 0x0ff501ff,
- 0x02000000, 0x00000000, 0x02010ff9, 0x00000006,
- 0x02000ff2, 0x0000000e, 0x01fd0fed, 0x0ffe0018,
- 0x01f80fe8, 0x0ffd0023, 0x01f20fe4, 0x0ffb002f,
- 0x01eb0fe0, 0x0ff9003c, 0x01e10fdd, 0x0ff7004b,
- 0x01d60fda, 0x0ff4005c, 0x01c90fd9, 0x0ff2006c,
- 0x01bc0fd8, 0x0fee007e, 0x01ab0fd8, 0x0fec0091,
- 0x019b0fd8, 0x0fe800a5, 0x018b0fd8, 0x0fe400b9,
- 0x01770fd9, 0x0fe200ce, 0x01620fdb, 0x0fdf00e4,
- 0x014f0fdb, 0x0fdb00fb, 0x01380fde, 0x0fda0110,
- 0x01210fe0, 0x0fd70128, 0x010a0fe2, 0x0fd5013f,
- 0x00f30fe6, 0x0fd30154, 0x00da0fe9, 0x0fd3016a,
- 0x00c30feb, 0x0fd20180, 0x00aa0fef, 0x0fd20195,
- 0x00940ff1, 0x0fd301a8, 0x007b0ff5, 0x0fd501bb,
- 0x00650ff7, 0x0fd801cc, 0x00510ffa, 0x0fdc01d9,
- 0x003c0ffd, 0x0fe101e6, 0x002a0ffe, 0x0fe701f1,
- 0x00190000, 0x0fee01f9, 0x000a0000, 0x0ff701ff,
+
+ 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,
@@ -870,7 +863,262 @@
0x00740ff4, 0x0fdc01bc, 0x00600ff7, 0x0fde01cb,
0x004e0ff9, 0x0fe101d8, 0x003e0ffb, 0x0fe401e3,
0x002e0ffd, 0x0fe801ed, 0x00200ffe, 0x0fed01f5,
- 0x00130000, 0x0ff201fb, 0x00080000, 0x0ff901ff
+ 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
};
@@ -878,71 +1126,202 @@
#define MDP4_QSEED_TABLE1_OFF 0x8200
#define MDP4_QSEED_TABLE2_OFF 0x9000
-void mdp4_vg_qseed_init(struct mdp_info *mdp, int vp_num)
+void mdp4_vg_qseed_init(int vp_num)
{
- uint32_t off;
+ uint32 *off;
int i, voff;
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
voff = MDP4_VIDEO_OFF * vp_num;
- off = MDP4_VIDEO_BASE + voff + MDP4_QSEED_TABLE0_OFF;
- for (i = 0; i < (sizeof(vg_qseed_table0) / sizeof(uint32_t)); i++) {
- mdp_writel(mdp, vg_qseed_table0[i], off);
- off += 4;
+ 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 = MDP4_VIDEO_BASE + voff + MDP4_QSEED_TABLE1_OFF;
- for (i = 0; i < (sizeof(vg_qseed_table1) / sizeof(uint32_t)); i++) {
- mdp_writel(mdp, vg_qseed_table1[i], off);
- off += 4;
+ 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 = MDP4_VIDEO_BASE + voff + MDP4_QSEED_TABLE2_OFF;
- for (i = 0; i < (sizeof(vg_qseed_table2) / sizeof(uint32_t)); i++) {
- mdp_writel(mdp, vg_qseed_table2[i], off);
- off += 4;
+ 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(struct mdp_info *mdp, int mixer_num)
+void mdp4_mixer_blend_init(mixer_num)
{
- unsigned long overlay_base;
+ unsigned char *overlay_base;
int off;
if (mixer_num) /* mixer number, /dev/fb0, /dev/fb1 */
- overlay_base = MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
else
- overlay_base = MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+ 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;
- mdp_writel(mdp, 0x010, overlay_base + off + 0x104);
- mdp_writel(mdp, 0xff, overlay_base + off + 0x108);/* FG */
- mdp_writel(mdp, 0x00, overlay_base + off + 0x10c);/* BG */
+ outpdw(overlay_base + off + 0x104, 0x010);
+ outpdw(overlay_base + off + 0x108, 0xff);/* FG */
+ outpdw(overlay_base + off + 0x10c, 0x00);/* BG */
off += 0x20;
- mdp_writel(mdp, 0x010, overlay_base + off + 0x104);
- mdp_writel(mdp, 0xff, overlay_base + off + 0x108);/* FG */
- mdp_writel(mdp, 0x00, overlay_base + off + 0x10c);/* BG */
+ outpdw(overlay_base + off + 0x104, 0x010);
+ outpdw(overlay_base + off + 0x108, 0xff);/* FG */
+ outpdw(overlay_base + off + 0x10c, 0x00);/* BG */
off += 0x20;
- mdp_writel(mdp, 0x010, overlay_base + off + 0x104);
- mdp_writel(mdp, 0xff, overlay_base + off + 0x108);/* FG */
- mdp_writel(mdp, 0x00, overlay_base + off + 0x10c);/* BG */
+ 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_t csc_matrix_tab[9] = {
- 0x0254, 0x0000, 0x0331,
- 0x0254, 0xff37, 0xfe60,
- 0x0254, 0x0409, 0x0000
+struct mdp_csc_cfg mdp_csc_convert[4] = {
+ { /*RGB2RGB*/
+ 0,
+ {
+ 0x0200, 0x0000, 0x0000,
+ 0x0000, 0x0200, 0x0000,
+ 0x0000, 0x0000, 0x0200,
+ },
+ { 0x0, 0x0, 0x0, },
+ { 0x0, 0x0, 0x0, },
+ { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, },
+ { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, },
+ },
+ { /*YUV2RGB*/
+ 0,
+ {
+ 0x0254, 0x0000, 0x0331,
+ 0x0254, 0xff37, 0xfe60,
+ 0x0254, 0x0409, 0x0000,
+ },
+ { 0xfff0, 0xff80, 0xff80, },
+ { 0x0, 0x0, 0x0, },
+ { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, },
+ { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, },
+ },
+ { /*RGB2YUV*/
+ 0,
+ {
+ 0x0083, 0x0102, 0x0032,
+ 0x1fb5, 0x1f6c, 0x00e1,
+ 0x00e1, 0x1f45, 0x1fdc
+ },
+ { 0x0, 0x0, 0x0, },
+ { 0x0010, 0x0080, 0x0080, },
+ { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, },
+ { 0x0010, 0x00eb, 0x0010, 0x00f0, 0x0010, 0x00f0, },
+ },
+ { /*YUV2YUV ???*/
+ 0,
+ {
+ 0x0200, 0x0000, 0x0000,
+ 0x0000, 0x0200, 0x0000,
+ 0x0000, 0x0000, 0x0200,
+ },
+ { 0x0, 0x0, 0x0, },
+ { 0x0, 0x0, 0x0, },
+ { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, },
+ { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, },
+ },
};
-static uint32_t csc_pre_bv_tab[3] = {0xfff0, 0xff80, 0xff80 };
-static uint32_t csc_post_bv_tab[3] = {0, 0, 0 };
+struct mdp_csc_cfg csc_matrix[3] = {
+ {
+ (MDP_CSC_FLAG_YUV_OUT),
+ {
+ 0x0254, 0x0000, 0x0331,
+ 0x0254, 0xff37, 0xfe60,
+ 0x0254, 0x0409, 0x0000,
+ },
+ {
+ 0xfff0, 0xff80, 0xff80,
+ },
+ {
+ 0, 0, 0,
+ },
+ {
+ 0, 0xff, 0, 0xff, 0, 0xff,
+ },
+ {
+ 0, 0xff, 0, 0xff, 0, 0xff,
+ },
+ },
+ {
+ (MDP_CSC_FLAG_YUV_OUT),
+ {
+ 0x0254, 0x0000, 0x0331,
+ 0x0254, 0xff37, 0xfe60,
+ 0x0254, 0x0409, 0x0000,
+ },
+ {
+ 0xfff0, 0xff80, 0xff80,
+ },
+ {
+ 0, 0, 0,
+ },
+ {
+ 0, 0xff, 0, 0xff, 0, 0xff,
+ },
+ {
+ 0, 0xff, 0, 0xff, 0, 0xff,
+ },
+ },
+ {
+ (0),
+ {
+ 0x0200, 0x0000, 0x0000,
+ 0x0000, 0x0200, 0x0000,
+ 0x0000, 0x0000, 0x0200,
+ },
+ {
+ 0x0, 0x0, 0x0,
+ },
+ {
+ 0, 0, 0,
+ },
+ {
+ 0, 0xff, 0, 0xff, 0, 0xff,
+ },
+ {
+ 0, 0xff, 0, 0xff, 0, 0xff,
+ },
+ },
+};
-static uint32_t csc_pre_lv_tab[6] = {0, 0xff, 0, 0xff, 0, 0xff };
-static uint32_t csc_post_lv_tab[6] = {0, 0xff, 0, 0xff, 0, 0xff };
+
#define MDP4_CSC_MV_OFF 0x4400
#define MDP4_CSC_PRE_BV_OFF 0x4500
@@ -950,158 +1329,352 @@
#define MDP4_CSC_PRE_LV_OFF 0x4600
#define MDP4_CSC_POST_LV_OFF 0x4680
-void mdp4_vg_csc_mv_setup(struct mdp_info *mdp, int vp_num)
+void mdp4_vg_csc_mv_setup(int vp_num)
{
- uint32_t off;
+ uint32 *off;
int i, voff;
voff = MDP4_VIDEO_OFF * vp_num;
- off = MDP4_VIDEO_BASE + voff + MDP4_CSC_MV_OFF;
+ 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++) {
- mdp_writel(mdp, csc_matrix_tab[i], off);
- off += 4;
+ outpdw(off, csc_matrix[vp_num].csc_mv[i]);
+ off++;
}
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
-void mdp4_vg_csc_pre_bv_setup(struct mdp_info *mdp, int vp_num)
+void mdp4_vg_csc_pre_bv_setup(int vp_num)
{
- uint32_t off;
+ uint32 *off;
int i, voff;
voff = MDP4_VIDEO_OFF * vp_num;
- off = MDP4_VIDEO_BASE + voff + MDP4_CSC_PRE_BV_OFF;
+ 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++) {
- mdp_writel(mdp, csc_pre_bv_tab[i], off);
- off += 4;
+ outpdw(off, csc_matrix[vp_num].csc_pre_bv[i]);
+ off++;
}
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
-void mdp4_vg_csc_post_bv_setup(struct mdp_info *mdp, int vp_num)
+void mdp4_vg_csc_post_bv_setup(int vp_num)
{
- uint32_t off;
+ uint32 *off;
int i, voff;
voff = MDP4_VIDEO_OFF * vp_num;
- off = MDP4_VIDEO_BASE + voff + MDP4_CSC_POST_BV_OFF;
+ 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++) {
- mdp_writel(mdp, csc_post_bv_tab[i], off);
- off += 4;
+ outpdw(off, csc_matrix[vp_num].csc_post_bv[i]);
+ off++;
}
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
-void mdp4_vg_csc_pre_lv_setup(struct mdp_info *mdp, int vp_num)
+void mdp4_vg_csc_pre_lv_setup(int vp_num)
{
- uint32_t off;
+ uint32 *off;
int i, voff;
voff = MDP4_VIDEO_OFF * vp_num;
- off = MDP4_VIDEO_BASE + voff + MDP4_CSC_PRE_LV_OFF;
+ 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++) {
- mdp_writel(mdp, csc_pre_lv_tab[i], off);
- off += 4;
+ outpdw(off, csc_matrix[vp_num].csc_pre_lv[i]);
+ off++;
}
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
-void mdp4_vg_csc_post_lv_setup(struct mdp_info *mdp, int vp_num)
+void mdp4_vg_csc_post_lv_setup(int vp_num)
{
- uint32_t off;
+ uint32 *off;
int i, voff;
voff = MDP4_VIDEO_OFF * vp_num;
- off = MDP4_VIDEO_BASE + voff + MDP4_CSC_POST_LV_OFF;
+ 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++) {
- mdp_writel(mdp, csc_post_lv_tab[i], off);
- off += 4;
+ outpdw(off, csc_matrix[vp_num].csc_post_lv[i]);
+ off++;
}
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
-static uint32_t csc_rgb2yuv_matrix_tab[9] = {
+void mdp4_vg_csc_convert_setup(int vp_num)
+{
+ struct mdp_csc_cfg_data cfg;
+
+ switch (vp_num) {
+ case 0:
+ cfg.block = MDP_BLOCK_VG_1;
+ break;
+ case 1:
+ cfg.block = MDP_BLOCK_VG_2;
+ break;
+ default:
+ pr_err("%s - invalid vp_num = %d", __func__, vp_num);
+ return;
+ }
+ cfg.csc_data = csc_matrix[vp_num];
+ mdp4_csc_enable(&cfg);
+}
+
+void mdp4_vg_csc_setup(int vp_num)
+{
+ /* yuv2rgb */
+ mdp4_vg_csc_mv_setup(vp_num);
+ mdp4_vg_csc_pre_bv_setup(vp_num);
+ mdp4_vg_csc_post_bv_setup(vp_num);
+ mdp4_vg_csc_pre_lv_setup(vp_num);
+ mdp4_vg_csc_post_lv_setup(vp_num);
+ mdp4_vg_csc_convert_setup(vp_num);
+}
+void mdp4_vg_csc_update(struct mdp_csc *p)
+{
+ struct mdp4_overlay_pipe *pipe;
+ int vp_num;
+
+ pipe = mdp4_overlay_ndx2pipe(p->id);
+ if (pipe == NULL) {
+ pr_err("%s: p->id = %d Error\n", __func__, p->id);
+ return;
+ }
+
+ vp_num = pipe->pipe_num - OVERLAY_PIPE_VG1;
+
+ if (vp_num == 0 || vp_num == 1) {
+ memcpy(csc_matrix[vp_num].csc_mv, p->csc_mv, sizeof(p->csc_mv));
+ memcpy(csc_matrix[vp_num].csc_pre_bv, p->csc_pre_bv,
+ sizeof(p->csc_pre_bv));
+ memcpy(csc_matrix[vp_num].csc_post_bv, p->csc_post_bv,
+ sizeof(p->csc_post_bv));
+ memcpy(csc_matrix[vp_num].csc_pre_lv, p->csc_pre_lv,
+ sizeof(p->csc_pre_lv));
+ memcpy(csc_matrix[vp_num].csc_post_lv, p->csc_post_lv,
+ sizeof(p->csc_post_lv));
+ mdp4_vg_csc_setup(vp_num);
+ }
+}
+static uint32 csc_rgb2yuv_matrix_tab[9] = {
0x0083, 0x0102, 0x0032,
- 0xffb5, 0xff6c, 0x00e1,
- 0x00e1, 0xff45, 0xffdc
+ 0x1fb5, 0x1f6c, 0x00e1,
+ 0x00e1, 0x1f45, 0x1fdc
};
-static uint32_t csc_rgb2yuv_pre_bv_tab[3] = {0, 0, 0};
+static uint32 csc_rgb2yuv_pre_bv_tab[3] = {0, 0, 0};
-static uint32_t csc_rgb2yuv_post_bv_tab[3] = {0x0010, 0x0080, 0x0080};
+static uint32 csc_rgb2yuv_post_bv_tab[3] = {0x0010, 0x0080, 0x0080};
-static uint32_t csc_rgb2yuv_pre_lv_tab[6] = {
+static uint32 csc_rgb2yuv_pre_lv_tab[6] = {
0x00, 0xff, 0x00,
0xff, 0x00, 0xff
};
-static uint32_t csc_rgb2yuv_post_lv_tab[6] = {
+static uint32 csc_rgb2yuv_post_lv_tab[6] = {
0x0010, 0x00eb, 0x0010,
0x00f0, 0x0010, 0x00f0
};
-void mdp4_mixer1_csc_mv_setup(struct mdp_info *mdp)
+void mdp4_mixer_csc_mv_setup(uint32 mixer)
{
- uint32_t off;
+ uint32 *off;
int i;
- off = MDP4_OVERLAYPROC1_BASE + 0x2400;
+ if (mixer == MDP4_MIXER1)
+ off = (uint32 *)(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x2400);
+ else
+ off = (uint32 *)(MDP_BASE + MDP4_OVERLAYPROC2_BASE + 0x2400);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
for (i = 0; i < 9; i++) {
- mdp_writel(mdp, csc_rgb2yuv_matrix_tab[i], off);
- off += 4;
+ 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(struct mdp_info *mdp)
+void mdp4_mixer_csc_pre_bv_setup(uint32 mixer)
{
- uint32_t off;
+ uint32 *off;
int i;
- off = MDP4_OVERLAYPROC1_BASE + 0x2500;
+ if (mixer == MDP4_MIXER1)
+ off = (uint32 *)(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x2500);
+ else
+ off = (uint32 *)(MDP_BASE + MDP4_OVERLAYPROC2_BASE + 0x2500);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
for (i = 0; i < 3; i++) {
- mdp_writel(mdp, csc_rgb2yuv_pre_bv_tab[i], off);
- off += 4;
+ 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(struct mdp_info *mdp)
+void mdp4_mixer_csc_post_bv_setup(uint32 mixer)
{
- uint32_t off;
+ uint32 *off;
int i;
- off = MDP4_OVERLAYPROC1_BASE + 0x2580;
+ if (mixer == MDP4_MIXER1)
+ off = (uint32 *)(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x2580);
+ else
+ off = (uint32 *)(MDP_BASE + MDP4_OVERLAYPROC2_BASE + 0x2580);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
for (i = 0; i < 3; i++) {
- mdp_writel(mdp, csc_rgb2yuv_post_bv_tab[i], off);
- off += 4;
+ 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(struct mdp_info *mdp)
+void mdp4_mixer_csc_pre_lv_setup(uint32 mixer)
{
- uint32_t off;
+ uint32 *off;
int i;
- off = MDP4_OVERLAYPROC1_BASE + 0x2600;
+ if (mixer == MDP4_MIXER1)
+ off = (uint32 *)(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x2600);
+ else
+ off = (uint32 *)(MDP_BASE + MDP4_OVERLAYPROC2_BASE + 0x2600);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
for (i = 0; i < 6; i++) {
- mdp_writel(mdp, csc_rgb2yuv_pre_lv_tab[i], off);
- off += 4;
+ 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(struct mdp_info *mdp)
+void mdp4_mixer_csc_post_lv_setup(uint32 mixer)
{
- uint32_t off;
+ uint32 *off;
int i;
- off = MDP4_OVERLAYPROC1_BASE + 0x2680;
+ if (mixer == MDP4_MIXER1)
+ off = (uint32 *)(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x2680);
+ else
+ off = (uint32 *)(MDP_BASE + MDP4_OVERLAYPROC2_BASE + 0x2680);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
for (i = 0; i < 6; i++) {
- mdp_writel(mdp, csc_rgb2yuv_post_lv_tab[i], off);
- off += 4;
+ outpdw(off, csc_rgb2yuv_post_lv_tab[i]);
+ off++;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_mixer_csc_setup(uint32 mixer)
+{
+ if (mixer >= MDP4_MIXER1) {
+ /* rgb2yuv */
+ mdp4_mixer_csc_mv_setup(mixer);
+ mdp4_mixer_csc_pre_bv_setup(mixer);
+ mdp4_mixer_csc_post_bv_setup(mixer);
+ mdp4_mixer_csc_pre_lv_setup(mixer);
+ mdp4_mixer_csc_post_lv_setup(mixer);
}
}
+#define DMA_P_BASE 0x90000
+void mdp4_dmap_csc_mv_setup(void)
+{
+ uint32 *off;
+ int i;
+
+ off = (uint32 *)(MDP_BASE + DMA_P_BASE + 0x3400);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ for (i = 0; i < 9; i++) {
+ outpdw(off, csc_matrix[2].csc_mv[i]);
+ off++;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_dmap_csc_pre_bv_setup(void)
+{
+ uint32 *off;
+ int i;
+
+ off = (uint32 *)(MDP_BASE + DMA_P_BASE + 0x3500);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ for (i = 0; i < 3; i++) {
+ outpdw(off, csc_matrix[2].csc_pre_bv[i]);
+ off++;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_dmap_csc_post_bv_setup(void)
+{
+ uint32 *off;
+ int i;
+
+ off = (uint32 *)(MDP_BASE + DMA_P_BASE + 0x3580);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ for (i = 0; i < 3; i++) {
+ outpdw(off, csc_matrix[2].csc_post_bv[i]);
+ off++;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_dmap_csc_pre_lv_setup(void)
+{
+ uint32 *off;
+ int i;
+
+ off = (uint32 *)(MDP_BASE + DMA_P_BASE + 0x3600);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ for (i = 0; i < 6; i++) {
+ outpdw(off, csc_matrix[2].csc_pre_lv[i]);
+ off++;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_dmap_csc_post_lv_setup(void)
+{
+ uint32 *off;
+ int i;
+
+ off = (uint32 *)(MDP_BASE + DMA_P_BASE + 0x3680);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ for (i = 0; i < 6; i++) {
+ outpdw(off, csc_matrix[2].csc_post_lv[i]);
+ off++;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp4_dmap_csc_setup(void)
+{
+ mdp4_dmap_csc_mv_setup();
+ mdp4_dmap_csc_pre_bv_setup();
+ mdp4_dmap_csc_post_bv_setup();
+ mdp4_dmap_csc_pre_lv_setup();
+ mdp4_dmap_csc_post_lv_setup();
+}
char gc_lut[] = {
0x0, 0x1, 0x2, 0x2, 0x3, 0x4, 0x5, 0x6,
@@ -1618,30 +2191,32 @@
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
};
-void mdp4_mixer_gc_lut_setup(struct mdp_info *mdp, int mixer_num)
+void mdp4_mixer_gc_lut_setup(int mixer_num)
{
- unsigned long base;
- uint32_t data;
+ unsigned char *base;
+ uint32 data;
char val;
int i, off;
if (mixer_num) /* mixer number, /dev/fb0, /dev/fb1 */
- base = MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
+ base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
else
- base = MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+ 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 */
- mdp_writel(mdp, data, base + off);
+ outpdw(base + off, data);
off += 4;
}
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
-uint32_t igc_video_lut[] = { /* non linear */
+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,
@@ -1676,26 +2251,28 @@
0xF04, 0xF27, 0xF4B, 0xF6E, 0xF92, 0xFB6, 0xFDB, 0xFFF,
};
-void mdp4_vg_igc_lut_setup(struct mdp_info *mdp, int vp_num)
+void mdp4_vg_igc_lut_setup(int vp_num)
{
- unsigned long base;
+ unsigned char *base;
int i, voff, off;
- uint32_t data, val;
+ uint32 data, val;
voff = MDP4_VIDEO_OFF * vp_num;
- base = MDP4_VIDEO_BASE + voff + 0x5000;
+ 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 */
- mdp_writel(mdp, data, base + off);
- mdp_writel(mdp, val, base + off + 0x800); /* color 2 */
+ 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_t igc_rgb_lut[] = { /* linear */
+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,
@@ -1730,26 +2307,875 @@
0xF8F, 0xF9F, 0xFAF, 0xFBF, 0xFCF, 0xFDF, 0xFEF, 0xFFF,
};
-void mdp4_rgb_igc_lut_setup(struct mdp_info *mdp, int num)
+void mdp4_rgb_igc_lut_setup(int num)
{
- unsigned long base;
+ unsigned char *base;
int i, voff, off;
- uint32_t data, val;
+ uint32 data, val;
voff = MDP4_RGB_OFF * num;
- base = MDP4_RGB_BASE + voff + 0x5000;
+ 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 */
- mdp_writel(mdp, data, base + off);
- mdp_writel(mdp, val, base + off + 0x800); /* color 2 */
+ 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;
+}
+
+static uint32_t mdp4_csc_block2base(uint32_t block)
+{
+ uint32_t base = 0x0;
+ switch (block) {
+ case MDP_BLOCK_OVERLAY_1:
+ base = 0x1A000;
+ break;
+ case MDP_BLOCK_OVERLAY_2:
+ base = (mdp_rev >= MDP_REV_44) ? 0x8A000 : 0x0;
+ break;
+ case MDP_BLOCK_VG_1:
+ base = 0x24000;
+ break;
+ case MDP_BLOCK_VG_2:
+ base = 0x34000;
+ break;
+ case MDP_BLOCK_DMA_P:
+ base = 0x93000;
+ break;
+ case MDP_BLOCK_DMA_S:
+ base = (mdp_rev >= MDP_REV_42) ? 0xA3000 : 0x0;
+ default:
+ break;
+ }
+ return base;
+}
+
+int mdp4_csc_enable(struct mdp_csc_cfg_data *config)
+{
+ uint32_t output, base, temp, mask;
+
+ switch (config->block) {
+ case MDP_BLOCK_DMA_P:
+ base = 0x90070;
+ output = (config->csc_data.flags << 3) & (0x08);
+ temp = (config->csc_data.flags << 10) & (0x1800);
+ output |= temp;
+ mask = 0x08 | 0x1800;
+ break;
+ case MDP_BLOCK_DMA_S:
+ base = 0xA0028;
+ output = (config->csc_data.flags << 3) & (0x08);
+ temp = (config->csc_data.flags << 10) & (0x1800);
+ output |= temp;
+ mask = 0x08 | 0x1800;
+ break;
+ case MDP_BLOCK_VG_1:
+ base = 0x20058;
+ output = (config->csc_data.flags << 11) & (0x800);
+ temp = (config->csc_data.flags << 8) & (0x600);
+ output |= temp;
+ mask = 0x800 | 0x600;
+ break;
+ case MDP_BLOCK_VG_2:
+ base = 0x30058;
+ output = (config->csc_data.flags << 11) & (0x800);
+ temp = (config->csc_data.flags << 8) & (0x600);
+ output |= temp;
+ mask = 0x800 | 0x600;
+ break;
+ case MDP_BLOCK_OVERLAY_1:
+ base = 0x18200;
+ output = config->csc_data.flags;
+ mask = 0x07;
+ break;
+ case MDP_BLOCK_OVERLAY_2:
+ base = 0x88200;
+ output = config->csc_data.flags;
+ mask = 0x07;
+ break;
+ default:
+ pr_err("%s - CSC block does not exist on MDP_BLOCK = %d\n",
+ __func__, config->block);
+ return -EINVAL;
+ }
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ temp = inpdw(MDP_BASE + base) & ~mask;
+ output |= temp;
+ outpdw(MDP_BASE + base, output);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ return 0;
+}
+
+#define CSC_MV_OFF 0x400
+#define CSC_BV_OFF 0x500
+#define CSC_LV_OFF 0x600
+#define CSC_POST_OFF 0x80
+
+void mdp4_csc_write(struct mdp_csc_cfg *data, uint32_t base)
+{
+ int i;
+ uint32_t *off;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ off = (uint32_t *) ((uint32_t) base + CSC_MV_OFF);
+ for (i = 0; i < 9; i++) {
+ outpdw(off, data->csc_mv[i]);
+ off++;
+ }
+
+ off = (uint32_t *) ((uint32_t) base + CSC_BV_OFF);
+ for (i = 0; i < 3; i++) {
+ outpdw(off, data->csc_pre_bv[i]);
+ outpdw((uint32_t *)((uint32_t)off + CSC_POST_OFF),
+ data->csc_post_bv[i]);
+ off++;
+ }
+
+ off = (uint32_t *) ((uint32_t) base + CSC_LV_OFF);
+ for (i = 0; i < 6; i++) {
+ outpdw(off, data->csc_pre_lv[i]);
+ outpdw((uint32_t *)((uint32_t)off + CSC_POST_OFF),
+ data->csc_post_lv[i]);
+ off++;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+int mdp4_csc_config(struct mdp_csc_cfg_data *config)
+{
+ int ret = 0;
+ uint32_t base;
+
+ base = mdp4_csc_block2base(config->block);
+ if (!base) {
+ pr_warn("%s: Block type %d isn't supported by CSC.\n",
+ __func__, config->block);
+ return -EINVAL;
+ }
+
+ mdp4_csc_write(&config->csc_data, (uint32_t) (MDP_BASE + base));
+
+ ret = mdp4_csc_enable(config);
+
+ return ret;
+}
+
+void mdp4_init_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num)
+{
+ struct mdp_buf_type *buf;
+
+ if (mix_num == MDP4_MIXER0)
+ buf = mfd->ov0_wb_buf;
+ else
+ buf = mfd->ov1_wb_buf;
+
+ buf->ihdl = NULL;
+ buf->write_addr = 0;
+ buf->read_addr = 0;
+}
+
+u32 mdp4_allocate_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num)
+{
+ struct mdp_buf_type *buf;
+ ion_phys_addr_t addr;
+ size_t buffer_size;
+ unsigned long len;
+
+ if (mix_num == MDP4_MIXER0)
+ buf = mfd->ov0_wb_buf;
+ else
+ buf = mfd->ov1_wb_buf;
+
+ if (buf->write_addr || !IS_ERR_OR_NULL(buf->ihdl))
+ return 0;
+
+ if (!buf->size) {
+ pr_err("%s:%d In valid size\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ buffer_size = roundup(mfd->panel_info.xres * \
+ mfd->panel_info.yres * 3 * 2, SZ_4K);
+
+ if (!IS_ERR_OR_NULL(mfd->iclient)) {
+ pr_info("%s:%d ion based allocation mfd->mem_hid 0x%x\n",
+ __func__, __LINE__, mfd->mem_hid);
+ buf->ihdl = ion_alloc(mfd->iclient, buffer_size, SZ_4K,
+ mfd->mem_hid);
+ if (!IS_ERR_OR_NULL(buf->ihdl)) {
+ if (ion_map_iommu(mfd->iclient, buf->ihdl,
+ DISPLAY_DOMAIN, GEN_POOL, SZ_4K, 0, &addr,
+ &len, 0, 0)) {
+ pr_err("ion_map_iommu() failed\n");
+ return -ENOMEM;
+ }
+ } else {
+ pr_err("%s:%d: ion_alloc failed\n", __func__,
+ __LINE__);
+ return -ENOMEM;
+ }
+ } else {
+ addr = allocate_contiguous_memory_nomap(buffer_size,
+ mfd->mem_hid, 4);
+ }
+ if (addr) {
+ pr_info("allocating %d bytes at %x for mdp writeback\n",
+ buffer_size, (u32) addr);
+ buf->write_addr = addr;
+ buf->read_addr = buf->write_addr;
+ return 0;
+ } else {
+ pr_err("%s cannot allocate memory for mdp writeback!\n",
+ __func__);
+ return -ENOMEM;
+ }
}
-uint32_t mdp4_rgb_igc_lut_cvt(uint32_t ndx)
+void mdp4_free_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num)
{
- return igc_rgb_lut[ndx & 0x0ff];
+ struct mdp_buf_type *buf;
+
+ if (mix_num == MDP4_MIXER0)
+ buf = mfd->ov0_wb_buf;
+ else
+ buf = mfd->ov1_wb_buf;
+
+ if (!IS_ERR_OR_NULL(mfd->iclient)) {
+ if (!IS_ERR_OR_NULL(buf->ihdl)) {
+ ion_unmap_iommu(mfd->iclient, buf->ihdl,
+ DISPLAY_DOMAIN, GEN_POOL);
+ ion_free(mfd->iclient, buf->ihdl);
+ buf->ihdl = NULL;
+ pr_info("%s:%d free ION writeback imem",
+ __func__, __LINE__);
+ }
+ } else {
+ if (buf->write_addr) {
+ free_contiguous_memory_by_paddr(buf->write_addr);
+ pr_info("%s:%d free writeback pmem\n", __func__,
+ __LINE__);
+ }
+ }
+ buf->write_addr = 0;
+ buf->read_addr = 0;
+}
+
+static int mdp4_update_pcc_regs(uint32_t offset,
+ struct mdp_pcc_cfg_data *cfg_ptr)
+{
+ int ret = -1;
+
+ if (offset && cfg_ptr) {
+
+ outpdw(offset, cfg_ptr->r.c);
+ outpdw(offset + 0x30, cfg_ptr->g.c);
+ outpdw(offset + 0x60, cfg_ptr->b.c);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.r);
+ outpdw(offset + 0x30, cfg_ptr->g.r);
+ outpdw(offset + 0x60, cfg_ptr->b.r);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.g);
+ outpdw(offset + 0x30, cfg_ptr->g.g);
+ outpdw(offset + 0x60, cfg_ptr->b.g);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.b);
+ outpdw(offset + 0x30, cfg_ptr->g.b);
+ outpdw(offset + 0x60, cfg_ptr->b.b);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.rr);
+ outpdw(offset + 0x30, cfg_ptr->g.rr);
+ outpdw(offset + 0x60, cfg_ptr->b.rr);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.gg);
+ outpdw(offset + 0x30, cfg_ptr->g.gg);
+ outpdw(offset + 0x60, cfg_ptr->b.gg);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.bb);
+ outpdw(offset + 0x30, cfg_ptr->g.bb);
+ outpdw(offset + 0x60, cfg_ptr->b.bb);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.rg);
+ outpdw(offset + 0x30, cfg_ptr->g.rg);
+ outpdw(offset + 0x60, cfg_ptr->b.rg);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.gb);
+ outpdw(offset + 0x30, cfg_ptr->g.gb);
+ outpdw(offset + 0x60, cfg_ptr->b.gb);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.rb);
+ outpdw(offset + 0x30, cfg_ptr->g.rb);
+ outpdw(offset + 0x60, cfg_ptr->b.rb);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.rgb_0);
+ outpdw(offset + 0x30, cfg_ptr->g.rgb_0);
+ outpdw(offset + 0x60, cfg_ptr->b.rgb_0);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.rgb_1);
+ outpdw(offset + 0x30, cfg_ptr->g.rgb_1);
+ outpdw(offset + 0x60, cfg_ptr->b.rgb_1);
+
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static int mdp4_read_pcc_regs(uint32_t offset,
+ struct mdp_pcc_cfg_data *cfg_ptr)
+{
+ int ret = -1;
+
+ if (offset && cfg_ptr) {
+ cfg_ptr->r.c = inpdw(offset);
+ cfg_ptr->g.c = inpdw(offset + 0x30);
+ cfg_ptr->b.c = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.r = inpdw(offset);
+ cfg_ptr->g.r = inpdw(offset + 0x30);
+ cfg_ptr->b.r = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.g = inpdw(offset);
+ cfg_ptr->g.g = inpdw(offset + 0x30);
+ cfg_ptr->b.g = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.b = inpdw(offset);
+ cfg_ptr->g.b = inpdw(offset + 0x30);
+ cfg_ptr->b.b = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.rr = inpdw(offset);
+ cfg_ptr->g.rr = inpdw(offset + 0x30);
+ cfg_ptr->b.rr = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.gg = inpdw(offset);
+ cfg_ptr->g.gg = inpdw(offset + 0x30);
+ cfg_ptr->b.gg = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.bb = inpdw(offset);
+ cfg_ptr->g.bb = inpdw(offset + 0x30);
+ cfg_ptr->b.bb = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.rg = inpdw(offset);
+ cfg_ptr->g.rg = inpdw(offset + 0x30);
+ cfg_ptr->b.rg = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.gb = inpdw(offset);
+ cfg_ptr->g.gb = inpdw(offset + 0x30);
+ cfg_ptr->b.gb = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.rb = inpdw(offset);
+ cfg_ptr->g.rb = inpdw(offset + 0x30);
+ cfg_ptr->b.rb = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.rgb_0 = inpdw(offset);
+ cfg_ptr->g.rgb_0 = inpdw(offset + 0x30);
+ cfg_ptr->b.rgb_0 = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.rgb_1 = inpdw(offset);
+ cfg_ptr->g.rgb_1 = inpdw(offset + 0x30);
+ cfg_ptr->b.rgb_1 = inpdw(offset + 0x60);
+
+ ret = 0;
+ }
+
+ return ret;
+}
+
+
+#define MDP_PCC_OFFSET 0xA000
+#define MDP_DMA_GC_OFFSET 0x8800
+#define MDP_LM_GC_OFFSET 0x4800
+
+#define MDP_DMA_P_OP_MODE_OFFSET 0x70
+#define MDP_DMA_S_OP_MODE_OFFSET 0x28
+#define MDP_LM_OP_MODE_OFFSET 0x14
+
+#define DMA_PCC_R2_OFFSET 0x100
+
+#define MDP_GC_COLOR_OFFSET 0x100
+#define MDP_GC_PARMS_OFFSET 0x80
+
+#define MDP_AR_GC_MAX_STAGES 16
+
+static uint32_t mdp_pp_block2pcc(uint32_t block)
+{
+ uint32_t valid = 0;
+
+ switch (block) {
+ case MDP_BLOCK_DMA_P:
+ case MDP_BLOCK_DMA_S:
+ valid = (mdp_rev >= MDP_REV_42) ? 1 : 0;
+ break;
+
+ default:
+ break;
+ }
+
+ return valid;
+}
+
+int mdp4_pcc_cfg(struct mdp_pcc_cfg_data *cfg_ptr)
+{
+ int ret = -1;
+ uint32_t pcc_offset = 0, mdp_cfg_offset = 0;
+ uint32_t mdp_dma_op_mode = 0;
+ uint32_t blockbase;
+
+ if (!mdp_pp_block2pcc(cfg_ptr->block))
+ return ret;
+
+ blockbase = mdp_block2base(cfg_ptr->block);
+ if (!blockbase)
+ return ret;
+
+ blockbase += (uint32_t) MDP_BASE;
+
+ switch (cfg_ptr->block) {
+ case MDP_BLOCK_DMA_P:
+ case MDP_BLOCK_DMA_S:
+ pcc_offset = blockbase + MDP_PCC_OFFSET;
+ mdp_cfg_offset = blockbase;
+ mdp_dma_op_mode = blockbase +
+ (MDP_BLOCK_DMA_P == cfg_ptr->block ?
+ MDP_DMA_P_OP_MODE_OFFSET
+ : MDP_DMA_S_OP_MODE_OFFSET);
+ break;
+
+ default:
+ break;
+ }
+
+ if (0x8 & cfg_ptr->ops)
+ pcc_offset += DMA_PCC_R2_OFFSET;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ switch ((0x6 & cfg_ptr->ops)>>1) {
+ case 0x1:
+ ret = mdp4_read_pcc_regs(pcc_offset, cfg_ptr);
+ break;
+
+ case 0x2:
+ ret = mdp4_update_pcc_regs(pcc_offset, cfg_ptr);
+ break;
+
+ default:
+ break;
+ }
+
+ if (0x8 & cfg_ptr->ops)
+ outpdw(mdp_dma_op_mode,
+ (inpdw(mdp_dma_op_mode)|((0x8&cfg_ptr->ops)<<10)));
+
+ outpdw(mdp_cfg_offset,
+ (inpdw(mdp_cfg_offset)|((cfg_ptr->ops&0x1)<<29)));
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ return ret;
+}
+
+static uint32_t mdp_pp_block2argc(uint32_t block)
+{
+ uint32_t valid = 0;
+
+ switch (block) {
+ case MDP_BLOCK_DMA_P:
+ case MDP_BLOCK_DMA_S:
+ case MDP_BLOCK_OVERLAY_0:
+ case MDP_BLOCK_OVERLAY_1:
+ valid = (mdp_rev >= MDP_REV_42) ? 1 : 0;
+ break;
+
+ case MDP_BLOCK_OVERLAY_2:
+ valid = (mdp_rev >= MDP_REV_44) ? 1 : 0;
+ break;
+
+ default:
+ break;
+ }
+
+ return valid;
+}
+
+static int update_ar_gc_lut(uint32_t *offset, struct mdp_pgc_lut_data *lut_data)
+{
+ int count = 0;
+
+ uint32_t *c0_offset = offset;
+ uint32_t *c0_params_offset = (uint32_t *)((uint32_t)c0_offset
+ + MDP_GC_PARMS_OFFSET);
+
+ uint32_t *c1_offset = (uint32_t *)((uint32_t)offset
+ + MDP_GC_COLOR_OFFSET);
+
+ uint32_t *c1_params_offset = (uint32_t *)((uint32_t)c1_offset
+ + MDP_GC_PARMS_OFFSET);
+
+ uint32_t *c2_offset = (uint32_t *)((uint32_t)offset
+ + 2*MDP_GC_COLOR_OFFSET);
+
+ uint32_t *c2_params_offset = (uint32_t *)((uint32_t)c2_offset
+ +MDP_GC_PARMS_OFFSET);
+
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ for (count = 0; count < MDP_AR_GC_MAX_STAGES; count++) {
+ if (count < lut_data->num_r_stages) {
+ outpdw(c0_offset+count,
+ ((0xfff & lut_data->r_data[count].x_start)
+ | 0x10000));
+
+ outpdw(c0_params_offset+count,
+ ((0x7fff & lut_data->r_data[count].slope)
+ | ((0xffff
+ & lut_data->r_data[count].offset)
+ << 16)));
+ } else
+ outpdw(c0_offset+count, 0);
+
+ if (count < lut_data->num_b_stages) {
+ outpdw(c1_offset+count,
+ ((0xfff & lut_data->b_data[count].x_start)
+ | 0x10000));
+
+ outpdw(c1_params_offset+count,
+ ((0x7fff & lut_data->b_data[count].slope)
+ | ((0xffff
+ & lut_data->b_data[count].offset)
+ << 16)));
+ } else
+ outpdw(c1_offset+count, 0);
+
+ if (count < lut_data->num_g_stages) {
+ outpdw(c2_offset+count,
+ ((0xfff & lut_data->g_data[count].x_start)
+ | 0x10000));
+
+ outpdw(c2_params_offset+count,
+ ((0x7fff & lut_data->g_data[count].slope)
+ | ((0xffff
+ & lut_data->g_data[count].offset)
+ << 16)));
+ } else
+ outpdw(c2_offset+count, 0);
+ }
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ return 0;
+}
+
+static int mdp4_argc_process_write_req(uint32_t *offset,
+ struct mdp_pgc_lut_data *pgc_ptr)
+{
+ int ret = -1;
+ struct mdp_ar_gc_lut_data r[MDP_AR_GC_MAX_STAGES];
+ struct mdp_ar_gc_lut_data g[MDP_AR_GC_MAX_STAGES];
+ struct mdp_ar_gc_lut_data b[MDP_AR_GC_MAX_STAGES];
+
+ ret = copy_from_user(&r[0], pgc_ptr->r_data,
+ pgc_ptr->num_r_stages * sizeof(struct mdp_ar_gc_lut_data));
+
+ if (!ret) {
+ ret = copy_from_user(&g[0],
+ pgc_ptr->g_data,
+ pgc_ptr->num_g_stages
+ * sizeof(struct mdp_ar_gc_lut_data));
+ if (!ret)
+ ret = copy_from_user(&b[0],
+ pgc_ptr->b_data,
+ pgc_ptr->num_b_stages
+ * sizeof(struct mdp_ar_gc_lut_data));
+ }
+
+ if (ret)
+ return ret;
+
+ pgc_ptr->r_data = &r[0];
+ pgc_ptr->g_data = &g[0];
+ pgc_ptr->b_data = &b[0];
+
+ ret = update_ar_gc_lut(offset, pgc_ptr);
+ return ret;
+}
+
+int mdp4_argc_cfg(struct mdp_pgc_lut_data *pgc_ptr)
+{
+ int ret = -1;
+ uint32_t *offset = 0, *pgc_enable_offset = 0, lshift_bits = 0;
+ uint32_t blockbase;
+
+ if (!mdp_pp_block2argc(pgc_ptr->block))
+ return ret;
+
+ blockbase = mdp_block2base(pgc_ptr->block);
+ if (!blockbase)
+ return ret;
+
+ blockbase += (uint32_t) MDP_BASE;
+ ret = 0;
+
+ switch (pgc_ptr->block) {
+ case MDP_BLOCK_DMA_P:
+ case MDP_BLOCK_DMA_S:
+ offset = (uint32_t *)(blockbase + MDP_DMA_GC_OFFSET);
+ pgc_enable_offset = (uint32_t *) blockbase;
+ lshift_bits = 28;
+ break;
+
+ case MDP_BLOCK_OVERLAY_0:
+ case MDP_BLOCK_OVERLAY_1:
+ case MDP_BLOCK_OVERLAY_2:
+ offset = (uint32_t *)(blockbase + MDP_LM_GC_OFFSET);
+ pgc_enable_offset = (uint32_t *)(blockbase
+ + MDP_LM_OP_MODE_OFFSET);
+ lshift_bits = 2;
+ break;
+
+ default:
+ ret = -1;
+ break;
+ }
+
+ if (!ret) {
+
+ switch ((0x6 & pgc_ptr->flags)>>1) {
+ case 0x1:
+ ret = -ENOTTY;
+ break;
+
+ case 0x2:
+ ret = mdp4_argc_process_write_req(offset, pgc_ptr);
+ break;
+
+ default:
+ break;
+ }
+
+ if (!ret) {
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ outpdw(pgc_enable_offset, (inpdw(pgc_enable_offset) |
+ ((0x1 & pgc_ptr->flags) << lshift_bits)));
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF,
+ FALSE);
+ }
+ }
+
+ return ret;
+}
+
+static uint32_t mdp4_pp_block2igc(uint32_t block)
+{
+ uint32_t valid = 0;
+ switch (block) {
+ case MDP_BLOCK_VG_1:
+ valid = 0x1;
+ break;
+ case MDP_BLOCK_VG_2:
+ valid = 0x1;
+ break;
+ case MDP_BLOCK_RGB_1:
+ valid = 0x1;
+ break;
+ case MDP_BLOCK_RGB_2:
+ valid = 0x1;
+ break;
+ case MDP_BLOCK_DMA_P:
+ valid = (mdp_rev >= MDP_REV_40) ? 1 : 0;
+ break;
+ case MDP_BLOCK_DMA_S:
+ valid = (mdp_rev >= MDP_REV_40) ? 1 : 0;
+ break;
+ default:
+ break;
+ }
+ return valid;
+}
+
+static int mdp4_igc_lut_write(struct mdp_igc_lut_data *cfg, uint32_t en_off,
+ uint32_t lut_off)
+{
+ int i;
+ uint32_t base, *off_low, *off_high;
+ uint32_t low[cfg->len];
+ uint32_t high[cfg->len];
+
+ base = mdp_block2base(cfg->block);
+
+ if (cfg->len != 256)
+ return -EINVAL;
+
+ off_low = (uint32_t *)(MDP_BASE + base + lut_off);
+ off_high = (uint32_t *)(MDP_BASE + base + lut_off + 0x800);
+ if (copy_from_user(&low, cfg->c0_c1_data, cfg->len * sizeof(uint32_t)))
+ return -EFAULT;
+ if (copy_from_user(&high, cfg->c2_data, cfg->len * sizeof(uint32_t)))
+ return -EFAULT;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ for (i = 0; i < cfg->len; i++) {
+ MDP_OUTP(off_low++, low[i]);
+ /*low address write should occur before high address write*/
+ wmb();
+ MDP_OUTP(off_high++, high[i]);
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ return 0;
+}
+
+static int mdp4_igc_lut_ctrl(struct mdp_igc_lut_data *cfg)
+{
+ uint32_t mask, out;
+ uint32_t base = mdp_block2base(cfg->block);
+ int8_t shift = 0;
+
+ switch (cfg->block) {
+ case MDP_BLOCK_DMA_P:
+ case MDP_BLOCK_DMA_S:
+ base = base;
+ shift = 30;
+ break;
+ case MDP_BLOCK_VG_1:
+ case MDP_BLOCK_VG_2:
+ case MDP_BLOCK_RGB_1:
+ case MDP_BLOCK_RGB_2:
+ base += 0x58;
+ shift = 16;
+ break;
+ default:
+ return -EINVAL;
+
+ }
+ out = 1<<shift;
+ mask = ~out;
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ out = inpdw(MDP_BASE + base) & mask;
+ MDP_OUTP(MDP_BASE + base, out | ((cfg->ops & 0x1)<<shift));
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ return 0;
+}
+
+static int mdp4_igc_lut_write_cfg(struct mdp_igc_lut_data *cfg)
+{
+ int ret = 0;
+
+ switch (cfg->block) {
+ case MDP_BLOCK_DMA_P:
+ case MDP_BLOCK_DMA_S:
+ ret = mdp4_igc_lut_write(cfg, 0x00, 0x9000);
+ break;
+ case MDP_BLOCK_VG_1:
+ case MDP_BLOCK_VG_2:
+ case MDP_BLOCK_RGB_1:
+ case MDP_BLOCK_RGB_2:
+ ret = mdp4_igc_lut_write(cfg, 0x58, 0x5000);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+int mdp4_igc_lut_config(struct mdp_igc_lut_data *cfg)
+{
+ int ret = 0;
+
+ if (!mdp4_pp_block2igc(cfg->block)) {
+ ret = -ENOTTY;
+ goto error;
+ }
+
+ switch ((cfg->ops & 0x6) >> 1) {
+ case 0x1:
+ pr_info("%s: IGC LUT read not supported\n", __func__);
+ break;
+ case 0x2:
+ ret = mdp4_igc_lut_write_cfg(cfg);
+ if (ret)
+ goto error;
+ break;
+ default:
+ break;
+ }
+
+ ret = mdp4_igc_lut_ctrl(cfg);
+
+error:
+ return ret;
}
diff --git a/drivers/video/msm/mdp4_wfd_writeback.c b/drivers/video/msm/mdp4_wfd_writeback.c
new file mode 100644
index 0000000..a8fdcc0
--- /dev/null
+++ b/drivers/video/msm/mdp4_wfd_writeback.c
@@ -0,0 +1,102 @@
+/* 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/types.h>
+#include <linux/list.h>
+#include <linux/ioctl.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/version.h>
+
+#include "mdp4_wfd_writeback_util.h"
+#include "msm_fb.h"
+
+static int writeback_on(struct platform_device *pdev)
+{
+ return 0;
+}
+static int writeback_off(struct platform_device *pdev)
+{
+ return 0;
+}
+static int writeback_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 = 0;
+
+ WRITEBACK_MSG_ERR("Inside writeback_probe\n");
+ mfd = platform_get_drvdata(pdev);
+ if (!mfd)
+ return -ENODEV;
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ 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;
+
+ if (platform_device_add_data
+ (mdp_dev, pdev->dev.platform_data,
+ sizeof(struct msm_fb_panel_data))) {
+ pr_err("writeback_probe: "
+ "platform_device_add_data failed!\n");
+ platform_device_put(mdp_dev);
+ return -ENOMEM;
+ }
+ pdata = (struct msm_fb_panel_data *)mdp_dev->dev.platform_data;
+ pdata->on = writeback_on;
+ pdata->off = writeback_off;
+ pdata->next = pdev;
+
+ /*
+ * get/set panel specific fb info
+ */
+ mfd->panel_info = pdata->panel_info;
+
+ mfd->fb_imgType = MDP_RGB_565;
+
+ platform_set_drvdata(mdp_dev, mfd);
+
+ rc = platform_device_add(mdp_dev);
+ if (rc) {
+ WRITEBACK_MSG_ERR("failed to add device");
+ platform_device_put(mdp_dev);
+ return rc;
+ }
+ return rc;
+}
+
+static struct platform_driver writeback_driver = {
+ .probe = writeback_probe,
+ .driver = {
+ .name = "writeback",
+ },
+};
+
+static int __init writeback_driver_init(void)
+{
+ int rc = 0;
+ WRITEBACK_MSG_ERR("Inside writeback_driver_init\n");
+ rc = platform_driver_register(&writeback_driver);
+ return rc;
+}
+
+module_init(writeback_driver_init);
diff --git a/drivers/video/msm/mdp4_wfd_writeback_panel.c b/drivers/video/msm/mdp4_wfd_writeback_panel.c
new file mode 100644
index 0000000..40ffb65
--- /dev/null
+++ b/drivers/video/msm/mdp4_wfd_writeback_panel.c
@@ -0,0 +1,83 @@
+/* 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/types.h>
+#include <linux/list.h>
+#include <linux/ioctl.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/version.h>
+
+#include "mdp4_wfd_writeback_util.h"
+#include "msm_fb.h"
+
+static int __devinit writeback_panel_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+ if (pdev->id == 0)
+ return 0;
+
+ if (!msm_fb_add_device(pdev)) {
+ WRITEBACK_MSG_ERR("Failed to add fd device\n");
+ rc = -ENOMEM;
+ }
+ return rc;
+}
+static struct msm_fb_panel_data writeback_msm_panel_data = {
+ .panel_info = {
+ .type = WRITEBACK_PANEL,
+ .xres = 1280,
+ .yres = 720,
+ .pdest = DISPLAY_3,
+ .wait_cycle = 0,
+ .bpp = 24,
+ .fb_num = 1,
+ .clk_rate = 74250000,
+ },
+};
+
+static struct platform_device writeback_panel_device = {
+ .name = "writeback_panel",
+ .id = 1,
+ .dev.platform_data = &writeback_msm_panel_data,
+};
+static struct platform_driver writeback_panel_driver = {
+ .probe = writeback_panel_probe,
+ .driver = {
+ .name = "writeback_panel"
+ }
+};
+
+static int __init writeback_panel_init(void)
+{
+ int rc = 0;
+ rc = platform_driver_register(&writeback_panel_driver);
+ if (rc) {
+ WRITEBACK_MSG_ERR("Failed to register platform driver\n");
+ goto fail_driver_registration;
+ }
+ rc = platform_device_register(&writeback_panel_device);
+ if (rc) {
+ WRITEBACK_MSG_ERR("Failed to register "
+ "writeback_panel_device\n");
+ goto fail_device_registration;
+ }
+ return rc;
+fail_device_registration:
+ platform_driver_unregister(&writeback_panel_driver);
+fail_driver_registration:
+ return rc;
+}
+
+module_init(writeback_panel_init);
diff --git a/drivers/video/msm/mdp4_wfd_writeback_util.h b/drivers/video/msm/mdp4_wfd_writeback_util.h
new file mode 100644
index 0000000..2d62713
--- /dev/null
+++ b/drivers/video/msm/mdp4_wfd_writeback_util.h
@@ -0,0 +1,28 @@
+/* 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 _WRITEBACK_UTIL_H_
+#define _WRITEBACK_UTIL_H_
+
+#define DEBUG
+
+#ifdef DEBUG
+ #define WRITEBACK_MSG_INFO(fmt...) pr_info(fmt)
+ #define WRITEBACK_MSG_WARN(fmt...) pr_warning(fmt)
+#else
+ #define WRITEBACK_MSG_INFO(fmt...)
+ #define WRITEBACK_MSG_WARN(fmt...)
+#endif
+ #define WRITEBACK_MSG_ERR(fmt...) pr_err(fmt)
+ #define WRITEBACK_MSG_CRIT(fmt...) pr_crit(fmt)
+#endif
diff --git a/drivers/video/msm/mdp_csc_table.h b/drivers/video/msm/mdp_csc_table.h
new file mode 100644
index 0000000..a0f72c0
--- /dev/null
+++ b/drivers/video/msm/mdp_csc_table.h
@@ -0,0 +1,641 @@
+/* drivers/video/msm/mdp_csc_table.h
+ *
+ * Copyright (C) 2007 QUALCOMM Incorporated
+ * 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.
+ */
+
+static struct {
+ uint32_t reg;
+ uint32_t val;
+} 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 },
+ { 0x4080c, 0x232323 },
+ { 0x40810, 0x272727 },
+ { 0x40814, 0x2b2b2b },
+ { 0x40818, 0x2f2f2f },
+ { 0x4081c, 0x333333 },
+ { 0x40820, 0x363636 },
+ { 0x40824, 0x393939 },
+ { 0x40828, 0x3b3b3b },
+ { 0x4082c, 0x3e3e3e },
+ { 0x40830, 0x404040 },
+ { 0x40834, 0x434343 },
+ { 0x40838, 0x454545 },
+ { 0x4083c, 0x474747 },
+ { 0x40840, 0x494949 },
+ { 0x40844, 0x4b4b4b },
+ { 0x40848, 0x4d4d4d },
+ { 0x4084c, 0x4f4f4f },
+ { 0x40850, 0x515151 },
+ { 0x40854, 0x535353 },
+ { 0x40858, 0x555555 },
+ { 0x4085c, 0x565656 },
+ { 0x40860, 0x585858 },
+ { 0x40864, 0x5a5a5a },
+ { 0x40868, 0x5b5b5b },
+ { 0x4086c, 0x5d5d5d },
+ { 0x40870, 0x5e5e5e },
+ { 0x40874, 0x606060 },
+ { 0x40878, 0x616161 },
+ { 0x4087c, 0x636363 },
+ { 0x40880, 0x646464 },
+ { 0x40884, 0x666666 },
+ { 0x40888, 0x676767 },
+ { 0x4088c, 0x686868 },
+ { 0x40890, 0x6a6a6a },
+ { 0x40894, 0x6b6b6b },
+ { 0x40898, 0x6c6c6c },
+ { 0x4089c, 0x6e6e6e },
+ { 0x408a0, 0x6f6f6f },
+ { 0x408a4, 0x707070 },
+ { 0x408a8, 0x717171 },
+ { 0x408ac, 0x727272 },
+ { 0x408b0, 0x747474 },
+ { 0x408b4, 0x757575 },
+ { 0x408b8, 0x767676 },
+ { 0x408bc, 0x777777 },
+ { 0x408c0, 0x787878 },
+ { 0x408c4, 0x797979 },
+ { 0x408c8, 0x7a7a7a },
+ { 0x408cc, 0x7c7c7c },
+ { 0x408d0, 0x7d7d7d },
+ { 0x408d4, 0x7e7e7e },
+ { 0x408d8, 0x7f7f7f },
+ { 0x408dc, 0x808080 },
+ { 0x408e0, 0x818181 },
+ { 0x408e4, 0x828282 },
+ { 0x408e8, 0x838383 },
+ { 0x408ec, 0x848484 },
+ { 0x408f0, 0x858585 },
+ { 0x408f4, 0x868686 },
+ { 0x408f8, 0x878787 },
+ { 0x408fc, 0x888888 },
+ { 0x40900, 0x898989 },
+ { 0x40904, 0x8a8a8a },
+ { 0x40908, 0x8b8b8b },
+ { 0x4090c, 0x8c8c8c },
+ { 0x40910, 0x8d8d8d },
+ { 0x40914, 0x8e8e8e },
+ { 0x40918, 0x8f8f8f },
+ { 0x4091c, 0x8f8f8f },
+ { 0x40920, 0x909090 },
+ { 0x40924, 0x919191 },
+ { 0x40928, 0x929292 },
+ { 0x4092c, 0x939393 },
+ { 0x40930, 0x949494 },
+ { 0x40934, 0x959595 },
+ { 0x40938, 0x969696 },
+ { 0x4093c, 0x969696 },
+ { 0x40940, 0x979797 },
+ { 0x40944, 0x989898 },
+ { 0x40948, 0x999999 },
+ { 0x4094c, 0x9a9a9a },
+ { 0x40950, 0x9b9b9b },
+ { 0x40954, 0x9c9c9c },
+ { 0x40958, 0x9c9c9c },
+ { 0x4095c, 0x9d9d9d },
+ { 0x40960, 0x9e9e9e },
+ { 0x40964, 0x9f9f9f },
+ { 0x40968, 0xa0a0a0 },
+ { 0x4096c, 0xa0a0a0 },
+ { 0x40970, 0xa1a1a1 },
+ { 0x40974, 0xa2a2a2 },
+ { 0x40978, 0xa3a3a3 },
+ { 0x4097c, 0xa4a4a4 },
+ { 0x40980, 0xa4a4a4 },
+ { 0x40984, 0xa5a5a5 },
+ { 0x40988, 0xa6a6a6 },
+ { 0x4098c, 0xa7a7a7 },
+ { 0x40990, 0xa7a7a7 },
+ { 0x40994, 0xa8a8a8 },
+ { 0x40998, 0xa9a9a9 },
+ { 0x4099c, 0xaaaaaa },
+ { 0x409a0, 0xaaaaaa },
+ { 0x409a4, 0xababab },
+ { 0x409a8, 0xacacac },
+ { 0x409ac, 0xadadad },
+ { 0x409b0, 0xadadad },
+ { 0x409b4, 0xaeaeae },
+ { 0x409b8, 0xafafaf },
+ { 0x409bc, 0xafafaf },
+ { 0x409c0, 0xb0b0b0 },
+ { 0x409c4, 0xb1b1b1 },
+ { 0x409c8, 0xb2b2b2 },
+ { 0x409cc, 0xb2b2b2 },
+ { 0x409d0, 0xb3b3b3 },
+ { 0x409d4, 0xb4b4b4 },
+ { 0x409d8, 0xb4b4b4 },
+ { 0x409dc, 0xb5b5b5 },
+ { 0x409e0, 0xb6b6b6 },
+ { 0x409e4, 0xb6b6b6 },
+ { 0x409e8, 0xb7b7b7 },
+ { 0x409ec, 0xb8b8b8 },
+ { 0x409f0, 0xb8b8b8 },
+ { 0x409f4, 0xb9b9b9 },
+ { 0x409f8, 0xbababa },
+ { 0x409fc, 0xbababa },
+ { 0x40a00, 0xbbbbbb },
+ { 0x40a04, 0xbcbcbc },
+ { 0x40a08, 0xbcbcbc },
+ { 0x40a0c, 0xbdbdbd },
+ { 0x40a10, 0xbebebe },
+ { 0x40a14, 0xbebebe },
+ { 0x40a18, 0xbfbfbf },
+ { 0x40a1c, 0xc0c0c0 },
+ { 0x40a20, 0xc0c0c0 },
+ { 0x40a24, 0xc1c1c1 },
+ { 0x40a28, 0xc1c1c1 },
+ { 0x40a2c, 0xc2c2c2 },
+ { 0x40a30, 0xc3c3c3 },
+ { 0x40a34, 0xc3c3c3 },
+ { 0x40a38, 0xc4c4c4 },
+ { 0x40a3c, 0xc5c5c5 },
+ { 0x40a40, 0xc5c5c5 },
+ { 0x40a44, 0xc6c6c6 },
+ { 0x40a48, 0xc6c6c6 },
+ { 0x40a4c, 0xc7c7c7 },
+ { 0x40a50, 0xc8c8c8 },
+ { 0x40a54, 0xc8c8c8 },
+ { 0x40a58, 0xc9c9c9 },
+ { 0x40a5c, 0xc9c9c9 },
+ { 0x40a60, 0xcacaca },
+ { 0x40a64, 0xcbcbcb },
+ { 0x40a68, 0xcbcbcb },
+ { 0x40a6c, 0xcccccc },
+ { 0x40a70, 0xcccccc },
+ { 0x40a74, 0xcdcdcd },
+ { 0x40a78, 0xcecece },
+ { 0x40a7c, 0xcecece },
+ { 0x40a80, 0xcfcfcf },
+ { 0x40a84, 0xcfcfcf },
+ { 0x40a88, 0xd0d0d0 },
+ { 0x40a8c, 0xd0d0d0 },
+ { 0x40a90, 0xd1d1d1 },
+ { 0x40a94, 0xd2d2d2 },
+ { 0x40a98, 0xd2d2d2 },
+ { 0x40a9c, 0xd3d3d3 },
+ { 0x40aa0, 0xd3d3d3 },
+ { 0x40aa4, 0xd4d4d4 },
+ { 0x40aa8, 0xd4d4d4 },
+ { 0x40aac, 0xd5d5d5 },
+ { 0x40ab0, 0xd6d6d6 },
+ { 0x40ab4, 0xd6d6d6 },
+ { 0x40ab8, 0xd7d7d7 },
+ { 0x40abc, 0xd7d7d7 },
+ { 0x40ac0, 0xd8d8d8 },
+ { 0x40ac4, 0xd8d8d8 },
+ { 0x40ac8, 0xd9d9d9 },
+ { 0x40acc, 0xd9d9d9 },
+ { 0x40ad0, 0xdadada },
+ { 0x40ad4, 0xdbdbdb },
+ { 0x40ad8, 0xdbdbdb },
+ { 0x40adc, 0xdcdcdc },
+ { 0x40ae0, 0xdcdcdc },
+ { 0x40ae4, 0xdddddd },
+ { 0x40ae8, 0xdddddd },
+ { 0x40aec, 0xdedede },
+ { 0x40af0, 0xdedede },
+ { 0x40af4, 0xdfdfdf },
+ { 0x40af8, 0xdfdfdf },
+ { 0x40afc, 0xe0e0e0 },
+ { 0x40b00, 0xe0e0e0 },
+ { 0x40b04, 0xe1e1e1 },
+ { 0x40b08, 0xe1e1e1 },
+ { 0x40b0c, 0xe2e2e2 },
+ { 0x40b10, 0xe3e3e3 },
+ { 0x40b14, 0xe3e3e3 },
+ { 0x40b18, 0xe4e4e4 },
+ { 0x40b1c, 0xe4e4e4 },
+ { 0x40b20, 0xe5e5e5 },
+ { 0x40b24, 0xe5e5e5 },
+ { 0x40b28, 0xe6e6e6 },
+ { 0x40b2c, 0xe6e6e6 },
+ { 0x40b30, 0xe7e7e7 },
+ { 0x40b34, 0xe7e7e7 },
+ { 0x40b38, 0xe8e8e8 },
+ { 0x40b3c, 0xe8e8e8 },
+ { 0x40b40, 0xe9e9e9 },
+ { 0x40b44, 0xe9e9e9 },
+ { 0x40b48, 0xeaeaea },
+ { 0x40b4c, 0xeaeaea },
+ { 0x40b50, 0xebebeb },
+ { 0x40b54, 0xebebeb },
+ { 0x40b58, 0xececec },
+ { 0x40b5c, 0xececec },
+ { 0x40b60, 0xededed },
+ { 0x40b64, 0xededed },
+ { 0x40b68, 0xeeeeee },
+ { 0x40b6c, 0xeeeeee },
+ { 0x40b70, 0xefefef },
+ { 0x40b74, 0xefefef },
+ { 0x40b78, 0xf0f0f0 },
+ { 0x40b7c, 0xf0f0f0 },
+ { 0x40b80, 0xf1f1f1 },
+ { 0x40b84, 0xf1f1f1 },
+ { 0x40b88, 0xf2f2f2 },
+ { 0x40b8c, 0xf2f2f2 },
+ { 0x40b90, 0xf2f2f2 },
+ { 0x40b94, 0xf3f3f3 },
+ { 0x40b98, 0xf3f3f3 },
+ { 0x40b9c, 0xf4f4f4 },
+ { 0x40ba0, 0xf4f4f4 },
+ { 0x40ba4, 0xf5f5f5 },
+ { 0x40ba8, 0xf5f5f5 },
+ { 0x40bac, 0xf6f6f6 },
+ { 0x40bb0, 0xf6f6f6 },
+ { 0x40bb4, 0xf7f7f7 },
+ { 0x40bb8, 0xf7f7f7 },
+ { 0x40bbc, 0xf8f8f8 },
+ { 0x40bc0, 0xf8f8f8 },
+ { 0x40bc4, 0xf9f9f9 },
+ { 0x40bc8, 0xf9f9f9 },
+ { 0x40bcc, 0xfafafa },
+ { 0x40bd0, 0xfafafa },
+ { 0x40bd4, 0xfafafa },
+ { 0x40bd8, 0xfbfbfb },
+ { 0x40bdc, 0xfbfbfb },
+ { 0x40be0, 0xfcfcfc },
+ { 0x40be4, 0xfcfcfc },
+ { 0x40be8, 0xfdfdfd },
+ { 0x40bec, 0xfdfdfd },
+ { 0x40bf0, 0xfefefe },
+ { 0x40bf4, 0xfefefe },
+ { 0x40bf8, 0xffffff },
+ { 0x40bfc, 0xffffff },
+ { 0x40c00, 0x0 },
+ { 0x40c04, 0x0 },
+ { 0x40c08, 0x0 },
+ { 0x40c0c, 0x0 },
+ { 0x40c10, 0x0 },
+ { 0x40c14, 0x0 },
+ { 0x40c18, 0x0 },
+ { 0x40c1c, 0x0 },
+ { 0x40c20, 0x0 },
+ { 0x40c24, 0x0 },
+ { 0x40c28, 0x0 },
+ { 0x40c2c, 0x0 },
+ { 0x40c30, 0x0 },
+ { 0x40c34, 0x0 },
+ { 0x40c38, 0x0 },
+ { 0x40c3c, 0x0 },
+ { 0x40c40, 0x10101 },
+ { 0x40c44, 0x10101 },
+ { 0x40c48, 0x10101 },
+ { 0x40c4c, 0x10101 },
+ { 0x40c50, 0x10101 },
+ { 0x40c54, 0x10101 },
+ { 0x40c58, 0x10101 },
+ { 0x40c5c, 0x10101 },
+ { 0x40c60, 0x10101 },
+ { 0x40c64, 0x10101 },
+ { 0x40c68, 0x20202 },
+ { 0x40c6c, 0x20202 },
+ { 0x40c70, 0x20202 },
+ { 0x40c74, 0x20202 },
+ { 0x40c78, 0x20202 },
+ { 0x40c7c, 0x20202 },
+ { 0x40c80, 0x30303 },
+ { 0x40c84, 0x30303 },
+ { 0x40c88, 0x30303 },
+ { 0x40c8c, 0x30303 },
+ { 0x40c90, 0x30303 },
+ { 0x40c94, 0x40404 },
+ { 0x40c98, 0x40404 },
+ { 0x40c9c, 0x40404 },
+ { 0x40ca0, 0x40404 },
+ { 0x40ca4, 0x40404 },
+ { 0x40ca8, 0x50505 },
+ { 0x40cac, 0x50505 },
+ { 0x40cb0, 0x50505 },
+ { 0x40cb4, 0x50505 },
+ { 0x40cb8, 0x60606 },
+ { 0x40cbc, 0x60606 },
+ { 0x40cc0, 0x60606 },
+ { 0x40cc4, 0x70707 },
+ { 0x40cc8, 0x70707 },
+ { 0x40ccc, 0x70707 },
+ { 0x40cd0, 0x70707 },
+ { 0x40cd4, 0x80808 },
+ { 0x40cd8, 0x80808 },
+ { 0x40cdc, 0x80808 },
+ { 0x40ce0, 0x90909 },
+ { 0x40ce4, 0x90909 },
+ { 0x40ce8, 0xa0a0a },
+ { 0x40cec, 0xa0a0a },
+ { 0x40cf0, 0xa0a0a },
+ { 0x40cf4, 0xb0b0b },
+ { 0x40cf8, 0xb0b0b },
+ { 0x40cfc, 0xb0b0b },
+ { 0x40d00, 0xc0c0c },
+ { 0x40d04, 0xc0c0c },
+ { 0x40d08, 0xd0d0d },
+ { 0x40d0c, 0xd0d0d },
+ { 0x40d10, 0xe0e0e },
+ { 0x40d14, 0xe0e0e },
+ { 0x40d18, 0xe0e0e },
+ { 0x40d1c, 0xf0f0f },
+ { 0x40d20, 0xf0f0f },
+ { 0x40d24, 0x101010 },
+ { 0x40d28, 0x101010 },
+ { 0x40d2c, 0x111111 },
+ { 0x40d30, 0x111111 },
+ { 0x40d34, 0x121212 },
+ { 0x40d38, 0x121212 },
+ { 0x40d3c, 0x131313 },
+ { 0x40d40, 0x131313 },
+ { 0x40d44, 0x141414 },
+ { 0x40d48, 0x151515 },
+ { 0x40d4c, 0x151515 },
+ { 0x40d50, 0x161616 },
+ { 0x40d54, 0x161616 },
+ { 0x40d58, 0x171717 },
+ { 0x40d5c, 0x171717 },
+ { 0x40d60, 0x181818 },
+ { 0x40d64, 0x191919 },
+ { 0x40d68, 0x191919 },
+ { 0x40d6c, 0x1a1a1a },
+ { 0x40d70, 0x1b1b1b },
+ { 0x40d74, 0x1b1b1b },
+ { 0x40d78, 0x1c1c1c },
+ { 0x40d7c, 0x1c1c1c },
+ { 0x40d80, 0x1d1d1d },
+ { 0x40d84, 0x1e1e1e },
+ { 0x40d88, 0x1f1f1f },
+ { 0x40d8c, 0x1f1f1f },
+ { 0x40d90, 0x202020 },
+ { 0x40d94, 0x212121 },
+ { 0x40d98, 0x212121 },
+ { 0x40d9c, 0x222222 },
+ { 0x40da0, 0x232323 },
+ { 0x40da4, 0x242424 },
+ { 0x40da8, 0x242424 },
+ { 0x40dac, 0x252525 },
+ { 0x40db0, 0x262626 },
+ { 0x40db4, 0x272727 },
+ { 0x40db8, 0x272727 },
+ { 0x40dbc, 0x282828 },
+ { 0x40dc0, 0x292929 },
+ { 0x40dc4, 0x2a2a2a },
+ { 0x40dc8, 0x2b2b2b },
+ { 0x40dcc, 0x2c2c2c },
+ { 0x40dd0, 0x2c2c2c },
+ { 0x40dd4, 0x2d2d2d },
+ { 0x40dd8, 0x2e2e2e },
+ { 0x40ddc, 0x2f2f2f },
+ { 0x40de0, 0x303030 },
+ { 0x40de4, 0x313131 },
+ { 0x40de8, 0x323232 },
+ { 0x40dec, 0x333333 },
+ { 0x40df0, 0x333333 },
+ { 0x40df4, 0x343434 },
+ { 0x40df8, 0x353535 },
+ { 0x40dfc, 0x363636 },
+ { 0x40e00, 0x373737 },
+ { 0x40e04, 0x383838 },
+ { 0x40e08, 0x393939 },
+ { 0x40e0c, 0x3a3a3a },
+ { 0x40e10, 0x3b3b3b },
+ { 0x40e14, 0x3c3c3c },
+ { 0x40e18, 0x3d3d3d },
+ { 0x40e1c, 0x3e3e3e },
+ { 0x40e20, 0x3f3f3f },
+ { 0x40e24, 0x404040 },
+ { 0x40e28, 0x414141 },
+ { 0x40e2c, 0x424242 },
+ { 0x40e30, 0x434343 },
+ { 0x40e34, 0x444444 },
+ { 0x40e38, 0x464646 },
+ { 0x40e3c, 0x474747 },
+ { 0x40e40, 0x484848 },
+ { 0x40e44, 0x494949 },
+ { 0x40e48, 0x4a4a4a },
+ { 0x40e4c, 0x4b4b4b },
+ { 0x40e50, 0x4c4c4c },
+ { 0x40e54, 0x4d4d4d },
+ { 0x40e58, 0x4f4f4f },
+ { 0x40e5c, 0x505050 },
+ { 0x40e60, 0x515151 },
+ { 0x40e64, 0x525252 },
+ { 0x40e68, 0x535353 },
+ { 0x40e6c, 0x545454 },
+ { 0x40e70, 0x565656 },
+ { 0x40e74, 0x575757 },
+ { 0x40e78, 0x585858 },
+ { 0x40e7c, 0x595959 },
+ { 0x40e80, 0x5b5b5b },
+ { 0x40e84, 0x5c5c5c },
+ { 0x40e88, 0x5d5d5d },
+ { 0x40e8c, 0x5e5e5e },
+ { 0x40e90, 0x606060 },
+ { 0x40e94, 0x616161 },
+ { 0x40e98, 0x626262 },
+ { 0x40e9c, 0x646464 },
+ { 0x40ea0, 0x656565 },
+ { 0x40ea4, 0x666666 },
+ { 0x40ea8, 0x686868 },
+ { 0x40eac, 0x696969 },
+ { 0x40eb0, 0x6a6a6a },
+ { 0x40eb4, 0x6c6c6c },
+ { 0x40eb8, 0x6d6d6d },
+ { 0x40ebc, 0x6f6f6f },
+ { 0x40ec0, 0x707070 },
+ { 0x40ec4, 0x717171 },
+ { 0x40ec8, 0x737373 },
+ { 0x40ecc, 0x747474 },
+ { 0x40ed0, 0x767676 },
+ { 0x40ed4, 0x777777 },
+ { 0x40ed8, 0x797979 },
+ { 0x40edc, 0x7a7a7a },
+ { 0x40ee0, 0x7c7c7c },
+ { 0x40ee4, 0x7d7d7d },
+ { 0x40ee8, 0x7f7f7f },
+ { 0x40eec, 0x808080 },
+ { 0x40ef0, 0x828282 },
+ { 0x40ef4, 0x838383 },
+ { 0x40ef8, 0x858585 },
+ { 0x40efc, 0x868686 },
+ { 0x40f00, 0x888888 },
+ { 0x40f04, 0x898989 },
+ { 0x40f08, 0x8b8b8b },
+ { 0x40f0c, 0x8d8d8d },
+ { 0x40f10, 0x8e8e8e },
+ { 0x40f14, 0x909090 },
+ { 0x40f18, 0x919191 },
+ { 0x40f1c, 0x939393 },
+ { 0x40f20, 0x959595 },
+ { 0x40f24, 0x969696 },
+ { 0x40f28, 0x989898 },
+ { 0x40f2c, 0x9a9a9a },
+ { 0x40f30, 0x9b9b9b },
+ { 0x40f34, 0x9d9d9d },
+ { 0x40f38, 0x9f9f9f },
+ { 0x40f3c, 0xa1a1a1 },
+ { 0x40f40, 0xa2a2a2 },
+ { 0x40f44, 0xa4a4a4 },
+ { 0x40f48, 0xa6a6a6 },
+ { 0x40f4c, 0xa7a7a7 },
+ { 0x40f50, 0xa9a9a9 },
+ { 0x40f54, 0xababab },
+ { 0x40f58, 0xadadad },
+ { 0x40f5c, 0xafafaf },
+ { 0x40f60, 0xb0b0b0 },
+ { 0x40f64, 0xb2b2b2 },
+ { 0x40f68, 0xb4b4b4 },
+ { 0x40f6c, 0xb6b6b6 },
+ { 0x40f70, 0xb8b8b8 },
+ { 0x40f74, 0xbababa },
+ { 0x40f78, 0xbbbbbb },
+ { 0x40f7c, 0xbdbdbd },
+ { 0x40f80, 0xbfbfbf },
+ { 0x40f84, 0xc1c1c1 },
+ { 0x40f88, 0xc3c3c3 },
+ { 0x40f8c, 0xc5c5c5 },
+ { 0x40f90, 0xc7c7c7 },
+ { 0x40f94, 0xc9c9c9 },
+ { 0x40f98, 0xcbcbcb },
+ { 0x40f9c, 0xcdcdcd },
+ { 0x40fa0, 0xcfcfcf },
+ { 0x40fa4, 0xd1d1d1 },
+ { 0x40fa8, 0xd3d3d3 },
+ { 0x40fac, 0xd5d5d5 },
+ { 0x40fb0, 0xd7d7d7 },
+ { 0x40fb4, 0xd9d9d9 },
+ { 0x40fb8, 0xdbdbdb },
+ { 0x40fbc, 0xdddddd },
+ { 0x40fc0, 0xdfdfdf },
+ { 0x40fc4, 0xe1e1e1 },
+ { 0x40fc8, 0xe3e3e3 },
+ { 0x40fcc, 0xe5e5e5 },
+ { 0x40fd0, 0xe7e7e7 },
+ { 0x40fd4, 0xe9e9e9 },
+ { 0x40fd8, 0xebebeb },
+ { 0x40fdc, 0xeeeeee },
+ { 0x40fe0, 0xf0f0f0 },
+ { 0x40fe4, 0xf2f2f2 },
+ { 0x40fe8, 0xf4f4f4 },
+ { 0x40fec, 0xf6f6f6 },
+ { 0x40ff0, 0xf8f8f8 },
+ { 0x40ff4, 0xfbfbfb },
+ { 0x40ff8, 0xfdfdfd },
+ { 0x40ffc, 0xffffff },
+};
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..0fad0a7
--- /dev/null
+++ b/drivers/video/msm/mdp_debugfs.c
@@ -0,0 +1,1423 @@
+/* Copyright (c) 2009-2012, 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;
+
+
+ if (*ppos)
+ return 0; /* the end */
+
+ bp = debug_buf;
+ dlen = sizeof(debug_buf);
+
+ len = snprintf(bp, dlen, "\nmdp:\n");
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "int_total: %08lu\t",
+ mdp4_stat.intr_tot);
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "int_overlay0: %08lu\t",
+ mdp4_stat.intr_overlay0);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "int_overlay1: %08lu\n",
+ mdp4_stat.intr_overlay1);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "int_overlay1: %08lu\n",
+ mdp4_stat.intr_overlay2);
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "int_dmap: %08lu\t",
+ mdp4_stat.intr_dma_p);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "int_dmas: %08lu\t",
+ mdp4_stat.intr_dma_s);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "int_dmae: %08lu\n",
+ mdp4_stat.intr_dma_e);
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "primary: vsync: %08lu\t",
+ mdp4_stat.intr_vsync_p);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "underrun: %08lu\n",
+ mdp4_stat.intr_underrun_p);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "external: vsync: %08lu\t",
+ mdp4_stat.intr_vsync_e);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "underrun: %08lu\n",
+ mdp4_stat.intr_underrun_e);
+
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "histogram: %08lu\t",
+ mdp4_stat.intr_histogram);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "read_ptr: %08lu\n\n",
+ mdp4_stat.intr_rdptr);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "dsi:\n");
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "int_total: %08lu\tmdp_start: %08lu\n",
+ mdp4_stat.intr_dsi, mdp4_stat.dsi_mdp_start);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "int_cmd: %08lu\t",
+ mdp4_stat.intr_dsi_cmd);
+
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "int_mdp: %08lu\t",
+ mdp4_stat.intr_dsi_mdp);
+
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "int_err: %08lu\n",
+ mdp4_stat.intr_dsi_err);
+
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "clk_on : %08lu\t",
+ mdp4_stat.dsi_clk_on);
+
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "clk_off: %08lu\n\n",
+ mdp4_stat.dsi_clk_off);
+
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "kickoff:\n");
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "overlay0: %08lu\t",
+ mdp4_stat.kickoff_ov0);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "dmap: %08lu\t",
+ mdp4_stat.kickoff_dmap);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "dmas: %08lu\n",
+ mdp4_stat.kickoff_dmas);
+
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "overlay1: %08lu\t",
+ mdp4_stat.kickoff_ov1);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "dmae: %08lu\n\n",
+ mdp4_stat.kickoff_dmae);
+
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "overlay0_play:\n");
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "set: %08lu\t",
+ mdp4_stat.overlay_set[0]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "unset: %08lu\t",
+ mdp4_stat.overlay_unset[0]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "play: %08lu\t",
+ mdp4_stat.overlay_play[0]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "commit: %08lu\n",
+ mdp4_stat.overlay_commit[0]);
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "overlay1_play:\n");
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "set: %08lu\t",
+ mdp4_stat.overlay_set[1]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "unset: %08lu\t",
+ mdp4_stat.overlay_unset[1]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "play: %08lu\t",
+ mdp4_stat.overlay_play[1]);
+
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "commit: %08lu\n\n",
+ mdp4_stat.overlay_commit[1]);
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "frame_push:\n");
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "vg1 : %08lu\t", mdp4_stat.pipe[0]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "vg2 : %08lu\t", mdp4_stat.pipe[1]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "vg3 : %08lu\n", mdp4_stat.pipe[5]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "rgb1: %08lu\t", mdp4_stat.pipe[2]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "rgb2: %08lu\t", mdp4_stat.pipe[3]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "rgb3: %08lu\n\n", mdp4_stat.pipe[4]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "wait4vsync: ");
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "mixer0 : %08lu\t", mdp4_stat.wait4vsync0);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "mixer1: %08lu\n\n", mdp4_stat.wait4vsync1);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "iommu: ");
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "map : %08lu\t", mdp4_stat.iommu_map);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "unmap: %08lu\t", mdp4_stat.iommu_unmap);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "drop: %08lu\n\n", mdp4_stat.iommu_drop);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "err_mixer : %08lu\t", 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\t", mdp4_stat.err_scale);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "err_format: %08lu\n", mdp4_stat.err_format);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "err_play : %08lu\t", mdp4_stat.err_play);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "err_stage : %08lu\n", mdp4_stat.err_stage);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "err_underflow: %08lu\n\n",
+ mdp4_stat.err_underflow);
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "writeback:\n");
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "dsi_cmd: %08lu\t",
+ mdp4_stat.blt_dsi_cmd);
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "dsi_video: %08lu\n",
+ mdp4_stat.blt_dsi_video);
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "lcdc: %08lu\t",
+ mdp4_stat.blt_lcdc);
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "dtv: %08lu\t",
+ mdp4_stat.blt_dtv);
+ bp += len;
+ dlen -= len;
+
+ len = snprintf(bp, dlen, "mddi: %08lu\n\n",
+ mdp4_stat.blt_mddi);
+ 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..da9761e
--- /dev/null
+++ b/drivers/video/msm/mdp_dma.c
@@ -0,0 +1,627 @@
+/* Copyright (c) 2008-2012, 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
+
+ spin_lock_bh(&dsi_clk_lock);
+ if (mipi_dsi_clk_on == 0)
+ mipi_dsi_turn_on_clks();
+ spin_unlock_bh(&dsi_clk_lock);
+#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_dma_vsync_ctrl(int enable)
+{
+ if (vsync_cntrl.vsync_irq_enabled == enable)
+ return;
+
+ vsync_cntrl.vsync_irq_enabled = enable;
+
+ if (enable) {
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ MDP_OUTP(MDP_BASE + 0x021c, 0x10); /* read pointer */
+ mdp3_vsync_irq_enable(MDP_PRIM_RDPTR, MDP_VSYNC_TERM);
+ } else {
+ mdp3_vsync_irq_disable(MDP_PRIM_RDPTR, MDP_VSYNC_TERM);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ }
+}
+
+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;
+ struct fb_info *fbi = mfd->fbi;
+ MDPIBUF *iBuf;
+ int bpp = info->var.bits_per_pixel / 8;
+
+ down(&mfd->sem);
+
+ iBuf = &mfd->ibuf;
+ if (mfd->map_buffer)
+ iBuf->buf = (uint8 *)mfd->map_buffer->iova[0];
+ else
+ iBuf->buf = (uint8 *) info->fix.smem_start;
+
+ iBuf->buf += calc_fb_offset(mfd, fbi, bpp);
+
+ 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..8a41c78
--- /dev/null
+++ b/drivers/video/msm/mdp_dma_dsi_video.c
@@ -0,0 +1,292 @@
+/* Copyright (c) 2011-2012, 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;
+ uint32 mask, curr;
+
+ 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;
+
+ vsync_cntrl.dev = mfd->fbi->dev;
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+
+ buf += calc_fb_offset(mfd, fbi, bpp);
+
+ 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 */
+ curr = inpdw(MDP_BASE + 0x90000);
+ mask = 0xBFFFFFFF;
+ dma2_cfg_reg = (dma2_cfg_reg & mask) | (curr & ~mask);
+ 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_dma_video_vsync_ctrl(int enable)
+{
+ if (vsync_cntrl.vsync_irq_enabled == enable)
+ return;
+
+ vsync_cntrl.vsync_irq_enabled = enable;
+
+ if (enable) {
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ mdp3_vsync_irq_enable(LCDC_FRAME_START, MDP_VSYNC_TERM);
+ } else {
+ mdp3_vsync_irq_disable(LCDC_FRAME_START, MDP_VSYNC_TERM);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ }
+}
+
+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 += calc_fb_offset(mfd, fbi, bpp);
+
+ /* 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..d576c46
--- /dev/null
+++ b/drivers/video/msm/mdp_dma_lcdc.c
@@ -0,0 +1,390 @@
+/* Copyright (c) 2008-2009, 2012 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;
+ vsync_cntrl.dev = mfd->fbi->dev;
+
+ /* 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 += calc_fb_offset(mfd, fbi, bpp);
+
+ 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
+
+ down(&mfd->dma->mutex);
+ /* 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);
+ up(&mfd->dma->mutex);
+
+ /* delay to make sure the last frame finishes */
+ msleep(16);
+
+ return ret;
+}
+
+void mdp_dma_lcdc_vsync_ctrl(int enable)
+{
+ if (vsync_cntrl.vsync_irq_enabled == enable)
+ return;
+
+ vsync_cntrl.vsync_irq_enabled = enable;
+
+ if (enable) {
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ mdp3_vsync_irq_enable(LCDC_FRAME_START, MDP_VSYNC_TERM);
+ } else {
+ mdp3_vsync_irq_disable(LCDC_FRAME_START, MDP_VSYNC_TERM);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ }
+}
+
+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;
+
+ down(&mfd->dma->mutex);
+ /* 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 += calc_fb_offset(mfd, fbi, bpp);
+
+ 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);
+ up(&mfd->dma->mutex);
+}
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..b578ba2
--- /dev/null
+++ b/drivers/video/msm/mdp_dma_tv.c
@@ -0,0 +1,140 @@
+/* Copyright (c) 2008-2009, 2012 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 += calc_fb_offset(mfd, fbi, bpp);
+
+ /* 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 += calc_fb_offset(mfd, fbi, bpp);
+
+ 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 66d37d7..f35a757 100644
--- a/drivers/video/msm/mdp_hw.h
+++ b/drivers/video/msm/mdp_hw.h
@@ -47,106 +47,11 @@
char * __iomem base;
int irq;
struct clk *clk;
- struct clk *pclk;
struct clk *ebi1_clk;
-#ifdef CONFIG_MDP4_HW_VSYNC
- struct clk *vsync_clk;
-#endif
struct mdp_out_interface out_if[MSM_MDP_NUM_INTERFACES];
- int dma_format;
- int dma_pack_pattern;
+ int format;
+ int pack_pattern;
bool dma_config_dirty;
- struct mdp_blit_req *req;
- uint32_t state;
- struct timer_list standby_timer;
- struct timer_list dma_timer;
-#ifdef CONFIG_MSM_MDP40
- int hw_version;
-#endif
-#ifdef CONFIG_MDP4_HW_VSYNC
- int total_lcd_line;
-#endif
- int (*enable_irq)(struct mdp_info *mdp, uint32_t mask);
- int (*disable_irq)(struct mdp_info *mdp, uint32_t mask);
- int (*write_regs)(struct mdp_info *mdp, const struct mdp_reg *reglist, int size);
-};
-
-struct mdp_lcdc_info {
- struct mdp_info *mdp;
- struct clk *mdp_clk;
- struct clk *mdp_pclk;
- 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;
- unsigned color_format;
- 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;
-};
-
-struct mdp_dtv_info {
- struct mdp_info *mdp;
- struct clk *mdp_clk;
- struct clk *tv_enc_clk;
- struct clk *tv_dac_clk;
- struct clk *tv_src_clk;
- struct clk *hdmi_clk;
- struct clk *mdp_tv_clk;
- struct msm_panel_data fb_panel_data;
- struct platform_device fb_pdev;
- struct msm_lcdc_platform_data *pdata;
- char *fb_base;
- uint32_t fb_start;
- uint32_t fb_size;
- bool active;
-
- struct msmfb_callback frame_start_cb;
- wait_queue_head_t vsync_waitq;
- int got_vsync;
- unsigned color_format;
- 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;
-
- void (*dtv_relay)(struct mdp_dtv_info *dtv, int on_off);
- void (*dtv_reconfig_timing)(struct mdp_dtv_info *dtv,
- struct msm_lcdc_timing *timing, struct msm_fb_data *fb_data);
-};
-
-
-struct panel_icm_info {
- bool icm_mode;
- bool icm_doable;
- bool clock_enabled;
- int panel_update;
- bool icm_suspend;
- struct mutex icm_lock;
- struct mdp_lcdc_info *lcdc;
- spinlock_t lock;
- void (*force_leave)(void);
};
extern int mdp_out_if_register(struct mdp_device *mdp_dev, int interface,
@@ -158,74 +63,33 @@
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);
-struct msm_mdp_platform_data;
void mdp_ppp_dump_debug(const struct mdp_info *mdp);
-int mdp_hw_init(struct mdp_info *mdp);
-void mdp_check_tearing(struct mdp_info *mdp, struct msm_mdp_platform_data *pdata);
-void mdp_dump_blit(struct mdp_blit_req *req);
-int mdp_wait(struct mdp_info *mdp, uint32_t mask, wait_queue_head_t *wq);
#define mdp_writel(mdp, value, offset) writel(value, mdp->base + offset)
#define mdp_readl(mdp, offset) readl(mdp->base + offset)
-#define panel_to_lcdc(p) container_of((p), struct mdp_lcdc_info, fb_panel_data)
-#define panel_to_dtv(p) container_of((p), struct mdp_dtv_info, fb_panel_data)
-/* define mdp state for multi purpose */
-#define MDP_STATE_STANDBY (1 << 0)
-
-#define MDP4_REVISION_V1 0
-#define MDP4_REVISION_V2 1
-#define MDP4_REVISION_V2_1 2
-#define MDP4_REVISION_NONE 0xffffffff
-#define MDP_AXI_RDMASTER_CONFIG (0x00028)
-
-#ifdef CONFIG_MSM_MDP302
-#define MDP_SYNC_CONFIG_0 (0x00300)
-#define MDP_SYNC_CONFIG_1 (0x00304)
-#define MDP_SYNC_CONFIG_2 (0x00308)
-#else
#define MDP_SYNC_CONFIG_0 (0x00000)
#define MDP_SYNC_CONFIG_1 (0x00004)
#define MDP_SYNC_CONFIG_2 (0x00008)
-#endif
-
#define MDP_SYNC_STATUS_0 (0x0000c)
#define MDP_SYNC_STATUS_1 (0x00010)
#define MDP_SYNC_STATUS_2 (0x00014)
-
-#ifdef CONFIG_MSM_MDP302
-#define MDP_SYNC_THRESH_0 (0x00200)
-#define MDP_SYNC_THRESH_1 (0x00204)
-#else
#define MDP_SYNC_THRESH_0 (0x00018)
#define MDP_SYNC_THRESH_1 (0x0001c)
-#endif
-#ifdef CONFIG_MSM_MDP40
-#define MDP_INTR_ENABLE (0x0050)
-#define MDP_INTR_STATUS (0x0054)
-#define MDP_INTR_CLEAR (0x0058)
-#define MDP_EBI2_LCD0 (0x0060)
-#define MDP_EBI2_LCD1 (0x0064)
-#define MDP_EBI2_PORTMAP_MODE (0x0070)
-
-#define MDP_DMA_P_HIST_INTR_STATUS (0x95014)
-#define MDP_DMA_P_HIST_INTR_CLEAR (0x95018)
-#define MDP_DMA_P_HIST_INTR_ENABLE (0x9501C)
-#else
#define MDP_INTR_ENABLE (0x00020)
#define MDP_INTR_STATUS (0x00024)
#define MDP_INTR_CLEAR (0x00028)
-#define MDP_EBI2_LCD0 (0x0003c)
-#define MDP_EBI2_LCD1 (0x00040)
-#define MDP_EBI2_PORTMAP_MODE (0x0005c)
-#endif
#define MDP_DISPLAY0_START (0x00030)
#define MDP_DISPLAY1_START (0x00034)
#define MDP_DISPLAY_STATUS (0x00038)
-/* CONFIG_MSM_MDP302 */
-#define MDP_TEAR_CHECK_EN (0x0020c)
-#define MDP_PRIM_START_POS (0x00210)
+#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)
@@ -248,14 +112,6 @@
#define MDP_VSYNC_CTRL (0x0008c)
#define MDP_MDDI_PARAM_WR_SEL (0x00090)
#define MDP_MDDI_PARAM (0x00094)
-#define MDP_MDDI_DATA_XFR (0x00098)
-
-
-#if defined(CONFIG_MSM_MDP40)
-#define MDP_LAYERMIXER_IN_CFG (0x10100)
-#define MDP_OVERLAYPROC0_CFG (0x10004)
-#define MDP_OVERLAYPROC1_CFG (0x18004)
-#endif
#define MDP_CGC_EN (0x00100)
#define MDP_CMD_STATUS (0x10008)
#define MDP_PROFILE_EN (0x10010)
@@ -371,11 +227,7 @@
#define MDP_TEST_CAPTURED_DCLK (0xd0210)
#define MDP_TEST_MISR_CAPT_VAL_DCLK (0xd0214)
-#ifdef CONFIG_MSM_MDP40
-#define MDP_DMA_P_START (0x000c)
-#else
#define MDP_DMA_P_START (0x00044)
-#endif
#define MDP_DMA_P_CONFIG (0x90000)
#define MDP_DMA_P_SIZE (0x90004)
#define MDP_DMA_P_IBUF_ADDR (0x90008)
@@ -383,45 +235,6 @@
#define MDP_DMA_P_OUT_XY (0x90010)
#define MDP_DMA_P_COLOR_CORRECT_CONFIG (0x90070)
-#define MDP_DMA_S_START (0x00048)
-#define MDP_DMA_S_CONFIG (0xa0000)
-#define MDP_DMA_S_SIZE (0xa0004)
-#define MDP_DMA_S_IBUF_ADDR (0xa0008)
-#define MDP_DMA_S_IBUF_Y_STRIDE (0xa000c)
-#define MDP_DMA_S_OUT_XY (0xa0010)
-
-#ifdef CONFIG_MSM_MDP40
-#define MDP_LCDC_EN (0xc0000)
-#define MDP_LCDC_HSYNC_CTL (0xc0004)
-#define MDP_LCDC_VSYNC_PERIOD (0xc0008)
-#define MDP_LCDC_VSYNC_PULSE_WIDTH (0xc000c)
-#define MDP_LCDC_DISPLAY_HCTL (0xc0010)
-#define MDP_LCDC_DISPLAY_V_START (0xc0014)
-#define MDP_LCDC_DISPLAY_V_END (0xc0018)
-#define MDP_LCDC_ACTIVE_HCTL (0xc001c)
-#define MDP_LCDC_ACTIVE_V_START (0xc0020)
-#define MDP_LCDC_ACTIVE_V_END (0xc0024)
-#define MDP_LCDC_BORDER_CLR (0xc0028)
-#define MDP_LCDC_UNDERFLOW_CTL (0xc002c)
-#define MDP_LCDC_HSYNC_SKEW (0xc0030)
-#define MDP_LCDC_TEST_CTL (0xc0034)
-#define MDP_LCDC_CTL_POLARITY (0xc0038)
-
-#define MDP_DTV_EN (0xd0000)
-#define MDP_DTV_HSYNC_CTL (0xd0004)
-#define MDP_DTV_VSYNC_PERIOD (0xd0008)
-#define MDP_DTV_VSYNC_PULSE_WIDTH (0xd000c)
-#define MDP_DTV_DISPLAY_HCTL (0xd0018)
-#define MDP_DTV_DISPLAY_V_START (0xd001c)
-#define MDP_DTV_DISPLAY_V_END (0xd0020)
-#define MDP_DTV_ACTIVE_HCTL (0xd002c)
-#define MDP_DTV_ACTIVE_V_START (0xd0030)
-#define MDP_DTV_ACTIVE_V_END (0xd0038)
-#define MDP_DTV_BORDER_CLR (0xd0040)
-#define MDP_DTV_UNDERFLOW_CTL (0xd0044)
-#define MDP_DTV_HSYNC_SKEW (0xd0048)
-#define MDP_DTV_CTL_POLARITY (0xd0050)
-#else
#define MDP_LCDC_EN (0xe0000)
#define MDP_LCDC_HSYNC_CTL (0xe0004)
#define MDP_LCDC_VSYNC_PERIOD (0xe0008)
@@ -437,7 +250,6 @@
#define MDP_LCDC_HSYNC_SKEW (0xe0030)
#define MDP_LCDC_TEST_CTL (0xe0034)
#define MDP_LCDC_CTL_POLARITY (0xe0038)
-#endif
#define MDP_PPP_SCALE_STATUS (0x50000)
#define MDP_PPP_BLEND_STATUS (0x70000)
@@ -449,31 +261,15 @@
#define DL0_ROI_DONE (1<<0)
#define TV_OUT_DMA3_DONE (1<<6)
#define TV_ENC_UNDERRUN (1<<7)
-#define TV_OUT_FRAME_START (1<<13)
-#define MDP_HIST_DONE (1<<20)
#ifdef CONFIG_MSM_MDP22
#define MDP_DMA_P_DONE (1 << 2)
-#define MDP_DMA_S_DONE (1 << 3)
#else /* CONFIG_MSM_MDP31 */
-
-#ifdef CONFIG_MSM_MDP40
-#define MDP_DMA_P_DONE (1 << 4)
-#else
#define MDP_DMA_P_DONE (1 << 14)
-#endif
-
-#define MDP_DMA_S_DONE (1 << 2)
#define MDP_LCDC_UNDERFLOW (1 << 16)
-
-#ifdef CONFIG_MSM_MDP40
-#define MDP_LCDC_FRAME_START (1 << 7)
-#else
#define MDP_LCDC_FRAME_START (1 << 15)
#endif
-#endif
-
#define MDP_TOP_LUMA 16
#define MDP_TOP_CHROMA 0
#define MDP_BOTTOM_LUMA 19
@@ -497,15 +293,9 @@
(((a)<<(bit*3))|((x)<<(bit*2))|((y)<<bit)|(z))
/* MDP_SYNC_CONFIG_0/1/2 */
-#if defined(CONFIG_MSM_MDP30)
-#define MDP_SYNCFG_HGT_LOC 21
-#define MDP_SYNCFG_VSYNC_EXT_EN (1<<20)
-#define MDP_SYNCFG_VSYNC_INT_EN (1<<19)
-#else
#define MDP_SYNCFG_HGT_LOC 22
#define MDP_SYNCFG_VSYNC_EXT_EN (1<<21)
#define MDP_SYNCFG_VSYNC_INT_EN (1<<20)
-#endif
/* MDP_SYNC_THRESH_0 */
#define MDP_PRIM_BELOW_LOC 0
@@ -518,11 +308,11 @@
/* MDP_VSYNC_CTRL */
#define DISP0_VSYNC_MAP_VSYNC0 0
#define DISP0_VSYNC_MAP_VSYNC1 (1<<0)
-#define DISP0_VSYNC_MAP_VSYNC2 (1<<0)|(1<<1)
+#define DISP0_VSYNC_MAP_VSYNC2 ((1<<0)|(1<<1))
#define DISP1_VSYNC_MAP_VSYNC0 0
#define DISP1_VSYNC_MAP_VSYNC1 (1<<2)
-#define DISP1_VSYNC_MAP_VSYNC2 (1<<2)|(1<<3)
+#define DISP1_VSYNC_MAP_VSYNC2 ((1<<2)|(1<<3))
#define PRIMARY_LCD_SYNC_EN (1<<4)
#define PRIMARY_LCD_SYNC_DISABLE 0
@@ -953,32 +743,13 @@
#define DMA_IBUF_FORMAT_MASK (1 << 20)
#define DMA_IBUF_NONCONTIGUOUS (1<<21)
-#elif defined(CONFIG_MSM_MDP30)
-
-#define DMA_OUT_SEL_AHB 0
-#define DMA_OUT_SEL_MDDI (1<<19)
-#define DMA_AHBM_LCD_SEL_PRIMARY 0
-#define DMA_AHBM_LCD_SEL_SECONDARY (0)
-#define DMA_IBUF_C3ALPHA_EN (0)
-#define DMA_DITHER_EN (1<<24)
-
-#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_MASK (1 << 20)
-#define DMA_IBUF_FORMAT_RGB565 (1<<25)
-#define DMA_IBUF_FORMAT_RGB888_OR_ARGB8888 (1<<26)
-#define DMA_IBUF_NONCONTIGUOUS (0)
-
-#else /* CONFIG_MSM_MDP31 | CONFIG_MSM_MDP302 */
+#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_DEFLKR_EN (1 << 24) /* dma_e */
#define DMA_IBUF_FORMAT_RGB888 (0 << 25)
#define DMA_IBUF_FORMAT_RGB565 (1 << 25)
#define DMA_IBUF_FORMAT_XRGB8888 (2 << 25)
@@ -991,9 +762,7 @@
#endif
/* MDDI REGISTER ? */
-#define MDDI_VDO_PACKET_DESC_RGB565 0x5565
-#define MDDI_VDO_PACKET_DESC_RGB666 0x5666
-#define MDDI_VDO_PACKET_DESC_RGB888 0x5888
+#define MDDI_VDO_PACKET_DESC 0x5666
#define MDDI_VDO_PACKET_PRIM 0xC3
#define MDDI_VDO_PACKET_SECD 0xC0
diff --git a/drivers/video/msm/mdp_hw40.c b/drivers/video/msm/mdp_hw40.c
new file mode 100644
index 0000000..a642c9b
--- /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 */
+ clk_set_rate(mdp->clk, 122880000); /* 122.88 Mhz */
+ 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..ff3ad41
--- /dev/null
+++ b/drivers/video/msm/mdp_hw_init.c
@@ -0,0 +1,714 @@
+/* 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);
+#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
index 4c3deb6..62b0975 100644
--- a/drivers/video/msm/mdp_lcdc.c
+++ b/drivers/video/msm/mdp_lcdc.c
@@ -1,7 +1,7 @@
/* drivers/video/msm/mdp_lcdc.c
*
* Copyright (c) 2009 Google Inc.
- * Copyright (c) 2009 QUALCOMM Incorporated
+ * 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
@@ -23,202 +23,52 @@
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/delay.h>
-#include <linux/slab.h>
#include <asm/io.h>
#include <asm/mach-types.h>
-#include <linux/msm_mdp.h>
+
#include <mach/msm_fb.h>
-#include <mach/debug_display.h>
#include "mdp_hw.h"
-#ifdef CONFIG_MSM_MDP40
-#include "mdp4.h"
-#endif
-#ifdef CONFIG_PANEL_SELF_REFRESH
-#include <linux/kthread.h>
-#endif
-#if 0
-#define D(fmt, args...) printk(KERN_INFO "Dispaly: " fmt, ##args)
-#else
-#define D(fmt, args...) do {} while (0)
-#endif
+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;
-#if defined(CONFIG_ARCH_MSM7227)
-#define LCDC_MUX_CTL (MSM_TGPIO1_BASE + 0x278)
-#endif
+ 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;
-#ifdef CONFIG_MSM_MDP40
-static struct mdp4_overlay_pipe *lcdc_pipe;
-#endif
-
-#ifdef CONFIG_PANEL_SELF_REFRESH
-#if 0
-#define ICM_DBG(s...) printk("[icm]" s)
-#else
-#define ICM_DBG(s...) do {} while (0)
-#endif
-
-/* set the timeout to 200 milliseconds */
-#define PANEL_ENTER_IDLE_TIMEOUT HZ/5
-/* Afetr setting ICM=1, we need to keep sending the RGB signal more than 2-frame */
-#define PANEL_IDLE_STABLE_TIMEOUT 48
-
-static struct task_struct *th_display;
-struct panel_icm_info *panel_icm;
-DECLARE_WAIT_QUEUE_HEAD(panel_update_wait_queue);
-#endif
-
-#ifdef CONFIG_PANEL_SELF_REFRESH
-static int icm_check_panel_update(void)
-{
- int ret;
- unsigned long irq_flags = 0;
-
- spin_lock_irqsave(&panel_icm->lock, irq_flags);
- ret = panel_icm->panel_update;
- spin_unlock_irqrestore(&panel_icm->lock, irq_flags);
- return ret;
-}
-
-static int icm_thread(void *data)
-{
- struct mdp_lcdc_info *lcdc;
- struct msm_lcdc_panel_ops *panel_ops;
- int rc;
- unsigned long irq_flags = 0;
-
- lcdc = data;
- panel_ops = lcdc->pdata->panel_ops;
- while (1) {
- rc = wait_event_timeout(panel_update_wait_queue, icm_check_panel_update() == 1, PANEL_ENTER_IDLE_TIMEOUT);
- ICM_DBG("ICM Thread:wake up rc=%d \n", rc);
- mutex_lock(&panel_icm->icm_lock);
- if (rc == 0 && icm_check_panel_update() != 1) {/* wait_timeout */
- ICM_DBG("EnterICM: icm_mode=%d icm_doable=%d \n", panel_icm->icm_mode, panel_icm->icm_doable);
- if (panel_icm->icm_mode == false && panel_icm->icm_doable == true) {
-
- if (panel_ops->refresh_enable)
- panel_ops->refresh_enable(panel_ops);
-
- panel_icm->icm_mode = true;
- msleep(PANEL_IDLE_STABLE_TIMEOUT);
-
- mdp_writel(lcdc->mdp, 0, MDP_LCDC_EN);
- clk_disable(lcdc->pad_pclk);
- clk_disable(lcdc->pclk);
- clk_disable(lcdc->mdp_clk);
- panel_icm->clock_enabled = false;
- PR_DISP_DEBUG("EnterICM: enter ICM MODE done!!!\n");
- }
- } else {/* get update event, no timeout */
- ICM_DBG("Leave ICM: icm_mode=%d icm_doable=%d \n", panel_icm->icm_mode, panel_icm->icm_doable);
- if (panel_icm->icm_mode == true && panel_icm->icm_doable == true) {
- clk_enable(lcdc->mdp_clk);
- clk_enable(lcdc->pclk);
- clk_enable(lcdc->pad_pclk);
- mdp_writel(lcdc->mdp, 1, MDP_LCDC_EN);
- panel_icm->clock_enabled = true;
-
- if (panel_ops->refresh_disable)
- panel_ops->refresh_disable(panel_ops);
-
- panel_icm->icm_mode = false;
- PR_DISP_DEBUG("LeaveICM: leave ICM MODE done !!!\n");
- }
- spin_lock_irqsave(&panel_icm->lock, irq_flags);
- panel_icm->panel_update = 0;
- spin_unlock_irqrestore(&panel_icm->lock, irq_flags);
- }
- mutex_unlock(&panel_icm->icm_lock);
- } /* end while */
- return 0;
-}
-
-static void icm_force_leave(void)
-{
- struct msm_lcdc_panel_ops *panel_ops;
- unsigned long irq_flags = 0;
-
- panel_ops = panel_icm->lcdc->pdata->panel_ops;
-
- mutex_lock(&panel_icm->icm_lock);
- ICM_DBG("Force Leave ICM: icm_mode=%d icm_doable=%d \n", panel_icm->icm_mode, panel_icm->icm_doable);
- if (panel_icm->icm_mode == true) {
- clk_enable(panel_icm->lcdc->mdp_clk);
- clk_enable(panel_icm->lcdc->pclk);
- clk_enable(panel_icm->lcdc->pad_pclk);
- mdp_writel(panel_icm->lcdc->mdp, 1, MDP_LCDC_EN);
- panel_icm->clock_enabled = true;
- if (panel_ops->refresh_disable)
- panel_ops->refresh_disable(panel_ops);
- panel_icm->icm_mode = false;
- panel_icm->icm_doable = true;
- PR_DISP_INFO("ForceLeaveICM: leave ICM MODE done !!!\n");
- }
- spin_lock_irqsave(&panel_icm->lock, irq_flags);
- panel_icm->panel_update = 0;
- spin_unlock_irqrestore(&panel_icm->lock, irq_flags);
- mutex_unlock(&panel_icm->icm_lock);
-}
-
-static int icm_init(struct mdp_lcdc_info *lcdc)
-{
- int ret = 0;
-
- /* init panel_icm_info */
- panel_icm = kzalloc(sizeof(struct panel_icm_info), GFP_KERNEL);
- if (!panel_icm)
- return -ENOMEM;
- panel_icm->icm_doable = 1;
- panel_icm->clock_enabled = true;
- panel_icm->lcdc = lcdc;
- panel_icm->force_leave = icm_force_leave;
- panel_icm->icm_suspend = false;
- mutex_init(&panel_icm->icm_lock);
- th_display = kthread_run(icm_thread, lcdc, "panel-enterIdle");
- if (IS_ERR(th_display)) {
- ret = PTR_ERR(th_display);
- PR_DISP_ERR("%s: panel_icm_thread create fail:%d!!!\n", __func__, ret);
- goto error_create_thread;
- }
- return ret;
-error_create_thread:
- kfree(panel_icm);
- return ret;
-}
-#endif
-#ifdef CONFIG_FB_MSM_WRITE_BACK
-void mdp4_lcdc_overlay_blt(ulong addr)
-{
- unsigned long flag;
-
- spin_lock_irqsave(&mdp_spin_lock, flag);
- lcdc_pipe->blt_addr = addr;
- lcdc_pipe->blt_cnt = 0;
- spin_unlock_irqrestore(&mdp_spin_lock, flag);
- mdp_writel(lcdc_pipe->mdp, 0x0, 0xc0000);
- mdelay(100);
- mdp4_overlayproc_cfg(lcdc_pipe);
- mdp4_overlay_dmap_xy(lcdc_pipe);
- mdelay(100);
- mdp_writel(lcdc_pipe->mdp, 0x1, 0xc0000);
-}
-#endif
+#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_DISP_INFO("%s: ()\n", __func__);
-
- if (panel_ops->unblank)
- panel_ops->unblank(panel_ops);
+ pr_info("%s: ()\n", __func__);
+ panel_ops->unblank(panel_ops);
return 0;
}
@@ -228,23 +78,8 @@
struct mdp_lcdc_info *lcdc = panel_to_lcdc(fb_panel);
struct msm_lcdc_panel_ops *panel_ops = lcdc->pdata->panel_ops;
- PR_DISP_INFO("%s: ()\n", __func__);
-
- if (panel_ops->blank)
- panel_ops->blank(panel_ops);
-
- return 0;
-}
-
-static int lcdc_shutdown(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_DISP_INFO("%s: ()\n", __func__);
-
- if (panel_ops->shutdown)
- panel_ops->shutdown(panel_ops);
+ pr_info("%s: ()\n", __func__);
+ panel_ops->blank(panel_ops);
return 0;
}
@@ -252,46 +87,13 @@
static int lcdc_suspend(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_DISP_INFO("%s: suspending\n", __func__);
+ pr_info("%s: suspending\n", __func__);
-#if defined(CONFIG_ARCH_MSM7227)
- writel(0x0, LCDC_MUX_CTL);
- D("suspend_lcdc_mux_ctl = %x\n", readl(LCDC_MUX_CTL));
-#endif
-#ifdef CONFIG_PANEL_SELF_REFRESH
- if (lcdc->mdp->mdp_dev.overrides & MSM_MDP_RGB_PANEL_SELE_REFRESH) {
- mutex_lock(&panel_icm->icm_lock);
- panel_icm->icm_doable = false;
- panel_icm->icm_suspend = true;
- PR_DISP_INFO("[ICM %s]: icm mode=%d, clock_enabled=%d\n", __func__, panel_icm->icm_mode, panel_icm->clock_enabled);
- if (panel_icm->icm_mode == true && panel_icm->clock_enabled == false) {
- if (panel_ops->refresh_disable)
- panel_ops->refresh_disable(panel_ops);
- panel_icm->icm_mode = false;
- } else {
- mdp_writel(lcdc->mdp, 0, MDP_LCDC_EN);
- clk_disable(lcdc->pad_pclk);
- clk_disable(lcdc->pclk);
- clk_disable(lcdc->mdp_clk);
- }
- panel_icm->clock_enabled = false;
- mutex_unlock(&panel_icm->icm_lock);
- } else {
- mdp_writel(lcdc->mdp, 0, MDP_LCDC_EN);
- clk_disable(lcdc->pad_pclk);
- clk_disable(lcdc->pclk);
- clk_disable(lcdc->mdp_clk);
- }
-#else
mdp_writel(lcdc->mdp, 0, MDP_LCDC_EN);
- clk_disable(lcdc->pad_pclk);
- clk_disable(lcdc->pclk);
- clk_disable(lcdc->mdp_clk);
-#endif
- if (panel_ops->uninit)
- panel_ops->uninit(panel_ops);
+ clk_disable_unprepare(lcdc->pad_pclk);
+ clk_disable_unprepare(lcdc->pclk);
+ clk_disable_unprepare(lcdc->mdp_clk);
return 0;
}
@@ -299,33 +101,13 @@
static int lcdc_resume(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_DISP_INFO("%s: resuming\n", __func__);
+ pr_info("%s: resuming\n", __func__);
- if (panel_ops->init) {
- if (panel_ops->init(panel_ops) < 0)
- PR_DISP_ERR("LCD init fail!\n");
- }
-
- clk_enable(lcdc->mdp_clk);
- clk_enable(lcdc->pclk);
- clk_enable(lcdc->pad_pclk);
-#if defined(CONFIG_ARCH_MSM7227)
- writel(0x1, LCDC_MUX_CTL);
- D("resume_lcdc_mux_ctl = %x\n", readl(LCDC_MUX_CTL));
-#endif
-
+ clk_prepare_enable(lcdc->mdp_clk);
+ clk_prepare_enable(lcdc->pclk);
+ clk_prepare_enable(lcdc->pad_pclk);
mdp_writel(lcdc->mdp, 1, MDP_LCDC_EN);
-#ifdef CONFIG_PANEL_SELF_REFRESH
- if (lcdc->mdp->mdp_dev.overrides & MSM_MDP_RGB_PANEL_SELE_REFRESH) {
- mutex_lock(&panel_icm->icm_lock);
- panel_icm->icm_doable = true;
- panel_icm->clock_enabled = true;
- panel_icm->icm_suspend = false;
- mutex_unlock(&panel_icm->icm_lock);
- }
-#endif
return 0;
}
@@ -335,16 +117,13 @@
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_prepare_enable(lcdc->mdp_clk);
+ clk_prepare_enable(lcdc->pclk);
+ clk_prepare_enable(lcdc->pad_pclk);
-#ifdef CONFIG_MSM_MDP40
- mdp_writel(lcdc->mdp, 0, MDP_LCDC_EN);
- mdelay(10);
-#endif
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);
@@ -362,29 +141,26 @@
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);
- if (lcdc->mdp->mdp_dev.overrides & MSM_MDP_DMA_PACK_ALIGN_LSB)
- dma_cfg &= ~DMA_PACK_ALIGN_MSB;
- else
- dma_cfg |= DMA_PACK_ALIGN_MSB;
-
- dma_cfg |= (DMA_PACK_PATTERN_RGB |
+ 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 (lcdc->color_format == MSM_MDP_OUT_IF_FMT_RGB565)
- dma_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
- else if (lcdc->color_format == MSM_MDP_OUT_IF_FMT_RGB666)
+
+ 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 if (lcdc->color_format == MSM_MDP_OUT_IF_FMT_RGB888)
- dma_cfg |= DMA_DSTC0G_8BITS | DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
+ else
+ dma_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
mdp_writel(lcdc->mdp, dma_cfg, MDP_DMA_P_CONFIG);
@@ -401,7 +177,7 @@
ret = wait_event_timeout(lcdc->vsync_waitq, lcdc->got_vsync, HZ / 2);
if (!ret && !lcdc->got_vsync)
- PR_DISP_ERR("%s: timeout waiting for VSYNC\n", __func__);
+ pr_err("%s: timeout waiting for VSYNC\n", __func__);
lcdc->got_vsync = 0;
}
@@ -437,58 +213,23 @@
wake_up(&lcdc->vsync_waitq);
}
-#ifdef CONFIG_MSM_MDP40
-static void lcdc_overlay_start(void *priv, uint32_t addr, uint32_t stride,
- uint32_t width, uint32_t height, uint32_t x,
- uint32_t y)
-{
- struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
-
- struct mdp4_overlay_pipe *pipe;
- pipe = lcdc_pipe;
- pipe->srcp0_addr = addr;
-
- if (mdp->dma_config_dirty) {
- if (mdp->dma_format == DMA_IBUF_FORMAT_RGB565) {
- pipe->src_format = MDP_RGB_565;
- pipe->srcp0_ystride = pipe->src_width * 2;
- } else if (mdp->dma_format == DMA_IBUF_FORMAT_XRGB8888) {
- pipe->src_format = MDP_RGBA_8888;
- pipe->srcp0_ystride = pipe->src_width * 4;
- }
- mdp4_overlay_format2pipe(pipe);
- mdp_writel(pipe->mdp, 0, MDP_LCDC_EN);
- mdelay(30);
- mdp4_overlay_dmap_xy(pipe);
- mdp4_overlay_dmap_cfg(pipe, 1);
- mdp4_overlayproc_cfg(pipe);
- mdp4_overlay_rgb_setup(pipe);
- mdp4_overlay_reg_flush(pipe, 1); /* rgb1 and mixer0 */
- mdp_writel(pipe->mdp, 1, MDP_LCDC_EN);
- mdp->dma_config_dirty = false;
- } else {
- mdp4_overlay_rgb_setup(pipe);
- mdp4_overlay_reg_flush(pipe, 1); /* rgb1 and mixer0 */
- }
-
-}
-#else
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) {
+ if (mdp->dma_config_dirty)
+ {
mdp_writel(lcdc->mdp, 0, MDP_LCDC_EN);
- mdelay(30);
+ 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);
}
-#endif
static void precompute_timing_parms(struct mdp_lcdc_info *lcdc)
{
@@ -501,21 +242,21 @@
unsigned int display_vstart;
unsigned int display_vend;
- hsync_period = (timing->hsync_pulse_width + timing->hsync_back_porch +
+ hsync_period = (timing->hsync_back_porch +
fb_data->xres + timing->hsync_front_porch);
- hsync_start_x = (timing->hsync_pulse_width + timing->hsync_back_porch);
+ hsync_start_x = timing->hsync_back_porch;
hsync_end_x = hsync_start_x + fb_data->xres - 1;
- vsync_period = (timing->vsync_pulse_width + timing->vsync_back_porch +
+ vsync_period = (timing->vsync_back_porch +
fb_data->yres + timing->vsync_front_porch);
vsync_period *= hsync_period;
- display_vstart = timing->vsync_pulse_width + timing->vsync_back_porch;
+ display_vstart = timing->vsync_back_porch;
display_vstart *= hsync_period;
display_vstart += timing->hsync_skew;
- display_vend = (timing->vsync_pulse_width + timing->vsync_back_porch +
- fb_data->yres) * hsync_period;
+ 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
@@ -542,13 +283,9 @@
struct msm_lcdc_platform_data *pdata = pdev->dev.platform_data;
struct mdp_lcdc_info *lcdc;
int ret = 0;
-#ifdef CONFIG_MSM_MDP40
- struct mdp4_overlay_pipe *pipe;
- int ptype;
-#endif
if (!pdata) {
- PR_DISP_ERR("%s: no LCDC platform data found\n", __func__);
+ pr_err("%s: no LCDC platform data found\n", __func__);
return -EINVAL;
}
@@ -559,21 +296,21 @@
/* 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_DISP_ERR("%s: failed to get mdp_clk\n", __func__);
+ 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_DISP_ERR("%s: failed to get lcdc_pclk\n", __func__);
+ 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_DISP_ERR("%s: failed to get lcdc_pad_pclk\n", __func__);
+ pr_err("%s: failed to get lcdc_pad_pclk\n", __func__);
ret = PTR_ERR(lcdc->pad_pclk);
goto err_get_pad_pclk;
}
@@ -583,53 +320,14 @@
lcdc->frame_start_cb.func = lcdc_frame_start;
platform_set_drvdata(pdev, lcdc);
-#ifdef CONFIG_MSM_MDP40
- mdp_out_if_register(mdp_dev, MSM_LCDC_INTERFACE, lcdc, INTR_OVERLAY0_DONE,
- lcdc_overlay_start);
-#else
+
mdp_out_if_register(mdp_dev, MSM_LCDC_INTERFACE, lcdc, MDP_DMA_P_DONE,
lcdc_dma_start);
-#endif
- lcdc->mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
+
precompute_timing_parms(lcdc);
lcdc->fb_start = pdata->fb_resource->start;
- if (lcdc->mdp->mdp_dev.color_format)
- lcdc->color_format = lcdc->mdp->mdp_dev.color_format;
- else
- lcdc->color_format = MSM_MDP_OUT_IF_FMT_RGB565;
-
-#ifdef CONFIG_MSM_MDP40
- if (lcdc_pipe == NULL) {
- ptype = mdp4_overlay_format2type(MDP_RGB_565);
- pipe = mdp4_overlay_pipe_alloc(ptype, false);
- if (!pipe)
- goto err_mdp4_overlay_pipe_alloc;
- pipe->mixer_stage = MDP4_MIXER_STAGE_BASE;
- pipe->pipe_used = 1;
- pipe->mixer_num = MDP4_MIXER0;
- pipe->src_format = MDP_RGB_565;
- mdp4_overlay_format2pipe(pipe);
- pipe->mdp = lcdc->mdp;
-
- lcdc_pipe = pipe; /* keep it */
- } else {
- pipe = lcdc_pipe;
- }
-
- pipe->src_height = pdata->fb_data->yres;
- pipe->src_width = pdata->fb_data->xres;
- pipe->src_h = pdata->fb_data->yres;
- pipe->src_w = pdata->fb_data->xres;
- pipe->src_y = 0;
- pipe->src_x = 0;
- pipe->srcp0_addr = (uint32_t) lcdc->fb_start;
-
- pipe->srcp0_ystride = pdata->fb_data->xres * 2;
-
- mdp4_overlay_rgb_setup(pipe);
- mdp4_mixer_stage_up(pipe);
-#endif
+ 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;
@@ -640,43 +338,34 @@
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;
- lcdc->fb_panel_data.shutdown = lcdc_shutdown;
+
ret = lcdc_hw_init(lcdc);
if (ret) {
- PR_DISP_ERR("%s: Cannot initialize the mdp_lcdc\n", __func__);
+ 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_DISP_ERR("%s: Cannot register msm_panel pdev\n", __func__);
+ pr_err("%s: Cannot register msm_panel pdev\n", __func__);
goto err_plat_dev_reg;
}
- PR_DISP_INFO("%s: initialized\n", __func__);
-#ifdef CONFIG_PANEL_SELF_REFRESH
- if (lcdc->mdp->mdp_dev.overrides & MSM_MDP_RGB_PANEL_SELE_REFRESH) {
- ret = icm_init(lcdc);
- if (ret) {
- PR_DISP_ERR("%s: Cannot init dispaly selfrefresh \n", __func__);
- goto err_plat_dev_reg;
- }
- }
-#endif
+ pr_info("%s: initialized\n", __func__);
return 0;
err_plat_dev_reg:
err_hw_init:
-#ifdef CONFIG_MSM_MDP40
-err_mdp4_overlay_pipe_alloc:
-#endif
platform_set_drvdata(pdev, NULL);
clk_put(lcdc->pad_pclk);
err_get_pad_pclk:
diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
new file mode 100644
index 0000000..b84fe44
--- /dev/null
+++ b/drivers/video/msm/mdp_ppp.c
@@ -0,0 +1,1724 @@
+/* drivers/video/msm/src/drv/mdp/mdp_ppp.c
+ *
+ * Copyright (C) 2007 Google Incorporated
+ * Copyright (c) 2008-2009, 2012 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.
+ */
+
+#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/msm_mdp.h>
+#include <linux/file.h>
+#include <linux/android_pmem.h>
+#include <linux/major.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 <linux/msm_kgsl.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+#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,
+ [MDP_RGB_888] = 3,
+ [MDP_XRGB_8888] = 4,
+ [MDP_ARGB_8888] = 4,
+ [MDP_RGBA_8888] = 4,
+ [MDP_BGRA_8888] = 4,
+ [MDP_RGBX_8888] = 4,
+ [MDP_Y_CBCR_H2V1] = 1,
+ [MDP_Y_CBCR_H2V2] = 1,
+ [MDP_Y_CBCR_H2V2_ADRENO] = 1,
+ [MDP_Y_CRCB_H2V1] = 1,
+ [MDP_Y_CRCB_H2V2] = 1,
+ [MDP_YCRYCB_H2V1] = 2,
+ [MDP_BGR_565] = 2
+};
+
+extern uint32 mdp_plv[];
+extern struct semaphore mdp_ppp_mutex;
+static struct ion_client *ppp_display_iclient;
+
+int mdp_get_bytes_per_pixel(uint32_t format,
+ struct msm_fb_data_type *mfd)
+{
+ 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 uint32 mdp_conv_matx_rgb2yuv(uint32 input_pixel,
+ uint16 *matrix_and_bias_vector,
+ uint32 *clamp_vector,
+ uint32 *look_up_table)
+{
+ 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;
+
+ 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;
+
+ 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;
+
+ /* 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;
+
+ /* 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;
+}
+
+uint32 mdp_conv_matx_yuv2rgb(uint32 input_pixel,
+ uint16 *matrix_and_bias_vector,
+ uint32 *clamp_vector, uint32 *look_up_table)
+{
+ 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;
+
+ 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;
+ }
+
+ 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_CBCR_H2V2_ADRENO) | \
+ (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_CBCR_H2V2_ADRENO || \
+ format == MDP_Y_CRCB_H2V2) ? 2 : (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)
+{
+ *len0 = IMG_LEN(rect->h, img->width, rect->w, bpp);
+ if (IS_PSEUDOPLNR(img->format))
+ *len1 = *len0/Y_TO_CRCB_RATIO(img->format);
+ else
+ *len1 = 0;
+}
+
+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)
+{
+ uint32_t src0_len, src1_len;
+
+ 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);
+ }
+
+}
+#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 src0_y1stride;
+ 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_CBCR_H2V2_ADRENO:
+ 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;
+ }
+ }
+ /* 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;
+ }
+ }
+ /* 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;
+ }
+ }
+
+ if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V2_ADRENO)
+ src0_ystride = ALIGN(src_width, 32) * inpBpp;
+ else
+ src0_ystride = src_width * inpBpp;
+
+ if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V2_ADRENO)
+ src0_y1stride = 2 * ALIGN(src_width/2, 32);
+ else
+ src0_y1stride = src0_ystride;
+
+ 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_y1stride << 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 int mdp_ppp_verify_req(struct mdp_blit_req *req)
+{
+ u32 src_width, src_height, dst_width, dst_height;
+
+ if (req == NULL) {
+ printk(KERN_ERR "\n%s(): Error in Line %u", __func__,
+ __LINE__);
+ return -1;
+ }
+
+ 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 {
+ dst_width = req->dst_rect.w;
+ dst_height = req->dst_rect.h;
+ }
+
+ 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;
+
+ 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;
+
+ default:
+ break;
+ }
+
+ 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 get_gem_img(struct mdp_img *img, unsigned long *start, unsigned long *len)
+{
+ /* Set len to zero to appropriately error out if
+ kgsl_gem_obj_addr fails */
+
+ *len = 0;
+ return kgsl_gem_obj_addr(img->memory_id, (int) img->priv, start, len);
+}
+
+int get_img(struct mdp_img *img, struct mdp_blit_req *req,
+ struct fb_info *info, unsigned long *start, unsigned long *len,
+ struct file **srcp_file, struct ion_handle **srcp_ihdl)
+{
+ int put_needed, fb_num, ret = 0;
+ struct file *file;
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+#endif
+#ifdef CONFIG_ANDROID_PMEM
+ unsigned long vstart;
+#endif
+
+ if (req->flags & MDP_MEMORY_ID_TYPE_FB) {
+ file = fget_light(img->memory_id, &put_needed);
+ if (file == NULL)
+ return -EINVAL;
+
+ 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,
+ DISPLAY_SUBSYSTEM_ID)) {
+ pr_err("get_fb_phys_info() failed\n");
+ fput_light(file, put_needed);
+ } else {
+ *srcp_file = file;
+ }
+
+ return ret;
+ } else {
+ fput_light(file, put_needed);
+ }
+ }
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ *srcp_ihdl = ion_import_fd(mfd->iclient, img->memory_id);
+ if (IS_ERR_OR_NULL(*srcp_ihdl))
+ return PTR_ERR(*srcp_ihdl);
+
+ if (!ion_phys(mfd->iclient, *srcp_ihdl, start, (size_t *) len))
+ return ret;
+ else
+ return -EINVAL;
+#endif
+
+#ifdef CONFIG_ANDROID_PMEM
+ if (!get_pmem_file(img->memory_id, start, &vstart, len, srcp_file))
+ return ret;
+ else
+ return -EINVAL;
+#endif
+}
+
+void put_img(struct file *p_src_file, struct ion_handle *p_ihdl)
+{
+#ifdef CONFIG_ANDROID_PMEM
+ if (p_src_file)
+ put_pmem_file(p_src_file);
+#endif
+
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ if (!IS_ERR_OR_NULL(p_ihdl))
+ ion_free(ppp_display_iclient, p_ihdl);
+#endif
+}
+
+
+static int mdp_ppp_blit_addr(struct fb_info *info, struct mdp_blit_req *req,
+ unsigned long srcp0_start, unsigned long srcp0_len,
+ unsigned long srcp1_start, unsigned long srcp1_len,
+ unsigned long dst_start, unsigned long dst_len,
+ struct file *p_src_file, struct file *p_dst_file,
+ struct ion_handle **src_ihdl, struct ion_handle **dst_ihdl)
+{
+ MDPIBUF iBuf;
+ u32 dst_width, dst_height;
+ struct msm_fb_data_type *mfd = 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 (mdp_ppp_verify_req(req)) {
+ pr_err("mdp_ppp: invalid image!\n");
+ put_img(p_src_file, *src_ihdl);
+ put_img(p_dst_file, *dst_ihdl);
+ return -1;
+ }
+
+ 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 *) (srcp0_start + req->src.offset);
+ if (iBuf.mdpImg.imgType == MDP_Y_CBCR_H2V2_ADRENO)
+ iBuf.mdpImg.cbcr_addr =
+ (uint32 *) ((uint32) iBuf.mdpImg.bmy_addr +
+ ALIGN((ALIGN(req->src.width, 32) *
+ ALIGN(req->src.height, 32)), 4096));
+ else
+ iBuf.mdpImg.cbcr_addr = srcp1_start ? (uint32 *)srcp1_start :
+ (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;
+ }
+
+ req->alpha &= 0xff;
+ if (req->alpha < MDP_ALPHA_NOP) {
+ iBuf.mdpImg.mdpOp |= MDPOP_ALPHAB;
+ iBuf.mdpImg.alpha = req->alpha;
+ } else {
+ iBuf.mdpImg.alpha = 0xff;
+ }
+
+ /* 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)
+ iBuf.mdpImg.mdpOp |= MDPOP_DITHER;
+
+ if (req->flags & MDP_BLEND_FG_PREMULT) {
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP303)
+ iBuf.mdpImg.mdpOp |= MDPOP_FG_PM_ALPHA;
+#else
+ put_img(p_src_file, *src_ihdl);
+ put_img(p_dst_file, *dst_ihdl);
+ return -EINVAL;
+#endif
+ }
+
+ 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, *src_ihdl);
+ put_img(p_dst_file, *dst_ihdl);
+ 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, *src_ihdl);
+ put_img(p_dst_file, *dst_ihdl);
+ return -EINVAL;
+ }
+
+ iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_SHARPENING;
+ iBuf.mdpImg.sp_value = req->sharpening_strength & 0xff;
+#else
+ put_img(p_src_file, *src_ihdl);
+ put_img(p_dst_file, *dst_ihdl);
+ 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, *src_ihdl);
+ put_img(p_dst_file, *dst_ihdl);
+ return 0;
+}
+
+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;
+ struct file *p_src_file = 0 , *p_dst_file = 0;
+ struct ion_handle *src_ihdl = NULL;
+ struct ion_handle *dst_ihdl = NULL;
+ struct msm_fb_data_type *mfd = info->par;
+ ppp_display_iclient = mfd->iclient;
+
+ if (req->flags & MDP_BLIT_SRC_GEM)
+ get_gem_img(&req->src, &src_start, &src_len);
+ else
+ get_img(&req->src, req, info, &src_start, &src_len, &p_src_file,
+ &src_ihdl);
+ if (src_len == 0) {
+ pr_err("mdp_ppp: could not retrieve source image from "
+ "memory\n");
+ return -EINVAL;
+ }
+ if (req->flags & MDP_BLIT_DST_GEM)
+ get_gem_img(&req->dst, &dst_start, &dst_len);
+ else
+ get_img(&req->dst, req, info, &dst_start, &dst_len, &p_dst_file,
+ &dst_ihdl);
+
+ if (dst_len == 0) {
+ put_img(p_src_file, src_ihdl);
+ pr_err("mdp_ppp: could not retrieve destination image from "
+ "memory\n");
+ return -EINVAL;
+ }
+
+ return mdp_ppp_blit_addr(info, req, src_start, src_len, 0, 0, dst_start,
+ dst_len, p_src_file, p_dst_file, &src_ihdl, &dst_ihdl);
+}
+
+static struct mdp_blit_req overlay_req;
+static bool mdp_overlay_req_set;
+
+int mdp_ppp_v4l2_overlay_set(struct fb_info *info, struct mdp_overlay *req)
+{
+ memset(&overlay_req, 0, sizeof(struct mdp_blit_req));
+
+ overlay_req.src.width = req->src.width;
+ overlay_req.src.height = req->src.height;
+ overlay_req.src.format = req->src.format;
+
+
+ overlay_req.dst.width = req->dst_rect.w;
+ overlay_req.dst.height = req->dst_rect.h;
+ overlay_req.dst.format = MDP_FB_FORMAT;
+ overlay_req.transp_mask = req->transp_mask;
+ overlay_req.flags = req->flags;
+ overlay_req.alpha = req->alpha;
+
+ overlay_req.src_rect.x = req->src_rect.x;
+ overlay_req.src_rect.y = req->src_rect.y;
+ overlay_req.src_rect.w = req->src_rect.w;
+ overlay_req.src_rect.h = req->src_rect.h;
+ overlay_req.dst_rect.x = req->dst_rect.x;
+ overlay_req.dst_rect.y = req->dst_rect.y;
+ overlay_req.dst_rect.w = req->dst_rect.w;
+ overlay_req.dst_rect.h = req->dst_rect.h;
+ mdp_overlay_req_set = true;
+
+ pr_debug("%s: Overlay parameters:", __func__);
+ pr_debug("Src_Image (%u %u)\n", overlay_req.src.width,
+ overlay_req.src.height);
+
+ if (overlay_req.src.format == MDP_Y_CRCB_H2V2)
+ pr_debug("Overlay format MDP_Y_CRCB_H2V2\n");
+ else if (overlay_req.src.format == MDP_RGB_565)
+ pr_debug("Overlay format MDP_RGB_565\n");
+ else
+ pr_debug("Overlay format(%u) unknown\n",
+ overlay_req.src.format);
+
+ pr_debug("Dst_Image (%u %u)\n", overlay_req.dst.width,
+ overlay_req.dst.height);
+ pr_debug("Src rect: (%u,%u,%u,%u), Dst rect: (%u,%u,%u,%u)\n",
+ overlay_req.src_rect.x, overlay_req.src_rect.y,
+ overlay_req.src_rect.w, overlay_req.src_rect.h,
+ overlay_req.dst_rect.x, overlay_req.dst_rect.y,
+ overlay_req.dst_rect.w, overlay_req.dst_rect.h);
+ return 0;
+}
+
+int mdp_ppp_v4l2_overlay_clear(void)
+{
+ memset(&overlay_req, 0, sizeof(struct mdp_overlay));
+ mdp_overlay_req_set = false;
+ return 0;
+}
+
+int mdp_ppp_v4l2_overlay_play(struct fb_info *info,
+ unsigned long srcp0_addr, unsigned long srcp0_size,
+ unsigned long srcp1_addr, unsigned long srcp1_size)
+{
+ int ret;
+
+ if (!mdp_overlay_req_set) {
+ pr_err("mdp_ppp:v4l2:No overlay set, ignore play req\n");
+ return -EINVAL;
+ }
+
+ overlay_req.dst.width = info->var.xres;
+ overlay_req.dst.height = info->var.yres;
+
+ ret = mdp_ppp_blit_addr(info, &overlay_req,
+ srcp0_addr, srcp0_size, srcp1_addr, srcp1_size,
+ info->fix.smem_start, info->fix.smem_len, NULL, NULL,
+ NULL, NULL);
+
+ if (ret)
+ pr_err("%s:Blitting overlay failed(%d)\n", __func__, ret);
+
+ return ret;
+}
diff --git a/drivers/video/msm/mdp_ppp.h b/drivers/video/msm/mdp_ppp.h
index 7a8ea37..e045643 100644
--- a/drivers/video/msm/mdp_ppp.h
+++ b/drivers/video/msm/mdp_ppp.h
@@ -16,7 +16,6 @@
#define _VIDEO_MSM_MDP_PPP_H_
#include <linux/types.h>
-#define PPP_DUMP_BLITS 0
struct ppp_regs {
uint32_t src0;
@@ -63,59 +62,21 @@
struct mdp_info;
struct mdp_rect;
struct mdp_blit_req;
-struct fb_info;
-#ifdef CONFIG_FB_MSM_MDP_PPP
-int mdp_get_bytes_per_pixel(int format);
-int mdp_ppp_blit(struct mdp_info *mdp, struct fb_info *fb,
- struct mdp_blit_req *req);
-void mdp_ppp_handle_isr(struct mdp_info *mdp, uint32_t mask);
-int mdp_ppp_blit_and_wait(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_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);
-/* these must be provided by h/w specific ppp files */
-void mdp_ppp_init_scale(struct mdp_info *mdp);
-int mdp_ppp_cfg_scale(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(struct mdp_info *mdp);
+#ifndef CONFIG_MSM_MDP31
int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req, struct ppp_regs *regs);
-int mdp_ppp_validate_blit(struct mdp_info *mdp, struct mdp_blit_req *req);
-int mdp_ppp_do_blit(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 mdp_fb_mirror(struct mdp_device *mdp_dev,
- struct fb_info *src_fb, struct fb_info *dst_fb,
- struct mdp_blit_req *req);
#else
-
-static inline int mdp_get_bytes_per_pixel(int format) { return -1; }
-static inline int mdp_ppp_blit(struct mdp_info *mdp, struct fb_info *fb,
- struct mdp_blit_req *req) { return -EINVAL; }
-static inline void mdp_ppp_handle_isr(struct mdp_info *mdp, uint32_t mask) {}
-static inline int mdp_ppp_blit_and_wait(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) { return 0; }
-
-static inline void mdp_ppp_init_scale(struct mdp_info *mdp) {}
-static inline int mdp_ppp_cfg_scale(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) { return 0; }
-static inline int mdp_ppp_load_blur(struct mdp_info *mdp) { return 0; }
-static inline int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req, struct ppp_regs *regs) { return 0; }
-static inline int mdp_ppp_validate_blit(struct mdp_info *mdp, struct mdp_blit_req *req) { return -EINVAL; }
-static inline int mdp_ppp_do_blit(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) { return 0; }
-
-
-#endif /* CONFIG_FB_MSM_MDP_PPP */
+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..fe237ee
--- /dev/null
+++ b/drivers/video/msm/mdp_ppp_v20.c
@@ -0,0 +1,2531 @@
+/* Copyright (c) 2008-2009, 2012 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_CBCR_H2V2_ADRENO:
+ 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_CBCR_H2V2_ADRENO:
+ 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 */
+ 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);
+ 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 (mdp_rev == MDP_REV_303) {
+ 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;
+ }
+ } 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 |
+ 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_scale_tables.c b/drivers/video/msm/mdp_scale_tables.c
new file mode 100644
index 0000000..604783b
--- /dev/null
+++ b/drivers/video/msm/mdp_scale_tables.c
@@ -0,0 +1,766 @@
+/* drivers/video/msm_fb/mdp_scale_tables.c
+ *
+ * Copyright (C) 2007 QUALCOMM Incorporated
+ * 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 "mdp_scale_tables.h"
+#include "mdp_hw.h"
+
+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 },
+};
diff --git a/drivers/video/msm/mdp_scale_tables.h b/drivers/video/msm/mdp_scale_tables.h
new file mode 100644
index 0000000..34077b1
--- /dev/null
+++ b/drivers/video/msm/mdp_scale_tables.h
@@ -0,0 +1,38 @@
+/* drivers/video/msm_fb/mdp_scale_tables.h
+ *
+ * Copyright (C) 2007 QUALCOMM Incorporated
+ * 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.
+ */
+#ifndef _MDP_SCALE_TABLES_H_
+#define _MDP_SCALE_TABLES_H_
+
+#include <linux/types.h>
+struct mdp_table_entry {
+ uint32_t reg;
+ uint32_t val;
+};
+
+extern struct mdp_table_entry mdp_upscale_table[64];
+
+enum {
+ MDP_DOWNSCALE_PT2TOPT4,
+ MDP_DOWNSCALE_PT4TOPT6,
+ MDP_DOWNSCALE_PT6TOPT8,
+ MDP_DOWNSCALE_PT8TO1,
+ MDP_DOWNSCALE_MAX,
+};
+
+extern struct mdp_table_entry *mdp_downscale_x_table[MDP_DOWNSCALE_MAX];
+extern struct mdp_table_entry *mdp_downscale_y_table[MDP_DOWNSCALE_MAX];
+extern struct mdp_table_entry mdp_gaussian_blur_table[];
+
+#endif
diff --git a/drivers/video/msm/mdp_vsync.c b/drivers/video/msm/mdp_vsync.c
new file mode 100644
index 0000000..cc350d3
--- /dev/null
+++ b/drivers/video/msm/mdp_vsync.c
@@ -0,0 +1,504 @@
+/* Copyright (c) 2008-2009, 2012 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);
+static DEFINE_SPINLOCK(vsync_timer_lock);
+
+static struct clk *mdp_vsync_clk;
+static struct msm_fb_data_type *vsync_mfd;
+static unsigned char timer_shutdown_flag;
+static uint32 vsync_cnt_cfg;
+
+
+void vsync_clk_prepare_enable(void)
+{
+ if (mdp_vsync_clk)
+ clk_prepare_enable(mdp_vsync_clk);
+}
+
+void vsync_clk_disable_unprepare(void)
+{
+ if (mdp_vsync_clk)
+ clk_disable_unprepare(mdp_vsync_clk);
+}
+
+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_prepare_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_unprepare(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) {
+ spin_lock(&vsync_timer_lock);
+ timer_shutdown_flag = 1;
+ spin_unlock(&vsync_timer_lock);
+ del_timer_sync(&vsync_mfd->vsync_resync_timer);
+ spin_lock(&vsync_timer_lock);
+ timer_shutdown_flag = 0;
+ spin_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);
+ }
+
+ spin_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);
+ }
+ spin_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
+
+void mdp_vsync_cfg_regs(struct msm_fb_data_type *mfd,
+ boolean first_time)
+{
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON,
+ FALSE);
+ if (first_time)
+ 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));
+
+ if (first_time)
+ mdp_hw_vsync_clk_disable(mfd);
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+#endif
+
+void mdp_config_vsync(struct platform_device *pdev,
+ 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(&pdev->dev, "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_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_vsync_cfg_regs(mfd, TRUE);
+ }
+ }
+#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/mhl_api.h b/drivers/video/msm/mhl_api.h
new file mode 100644
index 0000000..627f802
--- /dev/null
+++ b/drivers/video/msm/mhl_api.h
@@ -0,0 +1,26 @@
+
+/* 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 __MHL_API_H__
+#define __MHL_API_H__
+
+#ifdef CONFIG_FB_MSM_HDMI_MHL
+bool mhl_is_connected(void);
+#else
+static bool mhl_is_connected(void)
+{
+ return false;
+}
+#endif
+
+#endif /* __MHL_API_H__ */
diff --git a/drivers/video/msm/mipi_chimei_wuxga.c b/drivers/video/msm/mipi_chimei_wuxga.c
new file mode 100644
index 0000000..feb26a1
--- /dev/null
+++ b/drivers/video/msm/mipi_chimei_wuxga.c
@@ -0,0 +1,197 @@
+/* Copyright (c) 2012, 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.
+ *
+ */
+
+/*
+ * Chimei WUXGA LVDS Panel driver.
+ * The panel model is N101JSF-L21.
+ *
+ * The panel interface includes:
+ * 1. LVDS input for video (clock & data).
+ * 2. few configuration pins to control 3D module: Enable, Mode (2D/3D).
+ * 3. Backlight LED control (PWM 200 HZ).
+ *
+ * This panel is controled via the Toshiba DSI-to-LVDS bridge.
+ *
+ */
+
+/* #define DEBUG 1 */
+
+#include "msm_fb.h"
+#include "msm_fb_panel.h"
+#include "mipi_dsi.h"
+#include "mipi_tc358764_dsi2lvds.h"
+
+#define MHZ (1000*1000)
+
+/**
+ * Panel info parameters.
+ * The panel info is passed to the mipi framebuffer driver.
+ */
+static struct msm_panel_info chimei_wuxga_pinfo;
+
+/**
+ * The mipi_dsi_phy_ctrl is calculated according to the
+ * "dsi_timing_program.xlsm" excel sheet.
+ * Output is based on: 1200x1920, RGB565, 4 lanes , 58 frames
+ * per second.
+ */
+static struct mipi_dsi_phy_ctrl dsi_video_mode_phy_db = {
+ /* DSIPHY_REGULATOR_CTRL */
+ .regulator = {0x03, 0x0a, 0x04, 0x00, 0x20}, /* common 8960 */
+ /* DSIPHY_CTRL */
+ .ctrl = {0x5f, 0x00, 0x00, 0x10}, /* common 8960 */
+ /* DSIPHY_STRENGTH_CTRL */
+ .strength = {0xff, 0x00, 0x06, 0x00}, /* common 8960 */
+ /* DSIPHY_TIMING_CTRL */
+ .timing = { 0xC9, 0x92, 0x29, /* panel specific */
+ 0, /* DSIPHY_TIMING_CTRL_3 = 0 */
+ 0x2D, 0x9B, 0x2B, 0x94, 0x2D, 0x03, 0x04}, /* panel specific */
+
+ /* DSIPHY_PLL_CTRL */
+ .pll = { 0x00, /* common 8960 */
+ /* VCO */
+ 0x30, (0x01 | 0x30) , (0x19 | 0xC0), /* panel specific */
+ 0x00, 0x50, 0x48, 0x63,
+ 0x77, 0x88, 0x99, /* Auto update by dsi-mipi driver */
+ 0x00, 0x14, 0x03, 0x00, 0x02, /* common 8960 */
+ 0x00, 0x20, 0x00, 0x01 }, /* common 8960 */
+};
+
+/**
+ * Module init.
+ *
+ * Register the panel-info.
+ *
+ * Some parameters are from the panel datasheet
+ * and other are *calculated* by the "dsi_timing_program.xlsm"
+ * excel file
+ *
+ * @return int
+ */
+static int __init mipi_chimei_wuxga_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo = &chimei_wuxga_pinfo;
+
+ if (msm_fb_detect_client("mipi_video_chimei_wuxga"))
+ return 0;
+
+ pr_info("mipi-dsi chimei wuxga (1200x1920) driver ver 1.0.\n");
+
+ /* Portrait */
+ pinfo->xres = 1200;
+ pinfo->yres = 1920;
+ pinfo->type = MIPI_VIDEO_PANEL;
+ pinfo->pdest = DISPLAY_1; /* Primary Display */
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 24; /* RGB565 requires 24 bits-per-pixel :-O */
+ pinfo->fb_num = 2; /* using two frame buffers */
+
+ /*
+ * The CMI panel requires 80 MHZ LVDS-CLK.
+ * The D2L bridge drives the LVDS-CLK from the DSI-CLK.
+ * The DSI-CLK = bitclk/2, 640 MHZ/2= 320 MHZ.
+ * LVDS-CLK = DSI-CLK/4 , 320 MHZ/4= 80 MHZ.
+ */
+
+ pinfo->clk_rate = 635 * MHZ ; /* bitclk Calculated */
+
+ /*
+ * this panel is operated by DE,
+ * vsycn and hsync are ignored
+ */
+
+ pinfo->lcdc.h_front_porch = 160-48-32; /* thfp */
+ pinfo->lcdc.h_back_porch = 48; /* thb */
+ pinfo->lcdc.h_pulse_width = 32; /* thpw */
+
+ pinfo->lcdc.v_front_porch = 26-3-6; /* tvfp */
+ pinfo->lcdc.v_back_porch = 3; /* tvb */
+ pinfo->lcdc.v_pulse_width = 6; /* tvpw */
+
+ pinfo->lcdc.border_clr = 0; /* black */
+ pinfo->lcdc.underflow_clr = 0xff; /* blue */
+
+ pinfo->lcdc.hsync_skew = 0;
+
+ /* Backlight levels - controled via PMIC pwm gpio */
+ pinfo->bl_max = 15;
+ pinfo->bl_min = 1;
+
+ /* mipi - general */
+ pinfo->mipi.vc = 0; /* virtual channel */
+ pinfo->mipi.rgb_swap = DSI_RGB_SWAP_RGB;
+ pinfo->mipi.tx_eot_append = true;
+ pinfo->mipi.t_clk_post = 34; /* Calculated */
+ pinfo->mipi.t_clk_pre = 69; /* Calculated */
+
+ pinfo->mipi.dsi_phy_db = &dsi_video_mode_phy_db;
+
+ /* Four lanes are recomended for 1920x1200 at 60 frames per second */
+ pinfo->mipi.frame_rate = 60;
+ pinfo->mipi.data_lane0 = true;
+ pinfo->mipi.data_lane1 = true;
+ pinfo->mipi.data_lane2 = true;
+ pinfo->mipi.data_lane3 = true;
+ pinfo->mipi.esc_byte_ratio = 6;
+
+ pinfo->mipi.mode = DSI_VIDEO_MODE;
+ /*
+ * Note: The CMI panel input is RGB888,
+ * thus the DSI-to-LVDS bridge output is RGB888.
+ * This parameter selects the DSI-Core output to the bridge.
+ */
+ pinfo->mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB565;
+
+ /* mipi - video mode */
+ pinfo->mipi.traffic_mode = DSI_NON_BURST_SYNCH_EVENT;
+ pinfo->mipi.pulse_mode_hsa_he = false; /* sync mode */
+
+ 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;
+
+ /* mipi - command mode */
+ pinfo->mipi.te_sel = 1; /* TE from vsycn gpio */
+ pinfo->mipi.interleave_max = 1;
+ /* The bridge supports only Generic Read/Write commands */
+ pinfo->mipi.insert_dcs_cmd = false;
+ pinfo->mipi.wr_mem_continue = 0;
+ pinfo->mipi.wr_mem_start = 0;
+ pinfo->mipi.stream = false; /* dma_p */
+ pinfo->mipi.mdp_trigger = DSI_CMD_TRIGGER_NONE;
+ pinfo->mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+ /*
+ * toshiba d2l chip does not need max_pkt_size dcs cmd
+ * client reply len is directly configure through
+ * RDPKTLN register (0x0404)
+ */
+ pinfo->mipi.no_max_pkt_size = 1;
+ pinfo->mipi.force_clk_lane_hs = 1;
+
+ pinfo->is_3d_panel = FB_TYPE_3D_PANEL;
+
+ ret = mipi_tc358764_dsi2lvds_register(pinfo, MIPI_DSI_PRIM, 1);
+ if (ret)
+ pr_err("%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(mipi_chimei_wuxga_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Chimei WUXGA LVDS Panel driver");
+MODULE_AUTHOR("Amir Samuelov <amirs@codeaurora.org>");
diff --git a/drivers/video/msm/mipi_chimei_wxga_pt.c b/drivers/video/msm/mipi_chimei_wxga_pt.c
new file mode 100644
index 0000000..70a8787
--- /dev/null
+++ b/drivers/video/msm/mipi_chimei_wxga_pt.c
@@ -0,0 +1,192 @@
+/* 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.
+ *
+ */
+
+/*
+ * Chimei WXGA LVDS Panel driver.
+ * The panel model is N101BCG-L21.
+ *
+ * The panel interface includes:
+ * 1. LVDS input for video (clock & data).
+ * 2. few configuration pins: Up/Down scan, Left/Right scan etc.
+ * 3. Backlight LED control.
+ * 4. I2C interface for EEPROM access.
+ *
+ * The Panel is *internally* controlled by Novatek NT51009 controller.
+ * However, the "3-wire" SPI interface is not exposed on the panel interface.
+ *
+ * This panel is controled via the Toshiba DSI-to-LVDS bridge.
+ *
+ */
+
+/* #define DEBUG 1 */
+
+#include "msm_fb.h"
+#include "msm_fb_panel.h"
+#include "mipi_dsi.h"
+#include "mipi_tc358764_dsi2lvds.h"
+
+#define MHZ (1000*1000)
+
+/**
+ * Panel info parameters.
+ * The panel info is passed to the mipi framebuffer driver.
+ */
+static struct msm_panel_info chimei_wxga_pinfo;
+
+/**
+ * The mipi_dsi_phy_ctrl is calculated according to the
+ * "DSI_panel_bring_up_guide_ver3.docm" using the excel sheet.
+ * Output is based on: 1366x768, RGB888, 4 lanes , 60 frames per second.
+ */
+static struct mipi_dsi_phy_ctrl dsi_video_mode_phy_db = {
+ /* DSIPHY_REGULATOR_CTRL */
+ .regulator = {0x03, 0x0a, 0x04, 0x00, 0x20}, /* common 8960 */
+ /* DSIPHY_CTRL */
+ .ctrl = {0x5f, 0x00, 0x00, 0x10}, /* common 8960 */
+ /* DSIPHY_STRENGTH_CTRL */
+ .strength = {0xff, 0x00, 0x06, 0x00}, /* common 8960 */
+ /* DSIPHY_TIMING_CTRL */
+ .timing = { 0xB6, 0x8D, 0x1E, /* panel specific */
+ 0, /* DSIPHY_TIMING_CTRL_3 = 0 */
+ 0x21, 0x95, 0x21, 0x8F, 0x21, 0x03, 0x04}, /* panel specific */
+
+ /* DSIPHY_PLL_CTRL */
+ .pll = { 0x00, /* common 8960 */
+ /* VCO */
+ 0xC6, 0x01, 0x19, /* panel specific */
+ 0x00, 0x50, 0x48, 0x63,
+ 0x77, 0x88, 0x99, /* Auto update by dsi-mipi driver */
+ 0x00, 0x14, 0x03, 0x00, 0x02, /* common 8960 */
+ 0x00, 0x20, 0x00, 0x01 }, /* common 8960 */
+};
+
+/**
+ * Module init.
+ *
+ * Register the panel-info.
+ *
+ * Some parameters are from the panel datasheet
+ * and other are *calculated* according to the
+ * "DSI_panel_bring_up_guide_ver3.docm".
+ *
+ * @return int
+ */
+static int __init mipi_chimei_wxga_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo = &chimei_wxga_pinfo;
+
+ if (msm_fb_detect_client("mipi_video_chimei_wxga"))
+ return 0;
+
+ pr_debug("mipi-dsi chimei wxga (1366x768) driver ver 1.0.\n");
+ /* Landscape */
+ pinfo->xres = 1366;
+ pinfo->yres = 768;
+ pinfo->type = MIPI_VIDEO_PANEL;
+ pinfo->pdest = DISPLAY_1; /* Primary Display */
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 24; /* RGB888 = 24 bits-per-pixel */
+ pinfo->fb_num = 2; /* using two frame buffers */
+
+ /* bitclk */
+ pinfo->clk_rate = 473400000; /* 473.4 MHZ Calculated */
+
+ /*
+ * this panel is operated by DE,
+ * vsycn and hsync are ignored
+ */
+
+ pinfo->lcdc.h_front_porch = 96+2;/* thfp */
+ pinfo->lcdc.h_back_porch = 88; /* thb */
+ pinfo->lcdc.h_pulse_width = 40; /* thpw */
+
+ pinfo->lcdc.v_front_porch = 15; /* tvfp */
+ pinfo->lcdc.v_back_porch = 23; /* tvb */
+ pinfo->lcdc.v_pulse_width = 20; /* tvpw */
+
+ pinfo->lcdc.border_clr = 0; /* black */
+ pinfo->lcdc.underflow_clr = 0xff; /* blue */
+
+ pinfo->lcdc.hsync_skew = 0;
+
+ /* Backlight levels - controled via PMIC pwm gpio */
+ pinfo->bl_max = 15;
+ pinfo->bl_min = 1;
+
+ /* mipi - general */
+ pinfo->mipi.vc = 0; /* virtual channel */
+ pinfo->mipi.rgb_swap = DSI_RGB_SWAP_RGB;
+ pinfo->mipi.tx_eot_append = true;
+ pinfo->mipi.t_clk_post = 34; /* Calculated */
+ pinfo->mipi.t_clk_pre = 64; /* Calculated */
+ pinfo->mipi.esc_byte_ratio = 4;
+
+ pinfo->mipi.dsi_phy_db = &dsi_video_mode_phy_db;
+
+ /* Four lanes are recomended for 1366x768 at 60 frames per second */
+ pinfo->mipi.frame_rate = 60; /* 60 frames per second */
+ pinfo->mipi.data_lane0 = true;
+ pinfo->mipi.data_lane1 = true;
+ pinfo->mipi.data_lane2 = true;
+ pinfo->mipi.data_lane3 = true;
+
+ pinfo->mipi.mode = DSI_VIDEO_MODE;
+ /*
+ * Note: The CMI panel input is RGB888,
+ * thus the DSI-to-LVDS bridge output is RGB888.
+ * This parameter selects the DSI-Core output to the bridge.
+ */
+ pinfo->mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
+
+ /* mipi - video mode */
+ pinfo->mipi.traffic_mode = DSI_NON_BURST_SYNCH_EVENT;
+ pinfo->mipi.pulse_mode_hsa_he = false; /* sync mode */
+
+ 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;
+
+ /* mipi - command mode */
+ pinfo->mipi.te_sel = 1; /* TE from vsycn gpio */
+ pinfo->mipi.interleave_max = 1;
+ /* The bridge supports only Generic Read/Write commands */
+ pinfo->mipi.insert_dcs_cmd = false;
+ pinfo->mipi.wr_mem_continue = 0;
+ pinfo->mipi.wr_mem_start = 0;
+ pinfo->mipi.stream = false; /* dma_p */
+ pinfo->mipi.mdp_trigger = DSI_CMD_TRIGGER_NONE;
+ pinfo->mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+ /*
+ * toshiba d2l chip does not need max_pkt_szie dcs cmd
+ * client reply len is directly configure through
+ * RDPKTLN register (0x0404)
+ */
+ pinfo->mipi.no_max_pkt_size = 1;
+ pinfo->mipi.force_clk_lane_hs = 1;
+
+ ret = mipi_tc358764_dsi2lvds_register(pinfo, MIPI_DSI_PRIM,
+ MIPI_DSI_PANEL_WXGA);
+ if (ret)
+ pr_err("%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(mipi_chimei_wxga_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Chimei WXGA LVDS Panel driver");
+MODULE_AUTHOR("Amir Samuelov <amirs@codeaurora.org>");
diff --git a/drivers/video/msm/mipi_dsi.c b/drivers/video/msm/mipi_dsi.c
new file mode 100644
index 0000000..b4fb930
--- /dev/null
+++ b/drivers/video/msm/mipi_dsi.c
@@ -0,0 +1,614 @@
+/* Copyright (c) 2008-2012, 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;
+u32 esc_byte_ratio;
+
+static boolean tlmm_settings = FALSE;
+
+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);
+
+ /*
+ * 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) {
+ if (MDP_REV_303 != mdp_rev)
+ 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
+
+ spin_lock_bh(&dsi_clk_lock);
+ mipi_dsi_clk_disable();
+
+ /* disbale dsi engine */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0000, 0);
+
+ mipi_dsi_phy_ctrl(0);
+
+ mipi_dsi_ahb_ctrl(0);
+ spin_unlock_bh(&dsi_clk_lock);
+
+ mipi_dsi_unprepare_clocks();
+ 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;
+ esc_byte_ratio = pinfo->mipi.esc_byte_ratio;
+
+ if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save)
+ mipi_dsi_pdata->dsi_power_save(1);
+
+ cont_splash_clk_ctrl(0);
+ mipi_dsi_prepare_clocks();
+
+ mipi_dsi_ahb_ctrl(1);
+
+ clk_rate = mfd->fbi->var.pixclock;
+ clk_rate = min(clk_rate, mfd->panel_info.clk_max);
+
+ 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_dsi_clk_enable();
+
+ 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 = &mfd->panel_info.mipi;
+ if (mfd->panel_info.type == MIPI_VIDEO_PANEL) {
+ dummy_xres = mfd->panel_info.lcdc.xres_pad;
+ dummy_yres = mfd->panel_info.lcdc.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);
+
+ if (mipi->force_clk_lane_hs) {
+ u32 tmp;
+
+ tmp = MIPI_INP(MIPI_DSI_BASE + 0xA8);
+ tmp |= (1<<28);
+ MIPI_OUTP(MIPI_DSI_BASE + 0xA8, tmp);
+ wmb();
+ }
+
+ if (mdp_rev >= MDP_REV_41)
+ mutex_lock(&mfd->dma->ov_mutex);
+ else
+ down(&mfd->dma->mutex);
+
+ 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 (mdp_rev >= MDP_REV_41) {
+ 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);
+ } else if (mdp_rev == MDP_REV_303) {
+ if (!tlmm_settings && gpio_request(
+ vsync_gpio, "MDP_VSYNC") == 0) {
+ ret = gpio_tlmm_config(
+ GPIO_CFG(
+ vsync_gpio, 1,
+ GPIO_CFG_INPUT,
+ GPIO_CFG_PULL_DOWN,
+ GPIO_CFG_2MA),
+ GPIO_CFG_ENABLE);
+
+ if (ret) {
+ pr_err(
+ "%s: unable to config \
+ tlmm = %d\n",
+ __func__, vsync_gpio);
+ }
+ tlmm_settings = TRUE;
+
+ gpio_direction_input(
+ vsync_gpio);
+ } else {
+ if (!tlmm_settings) {
+ 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
+
+ mdp4_overlay_dsi_state_set(ST_DSI_RESUME);
+
+ 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_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__);
+ }
+ }
+
+ if (mipi_dsi_clk_init(pdev))
+ return -EPERM;
+
+ if (mipi_dsi_pdata->splash_is_enabled &&
+ !mipi_dsi_pdata->splash_is_enabled()) {
+ mipi_dsi_ahb_ctrl(1);
+ MIPI_OUTP(MIPI_DSI_BASE + 0x118, 0);
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0, 0);
+ MIPI_OUTP(MIPI_DSI_BASE + 0x200, 0);
+ mipi_dsi_ahb_ctrl(0);
+ }
+ mipi_dsi_resource_initialized = 1;
+
+ return 0;
+ }
+
+ 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;
+
+ if (!mfd->cont_splash_done)
+ cont_splash_clk_ctrl(1);
+
+ mdp_dev = platform_device_alloc("mdp", pdev->id);
+ if (!mdp_dev)
+ return -ENOMEM;
+
+ /*
+ * link to the latest pdev
+ */
+ mfd->pdev = mdp_dev;
+
+ /*
+ * 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 (mfd->panel_info.type == MIPI_VIDEO_PANEL)
+ mfd->dest = DISPLAY_LCDC;
+ else
+ mfd->dest = DISPLAY_LCD;
+
+ 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.lcdc.xres_pad;
+ v_period += mfd->panel_info.lcdc.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..2f691cf
--- /dev/null
+++ b/drivers/video/msm/mipi_dsi.h
@@ -0,0 +1,352 @@
+/* Copyright (c) 2009-2012, 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 MIPI_DSI_PANEL_WSVGA_PT 4
+#define MIPI_DSI_PANEL_QHD_PT 5
+#define MIPI_DSI_PANEL_WXGA 6
+#define MIPI_DSI_PANEL_WUXGA 7
+#define MIPI_DSI_PANEL_720P_PT 8
+#define DSI_PANEL_MAX 8
+
+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,
+};
+
+enum dsi_trigger_type {
+ DSI_CMD_MODE_DMA,
+ DSI_CMD_MODE_MDP,
+};
+
+#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_MDP_TERM BIT(8)
+#define DSI_CMD_TERM 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 u32 esc_byte_ratio;
+
+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 64
+#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
+
+/*
+ * dcs response
+ */
+#define DTYPE_ACK_ERR_RESP 0x02
+#define DTYPE_EOT_RESP 0x08 /* end of tx */
+#define DTYPE_GEN_READ1_RESP 0x11 /* 1 parameter, short */
+#define DTYPE_GEN_READ2_RESP 0x12 /* 2 parameter, short */
+#define DTYPE_GEN_LREAD_RESP 0x1a
+#define DTYPE_DCS_LREAD_RESP 0x1c
+#define DTYPE_DCS_READ1_RESP 0x21 /* 1 parameter, short */
+#define DTYPE_DCS_READ2_RESP 0x22 /* 2 parameter, short */
+
+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;
+};
+
+
+#define CMD_REQ_MAX 4
+
+typedef void (*fxn)(u32 data);
+
+#define CMD_REQ_RX 0x0001
+#define CMD_REQ_COMMIT 0x0002
+#define CMD_REQ_NO_MAX_PKT_SIZE 0x0008
+
+struct dcs_cmd_req {
+ struct dsi_cmd_desc *cmds;
+ int cmds_cnt;
+ u32 flags;
+ int rlen; /* rx length */
+ fxn cb;
+};
+
+struct dcs_cmd_list {
+ int put;
+ int get;
+ int tot;
+ struct dcs_cmd_req list[CMD_REQ_MAX];
+};
+
+
+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);
+void mipi_dsi_lane_cfg(void);
+void mipi_dsi_bist_ctrl(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 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_start(void);
+int mipi_dsi_ctrl_lock(int mdp);
+int mipi_dsi_ctrl_lock_query(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_set_backlight(struct msm_fb_data_type *mfd, int level);
+void mipi_dsi_cmd_backlight_tx(struct dsi_buf *dp);
+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);
+void mipi_dsi_controller_cfg(int enable);
+void mipi_dsi_sw_reset(void);
+void mipi_dsi_mdp_busy_wait(struct msm_fb_data_type *mfd);
+
+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);
+int mipi_dsi_clk_init(struct platform_device *pdev);
+void mipi_dsi_clk_deinit(struct device *dev);
+void mipi_dsi_prepare_clocks(void);
+void mipi_dsi_unprepare_clocks(void);
+void mipi_dsi_ahb_ctrl(u32 enable);
+void cont_splash_clk_ctrl(int enable);
+void mipi_dsi_turn_on_clks(void);
+void mipi_dsi_turn_off_clks(void);
+void mipi_dsi_clk_cfg(int on);
+
+int mipi_dsi_cmdlist_put(struct dcs_cmd_req *cmdreq);
+struct dcs_cmd_req *mipi_dsi_cmdlist_get(void);
+void mipi_dsi_cmdlist_commit(int from_mdp);
+
+#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..e495112
--- /dev/null
+++ b/drivers/video/msm/mipi_dsi_host.c
@@ -0,0 +1,1770 @@
+
+/* Copyright (c) 2008-2012, 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 completion dsi_mdp_comp;
+static struct dsi_buf dsi_tx_buf;
+static struct dsi_buf dsi_rx_buf;
+static spinlock_t dsi_irq_lock;
+static spinlock_t dsi_mdp_lock;
+spinlock_t dsi_clk_lock;
+static int dsi_ctrl_lock;
+static int dsi_mdp_busy;
+static struct mutex cmd_mutex;
+
+static struct list_head pre_kickoff_list;
+static struct list_head post_kickoff_list;
+
+enum {
+ STAT_DSI_START,
+ STAT_DSI_ERROR,
+ STAT_DSI_CMD,
+ STAT_DSI_MDP
+};
+
+struct dcs_cmd_list cmdlist;
+
+#ifdef CONFIG_FB_MSM_MDP40
+void mipi_dsi_mdp_stat_inc(int which)
+{
+ switch (which) {
+ case STAT_DSI_START:
+ mdp4_stat.dsi_mdp_start++;
+ break;
+ case STAT_DSI_ERROR:
+ mdp4_stat.intr_dsi_err++;
+ break;
+ case STAT_DSI_CMD:
+ mdp4_stat.intr_dsi_cmd++;
+ break;
+ case STAT_DSI_MDP:
+ mdp4_stat.intr_dsi_mdp++;
+ break;
+ default:
+ break;
+ }
+}
+#else
+void mipi_dsi_mdp_stat_inc(int which)
+{
+}
+#endif
+
+void mipi_dsi_init(void)
+{
+ init_completion(&dsi_dma_comp);
+ init_completion(&dsi_mdp_comp);
+ mipi_dsi_buf_alloc(&dsi_tx_buf, DSI_BUF_SIZE);
+ mipi_dsi_buf_alloc(&dsi_rx_buf, DSI_BUF_SIZE);
+ spin_lock_init(&dsi_irq_lock);
+ spin_lock_init(&dsi_mdp_lock);
+ spin_lock_init(&dsi_clk_lock);
+ mutex_init(&cmd_mutex);
+
+ INIT_LIST_HEAD(&pre_kickoff_list);
+ INIT_LIST_HEAD(&post_kickoff_list);
+}
+
+
+static u32 dsi_irq_mask;
+
+void mipi_dsi_enable_irq(u32 term)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dsi_irq_lock, flags);
+ if (dsi_irq_mask & term) {
+ spin_unlock_irqrestore(&dsi_irq_lock, flags);
+ return;
+ }
+ if (dsi_irq_mask == 0) {
+ enable_irq(dsi_irq);
+ pr_debug("%s: IRQ Enable, mask=%x term=%x\n",
+ __func__, (int)dsi_irq_mask, (int)term);
+ }
+ dsi_irq_mask |= term;
+ spin_unlock_irqrestore(&dsi_irq_lock, flags);
+}
+
+void mipi_dsi_disable_irq(u32 term)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dsi_irq_lock, flags);
+ if (!(dsi_irq_mask & term)) {
+ spin_unlock_irqrestore(&dsi_irq_lock, flags);
+ return;
+ }
+ dsi_irq_mask &= ~term;
+ if (dsi_irq_mask == 0) {
+ disable_irq(dsi_irq);
+ pr_debug("%s: IRQ Disable, mask=%x term=%x\n",
+ __func__, (int)dsi_irq_mask, (int)term);
+ }
+ spin_unlock_irqrestore(&dsi_irq_lock, flags);
+}
+
+/*
+ * mipi_dsi_disale_irq_nosync() should be called
+ * from interrupt context
+ */
+void mipi_dsi_disable_irq_nosync(u32 term)
+{
+ spin_lock(&dsi_irq_lock);
+ if (!(dsi_irq_mask & term)) {
+ spin_unlock(&dsi_irq_lock);
+ return;
+ }
+ dsi_irq_mask &= ~term;
+ if (dsi_irq_mask == 0) {
+ disable_irq_nosync(dsi_irq);
+ pr_debug("%s: IRQ Disable, mask=%x term=%x\n",
+ __func__, (int)dsi_irq_mask, (int)term);
+ }
+ spin_unlock(&dsi_irq_lock);
+}
+
+void mipi_dsi_clk_cfg(int on)
+{
+ unsigned long flags;
+ static int dsi_clk_cnt;
+
+ spin_lock_irqsave(&mdp_spin_lock, flags);
+ if (on) {
+ if (dsi_clk_cnt == 0) {
+ mipi_dsi_ahb_ctrl(1);
+ mipi_dsi_clk_enable();
+ }
+ dsi_clk_cnt++;
+ } else {
+ if (dsi_clk_cnt) {
+ dsi_clk_cnt--;
+ if (dsi_clk_cnt == 0) {
+ mipi_dsi_clk_disable();
+ mipi_dsi_ahb_ctrl(0);
+ }
+ }
+ }
+ spin_unlock_irqrestore(&mdp_spin_lock, flags);
+}
+
+void mipi_dsi_turn_on_clks(void)
+{
+ mipi_dsi_ahb_ctrl(1);
+ mipi_dsi_clk_enable();
+}
+
+void mipi_dsi_turn_off_clks(void)
+{
+ mipi_dsi_clk_disable();
+ mipi_dsi_ahb_ctrl(0);
+}
+
+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;
+}
+
+/*
+ * mipi_dsi_short_read1_resp: 1 parameter
+ */
+static int mipi_dsi_short_read1_resp(struct dsi_buf *rp)
+{
+ /* strip out dcs type */
+ rp->data++;
+ rp->len = 1;
+ return rp->len;
+}
+
+/*
+ * mipi_dsi_short_read2_resp: 2 parameter
+ */
+static int mipi_dsi_short_read2_resp(struct dsi_buf *rp)
+{
+ /* strip out dcs type */
+ rp->data++;
+ rp->len = 2;
+ return rp->len;
+}
+
+static int mipi_dsi_long_read_resp(struct dsi_buf *rp)
+{
+ short len;
+
+ len = rp->data[2];
+ len <<= 8;
+ len |= rp->data[1];
+ /* strip out dcs header */
+ rp->data += 4;
+ rp->len -= 4;
+ /* strip out 2 bytes of checksum */
+ rp->len -= 2;
+ return len;
+}
+
+void mipi_dsi_host_init(struct mipi_panel_info *pinfo)
+{
+ uint32 dsi_ctrl, intr_ctrl;
+ uint32 data;
+
+ if (mdp_rev > MDP_REV_41 || mdp_rev == MDP_REV_303)
+ pinfo->rgb_swap = DSI_RGB_SWAP_RGB;
+ else
+ pinfo->rgb_swap = DSI_RGB_SWAP_BGR;
+
+ 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_sw_reset(void)
+{
+ MIPI_OUTP(MIPI_DSI_BASE + 0x114, 0x01);
+ wmb();
+ MIPI_OUTP(MIPI_DSI_BASE + 0x114, 0x00);
+ wmb();
+}
+
+void mipi_dsi_controller_cfg(int enable)
+{
+
+ uint32 dsi_ctrl;
+ uint32 status;
+ int cnt;
+
+ cnt = 16;
+ while (cnt--) {
+ status = MIPI_INP(MIPI_DSI_BASE + 0x0004);
+ status &= 0x02; /* CMD_MODE_DMA_BUSY */
+ if (status == 0)
+ break;
+ usleep(1000);
+ }
+ if (cnt == 0)
+ pr_info("%s: DSI status=%x failed\n", __func__, status);
+
+ cnt = 16;
+ while (cnt--) {
+ status = MIPI_INP(MIPI_DSI_BASE + 0x0008);
+ status &= 0x11111000; /* x_HS_FIFO_EMPTY */
+ if (status == 0x11111000) /* all empty */
+ break;
+ usleep(1000);
+ }
+
+ if (cnt == 0)
+ pr_info("%s: FIFO status=%x failed\n", __func__, status);
+
+ dsi_ctrl = MIPI_INP(MIPI_DSI_BASE + 0x0000);
+ if (enable)
+ dsi_ctrl |= 0x01;
+ else
+ dsi_ctrl &= ~0x01;
+
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0000, dsi_ctrl);
+ wmb();
+}
+
+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_mdp_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(&dsi_mdp_lock, flag);
+ if (dsi_mdp_busy == TRUE) {
+ INIT_COMPLETION(dsi_mdp_comp);
+ need_wait++;
+ }
+ spin_unlock_irqrestore(&dsi_mdp_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(&dsi_mdp_comp);
+ }
+ pr_debug("%s: done pid=%d\n",
+ __func__, current->pid);
+}
+
+void mipi_dsi_cmd_mdp_start(void)
+{
+ unsigned long flag;
+
+ mipi_dsi_mdp_stat_inc(STAT_DSI_START);
+
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ mipi_dsi_enable_irq(DSI_MDP_TERM);
+ dsi_mdp_busy = TRUE;
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+}
+
+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(&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(&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:
+ * thread context only
+ */
+int mipi_dsi_cmds_tx(struct dsi_buf *tp, struct dsi_cmd_desc *cmds, int cnt)
+{
+ struct dsi_cmd_desc *cm;
+ uint32 dsi_ctrl, ctrl;
+ int i, video_mode;
+ unsigned long flag;
+
+ /* 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);
+ }
+
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ dsi_mdp_busy = TRUE;
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+
+ cm = cmds;
+ mipi_dsi_buf_init(tp);
+ for (i = 0; i < cnt; i++) {
+ mipi_dsi_enable_irq(DSI_CMD_TERM);
+ 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++;
+ }
+
+ if (video_mode)
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0000, dsi_ctrl); /* restore */
+
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ dsi_mdp_busy = FALSE;
+ complete(&dsi_mdp_comp);
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+
+ 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 rlen)
+{
+ int cnt, len, diff, pkt_size;
+ char cmd;
+ unsigned long flag;
+
+ if (mfd->panel_info.mipi.no_max_pkt_size) {
+ /* Only support rlen = 4*n */
+ rlen += 3;
+ rlen &= ~0x03;
+ }
+
+ len = rlen;
+ diff = 0;
+
+ if (len <= 2)
+ cnt = 4; /* short read */
+ else {
+ if (len > MIPI_DSI_LEN)
+ len = MIPI_DSI_LEN; /* 8 bytes at most */
+
+ len = (len + 3) & ~0x03; /* len 4 bytes align */
+ diff = len - rlen;
+ /*
+ * 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 */
+#ifdef CONFIG_FB_MSM_MDP303
+ mdp3_dsi_cmd_dma_busy_wait(mfd);
+#endif
+ }
+
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ dsi_mdp_busy = TRUE;
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+
+ if (!mfd->panel_info.mipi.no_max_pkt_size) {
+ /* packet size need to be set at every read */
+ pkt_size = len;
+ max_pktsize[0] = pkt_size;
+ mipi_dsi_enable_irq(DSI_CMD_TERM);
+ mipi_dsi_buf_init(tp);
+ mipi_dsi_cmd_dma_add(tp, pkt_size_cmd);
+ mipi_dsi_cmd_dma_tx(tp);
+ }
+
+ mipi_dsi_enable_irq(DSI_CMD_TERM);
+ mipi_dsi_buf_init(tp);
+ mipi_dsi_cmd_dma_add(tp, cmds);
+
+ /* transmit read comamnd to client */
+ mipi_dsi_cmd_dma_tx(tp);
+
+ mipi_dsi_disable_irq(DSI_CMD_TERM);
+ /*
+ * once cmd_dma_done interrupt received,
+ * return data from client is ready and stored
+ * at RDBK_DATA register already
+ */
+ mipi_dsi_buf_init(rp);
+ if (mfd->panel_info.mipi.no_max_pkt_size) {
+ /*
+ * expect rlen = n * 4
+ * short alignement for start addr
+ */
+ rp->data += 2;
+ }
+
+ mipi_dsi_cmd_dma_rx(rp, cnt);
+
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ dsi_mdp_busy = FALSE;
+ complete(&dsi_mdp_comp);
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+
+ if (mfd->panel_info.mipi.no_max_pkt_size) {
+ /*
+ * remove extra 2 bytes from previous
+ * rx transaction at shift register
+ * which was inserted during copy
+ * shift registers to rx buffer
+ * rx payload start from long alignment addr
+ */
+ rp->data += 2;
+ }
+
+ cmd = rp->data[0];
+ switch (cmd) {
+ case DTYPE_ACK_ERR_RESP:
+ pr_debug("%s: rx ACK_ERR_PACLAGE\n", __func__);
+ break;
+ case DTYPE_GEN_READ1_RESP:
+ case DTYPE_DCS_READ1_RESP:
+ mipi_dsi_short_read1_resp(rp);
+ break;
+ case DTYPE_GEN_READ2_RESP:
+ case DTYPE_DCS_READ2_RESP:
+ mipi_dsi_short_read2_resp(rp);
+ break;
+ case DTYPE_GEN_LREAD_RESP:
+ case DTYPE_DCS_LREAD_RESP:
+ mipi_dsi_long_read_resp(rp);
+ rp->len -= 2; /* extra 2 bytes added */
+ rp->len -= diff; /* align bytes */
+ break;
+ default:
+ break;
+ }
+
+ return rp->len;
+}
+
+int mipi_dsi_cmds_rx_new(struct dsi_buf *tp, struct dsi_buf *rp,
+ struct dcs_cmd_req *req, int rlen)
+{
+ struct dsi_cmd_desc *cmds;
+ int cnt, len, diff, pkt_size;
+ char cmd;
+ unsigned long flag;
+
+ if (req->flags & CMD_REQ_NO_MAX_PKT_SIZE) {
+ /* Only support rlen = 4*n */
+ rlen += 3;
+ rlen &= ~0x03;
+ }
+
+ cmds = req->cmds;
+
+ len = rlen;
+ diff = 0;
+
+ if (len <= 2)
+ cnt = 4; /* short read */
+ else {
+ if (len > MIPI_DSI_LEN)
+ len = MIPI_DSI_LEN; /* 8 bytes at most */
+
+ len = (len + 3) & ~0x03; /* len 4 bytes align */
+ diff = len - rlen;
+ /*
+ * 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 */
+ }
+
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ dsi_mdp_busy = TRUE;
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+
+ if (!(req->flags & CMD_REQ_NO_MAX_PKT_SIZE)) {
+
+
+ /* packet size need to be set at every read */
+ pkt_size = len;
+ max_pktsize[0] = pkt_size;
+ mipi_dsi_enable_irq(DSI_CMD_TERM);
+ mipi_dsi_buf_init(tp);
+ mipi_dsi_cmd_dma_add(tp, pkt_size_cmd);
+ mipi_dsi_cmd_dma_tx(tp);
+ }
+
+ mipi_dsi_enable_irq(DSI_CMD_TERM);
+ mipi_dsi_buf_init(tp);
+ mipi_dsi_cmd_dma_add(tp, cmds);
+
+ /* transmit read comamnd to client */
+ mipi_dsi_cmd_dma_tx(tp);
+
+ mipi_dsi_disable_irq(DSI_CMD_TERM);
+ /*
+ * once cmd_dma_done interrupt received,
+ * return data from client is ready and stored
+ * at RDBK_DATA register already
+ */
+ mipi_dsi_buf_init(rp);
+ if (req->flags & CMD_REQ_NO_MAX_PKT_SIZE) {
+ /*
+ * expect rlen = n * 4
+ * short alignement for start addr
+ */
+ rp->data += 2;
+ }
+
+ mipi_dsi_cmd_dma_rx(rp, cnt);
+
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ dsi_mdp_busy = FALSE;
+ complete(&dsi_mdp_comp);
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+
+ if (req->flags & CMD_REQ_NO_MAX_PKT_SIZE) {
+ /*
+ * remove extra 2 bytes from previous
+ * rx transaction at shift register
+ * which was inserted during copy
+ * shift registers to rx buffer
+ * rx payload start from long alignment addr
+ */
+ rp->data += 2;
+ }
+
+ cmd = rp->data[0];
+ switch (cmd) {
+ case DTYPE_ACK_ERR_RESP:
+ pr_debug("%s: rx ACK_ERR_PACLAGE\n", __func__);
+ break;
+ case DTYPE_GEN_READ1_RESP:
+ case DTYPE_DCS_READ1_RESP:
+ mipi_dsi_short_read1_resp(rp);
+ break;
+ case DTYPE_GEN_READ2_RESP:
+ case DTYPE_DCS_READ2_RESP:
+ mipi_dsi_short_read2_resp(rp);
+ break;
+ case DTYPE_GEN_LREAD_RESP:
+ case DTYPE_DCS_LREAD_RESP:
+ mipi_dsi_long_read_resp(rp);
+ rp->len -= 2; /* extra 2 bytes added */
+ rp->len -= diff; /* align bytes */
+ break;
+ default:
+ break;
+ }
+
+ return rp->len;
+}
+
+int mipi_dsi_cmd_dma_tx(struct dsi_buf *tp)
+{
+
+ unsigned long flags;
+
+#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
+
+ if (tp->len == 0) {
+ pr_err("%s: Error, len=0\n", __func__);
+ return 0;
+ }
+
+ spin_lock_irqsave(&dsi_mdp_lock, flags);
+ tp->len += 3;
+ tp->len &= ~0x03; /* multipled by 4 */
+
+ tp->dmap = dma_map_single(&dsi_dev, tp->data, tp->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, tp->len);
+ wmb();
+ MIPI_OUTP(MIPI_DSI_BASE + 0x08c, 0x01); /* trigger */
+ wmb();
+ spin_unlock_irqrestore(&dsi_mdp_lock, flags);
+
+ wait_for_completion(&dsi_dma_comp);
+
+ dma_unmap_single(&dsi_dev, tp->dmap, tp->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_cmd_mdp_busy(void)
+{
+ u32 status;
+ unsigned long flags;
+ int need_wait;
+
+ spin_lock_irqsave(&dsi_mdp_lock, flags);
+ status = MIPI_INP(MIPI_DSI_BASE + 0x0004);/* DSI_STATUS */
+ if (status & 0x04) { /* MDP BUSY */
+ INIT_COMPLETION(dsi_mdp_comp);
+ need_wait = 1;
+printk("%s: status=%x need_wait\n",__func__, (int)status);
+ mipi_dsi_enable_irq(DSI_MDP_TERM);
+ }
+ spin_unlock_irqrestore(&dsi_mdp_lock, flags);
+
+ if (need_wait)
+ wait_for_completion(&dsi_mdp_comp);
+}
+
+/*
+ * mipi_dsi_cmd_get: cmd_mutex acquired by caller
+ */
+struct dcs_cmd_req *mipi_dsi_cmdlist_get(void)
+{
+ struct dcs_cmd_req *req = NULL;
+
+ if (cmdlist.get != cmdlist.put) {
+ req = &cmdlist.list[cmdlist.get];
+ cmdlist.get++;
+ cmdlist.get %= CMD_REQ_MAX;
+ cmdlist.tot--;
+ pr_debug("%s: tot=%d put=%d get=%d\n", __func__,
+ cmdlist.tot, cmdlist.put, cmdlist.get);
+ }
+ return req;
+}
+void mipi_dsi_cmdlist_tx(struct dcs_cmd_req *req)
+{
+ struct dsi_buf *tp;
+ int ret;
+
+ mipi_dsi_buf_init(&dsi_tx_buf);
+ tp = &dsi_tx_buf;
+ ret = mipi_dsi_cmds_tx(tp, req->cmds, req->cmds_cnt);
+
+ if (req->cb)
+ req->cb(ret);
+
+}
+
+void mipi_dsi_cmdlist_rx(struct dcs_cmd_req *req)
+{
+ int len;
+ u32 *dp;
+ struct dsi_buf *tp;
+ struct dsi_buf *rp;
+
+ mipi_dsi_buf_init(&dsi_tx_buf);
+ mipi_dsi_buf_init(&dsi_rx_buf);
+
+ tp = &dsi_tx_buf;
+ rp = &dsi_rx_buf;
+
+ len = mipi_dsi_cmds_rx_new(tp, rp, req, req->rlen);
+ dp = (u32 *)rp->data;
+
+ if (req->cb)
+ req->cb(*dp);
+}
+
+void mipi_dsi_cmdlist_commit(int from_mdp)
+{
+ struct dcs_cmd_req *req;
+
+ mutex_lock(&cmd_mutex);
+ req = mipi_dsi_cmdlist_get();
+ if (req == NULL) {
+ mutex_unlock(&cmd_mutex);
+ return;
+ }
+
+ pr_debug("%s: from_mdp=%d pid=%d\n",__func__, from_mdp, current->pid);
+
+ if (!from_mdp) { /* from put */
+ /* make sure dsi_cmd_mdp is idle */
+ mipi_dsi_cmd_mdp_busy();
+ }
+
+ if (req->flags && CMD_REQ_RX)
+ mipi_dsi_cmdlist_rx(req);
+ else
+ mipi_dsi_cmdlist_tx(req);
+
+ mutex_unlock(&cmd_mutex);
+}
+
+int mipi_dsi_cmdlist_put(struct dcs_cmd_req *cmdreq)
+{
+ struct dcs_cmd_req *req;
+ int ret = 0;
+
+ mutex_lock(&cmd_mutex);
+ req = &cmdlist.list[cmdlist.put];
+ *req = *cmdreq;
+ cmdlist.put++;
+ cmdlist.put %= CMD_REQ_MAX;
+ cmdlist.tot++;
+ if (cmdlist.put == cmdlist.get) {
+ /* drop the oldest one */
+ pr_debug("%s: DROP, tot=%d put=%d get=%d\n", __func__,
+ cmdlist.tot, cmdlist.put, cmdlist.get);
+ cmdlist.get++;
+ cmdlist.get %= CMD_REQ_MAX;
+ cmdlist.tot--;
+ }
+ mutex_unlock(&cmd_mutex);
+
+ ret++;
+ pr_debug("%s: tot=%d put=%d get=%d\n", __func__,
+ cmdlist.tot, cmdlist.put, cmdlist.get);
+
+ if (req->flags & CMD_REQ_COMMIT)
+ mipi_dsi_cmdlist_commit(0);
+
+ return ret;
+}
+
+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);
+
+ pr_debug("%s: isr=%x\n", __func__, (int)isr);
+
+#ifdef CONFIG_FB_MSM_MDP40
+ mdp4_stat.intr_dsi++;
+#endif
+ if (isr & DSI_INTR_ERROR) {
+ mipi_dsi_mdp_stat_inc(STAT_DSI_ERROR);
+ mipi_dsi_error();
+ }
+
+ if (isr & DSI_INTR_VIDEO_DONE) {
+ /*
+ * do something here
+ */
+ }
+
+ if (isr & DSI_INTR_CMD_DMA_DONE) {
+ mipi_dsi_mdp_stat_inc(STAT_DSI_CMD);
+ spin_lock(&dsi_mdp_lock);
+ complete(&dsi_dma_comp);
+ dsi_ctrl_lock = FALSE;
+ mipi_dsi_disable_irq_nosync(DSI_CMD_TERM);
+ spin_unlock(&dsi_mdp_lock);
+ }
+
+ if (isr & DSI_INTR_CMD_MDP_DONE) {
+ mipi_dsi_mdp_stat_inc(STAT_DSI_MDP);
+ spin_lock(&dsi_mdp_lock);
+ dsi_ctrl_lock = FALSE;
+ mipi_dsi_disable_irq_nosync(DSI_MDP_TERM);
+ dsi_mdp_busy = FALSE;
+ complete(&dsi_mdp_comp);
+ spin_unlock(&dsi_mdp_lock);
+ }
+
+
+ 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..2dde711
--- /dev/null
+++ b/drivers/video/msm/mipi_novatek.c
@@ -0,0 +1,635 @@
+/* Copyright (c) 2010-2012, 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.
+ *
+ */
+
+#ifdef CONFIG_SPI_QUP
+#include <linux/spi/spi.h>
+#endif
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_novatek.h"
+#include "mdp4.h"
+
+
+static struct mipi_dsi_panel_platform_data *mipi_novatek_pdata;
+
+static struct dsi_buf novatek_tx_buf;
+static struct dsi_buf novatek_rx_buf;
+static int mipi_novatek_lcd_init(void);
+
+#define MIPI_DSI_NOVATEK_SPI_DEVICE_NAME "dsi_novatek_3d_panel_spi"
+#define HPCI_FPGA_READ_CMD 0x84
+#define HPCI_FPGA_WRITE_CMD 0x04
+
+#ifdef CONFIG_SPI_QUP
+static struct spi_device *panel_3d_spi_client;
+
+static void novatek_fpga_write(uint8 addr, uint16 value)
+{
+ char tx_buf[32];
+ int rc;
+ struct spi_message m;
+ struct spi_transfer t;
+ u8 data[4] = {0x0, 0x0, 0x0, 0x0};
+
+ if (!panel_3d_spi_client) {
+ pr_err("%s panel_3d_spi_client is NULL\n", __func__);
+ return;
+ }
+ data[0] = HPCI_FPGA_WRITE_CMD;
+ data[1] = addr;
+ data[2] = ((value >> 8) & 0xFF);
+ data[3] = (value & 0xFF);
+
+ memset(&t, 0, sizeof t);
+ memset(tx_buf, 0, sizeof tx_buf);
+ t.tx_buf = data;
+ t.len = 4;
+ spi_setup(panel_3d_spi_client);
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+
+ rc = spi_sync(panel_3d_spi_client, &m);
+ if (rc)
+ pr_err("%s: SPI transfer failed\n", __func__);
+
+ return;
+}
+
+static void novatek_fpga_read(uint8 addr)
+{
+ char tx_buf[32];
+ int rc;
+ struct spi_message m;
+ struct spi_transfer t;
+ struct spi_transfer rx;
+ char rx_value[2];
+ u8 data[4] = {0x0, 0x0};
+
+ if (!panel_3d_spi_client) {
+ pr_err("%s panel_3d_spi_client is NULL\n", __func__);
+ return;
+ }
+
+ data[0] = HPCI_FPGA_READ_CMD;
+ data[1] = addr;
+
+ memset(&t, 0, sizeof t);
+ memset(tx_buf, 0, sizeof tx_buf);
+ memset(&rx, 0, sizeof rx);
+ memset(rx_value, 0, sizeof rx_value);
+ t.tx_buf = data;
+ t.len = 2;
+ rx.rx_buf = rx_value;
+ rx.len = 2;
+ spi_setup(panel_3d_spi_client);
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+ spi_message_add_tail(&rx, &m);
+
+ rc = spi_sync(panel_3d_spi_client, &m);
+ if (rc)
+ pr_err("%s: SPI transfer failed\n", __func__);
+ else
+ pr_info("%s: rx_value = 0x%x, 0x%x\n", __func__,
+ rx_value[0], rx_value[1]);
+
+ return;
+}
+
+static int __devinit panel_3d_spi_probe(struct spi_device *spi)
+{
+ panel_3d_spi_client = spi;
+ return 0;
+}
+static int __devexit panel_3d_spi_remove(struct spi_device *spi)
+{
+ panel_3d_spi_client = NULL;
+ return 0;
+}
+static struct spi_driver panel_3d_spi_driver = {
+ .probe = panel_3d_spi_probe,
+ .remove = __devexit_p(panel_3d_spi_remove),
+ .driver = {
+ .name = "dsi_novatek_3d_panel_spi",
+ .owner = THIS_MODULE,
+ }
+};
+
+#else
+
+static void novatek_fpga_write(uint8 addr, uint16 value)
+{
+ return;
+}
+
+static void novatek_fpga_read(uint8 addr)
+{
+ return;
+}
+
+#endif
+
+
+/* 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_pwm2[2] = {0x53, 0x24}; /* DTYPE_DCS_WRITE1 */
+static char led_pwm3[2] = {0x55, 0x00}; /* DTYPE_DCS_WRITE1 */
+
+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;
+ cmd = &novatek_manufacture_id_cmd;
+ mipi_dsi_cmds_rx(mfd, tp, rp, cmd, 3);
+ lp = (uint32 *)rp->data;
+ pr_info("%s: manufacture_id=%x\n", __func__, *lp);
+ return *lp;
+}
+
+static int fpga_addr;
+static int fpga_access_mode;
+static bool support_3d;
+
+static void mipi_novatek_3d_init(int addr, int mode)
+{
+ fpga_addr = addr;
+ fpga_access_mode = mode;
+}
+
+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;
+ }
+
+ if (fpga_access_mode == FPGA_SPI_INTF) {
+ if (mode == LANDSCAPE)
+ novatek_fpga_write(fpga_addr, 1);
+ else if (mode == PORTRAIT)
+ novatek_fpga_write(fpga_addr, 3);
+ else
+ novatek_fpga_write(fpga_addr, 0);
+
+ mb();
+ novatek_fpga_read(fpga_addr);
+ } else if (fpga_access_mode == FPGA_EBI2_INTF) {
+ 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);
+ } else
+ pr_err("%s: 3D barrier not configured correctly\n",
+ __func__);
+}
+
+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(&novatek_tx_buf, novatek_video_on_cmds,
+ ARRAY_SIZE(novatek_video_on_cmds));
+ } else {
+ mipi_dsi_cmds_tx(&novatek_tx_buf, novatek_cmd_on_cmds,
+ ARRAY_SIZE(novatek_cmd_on_cmds));
+
+ /* clean up ack_err_status */
+ mipi_dsi_cmd_bta_sw_trigger();
+ 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(&novatek_tx_buf, novatek_display_off_cmds,
+ ARRAY_SIZE(novatek_display_off_cmds));
+
+ return 0;
+}
+
+static char led_pwm1[2] = {0x51, 0x0}; /* DTYPE_DCS_WRITE1 */
+static struct dsi_cmd_desc backlight_cmd = {
+ DTYPE_DCS_LWRITE, 1, 0, 0, 1, sizeof(led_pwm1), led_pwm1};
+
+struct dcs_cmd_req cmdreq;
+
+static void mipi_novatek_set_backlight(struct msm_fb_data_type *mfd)
+{
+ led_pwm1[1] = (unsigned char)mfd->bl_level;
+
+ cmdreq.cmds = &backlight_cmd;
+ cmdreq.cmds_cnt = 1;
+ cmdreq.flags = 0;
+ cmdreq.rlen = 0;
+ cmdreq.cb = NULL;
+
+ mipi_dsi_cmdlist_put(&cmdreq);
+}
+
+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)
+{
+ struct msm_fb_data_type *mfd;
+ struct mipi_panel_info *mipi;
+ struct platform_device *current_pdev;
+ static struct mipi_dsi_phy_ctrl *phy_settings;
+ static char dlane_swap;
+
+ if (pdev->id == 0) {
+ mipi_novatek_pdata = pdev->dev.platform_data;
+
+ if (mipi_novatek_pdata
+ && mipi_novatek_pdata->phy_ctrl_settings) {
+ phy_settings = (mipi_novatek_pdata->phy_ctrl_settings);
+ }
+
+ if (mipi_novatek_pdata
+ && mipi_novatek_pdata->dlane_swap) {
+ dlane_swap = (mipi_novatek_pdata->dlane_swap);
+ }
+
+ if (mipi_novatek_pdata
+ && mipi_novatek_pdata->fpga_3d_config_addr)
+ mipi_novatek_3d_init(mipi_novatek_pdata
+ ->fpga_3d_config_addr, mipi_novatek_pdata->fpga_ctrl_mode);
+
+ /* 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;
+ }
+
+ current_pdev = msm_fb_add_device(pdev);
+
+ if (current_pdev) {
+ mfd = platform_get_drvdata(current_pdev);
+ if (!mfd)
+ return -ENODEV;
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ mipi = &mfd->panel_info.mipi;
+
+ if (phy_settings != NULL)
+ mipi->dsi_phy_db = phy_settings;
+
+ if (dlane_swap)
+ mipi->dlane_swap = dlane_swap;
+ }
+ 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, 0664, 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;
+
+ ret = mipi_novatek_lcd_init();
+ if (ret) {
+ pr_err("mipi_novatek_lcd_init() failed with ret %u\n", ret);
+ return ret;
+ }
+
+ 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 mipi_novatek_lcd_init(void)
+{
+#ifdef CONFIG_SPI_QUP
+ int ret;
+ ret = spi_register_driver(&panel_3d_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__);
+#endif
+
+ 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);
+}
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..f139f4c
--- /dev/null
+++ b/drivers/video/msm/mipi_novatek_cmd_qhd_pt.c
@@ -0,0 +1,100 @@
+/* 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;
+
+ if (msm_fb_detect_client("mipi_cmd_novatek_qhd"))
+ return 0;
+
+ 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.lcd.v_back_porch = 11;
+ pinfo.lcd.v_front_porch = 10;
+ pinfo.lcd.v_pulse_width = 5;
+
+ pinfo.mipi.mode = DSI_CMD_MODE;
+ pinfo.mipi.dst_format = DSI_CMD_DST_FORMAT_RGB888;
+ pinfo.mipi.vc = 0;
+ pinfo.mipi.data_lane0 = TRUE;
+ pinfo.mipi.esc_byte_ratio = 4;
+#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_NONE;
+ 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_QHD_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..7a9d556
--- /dev/null
+++ b/drivers/video/msm/mipi_novatek_video_qhd_pt.c
@@ -0,0 +1,97 @@
+/* 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;
+
+ if (msm_fb_detect_client("mipi_video_novatek_qhd"))
+ return 0;
+
+ 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;
+ pinfo.mipi.esc_byte_ratio = 4;
+#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_QHD_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_orise.c b/drivers/video/msm/mipi_orise.c
new file mode 100644
index 0000000..d1d6956
--- /dev/null
+++ b/drivers/video/msm/mipi_orise.c
@@ -0,0 +1,194 @@
+/* Copyright (c) 2012, 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_orise.h"
+#include "mdp4.h"
+
+
+static struct mipi_dsi_panel_platform_data *mipi_orise_pdata;
+
+static struct dsi_buf orise_tx_buf;
+static struct dsi_buf orise_rx_buf;
+
+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 struct dsi_cmd_desc orise_video_on_cmds[] = {
+ {DTYPE_DCS_WRITE, 1, 0, 0, 10,
+ sizeof(exit_sleep), exit_sleep},
+ {DTYPE_DCS_WRITE, 1, 0, 0, 10,
+ sizeof(display_on), display_on},
+};
+
+static struct dsi_cmd_desc orise_cmd_on_cmds[] = {
+ {DTYPE_DCS_WRITE, 1, 0, 0, 10,
+ sizeof(exit_sleep), exit_sleep},
+ {DTYPE_DCS_WRITE, 1, 0, 0, 10,
+ sizeof(display_on), display_on},
+};
+
+static struct dsi_cmd_desc orise_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 int mipi_orise_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;
+ mipi = &mfd->panel_info.mipi;
+
+ if (mipi->mode == DSI_VIDEO_MODE) {
+ mipi_dsi_cmds_tx(&orise_tx_buf, orise_video_on_cmds,
+ ARRAY_SIZE(orise_video_on_cmds));
+ } else {
+ mipi_dsi_cmds_tx(&orise_tx_buf, orise_cmd_on_cmds,
+ ARRAY_SIZE(orise_cmd_on_cmds));
+
+ mipi_dsi_cmd_bta_sw_trigger(); /* clean up ack_err_status */
+ }
+
+ return 0;
+}
+
+static int mipi_orise_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(&orise_tx_buf, orise_display_off_cmds,
+ ARRAY_SIZE(orise_display_off_cmds));
+
+ return 0;
+}
+
+
+
+static int __devinit mipi_orise_lcd_probe(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct mipi_panel_info *mipi;
+ struct platform_device *current_pdev;
+ static struct mipi_dsi_phy_ctrl *phy_settings;
+
+ if (pdev->id == 0) {
+ mipi_orise_pdata = pdev->dev.platform_data;
+
+ if (mipi_orise_pdata
+ && mipi_orise_pdata->phy_ctrl_settings) {
+ phy_settings = (mipi_orise_pdata->phy_ctrl_settings);
+ }
+
+ return 0;
+ }
+
+ current_pdev = msm_fb_add_device(pdev);
+
+ if (current_pdev) {
+ mfd = platform_get_drvdata(current_pdev);
+ if (!mfd)
+ return -ENODEV;
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ mipi = &mfd->panel_info.mipi;
+
+ if (phy_settings != NULL)
+ mipi->dsi_phy_db = phy_settings;
+ }
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = mipi_orise_lcd_probe,
+ .driver = {
+ .name = "mipi_orise",
+ },
+};
+
+static struct msm_fb_panel_data orise_panel_data = {
+ .on = mipi_orise_lcd_on,
+ .off = mipi_orise_lcd_off,
+};
+
+static int ch_used[3];
+
+int mipi_orise_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_orise", (panel << 8)|channel);
+ if (!pdev)
+ return -ENOMEM;
+
+ orise_panel_data.panel_info = *pinfo;
+
+ ret = platform_device_add_data(pdev, &orise_panel_data,
+ sizeof(orise_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_orise_lcd_init(void)
+{
+ mipi_dsi_buf_alloc(&orise_tx_buf, DSI_BUF_SIZE);
+ mipi_dsi_buf_alloc(&orise_rx_buf, DSI_BUF_SIZE);
+
+ return platform_driver_register(&this_driver);
+}
+
+module_init(mipi_orise_lcd_init);
diff --git a/drivers/video/msm/mipi_orise.h b/drivers/video/msm/mipi_orise.h
new file mode 100644
index 0000000..1659479
--- /dev/null
+++ b/drivers/video/msm/mipi_orise.h
@@ -0,0 +1,21 @@
+/* Copyright (c) 2012, 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_ORISE_H
+#define MIPI_ORISE_H
+
+int mipi_orise_device_register(struct msm_panel_info *pinfo,
+ u32 channel, u32 panel);
+
+#endif /* MIPI_ORISE_H */
diff --git a/drivers/video/msm/mipi_orise_cmd_720p_pt.c b/drivers/video/msm/mipi_orise_cmd_720p_pt.c
new file mode 100644
index 0000000..c2a158d
--- /dev/null
+++ b/drivers/video/msm/mipi_orise_cmd_720p_pt.c
@@ -0,0 +1,96 @@
+/* Copyright (c) 2012, 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_orise.h"
+
+static struct msm_panel_info pinfo;
+
+static struct mipi_dsi_phy_ctrl dsi_cmd_mode_phy_db = {
+/* DSI_BIT_CLK at 507MHz, 4 lane, RGB888 */
+ {0x03, 0x0a, 0x04, 0x00, 0x20},
+ /* timing */
+ {0x8c, 0x34, 0x15, 0x00, 0x46, 0x50, 0x1a, 0x38,
+ 0x24, 0x03, 0x04, 0xa0},
+ /* phy ctrl */
+ {0x5f, 0x00, 0x00, 0x10},
+ /* strength */
+ {0xff, 0x00, 0x06, 0x00},
+ /* pll control */
+ {0x0, 0xf9, 0x30, 0xda, 0x00, 0x40, 0x03, 0x62,
+ 0x40, 0x07, 0x03,
+ 0x00, 0x1a, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0x01 },
+};
+
+static int __init mipi_cmd_orise_720p_pt_init(void)
+{
+ int ret;
+
+ if (msm_fb_detect_client("mipi_cmd_orise_720p"))
+ return 0;
+
+ pinfo.xres = 720;
+ pinfo.yres = 1280;
+ pinfo.type = MIPI_CMD_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 24;
+ pinfo.lcdc.h_back_porch = 160;
+ pinfo.lcdc.h_front_porch = 160;
+ pinfo.lcdc.h_pulse_width = 8;
+ pinfo.lcdc.v_back_porch = 32;
+ pinfo.lcdc.v_front_porch = 32;
+ 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 = 200;
+ pinfo.bl_min = 1;
+ pinfo.fb_num = 2;
+ pinfo.clk_rate = 507000000;
+ pinfo.lcd.vsync_enable = TRUE;
+ pinfo.lcd.hw_vsync_mode = TRUE;
+ pinfo.lcd.refx100 = 6000; /* adjust refx100 to prevent tearing */
+ pinfo.lcd.v_back_porch = 32;
+ pinfo.lcd.v_front_porch = 32;
+ pinfo.lcd.v_pulse_width = 1;
+
+ pinfo.mipi.mode = DSI_CMD_MODE;
+ pinfo.mipi.dst_format = DSI_CMD_DST_FORMAT_RGB888;
+ pinfo.mipi.vc = 0;
+ pinfo.mipi.data_lane0 = TRUE;
+ pinfo.mipi.data_lane1 = TRUE;
+ pinfo.mipi.data_lane2 = TRUE;
+ pinfo.mipi.data_lane3 = TRUE;
+ pinfo.mipi.t_clk_post = 0x04;
+ pinfo.mipi.t_clk_pre = 0x1e;
+ pinfo.mipi.stream = 0; /* dma_p */
+ pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_NONE;
+ 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_orise_device_register(&pinfo, MIPI_DSI_PRIM,
+ MIPI_DSI_PANEL_720P_PT);
+ if (ret)
+ pr_err("%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(mipi_cmd_orise_720p_pt_init);
diff --git a/drivers/video/msm/mipi_orise_video_720p_pt.c b/drivers/video/msm/mipi_orise_video_720p_pt.c
new file mode 100644
index 0000000..da8b5e5
--- /dev/null
+++ b/drivers/video/msm/mipi_orise_video_720p_pt.c
@@ -0,0 +1,98 @@
+/* Copyright (c) 2012, 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_orise.h"
+
+static struct msm_panel_info pinfo;
+
+static struct mipi_dsi_phy_ctrl dsi_video_mode_phy_db = {
+ /* regulator */
+ {0x03, 0x0a, 0x04, 0x00, 0x20},
+ /* timing */
+ {0x83, 0x31, 0x13, 0x00, 0x42, 0x4d, 0x18, 0x35,
+ 0x21, 0x03, 0x04, 0xa0},
+ /* phy ctrl */
+ {0x5f, 0x00, 0x00, 0x10},
+ /* strength */
+ {0xff, 0x00, 0x06, 0x00},
+ /* pll control */
+ {0x0, 0x0e, 0x30, 0xc0, 0x00, 0x40, 0x03, 0x62,
+ 0x40, 0x07, 0x07,
+ 0x00, 0x1a, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0x01 },
+};
+
+static int __init mipi_video_orise_720p_pt_init(void)
+{
+ int ret;
+
+ if (msm_fb_detect_client("mipi_video_orise_720p"))
+ return 0;
+
+ pinfo.xres = 720;
+ pinfo.yres = 1280;
+ pinfo.lcdc.xres_pad = 0;
+ pinfo.lcdc.yres_pad = 0;
+
+ pinfo.type = MIPI_VIDEO_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 24;
+ pinfo.lcdc.h_back_porch = 160;
+ pinfo.lcdc.h_front_porch = 160;
+ pinfo.lcdc.h_pulse_width = 8;
+ pinfo.lcdc.v_back_porch = 32;
+ pinfo.lcdc.v_front_porch = 32;
+ 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 = 200;
+ 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 = FALSE;
+ pinfo.mipi.eof_bllp_power_stop = TRUE;
+ pinfo.mipi.bllp_power_stop = TRUE;
+ 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.data_lane3 = TRUE;
+ pinfo.mipi.t_clk_post = 0x04;
+ pinfo.mipi.t_clk_pre = 0x1c;
+ 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;
+ pinfo.mipi.esc_byte_ratio = 4;
+
+ ret = mipi_orise_device_register(&pinfo, MIPI_DSI_PRIM,
+ MIPI_DSI_PANEL_720P_PT);
+ if (ret)
+ printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(mipi_video_orise_720p_pt_init);
diff --git a/drivers/video/msm/mipi_renesas.c b/drivers/video/msm/mipi_renesas.c
new file mode 100644
index 0000000..2e1a805
--- /dev/null
+++ b/drivers/video/msm/mipi_renesas.c
@@ -0,0 +1,1262 @@
+/* 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"
+#include <mach/socinfo.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 int mipi_renesas_lcd_init(void);
+
+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_DSIRXCTL[2] = {0x41, 0x01};
+static char config_TEON[2] = {0x35, 0x00};
+static char config_TEOFF[1] = {0x34};
+
+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},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_TEOFF), config_TEOFF},
+};
+
+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_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_DSIRXCTL), config_DSIRXCTL},
+ {DTYPE_DCS_WRITE1, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_TEON), config_TEON},
+ {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 char config_WRTXHT2[7] = {0x92, 0x15, 0x05, 0x0F, 0x00, 0x01, 0xe0};
+static char config_WRTXVT2[7] = {0x8b, 0x14, 0x01, 0x14, 0x00, 0x03, 0x60};
+
+static struct dsi_cmd_desc renesas_hvga_on_cmds[] = {
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_WRTXHT2), config_WRTXHT2},
+ {DTYPE_DCS_LWRITE, 1, 0, 0, RENESAS_CMD_DELAY,
+ sizeof(config_WRTXVT2), config_WRTXVT2},
+};
+
+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(&renesas_tx_buf, renesas_sleep_off_cmds,
+ ARRAY_SIZE(renesas_sleep_off_cmds));
+
+ mipi_set_tx_power_mode(1);
+ mipi_dsi_cmds_tx(&renesas_tx_buf, renesas_display_on_cmds,
+ ARRAY_SIZE(renesas_display_on_cmds));
+
+ if (cpu_is_msm7x25a() || cpu_is_msm7x25aa()) {
+ mipi_dsi_cmds_tx(&renesas_tx_buf, renesas_hvga_on_cmds,
+ ARRAY_SIZE(renesas_hvga_on_cmds));
+ }
+
+ if (mipi->mode == DSI_VIDEO_MODE)
+ mipi_dsi_cmds_tx(&renesas_tx_buf, renesas_video_on_cmds,
+ ARRAY_SIZE(renesas_video_on_cmds));
+ else
+ mipi_dsi_cmds_tx(&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(&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;
+
+ ret = mipi_renesas_lcd_init();
+ if (ret) {
+ pr_err("mipi_renesas_lcd_init() failed with ret %u\n", ret);
+ return ret;
+ }
+
+ 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 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);
+}
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..7f5ac70
--- /dev/null
+++ b/drivers/video/msm/mipi_renesas_cmd_fwvga_pt.c
@@ -0,0 +1,157 @@
+/* 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;
+
+ if (msm_fb_detect_client("mipi_cmd_renesas_fwvga"))
+ return 0;
+
+ 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
+ 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.lcd.vsync_enable = TRUE;
+ pinfo.lcd.hw_vsync_mode = 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_SW;
+ pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.te_sel = 1; /* 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..e826773
--- /dev/null
+++ b/drivers/video/msm/mipi_renesas_video_fwvga_pt.c
@@ -0,0 +1,163 @@
+/* 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;
+
+ if (msm_fb_detect_client("mipi_video_renesas_fwvga"))
+ return 0;
+
+ 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..c751472
--- /dev/null
+++ b/drivers/video/msm/mipi_simulator.c
@@ -0,0 +1,167 @@
+/* Copyright (c) 2011-2012, 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 int mipi_simulator_lcd_init(void);
+
+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(&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(&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__);
+ ret = mipi_simulator_lcd_init();
+ if (ret) {
+ pr_err("mipi_simulator_lcd_init() failed with ret %u\n", ret);
+ return ret;
+ }
+
+ 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 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);
+}
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..845df75
--- /dev/null
+++ b/drivers/video/msm/mipi_simulator_video.c
@@ -0,0 +1,86 @@
+/* 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;
+
+ if (msm_fb_detect_client("mipi_video_simulator_vga"))
+ return 0;
+ 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_VGA);
+ 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_tc358764_dsi2lvds.c b/drivers/video/msm/mipi_tc358764_dsi2lvds.c
new file mode 100644
index 0000000..aa0e29c
--- /dev/null
+++ b/drivers/video/msm/mipi_tc358764_dsi2lvds.c
@@ -0,0 +1,1006 @@
+/* Copyright (c) 2011-2012, 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.
+ *
+ */
+
+/*
+ * Toshiba MIPI-DSI-to-LVDS Bridge driver.
+ * Device Model TC358764XBG/65XBG.
+ * Reference document: TC358764XBG_65XBG_V119.pdf
+ *
+ * The Host sends a DSI Generic Long Write packet (Data ID = 0x29) over the
+ * DSI link for each write access transaction to the chip configuration
+ * registers.
+ * Payload of this packet is 16-bit register address and 32-bit data.
+ * Multiple data values are allowed for sequential addresses.
+ *
+ * The Host sends a DSI Generic Read packet (Data ID = 0x24) over the DSI
+ * link for each read request transaction to the chip configuration
+ * registers. Payload of this packet is further defined as follows:
+ * 16-bit address followed by a 32-bit value (Generic Long Read Response
+ * packet).
+ *
+ * The bridge supports 5 GPIO lines controlled via the GPC register.
+ *
+ * The bridge support I2C Master/Slave.
+ * The I2C slave can be used for read/write to the bridge register instead of
+ * using the DSI interface.
+ * I2C slave address is 0x0F (read/write 0x1F/0x1E).
+ * The I2C Master can be used for communication with the panel if
+ * it has an I2C slave.
+ *
+ * NOTE: The I2C interface is not used in this driver.
+ * Only the DSI interface is used for read/write the bridge registers.
+ *
+ * Pixel data can be transmitted in non-burst or burst fashion.
+ * Non-burst refers to pixel data packet transmission time on DSI link
+ * being roughly the same (to account for packet overhead time)
+ * as active video line time on LVDS output (i.e. DE = 1).
+ * And burst refers to pixel data packet transmission time on DSI link
+ * being less than the active video line time on LVDS output.
+ * Video mode transmission is further differentiated by the types of
+ * timing events being transmitted.
+ * Video pulse mode refers to the case where both sync start and sync end
+ * events (for frame and line) are transmitted.
+ * Video event mode refers to the case where only sync start events
+ * are transmitted.
+ * This is configured via register bit VPCTRL.EVTMODE.
+ *
+ */
+
+/* #define DEBUG 1 */
+
+/**
+ * Use the I2C master to control the panel.
+ */
+/* #define TC358764_USE_I2C_MASTER */
+
+#define DRV_NAME "mipi_tc358764"
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/pwm.h>
+#include <linux/gpio.h>
+#include "msm_fb.h"
+#include "mdp4.h"
+#include "mipi_dsi.h"
+#include "mipi_tc358764_dsi2lvds.h"
+
+/* Registers definition */
+
+/* DSI D-PHY Layer Registers */
+#define D0W_DPHYCONTTX 0x0004 /* Data Lane 0 DPHY Tx Control */
+#define CLW_DPHYCONTRX 0x0020 /* Clock Lane DPHY Rx Control */
+#define D0W_DPHYCONTRX 0x0024 /* Data Lane 0 DPHY Rx Control */
+#define D1W_DPHYCONTRX 0x0028 /* Data Lane 1 DPHY Rx Control */
+#define D2W_DPHYCONTRX 0x002C /* Data Lane 2 DPHY Rx Control */
+#define D3W_DPHYCONTRX 0x0030 /* Data Lane 3 DPHY Rx Control */
+#define COM_DPHYCONTRX 0x0038 /* DPHY Rx Common Control */
+#define CLW_CNTRL 0x0040 /* Clock Lane Control */
+#define D0W_CNTRL 0x0044 /* Data Lane 0 Control */
+#define D1W_CNTRL 0x0048 /* Data Lane 1 Control */
+#define D2W_CNTRL 0x004C /* Data Lane 2 Control */
+#define D3W_CNTRL 0x0050 /* Data Lane 3 Control */
+#define DFTMODE_CNTRL 0x0054 /* DFT Mode Control */
+
+/* DSI PPI Layer Registers */
+#define PPI_STARTPPI 0x0104 /* START control bit of PPI-TX function. */
+#define PPI_BUSYPPI 0x0108
+#define PPI_LINEINITCNT 0x0110 /* Line Initialization Wait Counter */
+#define PPI_LPTXTIMECNT 0x0114
+#define PPI_LANEENABLE 0x0134 /* Enables each lane at the PPI layer. */
+#define PPI_TX_RX_TA 0x013C /* DSI Bus Turn Around timing parameters */
+
+/* Analog timer function enable */
+#define PPI_CLS_ATMR 0x0140 /* Delay for Clock Lane in LPRX */
+#define PPI_D0S_ATMR 0x0144 /* Delay for Data Lane 0 in LPRX */
+#define PPI_D1S_ATMR 0x0148 /* Delay for Data Lane 1 in LPRX */
+#define PPI_D2S_ATMR 0x014C /* Delay for Data Lane 2 in LPRX */
+#define PPI_D3S_ATMR 0x0150 /* Delay for Data Lane 3 in LPRX */
+#define PPI_D0S_CLRSIPOCOUNT 0x0164
+
+#define PPI_D1S_CLRSIPOCOUNT 0x0168 /* For lane 1 */
+#define PPI_D2S_CLRSIPOCOUNT 0x016C /* For lane 2 */
+#define PPI_D3S_CLRSIPOCOUNT 0x0170 /* For lane 3 */
+
+#define CLS_PRE 0x0180 /* Digital Counter inside of PHY IO */
+#define D0S_PRE 0x0184 /* Digital Counter inside of PHY IO */
+#define D1S_PRE 0x0188 /* Digital Counter inside of PHY IO */
+#define D2S_PRE 0x018C /* Digital Counter inside of PHY IO */
+#define D3S_PRE 0x0190 /* Digital Counter inside of PHY IO */
+#define CLS_PREP 0x01A0 /* Digital Counter inside of PHY IO */
+#define D0S_PREP 0x01A4 /* Digital Counter inside of PHY IO */
+#define D1S_PREP 0x01A8 /* Digital Counter inside of PHY IO */
+#define D2S_PREP 0x01AC /* Digital Counter inside of PHY IO */
+#define D3S_PREP 0x01B0 /* Digital Counter inside of PHY IO */
+#define CLS_ZERO 0x01C0 /* Digital Counter inside of PHY IO */
+#define D0S_ZERO 0x01C4 /* Digital Counter inside of PHY IO */
+#define D1S_ZERO 0x01C8 /* Digital Counter inside of PHY IO */
+#define D2S_ZERO 0x01CC /* Digital Counter inside of PHY IO */
+#define D3S_ZERO 0x01D0 /* Digital Counter inside of PHY IO */
+
+#define PPI_CLRFLG 0x01E0 /* PRE Counters has reached set values */
+#define PPI_CLRSIPO 0x01E4 /* Clear SIPO values, Slave mode use only. */
+#define HSTIMEOUT 0x01F0 /* HS Rx Time Out Counter */
+#define HSTIMEOUTENABLE 0x01F4 /* Enable HS Rx Time Out Counter */
+#define DSI_STARTDSI 0x0204 /* START control bit of DSI-TX function */
+#define DSI_BUSYDSI 0x0208
+#define DSI_LANEENABLE 0x0210 /* Enables each lane at the Protocol layer. */
+#define DSI_LANESTATUS0 0x0214 /* Displays lane is in HS RX mode. */
+#define DSI_LANESTATUS1 0x0218 /* Displays lane is in ULPS or STOP state */
+
+#define DSI_INTSTATUS 0x0220 /* Interrupt Status */
+#define DSI_INTMASK 0x0224 /* Interrupt Mask */
+#define DSI_INTCLR 0x0228 /* Interrupt Clear */
+#define DSI_LPTXTO 0x0230 /* Low Power Tx Time Out Counter */
+
+#define DSIERRCNT 0x0300 /* DSI Error Count */
+#define APLCTRL 0x0400 /* Application Layer Control */
+#define RDPKTLN 0x0404 /* Command Read Packet Length */
+#define VPCTRL 0x0450 /* Video Path Control */
+#define HTIM1 0x0454 /* Horizontal Timing Control 1 */
+#define HTIM2 0x0458 /* Horizontal Timing Control 2 */
+#define VTIM1 0x045C /* Vertical Timing Control 1 */
+#define VTIM2 0x0460 /* Vertical Timing Control 2 */
+#define VFUEN 0x0464 /* Video Frame Timing Update Enable */
+
+/* Mux Input Select for LVDS LINK Input */
+#define LVMX0003 0x0480 /* Bit 0 to 3 */
+#define LVMX0407 0x0484 /* Bit 4 to 7 */
+#define LVMX0811 0x0488 /* Bit 8 to 11 */
+#define LVMX1215 0x048C /* Bit 12 to 15 */
+#define LVMX1619 0x0490 /* Bit 16 to 19 */
+#define LVMX2023 0x0494 /* Bit 20 to 23 */
+#define LVMX2427 0x0498 /* Bit 24 to 27 */
+
+#define LVCFG 0x049C /* LVDS Configuration */
+#define LVPHY0 0x04A0 /* LVDS PHY 0 */
+#define LVPHY1 0x04A4 /* LVDS PHY 1 */
+#define SYSSTAT 0x0500 /* System Status */
+#define SYSRST 0x0504 /* System Reset */
+
+/* GPIO Registers */
+#define GPIOC 0x0520 /* GPIO Control */
+#define GPIOO 0x0524 /* GPIO Output */
+#define GPIOI 0x0528 /* GPIO Input */
+
+/* I2C Registers */
+#define I2CTIMCTRL 0x0540 /* I2C IF Timing and Enable Control */
+#define I2CMADDR 0x0544 /* I2C Master Addressing */
+#define WDATAQ 0x0548 /* Write Data Queue */
+#define RDATAQ 0x054C /* Read Data Queue */
+
+/* Chip ID and Revision ID Register */
+#define IDREG 0x0580
+
+#define TC358764XBG_ID 0x00006500
+
+/* Debug Registers */
+#define DEBUG00 0x05A0 /* Debug */
+#define DEBUG01 0x05A4 /* LVDS Data */
+
+/* PWM */
+static u32 d2l_pwm_freq_hz = (66*1000);
+
+/* 1366x768 uses pwm at 66 KHZ */
+/* 1200x1920 uses pwm at 25 KHZ */
+#define PWM_FREQ_HZ (d2l_pwm_freq_hz)
+#define PWM_LEVEL 15
+#define PWM_PERIOD_USEC (USEC_PER_SEC / PWM_FREQ_HZ)
+#define PWM_DUTY_LEVEL (PWM_PERIOD_USEC / PWM_LEVEL)
+
+#define CMD_DELAY 100
+#define DSI_MAX_LANES 4
+#define KHZ 1000
+#define MHZ (1000*1000)
+
+/**
+ * Command payload for DTYPE_GEN_LWRITE (0x29) / DTYPE_GEN_READ2 (0x24).
+ */
+struct wr_cmd_payload {
+ u16 addr;
+ u32 data;
+} __packed;
+
+/*
+ * Driver state.
+ */
+static struct msm_panel_common_pdata *d2l_common_pdata;
+struct msm_fb_data_type *d2l_mfd;
+static struct dsi_buf d2l_tx_buf;
+static struct dsi_buf d2l_rx_buf;
+static int led_pwm;
+static struct pwm_device *bl_pwm;
+static struct pwm_device *tn_pwm;
+static int bl_level;
+static u32 d2l_gpio_out_mask;
+static u32 d2l_gpio_out_val;
+static u32 d2l_3d_gpio_enable;
+static u32 d2l_3d_gpio_mode;
+static int d2l_enable_3d;
+static struct i2c_client *d2l_i2c_client;
+static struct i2c_driver d2l_i2c_slave_driver;
+
+static int mipi_d2l_init(void);
+static int mipi_d2l_enable_3d(struct msm_fb_data_type *mfd,
+ bool enable, bool mode);
+static u32 d2l_i2c_read_reg(struct i2c_client *client, u16 reg);
+static u32 d2l_i2c_write_reg(struct i2c_client *client, u16 reg, u32 val);
+
+/**
+ * Read a bridge register
+ *
+ * @param mfd
+ *
+ * @return register data value
+ */
+static u32 mipi_d2l_read_reg(struct msm_fb_data_type *mfd, u16 reg)
+{
+ u32 data;
+ int len = 4;
+ struct dsi_cmd_desc cmd_read_reg = {
+ DTYPE_GEN_READ2, 1, 0, 1, 0, /* cmd 0x24 */
+ sizeof(reg), (char *) ®};
+
+ mipi_dsi_buf_init(&d2l_tx_buf);
+ mipi_dsi_buf_init(&d2l_rx_buf);
+
+ /* mutex had been acquired at mipi_dsi_on */
+ len = mipi_dsi_cmds_rx(mfd, &d2l_tx_buf, &d2l_rx_buf,
+ &cmd_read_reg, len);
+
+ data = *(u32 *)d2l_rx_buf.data;
+
+ if (len != 4)
+ pr_err("%s: invalid rlen=%d, expecting 4.\n", __func__, len);
+
+ pr_debug("%s: reg=0x%x.data=0x%08x.\n", __func__, reg, data);
+
+ return data;
+}
+
+/**
+ * Write a bridge register
+ *
+ * @param mfd
+ *
+ * @return int
+ */
+static int mipi_d2l_write_reg(struct msm_fb_data_type *mfd, u16 reg, u32 data)
+{
+ struct wr_cmd_payload payload;
+ struct dsi_cmd_desc cmd_write_reg = {
+ DTYPE_GEN_LWRITE, 1, 0, 0, 0,
+ sizeof(payload), (char *)&payload};
+
+ payload.addr = reg;
+ payload.data = data;
+
+ /* mutex had been acquried at dsi_on */
+ mipi_dsi_cmds_tx(&d2l_tx_buf, &cmd_write_reg, 1);
+
+ pr_debug("%s: reg=0x%x. data=0x%x.\n", __func__, reg, data);
+
+ return 0;
+}
+
+static void mipi_d2l_read_status(struct msm_fb_data_type *mfd)
+{
+ mipi_d2l_read_reg(mfd, DSI_LANESTATUS0); /* 0x214 */
+ mipi_d2l_read_reg(mfd, DSI_LANESTATUS1); /* 0x218 */
+ mipi_d2l_read_reg(mfd, DSI_INTSTATUS); /* 0x220 */
+ mipi_d2l_read_reg(mfd, SYSSTAT); /* 0x500 */
+}
+
+static void mipi_d2l_read_status_via_i2c(struct i2c_client *client)
+{
+ u32 tmp = 0;
+
+ tmp = d2l_i2c_read_reg(client, DSIERRCNT);
+ d2l_i2c_write_reg(client, DSIERRCNT, 0xFFFF0000);
+
+ d2l_i2c_read_reg(client, DSI_LANESTATUS0); /* 0x214 */
+ d2l_i2c_read_reg(client, DSI_LANESTATUS1); /* 0x218 */
+ d2l_i2c_read_reg(client, DSI_INTSTATUS); /* 0x220 */
+ d2l_i2c_read_reg(client, SYSSTAT); /* 0x500 */
+
+ d2l_i2c_write_reg(client, DSIERRCNT, tmp);
+}
+/**
+ * Init the D2L bridge via the DSI interface for Video.
+ *
+ * VPCTRL.EVTMODE (0x20) configuration bit is needed to determine whether
+ * video timing information is delivered in pulse mode or event mode.
+ * In pulse mode, both Sync Start and End packets are required.
+ * In event mode, only Sync Start packets are required.
+ *
+ * @param mfd
+ *
+ * @return int
+ */
+static int mipi_d2l_dsi_init_sequence(struct msm_fb_data_type *mfd)
+{
+ struct mipi_panel_info *mipi = &mfd->panel_info.mipi;
+ u32 lanes_enable;
+ u32 vpctrl;
+ u32 htime1;
+ u32 vtime1;
+ u32 htime2;
+ u32 vtime2;
+ u32 ppi_tx_rx_ta; /* BTA Bus-Turn-Around */
+ u32 lvcfg;
+ u32 hbpr; /* Horizontal Back Porch */
+ u32 hpw; /* Horizontal Pulse Width */
+ u32 vbpr; /* Vertical Back Porch */
+ u32 vpw; /* Vertical Pulse Width */
+
+ u32 hfpr; /* Horizontal Front Porch */
+ u32 hsize; /* Horizontal Active size */
+ u32 vfpr; /* Vertical Front Porch */
+ u32 vsize; /* Vertical Active size */
+ bool vesa_rgb888 = false;
+
+ lanes_enable = 0x01; /* clock-lane enable */
+ lanes_enable |= (mipi->data_lane0 << 1);
+ lanes_enable |= (mipi->data_lane1 << 2);
+ lanes_enable |= (mipi->data_lane2 << 3);
+ lanes_enable |= (mipi->data_lane3 << 4);
+
+ if (mipi->traffic_mode == DSI_NON_BURST_SYNCH_EVENT)
+ vpctrl = 0x01000120;
+ else if (mipi->traffic_mode == DSI_NON_BURST_SYNCH_PULSE)
+ vpctrl = 0x01000100;
+ else {
+ pr_err("%s.unsupported traffic_mode %d.\n",
+ __func__, mipi->traffic_mode);
+ return -EINVAL;
+ }
+
+ if (mfd->panel_info.clk_rate > 800*1000*1000) {
+ pr_err("%s.unsupported clk_rate %d.\n",
+ __func__, mfd->panel_info.clk_rate);
+ return -EINVAL;
+ }
+
+ pr_debug("%s.xres=%d.yres=%d.fps=%d.dst_format=%d.\n",
+ __func__,
+ mfd->panel_info.xres,
+ mfd->panel_info.yres,
+ mfd->panel_info.mipi.frame_rate,
+ mfd->panel_info.mipi.dst_format);
+
+ hbpr = mfd->panel_info.lcdc.h_back_porch;
+ hpw = mfd->panel_info.lcdc.h_pulse_width;
+ vbpr = mfd->panel_info.lcdc.v_back_porch;
+ vpw = mfd->panel_info.lcdc.v_pulse_width;
+
+ htime1 = (hbpr << 16) + hpw;
+ vtime1 = (vbpr << 16) + vpw;
+
+ hfpr = mfd->panel_info.lcdc.h_front_porch;
+ hsize = mfd->panel_info.xres;
+ vfpr = mfd->panel_info.lcdc.v_front_porch;
+ vsize = mfd->panel_info.yres;
+
+ htime2 = (hfpr << 16) + hsize;
+ vtime2 = (vfpr << 16) + vsize;
+
+ lvcfg = 0x0003; /* PCLK=DCLK/3, Dual Link, LVEN */
+ vpctrl = 0x01000120; /* Output RGB888 , Event-Mode , */
+ ppi_tx_rx_ta = 0x00040004;
+
+ if (mfd->panel_info.xres == 1366) {
+ ppi_tx_rx_ta = 0x00040004;
+ lvcfg = 0x01; /* LVEN */
+ vesa_rgb888 = true;
+ }
+
+ if (mfd->panel_info.xres == 1200) {
+ lvcfg = 0x0103; /* PCLK=DCLK/4, Dual Link, LVEN */
+ vesa_rgb888 = true;
+ }
+
+ pr_debug("%s.htime1=0x%x.\n", __func__, htime1);
+ pr_debug("%s.vtime1=0x%x.\n", __func__, vtime1);
+ pr_debug("%s.vpctrl=0x%x.\n", __func__, vpctrl);
+ pr_debug("%s.lvcfg=0x%x.\n", __func__, lvcfg);
+
+ mipi_d2l_write_reg(mfd, SYSRST, 0xFF);
+ msleep(30);
+
+ if (vesa_rgb888) {
+ /* VESA format instead of JEIDA format for RGB888 */
+ mipi_d2l_write_reg(mfd, LVMX0003, 0x03020100);
+ mipi_d2l_write_reg(mfd, LVMX0407, 0x08050704);
+ mipi_d2l_write_reg(mfd, LVMX0811, 0x0F0E0A09);
+ mipi_d2l_write_reg(mfd, LVMX1215, 0x100D0C0B);
+ mipi_d2l_write_reg(mfd, LVMX1619, 0x12111716);
+ mipi_d2l_write_reg(mfd, LVMX2023, 0x1B151413);
+ mipi_d2l_write_reg(mfd, LVMX2427, 0x061A1918);
+ }
+
+ mipi_d2l_write_reg(mfd, PPI_TX_RX_TA, ppi_tx_rx_ta); /* BTA */
+ mipi_d2l_write_reg(mfd, PPI_LPTXTIMECNT, 0x00000004);
+ mipi_d2l_write_reg(mfd, PPI_D0S_CLRSIPOCOUNT, 0x00000003);
+ mipi_d2l_write_reg(mfd, PPI_D1S_CLRSIPOCOUNT, 0x00000003);
+ mipi_d2l_write_reg(mfd, PPI_D2S_CLRSIPOCOUNT, 0x00000003);
+ mipi_d2l_write_reg(mfd, PPI_D3S_CLRSIPOCOUNT, 0x00000003);
+ mipi_d2l_write_reg(mfd, PPI_LANEENABLE, lanes_enable);
+ mipi_d2l_write_reg(mfd, DSI_LANEENABLE, lanes_enable);
+ mipi_d2l_write_reg(mfd, PPI_STARTPPI, 0x00000001);
+ mipi_d2l_write_reg(mfd, DSI_STARTDSI, 0x00000001);
+
+ mipi_d2l_write_reg(mfd, VPCTRL, vpctrl); /* RGB888 + Event mode */
+ mipi_d2l_write_reg(mfd, HTIM1, htime1);
+ mipi_d2l_write_reg(mfd, VTIM1, vtime1);
+ mipi_d2l_write_reg(mfd, HTIM2, htime2);
+ mipi_d2l_write_reg(mfd, VTIM2, vtime2);
+ mipi_d2l_write_reg(mfd, VFUEN, 0x00000001);
+ mipi_d2l_write_reg(mfd, LVCFG, lvcfg); /* Enables LVDS tx */
+
+ return 0;
+}
+
+/**
+ * Set Backlight level.
+ *
+ * @param pwm
+ * @param level
+ *
+ * @return int
+ */
+static int mipi_d2l_set_backlight_level(struct pwm_device *pwm, int level)
+{
+ int ret = 0;
+
+ pr_debug("%s: level=%d.\n", __func__, level);
+
+ if ((pwm == NULL) || (level > PWM_LEVEL) || (level < 0)) {
+ pr_err("%s.pwm=NULL.\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = pwm_config(pwm, PWM_DUTY_LEVEL * level, PWM_PERIOD_USEC);
+ if (ret) {
+ pr_err("%s: pwm_config() failed err=%d.\n", __func__, ret);
+ return ret;
+ }
+
+ ret = pwm_enable(pwm);
+ if (ret) {
+ pr_err("%s: pwm_enable() failed err=%d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * Set TN CLK.
+ *
+ * @param pwm
+ * @param level
+ *
+ * @return int
+ */
+static int mipi_d2l_set_tn_clk(struct pwm_device *pwm, u32 usec)
+{
+ int ret = 0;
+
+ pr_debug("%s: usec=%d.\n", __func__, usec);
+
+ ret = pwm_config(pwm, usec/2 , usec);
+ if (ret) {
+ pr_err("%s: pwm_config() failed err=%d.\n", __func__, ret);
+ return ret;
+ }
+
+ ret = pwm_enable(pwm);
+ if (ret) {
+ pr_err("%s: pwm_enable() failed err=%d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * LCD ON.
+ *
+ * Set LCD On via MIPI interface or I2C-Slave interface.
+ * Set Backlight on.
+ *
+ * @param pdev
+ *
+ * @return int
+ */
+static int mipi_d2l_lcd_on(struct platform_device *pdev)
+{
+ int ret = 0;
+ u32 chip_id;
+ struct msm_fb_data_type *mfd;
+
+ pr_info("%s.\n", __func__);
+
+ /* wait for valid clock before sending data over DSI or I2C. */
+ msleep(30);
+
+ mfd = platform_get_drvdata(pdev);
+ d2l_mfd = mfd;
+
+ if (!mfd)
+ return -ENODEV;
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ chip_id = mipi_d2l_read_reg(mfd, IDREG);
+
+
+ if (chip_id != TC358764XBG_ID) {
+ pr_err("%s: invalid chip_id=0x%x", __func__, chip_id);
+ return -ENODEV;
+ }
+
+ ret = mipi_d2l_dsi_init_sequence(mfd);
+ if (ret)
+ return ret;
+
+ mipi_d2l_write_reg(mfd, GPIOC, d2l_gpio_out_mask);
+ /* Set gpio#4=U/D=0, gpio#3=L/R=1 , gpio#2,1=CABC=0, gpio#0=NA. */
+ mipi_d2l_write_reg(mfd, GPIOO, d2l_gpio_out_val);
+
+ if (mfd->panel_info.xres == 1366)
+ d2l_pwm_freq_hz = (66*1000);
+ else
+ d2l_pwm_freq_hz = (25*1000);
+
+ if (bl_level == 0)
+ bl_level = PWM_LEVEL * 2 / 3 ; /* Default ON value */
+
+ /* Set backlight via PWM */
+ if (bl_pwm) {
+ ret = mipi_d2l_set_backlight_level(bl_pwm, bl_level);
+ if (ret)
+ pr_err("%s.mipi_d2l_set_backlight_level.ret=%d",
+ __func__, ret);
+ }
+
+ mipi_d2l_read_status(mfd);
+
+ mipi_d2l_enable_3d(mfd, false, false);
+
+ /* Add I2C driver only after DSI-CLK is running */
+ if (d2l_i2c_client == NULL)
+ i2c_add_driver(&d2l_i2c_slave_driver);
+
+ pr_info("%s.ret=%d.\n", __func__, ret);
+
+ return ret;
+}
+
+/**
+ * LCD OFF.
+ *
+ * @param pdev
+ *
+ * @return int
+ */
+static int mipi_d2l_lcd_off(struct platform_device *pdev)
+{
+ int ret;
+ struct msm_fb_data_type *mfd;
+
+ pr_info("%s.\n", __func__);
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ ret = mipi_d2l_set_backlight_level(bl_pwm, 1);
+
+ pr_info("%s.ret=%d.\n", __func__, ret);
+
+ return ret;
+}
+
+static void mipi_d2l_set_backlight(struct msm_fb_data_type *mfd)
+{
+ int level = mfd->bl_level;
+
+ pr_debug("%s.lvl=%d.\n", __func__, level);
+
+ mipi_d2l_set_backlight_level(bl_pwm, level);
+
+ bl_level = level;
+}
+
+static struct msm_fb_panel_data d2l_panel_data = {
+ .on = mipi_d2l_lcd_on,
+ .off = mipi_d2l_lcd_off,
+ .set_backlight = mipi_d2l_set_backlight,
+};
+
+static u32 d2l_i2c_read_reg(struct i2c_client *client, u16 reg)
+{
+ int rc;
+ u32 val = 0;
+ u8 buf[6];
+
+ if (client == NULL) {
+ pr_err("%s.invalid i2c client.\n", __func__);
+ return -EINVAL;
+ }
+
+ buf[0] = reg >> 8;
+ buf[1] = reg & 0xFF;
+
+ rc = i2c_master_send(client, buf, sizeof(reg));
+ rc = i2c_master_recv(client, buf, 4);
+
+ if (rc >= 0) {
+ val = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24);
+ pr_debug("%s.reg=0x%x.val=0x%x.\n", __func__, reg, val);
+ } else
+ pr_err("%s.fail.reg=0x%x.\n", __func__, reg);
+
+ return val;
+}
+
+static u32 d2l_i2c_write_reg(struct i2c_client *client, u16 reg, u32 val)
+{
+ int rc;
+ u8 buf[6];
+
+ if (client == NULL) {
+ pr_err("%s.invalid i2c client.\n", __func__);
+ return -EINVAL;
+ }
+
+ buf[0] = reg >> 8;
+ buf[1] = reg & 0xFF;
+
+ buf[2] = (val >> 0) & 0xFF;
+ buf[3] = (val >> 8) & 0xFF;
+ buf[4] = (val >> 16) & 0xFF;
+ buf[5] = (val >> 24) & 0xFF;
+
+ rc = i2c_master_send(client, buf, sizeof(buf));
+
+ if (rc >= 0)
+ pr_debug("%s.reg=0x%x.val=0x%x.\n", __func__, reg, val);
+ else
+ pr_err("%s.fail.reg=0x%x.\n", __func__, reg);
+
+ return val;
+}
+
+static int __devinit d2l_i2c_slave_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ static const u32 i2c_funcs = I2C_FUNC_I2C;
+
+ d2l_i2c_client = client;
+
+ if (!i2c_check_functionality(client->adapter, i2c_funcs)) {
+ pr_err("%s.i2c_check_functionality failed.\n", __func__);
+ return -ENOSYS;
+ } else {
+ pr_debug("%s.i2c_check_functionality OK.\n", __func__);
+ }
+
+ d2l_i2c_read_reg(client, IDREG);
+
+ mipi_d2l_read_status_via_i2c(d2l_i2c_client);
+
+ return 0;
+}
+
+static __devexit int d2l_i2c_slave_remove(struct i2c_client *client)
+{
+ d2l_i2c_client = NULL;
+
+ return 0;
+}
+
+static const struct i2c_device_id d2l_i2c_id[] = {
+ {"tc358764-i2c", 0},
+ {}
+};
+
+static struct i2c_driver d2l_i2c_slave_driver = {
+ .driver = {
+ .name = "tc358764-i2c",
+ .owner = THIS_MODULE
+ },
+ .probe = d2l_i2c_slave_probe,
+ .remove = __devexit_p(d2l_i2c_slave_remove),
+ .id_table = d2l_i2c_id,
+};
+
+static int mipi_d2l_enable_3d(struct msm_fb_data_type *mfd,
+ bool enable, bool mode)
+{
+ u32 tn_usec = 1000000 / 66; /* 66 HZ */
+
+ pr_debug("%s.enable=%d.mode=%d.\n", __func__, enable, mode);
+
+ gpio_direction_output(d2l_3d_gpio_enable, enable);
+ gpio_direction_output(d2l_3d_gpio_mode, mode);
+
+ mipi_d2l_set_tn_clk(tn_pwm, tn_usec);
+
+ return 0;
+}
+
+static ssize_t mipi_d2l_enable_3d_read(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf((char *)buf, sizeof(buf), "%u\n", d2l_enable_3d);
+}
+
+static ssize_t mipi_d2l_enable_3d_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. Invalid input.\n", __func__);
+ ret = -EINVAL;
+ } else {
+ d2l_enable_3d = data;
+ if (data == 1) /* LANDSCAPE */
+ mipi_d2l_enable_3d(d2l_mfd, true, true);
+ else if (data == 2) /* PORTRAIT */
+ mipi_d2l_enable_3d(d2l_mfd, true, false);
+ else if (data == 0)
+ mipi_d2l_enable_3d(d2l_mfd, false, false);
+ else if (data == 9)
+ mipi_d2l_read_status_via_i2c(d2l_i2c_client);
+ else
+ pr_err("%s.Invalid value=%d.\n", __func__, data);
+ }
+
+ return count;
+}
+
+static struct device_attribute mipi_d2l_3d_barrier_attributes[] = {
+ __ATTR(enable_3d_barrier, 0666,
+ mipi_d2l_enable_3d_read,
+ mipi_d2l_enable_3d_write),
+};
+
+static int mipi_dsi_3d_barrier_sysfs_register(struct device *dev)
+{
+ int ret;
+
+ pr_debug("%s.d2l_3d_gpio_enable=%d.\n", __func__, d2l_3d_gpio_enable);
+ pr_debug("%s.d2l_3d_gpio_mode=%d.\n", __func__, d2l_3d_gpio_mode);
+
+ ret = device_create_file(dev, mipi_d2l_3d_barrier_attributes);
+ if (ret) {
+ pr_err("%s.failed to create 3D sysfs.\n", __func__);
+ goto err_device_create_file;
+ }
+
+ ret = gpio_request(d2l_3d_gpio_enable, "d2l_3d_gpio_enable");
+ if (ret) {
+ pr_err("%s.failed to get d2l_3d_gpio_enable=%d.\n",
+ __func__, d2l_3d_gpio_enable);
+ goto err_d2l_3d_gpio_enable;
+ }
+
+ ret = gpio_request(d2l_3d_gpio_mode, "d2l_3d_gpio_mode");
+ if (ret) {
+ pr_err("%s.failed to get d2l_3d_gpio_mode=%d.\n",
+ __func__, d2l_3d_gpio_mode);
+ goto err_d2l_3d_gpio_mode;
+ }
+
+ return 0;
+
+err_d2l_3d_gpio_mode:
+ gpio_free(d2l_3d_gpio_enable);
+err_d2l_3d_gpio_enable:
+ device_remove_file(dev, mipi_d2l_3d_barrier_attributes);
+err_device_create_file:
+
+ return ret;
+}
+
+/**
+ * Probe for device.
+ *
+ * Both the "target" and "panel" device use the same probe function.
+ * "Target" device has id=0, "Panel" devic has non-zero id.
+ * Target device should register first, passing msm_panel_common_pdata.
+ * Panel device passing msm_panel_info.
+ *
+ * @param pdev
+ *
+ * @return int
+ */
+static int __devinit mipi_d2l_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct msm_panel_info *pinfo = NULL;
+
+ pr_debug("%s.id=%d.\n", __func__, pdev->id);
+
+ if (pdev->id == 0) {
+ d2l_common_pdata = pdev->dev.platform_data;
+
+ if (d2l_common_pdata == NULL) {
+ pr_err("%s: no PWM gpio specified.\n", __func__);
+ return 0;
+ }
+
+ led_pwm = d2l_common_pdata->gpio_num[0];
+ d2l_gpio_out_mask = d2l_common_pdata->gpio_num[1] >> 8;
+ d2l_gpio_out_val = d2l_common_pdata->gpio_num[1] & 0xFF;
+ d2l_3d_gpio_enable = d2l_common_pdata->gpio_num[2];
+ d2l_3d_gpio_mode = d2l_common_pdata->gpio_num[3];
+
+ mipi_dsi_buf_alloc(&d2l_tx_buf, DSI_BUF_SIZE);
+ mipi_dsi_buf_alloc(&d2l_rx_buf, DSI_BUF_SIZE);
+
+ return 0;
+ }
+
+ if (d2l_common_pdata == NULL) {
+ pr_err("%s: d2l_common_pdata is NULL.\n", __func__);
+ return -ENODEV;
+ }
+
+ bl_pwm = NULL;
+ if (led_pwm >= 0) {
+ bl_pwm = pwm_request(led_pwm, "lcd-backlight");
+ if (bl_pwm == NULL || IS_ERR(bl_pwm)) {
+ pr_err("%s pwm_request() failed.id=%d.bl_pwm=%d.\n",
+ __func__, led_pwm, (int) bl_pwm);
+ bl_pwm = NULL;
+ return -EIO;
+ } else {
+ pr_debug("%s.pwm_request() ok.pwm-id=%d.\n",
+ __func__, led_pwm);
+
+ }
+ } else {
+ pr_err("%s. led_pwm is invalid.\n", __func__);
+ }
+
+ tn_pwm = pwm_request(1, "3D_TN_clk");
+ if (tn_pwm == NULL || IS_ERR(tn_pwm)) {
+ pr_err("%s pwm_request() failed.id=%d.tn_pwm=%d.\n",
+ __func__, 1, (int) tn_pwm);
+ tn_pwm = NULL;
+ return -EIO;
+ } else {
+ pr_debug("%s.pwm_request() ok.pwm-id=%d.\n", __func__, 1);
+
+ }
+
+ pinfo = pdev->dev.platform_data;
+
+ if (pinfo == NULL) {
+ pr_err("%s: pinfo is NULL.\n", __func__);
+ return -ENODEV;
+ }
+
+ d2l_panel_data.panel_info = *pinfo;
+
+ pdev->dev.platform_data = &d2l_panel_data;
+
+ msm_fb_add_device(pdev);
+
+ if (pinfo->is_3d_panel)
+ mipi_dsi_3d_barrier_sysfs_register(&(pdev->dev));
+
+ return ret;
+}
+
+/**
+ * Device removal notification handler.
+ *
+ * @param pdev
+ *
+ * @return int
+ */
+static int __devexit mipi_d2l_remove(struct platform_device *pdev)
+{
+ /* Note: There are no APIs to remove fb device and free DSI buf. */
+ pr_debug("%s.\n", __func__);
+
+ if (bl_pwm) {
+ pwm_free(bl_pwm);
+ bl_pwm = NULL;
+ }
+
+ return 0;
+}
+
+/**
+ * Register the panel device.
+ *
+ * @param pinfo
+ * @param channel_id
+ * @param panel_id
+ *
+ * @return int
+ */
+int mipi_tc358764_dsi2lvds_register(struct msm_panel_info *pinfo,
+ u32 channel_id, u32 panel_id)
+{
+ struct platform_device *pdev = NULL;
+ int ret;
+ /* Use DSI-to-LVDS bridge */
+ const char driver_name[] = "mipi_tc358764";
+
+ pr_debug("%s.\n", __func__);
+ ret = mipi_d2l_init();
+ if (ret) {
+ pr_err("mipi_d2l_init() failed with ret %u\n", ret);
+ return ret;
+ }
+
+ /* Note: the device id should be non-zero */
+ pdev = platform_device_alloc(driver_name, (panel_id << 8)|channel_id);
+ if (pdev == NULL)
+ return -ENOMEM;
+
+ pdev->dev.platform_data = pinfo;
+
+ 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 struct platform_driver d2l_driver = {
+ .probe = mipi_d2l_probe,
+ .remove = __devexit_p(mipi_d2l_remove),
+ .driver = {
+ .name = DRV_NAME,
+ },
+};
+
+/**
+ * Module Init
+ *
+ * @return int
+ */
+static int mipi_d2l_init(void)
+{
+ pr_debug("%s.\n", __func__);
+
+ d2l_i2c_client = NULL;
+
+ return platform_driver_register(&d2l_driver);
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Toshiba MIPI-DSI-to-LVDS bridge driver");
+MODULE_AUTHOR("Amir Samuelov <amirs@codeaurora.org>");
diff --git a/drivers/video/msm/mipi_tc358764_dsi2lvds.h b/drivers/video/msm/mipi_tc358764_dsi2lvds.h
new file mode 100644
index 0000000..072d1f4
--- /dev/null
+++ b/drivers/video/msm/mipi_tc358764_dsi2lvds.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_TC358764_DSI2LVDS_H
+#define MIPI_TC358764_DSI2LVDS_H
+
+int mipi_tc358764_dsi2lvds_register(struct msm_panel_info *pinfo,
+ u32 channel_id, u32 panel_id);
+#endif /* MIPI_TC358764_DSI2LVDS_H */
diff --git a/drivers/video/msm/mipi_toshiba.c b/drivers/video/msm/mipi_toshiba.c
new file mode 100644
index 0000000..520c67b
--- /dev/null
+++ b/drivers/video/msm/mipi_toshiba.c
@@ -0,0 +1,355 @@
+/* Copyright (c) 2008-2012, 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 pwm_device *bl_lpm;
+static struct mipi_dsi_panel_platform_data *mipi_toshiba_pdata;
+
+#define TM_GET_PID(id) (((id) & 0xff00)>>8)
+
+static struct dsi_buf toshiba_tx_buf;
+static struct dsi_buf toshiba_rx_buf;
+static int mipi_toshiba_lcd_init(void);
+
+#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};
+
+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_wvga_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}
+};
+
+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_wsvga_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}
+};
+
+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;
+
+ if (TM_GET_PID(mfd->panel.id) == MIPI_DSI_PANEL_WVGA_PT)
+ mipi_dsi_cmds_tx(&toshiba_tx_buf,
+ toshiba_wvga_display_on_cmds,
+ ARRAY_SIZE(toshiba_wvga_display_on_cmds));
+ else if (TM_GET_PID(mfd->panel.id) == MIPI_DSI_PANEL_WSVGA_PT ||
+ TM_GET_PID(mfd->panel.id) == MIPI_DSI_PANEL_WUXGA)
+ mipi_dsi_cmds_tx(&toshiba_tx_buf,
+ toshiba_wsvga_display_on_cmds,
+ ARRAY_SIZE(toshiba_wsvga_display_on_cmds));
+ else
+ return -EINVAL;
+
+ 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(&toshiba_tx_buf, toshiba_display_off_cmds,
+ ARRAY_SIZE(toshiba_display_off_cmds));
+
+ return 0;
+}
+
+void mipi_bklight_pwm_cfg(void)
+{
+ if (mipi_toshiba_pdata && mipi_toshiba_pdata->dsi_pwm_cfg)
+ mipi_toshiba_pdata->dsi_pwm_cfg();
+}
+
+static void mipi_toshiba_set_backlight(struct msm_fb_data_type *mfd)
+{
+ int ret;
+ static int bklight_pwm_cfg;
+
+ if (bklight_pwm_cfg == 0) {
+ mipi_bklight_pwm_cfg();
+ bklight_pwm_cfg++;
+ }
+
+ if (bl_lpm) {
+ ret = pwm_config(bl_lpm, MIPI_TOSHIBA_PWM_DUTY_LEVEL *
+ mfd->bl_level, MIPI_TOSHIBA_PWM_PERIOD_USEC);
+ if (ret) {
+ pr_err("pwm_config on lpm failed %d\n", ret);
+ return;
+ }
+ if (mfd->bl_level) {
+ ret = pwm_enable(bl_lpm);
+ if (ret)
+ pr_err("pwm enable/disable on lpm failed"
+ "for bl %d\n", mfd->bl_level);
+ } else {
+ pwm_disable(bl_lpm);
+ }
+ }
+}
+
+static int __devinit mipi_toshiba_lcd_probe(struct platform_device *pdev)
+{
+ if (pdev->id == 0) {
+ mipi_toshiba_pdata = pdev->dev.platform_data;
+ return 0;
+ }
+
+ if (mipi_toshiba_pdata == NULL) {
+ pr_err("%s.invalid platform data.\n", __func__);
+ return -ENODEV;
+ }
+
+ if (mipi_toshiba_pdata != NULL)
+ bl_lpm = pwm_request(mipi_toshiba_pdata->gpio[0],
+ "backlight");
+
+ if (bl_lpm == NULL || IS_ERR(bl_lpm)) {
+ pr_err("%s pwm_request() failed\n", __func__);
+ bl_lpm = NULL;
+ }
+ pr_debug("bl_lpm = %p lpm = %d\n", bl_lpm,
+ mipi_toshiba_pdata->gpio[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,
+ .set_backlight = mipi_toshiba_set_backlight,
+};
+
+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;
+
+ ret = mipi_toshiba_lcd_init();
+ if (ret) {
+ pr_err("mipi_toshiba_lcd_init() failed with ret %u\n", ret);
+ return ret;
+ }
+
+ 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 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);
+}
diff --git a/drivers/video/msm/mipi_toshiba.h b/drivers/video/msm/mipi_toshiba.h
new file mode 100644
index 0000000..632bbd3
--- /dev/null
+++ b/drivers/video/msm/mipi_toshiba.h
@@ -0,0 +1,30 @@
+
+/* 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_TOSHIBA_H
+#define MIPI_TOSHIBA_H
+
+#include <linux/pwm.h>
+#include <linux/mfd/pm8xxx/pm8921.h>
+
+int mipi_toshiba_device_register(struct msm_panel_info *pinfo,
+ u32 channel, u32 panel);
+
+#define MIPI_TOSHIBA_PWM_FREQ_HZ 300
+#define MIPI_TOSHIBA_PWM_PERIOD_USEC (USEC_PER_SEC / MIPI_TOSHIBA_PWM_FREQ_HZ)
+#define MIPI_TOSHIBA_PWM_LEVEL 100
+#define MIPI_TOSHIBA_PWM_DUTY_LEVEL \
+ (MIPI_TOSHIBA_PWM_PERIOD_USEC / MIPI_TOSHIBA_PWM_LEVEL)
+
+#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..eb2946b
--- /dev/null
+++ b/drivers/video/msm/mipi_toshiba_video_wsvga_pt.c
@@ -0,0 +1,104 @@
+/* Copyright (c) 2011-2012, 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 */
+ {0x09, 0x08, 0x05, 0x00, 0x20},
+ /* timing */
+ {0x73, 0x2e, 0x11, 0x00, 0x3c, 0x46, 0x14, 0x31,
+ 0x1c, 0x03, 0x04, 0xa0},
+ /* phy ctrl */
+ {0x5f, 0x00, 0x00, 0x10},
+ /* strength */
+ {0xff, 0x00, 0x06, 0x00},
+ /* pll control */
+ {0x0, 0x49, 0x30, 0xc4, 0x00, 0x20, 0x07, 0x62,
+ 0x41, 0x0f, 0x01,
+ 0x00, 0x14, 0x03, 0x00, 0x02, 0x00, 0x20, 0x00, 0x01 },
+};
+
+static int __init mipi_video_toshiba_wsvga_pt_init(void)
+{
+ int ret;
+
+ if (msm_fb_detect_client("mipi_video_toshiba_wsvga"))
+ return 0;
+
+ 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.lcdc.xres_pad = 200;
+ pinfo.lcdc.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 = 3;
+ pinfo.lcdc.v_front_porch = 45;
+ 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 = MIPI_TOSHIBA_PWM_LEVEL;
+ pinfo.bl_min = 1;
+ pinfo.fb_num = 2;
+
+ 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 = 0x04;
+ pinfo.mipi.t_clk_pre = 0x1a;
+ pinfo.mipi.esc_byte_ratio = 4;
+ 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_WSVGA_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_wuxga.c b/drivers/video/msm/mipi_toshiba_video_wuxga.c
new file mode 100644
index 0000000..8eddce4
--- /dev/null
+++ b/drivers/video/msm/mipi_toshiba_video_wuxga.c
@@ -0,0 +1,98 @@
+/* Copyright (c) 2012, 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 = {
+ /* 1920*1200, RGB888, 4 Lane 60 fps video mode */
+ /* regulator */
+ {0x03, 0x0a, 0x04, 0x00, 0x20},
+ /* timing */
+ {0x66, 0x26, 0x1F, 0x00, 0x55, 0x9C, 0x16, 0x90,
+ 0x23, 0x03, 0x04, 0xa0},
+ /* phy ctrl */
+ {0x5f, 0x00, 0x00, 0x10},
+ /* strength */
+ {0xff, 0x00, 0x06, 0x00},
+ /* pll control */
+ {0x0, 0xD7, 0x1, 0x19, 0x00, 0x50, 0x48, 0x63,
+ 0x41, 0x0f, 0x01,
+ 0x00, 0x14, 0x03, 0x00, 0x02, 0x00, 0x20, 0x00, 0x01 },
+};
+
+static int __init mipi_video_toshiba_wuxga_init(void)
+{
+ int ret;
+
+ if (msm_fb_detect_client("mipi_video_toshiba_wuxga"))
+ return 0;
+
+ pinfo.xres = 1920;
+ pinfo.yres = 1200;
+
+ pinfo.type = MIPI_VIDEO_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 = 170;
+ pinfo.lcdc.v_back_porch = 7;
+ pinfo.lcdc.v_front_porch = 8;
+ pinfo.lcdc.v_pulse_width = 30;
+ pinfo.lcdc.border_clr = 0; /* blk */
+ pinfo.lcdc.underflow_clr = 0xff; /* blue */
+ pinfo.lcdc.hsync_skew = 0;
+ pinfo.bl_max = MIPI_TOSHIBA_PWM_LEVEL;
+ pinfo.bl_min = 1;
+ pinfo.fb_num = 2;
+ pinfo.clk_rate = 981560000;
+
+ 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.data_lane2 = TRUE;
+ pinfo.mipi.data_lane3 = TRUE;
+ 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;
+ pinfo.mipi.esc_byte_ratio = 9;
+
+ ret = mipi_toshiba_device_register(&pinfo, MIPI_DSI_PRIM,
+ MIPI_DSI_PANEL_WUXGA);
+ if (ret)
+ printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(mipi_video_toshiba_wuxga_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..d6cabfc
--- /dev/null
+++ b/drivers/video/msm/mipi_toshiba_video_wvga_pt.c
@@ -0,0 +1,106 @@
+/* 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;
+
+ if (msm_fb_detect_client("mipi_video_toshiba_wvga"))
+ return 0;
+
+ 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/mipi_truly.c b/drivers/video/msm/mipi_truly.c
new file mode 100644
index 0000000..fd2a3ea
--- /dev/null
+++ b/drivers/video/msm/mipi_truly.c
@@ -0,0 +1,259 @@
+/* Copyright (c) 2011-2012, 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_truly.h"
+
+static struct msm_panel_common_pdata *mipi_truly_pdata;
+static struct dsi_buf truly_tx_buf;
+static struct dsi_buf truly_rx_buf;
+
+#define TRULY_CMD_DELAY 0
+#define TRULY_SLEEP_OFF_DELAY 150
+#define TRULY_DISPLAY_ON_DELAY 150
+#define GPIO_TRULY_LCD_RESET 129
+
+static int prev_bl = 17;
+
+static char extend_cmd_enable[4] = {0xB9, 0xFF, 0x83, 0x69};
+static char display_setting[16] = {
+ 0xB2, 0x00, 0x23, 0x62,
+ 0x62, 0x70, 0x00, 0xFF,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x03, 0x00, 0x01,
+};
+static char wave_cycle_setting[6] = {0xB4, 0x00, 0x1D, 0x5F, 0x0E, 0x06};
+static char gip_setting[27] = {
+ 0xD5, 0x00, 0x04, 0x03,
+ 0x00, 0x01, 0x05, 0x1C,
+ 0x70, 0x01, 0x03, 0x00,
+ 0x00, 0x40, 0x06, 0x51,
+ 0x07, 0x00, 0x00, 0x41,
+ 0x06, 0x50, 0x07, 0x07,
+ 0x0F, 0x04, 0x00,
+};
+static char power_setting[20] = {
+ 0xB1, 0x01, 0x00, 0x34,
+ 0x06, 0x00, 0x0F, 0x0F,
+ 0x2A, 0x32, 0x3F, 0x3F,
+ 0x07, 0x3A, 0x01, 0xE6,
+ 0xE6, 0xE6, 0xE6, 0xE6,
+};
+static char vcom_setting[3] = {0xB6, 0x56, 0x56};
+static char pannel_setting[2] = {0xCC, 0x02};
+static char gamma_setting[35] = {
+ 0xE0, 0x00, 0x1D, 0x22,
+ 0x38, 0x3D, 0x3F, 0x2E,
+ 0x4A, 0x06, 0x0D, 0x0F,
+ 0x13, 0x15, 0x13, 0x16,
+ 0x10, 0x19, 0x00, 0x1D,
+ 0x22, 0x38, 0x3D, 0x3F,
+ 0x2E, 0x4A, 0x06, 0x0D,
+ 0x0F, 0x13, 0x15, 0x13,
+ 0x16, 0x10, 0x19,
+};
+static char mipi_setting[14] = {
+ 0xBA, 0x00, 0xA0, 0xC6,
+ 0x00, 0x0A, 0x00, 0x10,
+ 0x30, 0x6F, 0x02, 0x11,
+ 0x18, 0x40,
+};
+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};
+
+static struct dsi_cmd_desc truly_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 struct dsi_cmd_desc truly_display_on_cmds[] = {
+ {DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
+ sizeof(extend_cmd_enable), extend_cmd_enable},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
+ sizeof(display_setting), display_setting},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
+ sizeof(wave_cycle_setting), wave_cycle_setting},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
+ sizeof(gip_setting), gip_setting},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
+ sizeof(power_setting), power_setting},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
+ sizeof(vcom_setting), vcom_setting},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
+ sizeof(pannel_setting), pannel_setting},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
+ sizeof(gamma_setting), gamma_setting},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, TRULY_CMD_DELAY,
+ sizeof(mipi_setting), mipi_setting},
+ {DTYPE_DCS_WRITE, 1, 0, 0, TRULY_SLEEP_OFF_DELAY,
+ sizeof(exit_sleep), exit_sleep},
+ {DTYPE_DCS_WRITE, 1, 0, 0, TRULY_DISPLAY_ON_DELAY,
+ sizeof(display_on), display_on},
+};
+
+static int mipi_truly_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;
+
+ msleep(20);
+ mipi_dsi_cmds_tx(&truly_tx_buf, truly_display_on_cmds,
+ ARRAY_SIZE(truly_display_on_cmds));
+
+ return 0;
+}
+
+static int mipi_truly_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(&truly_tx_buf, truly_display_off_cmds,
+ ARRAY_SIZE(truly_display_off_cmds));
+
+ return 0;
+}
+
+#define BL_LEVEL 17
+static void mipi_truly_set_backlight(struct msm_fb_data_type *mfd)
+{
+ int step = 0, i = 0;
+ int bl_level = mfd->bl_level;
+
+ /* real backlight level, 1 - max, 16 - min, 17 - off */
+ bl_level = BL_LEVEL - bl_level;
+
+ if (bl_level > prev_bl) {
+ step = bl_level - prev_bl;
+ if (bl_level == BL_LEVEL)
+ step--;
+ } else if (bl_level < prev_bl) {
+ step = bl_level + 16 - prev_bl;
+ } else {
+ pr_debug("%s: no change\n", __func__);
+ return;
+ }
+
+ if (bl_level == BL_LEVEL) {
+ /* turn off backlight */
+ mipi_truly_pdata->pmic_backlight(0);
+ } else {
+ if (prev_bl == BL_LEVEL) {
+ /* turn on backlight */
+ mipi_truly_pdata->pmic_backlight(1);
+ udelay(30);
+ }
+ /* adjust backlight level */
+ for (i = 0; i < step; i++) {
+ mipi_truly_pdata->pmic_backlight(0);
+ udelay(1);
+ mipi_truly_pdata->pmic_backlight(1);
+ udelay(1);
+ }
+ }
+ msleep(20);
+ prev_bl = bl_level;
+
+ return;
+}
+
+static int __devinit mipi_truly_lcd_probe(struct platform_device *pdev)
+{
+ if (pdev->id == 0) {
+ mipi_truly_pdata = pdev->dev.platform_data;
+ return 0;
+ }
+
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = mipi_truly_lcd_probe,
+ .driver = {
+ .name = "mipi_truly",
+ },
+};
+
+static struct msm_fb_panel_data truly_panel_data = {
+ .on = mipi_truly_lcd_on,
+ .off = mipi_truly_lcd_off,
+ .set_backlight = mipi_truly_set_backlight,
+};
+
+static int ch_used[3];
+
+int mipi_truly_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_truly", (panel << 8)|channel);
+
+ if (!pdev)
+ return -ENOMEM;
+
+ truly_panel_data.panel_info = *pinfo;
+
+ ret = platform_device_add_data(pdev, &truly_panel_data,
+ sizeof(truly_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_truly_lcd_init(void)
+{
+ mipi_dsi_buf_alloc(&truly_tx_buf, DSI_BUF_SIZE);
+ mipi_dsi_buf_alloc(&truly_rx_buf, DSI_BUF_SIZE);
+
+ return platform_driver_register(&this_driver);
+}
+
+module_init(mipi_truly_lcd_init);
diff --git a/drivers/video/msm/mipi_truly.h b/drivers/video/msm/mipi_truly.h
new file mode 100644
index 0000000..900e6f6
--- /dev/null
+++ b/drivers/video/msm/mipi_truly.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_TRULY_H
+#define MIPI_TRULY_H
+
+/* #define MIPI_TRULY_FAKE_PANEL */ /* FAKE PANEL for test */
+
+int mipi_truly_device_register(struct msm_panel_info *pinfo,
+ u32 channel, u32 panel);
+
+#endif /* MIPI_TRULY_H */
diff --git a/drivers/video/msm/mipi_truly_video_wvga_pt.c b/drivers/video/msm/mipi_truly_video_wvga_pt.c
new file mode 100644
index 0000000..931c564
--- /dev/null
+++ b/drivers/video/msm/mipi_truly_video_wvga_pt.c
@@ -0,0 +1,110 @@
+/* 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_truly.h"
+
+static struct msm_panel_info pinfo;
+
+static struct mipi_dsi_phy_ctrl dsi_video_mode_phy_db = {
+ /* 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},
+};
+
+static int __init mipi_video_truly_wvga_pt_init(void)
+{
+ int ret;
+
+#ifdef CONFIG_FB_MSM_MIPI_PANEL_DETECT
+ if (msm_fb_detect_client("mipi_video_truly_wvga"))
+ return 0;
+#endif
+
+ pinfo.xres = 480;
+ pinfo.yres = 800;
+ pinfo.type = MIPI_VIDEO_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 24;
+ 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.lcdc.border_clr = 0; /* blk */
+ pinfo.lcdc.underflow_clr = 0xff; /* blue */
+ /* number of dot_clk cycles HSYNC active edge
+ is delayed from VSYNC active edge */
+ pinfo.lcdc.hsync_skew = 0;
+ pinfo.clk_rate = 499000000;
+ 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; /* send HSA and HE following
+ VS/VE packet */
+ pinfo.mipi.hfp_power_stop = TRUE; /* LP-11 during the HFP period */
+ pinfo.mipi.hbp_power_stop = TRUE; /* LP-11 during the HBP period */
+ pinfo.mipi.hsa_power_stop = TRUE; /* LP-11 during the HSA period */
+ /* LP-11 or let Command Mode Engine send packets in
+ HS or LP mode for the BLLP of the last line of a frame */
+ pinfo.mipi.eof_bllp_power_stop = TRUE;
+ /* LP-11 or let Command Mode Engine send packets in
+ HS or LP mode for packets sent during BLLP period */
+ pinfo.mipi.bllp_power_stop = TRUE;
+
+ 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; /* 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; /* FIXME */
+
+ pinfo.mipi.dsi_phy_db = &dsi_video_mode_phy_db;
+ pinfo.mipi.dlane_swap = 0x01;
+ pinfo.mipi.tx_eot_append = 0x01; /* append EOT at the end
+ of data burst */
+
+ ret = mipi_truly_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_truly_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..17ee976
--- /dev/null
+++ b/drivers/video/msm/msm_dss_io_7x27a.c
@@ -0,0 +1,470 @@
+/* Copyright (c) 2008-2012, 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;
+
+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;
+static struct clk *ebi1_dsi_clk;
+int mipi_dsi_clk_on;
+
+int mipi_dsi_clk_init(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ dsi_esc_clk = clk_get(dev, "esc_clk");
+ if (IS_ERR_OR_NULL(dsi_esc_clk)) {
+ printk(KERN_ERR "can't find dsi_esc_clk\n");
+ dsi_esc_clk = NULL;
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_byte_div_clk = clk_get(dev, "byte_clk");
+ if (IS_ERR_OR_NULL(dsi_byte_div_clk)) {
+ pr_err("can't find dsi_byte_div_clk\n");
+ dsi_byte_div_clk = NULL;
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_pixel_clk = clk_get(dev, "pixel_clk");
+ if (IS_ERR_OR_NULL(dsi_pixel_clk)) {
+ pr_err("can't find dsi_pixel_clk\n");
+ dsi_pixel_clk = NULL;
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_clk = clk_get(dev, "core_clk");
+ if (IS_ERR_OR_NULL(dsi_clk)) {
+ pr_err("can't find dsi_clk\n");
+ dsi_clk = NULL;
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_ref_clk = clk_get(dev, "ref_clk");
+ if (IS_ERR_OR_NULL(dsi_ref_clk)) {
+ pr_err("can't find dsi_ref_clk\n");
+ dsi_ref_clk = NULL;
+ goto mipi_dsi_clk_err;
+ }
+
+ mdp_dsi_pclk = clk_get(dev, "mdp_clk");
+ if (IS_ERR_OR_NULL(mdp_dsi_pclk)) {
+ pr_err("can't find mdp_dsi_pclk\n");
+ mdp_dsi_pclk = NULL;
+ goto mipi_dsi_clk_err;
+ }
+
+ ahb_m_clk = clk_get(dev, "master_iface_clk");
+ if (IS_ERR_OR_NULL(ahb_m_clk)) {
+ pr_err("can't find ahb_m_clk\n");
+ ahb_m_clk = NULL;
+ goto mipi_dsi_clk_err;
+ }
+
+ ahb_s_clk = clk_get(dev, "slave_iface_clk");
+ if (IS_ERR_OR_NULL(ahb_s_clk)) {
+ pr_err("can't find ahb_s_clk\n");
+ ahb_s_clk = NULL;
+ goto mipi_dsi_clk_err;
+ }
+
+ ebi1_dsi_clk = clk_get(dev, "mem_clk");
+ if (IS_ERR_OR_NULL(ebi1_dsi_clk)) {
+ pr_err("can't find ebi1_dsi_clk\n");
+ ebi1_dsi_clk = NULL;
+ goto mipi_dsi_clk_err;
+ }
+
+ return 0;
+
+mipi_dsi_clk_err:
+ mipi_dsi_clk_deinit(NULL);
+ return -EPERM;
+}
+
+void mipi_dsi_clk_deinit(struct device *dev)
+{
+ if (mdp_dsi_pclk)
+ clk_put(mdp_dsi_pclk);
+ if (ahb_m_clk)
+ clk_put(ahb_m_clk);
+ if (ahb_s_clk)
+ clk_put(ahb_s_clk);
+ if (dsi_ref_clk)
+ clk_put(dsi_ref_clk);
+ if (dsi_byte_div_clk)
+ clk_put(dsi_byte_div_clk);
+ if (dsi_esc_clk)
+ clk_put(dsi_esc_clk);
+ if (ebi1_dsi_clk)
+ clk_put(ebi1_dsi_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 */
+ wmb();
+ usleep(1000);
+ MIPI_OUTP(MIPI_DSI_BASE + 0x128, 0x0000);/* end phy w reset */
+ wmb();
+ usleep(1000);
+ 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 + 0x0200, pd->pll[0]);
+ wmb();
+}
+
+void cont_splash_clk_ctrl(int enable)
+{
+}
+
+void mipi_dsi_prepare_clocks(void)
+{
+ clk_prepare(dsi_ref_clk);
+ clk_prepare(ahb_m_clk);
+ clk_prepare(ahb_s_clk);
+ clk_prepare(ebi1_dsi_clk);
+ clk_prepare(mdp_dsi_pclk);
+ clk_prepare(dsi_byte_div_clk);
+ clk_prepare(dsi_esc_clk);
+ clk_prepare(dsi_clk);
+ clk_prepare(dsi_pixel_clk);
+}
+
+void mipi_dsi_unprepare_clocks(void)
+{
+ clk_unprepare(dsi_esc_clk);
+ clk_unprepare(dsi_byte_div_clk);
+ clk_unprepare(mdp_dsi_pclk);
+ clk_unprepare(ebi1_dsi_clk);
+ clk_unprepare(ahb_m_clk);
+ clk_unprepare(ahb_s_clk);
+ clk_unprepare(dsi_ref_clk);
+ clk_unprepare(dsi_clk);
+ clk_unprepare(dsi_pixel_clk);
+}
+
+void mipi_dsi_ahb_ctrl(u32 enable)
+{
+ static int ahb_ctrl_done;
+ if (enable) {
+ if (ahb_ctrl_done) {
+ pr_info("%s: ahb clks already ON\n", __func__);
+ return;
+ }
+ clk_enable(dsi_ref_clk);
+ clk_enable(ahb_m_clk);
+ clk_enable(ahb_s_clk);
+ ahb_ctrl_done = 1;
+ } else {
+ if (ahb_ctrl_done == 0) {
+ pr_info("%s: ahb clks already OFF\n", __func__);
+ return;
+ }
+ clk_disable(ahb_m_clk);
+ clk_disable(ahb_s_clk);
+ clk_disable(dsi_ref_clk);
+ ahb_ctrl_done = 0;
+ }
+}
+
+void mipi_dsi_clk_enable(void)
+{
+ unsigned data = 0;
+ uint32 pll_ctrl;
+
+ if (mipi_dsi_clk_on) {
+ pr_info("%s: mipi_dsi_clks already ON\n", __func__);
+ return;
+ }
+ if (clk_set_rate(ebi1_dsi_clk, 65000000)) /* 65 MHz */
+ pr_err("%s: ebi1_dsi_clk set rate failed\n", __func__);
+ clk_enable(ebi1_dsi_clk);
+
+ pll_ctrl = MIPI_INP(MIPI_DSI_BASE + 0x0200);
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0200, pll_ctrl | 0x01);
+ mb();
+
+ clk_set_rate(dsi_byte_div_clk, data);
+ clk_set_rate(dsi_esc_clk, data);
+ clk_enable(mdp_dsi_pclk);
+ 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_clk_on = 1;
+}
+
+void mipi_dsi_clk_disable(void)
+{
+ if (mipi_dsi_clk_on == 0) {
+ pr_info("%s: mipi_dsi_clks already OFF\n", __func__);
+ return;
+ }
+ 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);
+ /* DSIPHY_PLL_CTRL_0, disable dsi pll */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0200, 0x40);
+ if (clk_set_rate(ebi1_dsi_clk, 0))
+ pr_err("%s: ebi1_dsi_clk set rate failed\n", __func__);
+ clk_disable(ebi1_dsi_clk);
+ mipi_dsi_clk_on = 0;
+}
+
+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);
+
+ /* disable 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..828be9c
--- /dev/null
+++ b/drivers/video/msm/msm_dss_io_8960.c
@@ -0,0 +1,824 @@
+/* Copyright (c) 2008-2012, 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 "mdp.h"
+#include "mdp4.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;
+
+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;
+int mipi_dsi_clk_on;
+
+int mipi_dsi_clk_init(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct device *dev = &pdev->dev;
+
+ mfd = platform_get_drvdata(pdev);
+
+ amp_pclk = clk_get(dev, "arb_clk");
+ if (IS_ERR_OR_NULL(amp_pclk)) {
+ pr_err("can't find amp_pclk\n");
+ amp_pclk = NULL;
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_m_pclk = clk_get(dev, "master_iface_clk");
+ if (IS_ERR_OR_NULL(dsi_m_pclk)) {
+ pr_err("can't find dsi_m_pclk\n");
+ dsi_m_pclk = NULL;
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_s_pclk = clk_get(dev, "slave_iface_clk");
+ if (IS_ERR_OR_NULL(dsi_s_pclk)) {
+ pr_err("can't find dsi_s_pclk\n");
+ dsi_s_pclk = NULL;
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_byte_div_clk = clk_get(dev, "byte_clk");
+ if (IS_ERR(dsi_byte_div_clk)) {
+ pr_err("can't find dsi_byte_div_clk\n");
+ dsi_byte_div_clk = NULL;
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_esc_clk = clk_get(dev, "esc_clk");
+ if (IS_ERR(dsi_esc_clk)) {
+ printk(KERN_ERR "can't find dsi_esc_clk\n");
+ dsi_esc_clk = NULL;
+ goto mipi_dsi_clk_err;
+ }
+
+ return 0;
+
+mipi_dsi_clk_err:
+ mipi_dsi_clk_deinit(dev);
+ return -EPERM;
+}
+
+void mipi_dsi_clk_deinit(struct device *dev)
+{
+ if (amp_pclk)
+ clk_put(amp_pclk);
+ if (amp_pclk)
+ clk_put(dsi_m_pclk);
+ if (dsi_s_pclk)
+ clk_put(dsi_s_pclk);
+ if (dsi_byte_div_clk)
+ clk_put(dsi_byte_div_clk);
+ if (dsi_esc_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));
+}
+
+void mipi_dsi_lane_cfg(void)
+{
+ int i, ln_offset;
+
+ ln_offset = 0x300;
+ for (i = 0; i < 4; i++) {
+ /* DSI1_DSIPHY_LN_CFG0 */
+ MIPI_OUTP(MIPI_DSI_BASE + ln_offset, 0x80);
+ /* DSI1_DSIPHY_LN_CFG1 */
+ MIPI_OUTP(MIPI_DSI_BASE + ln_offset + 0x04, 0x45);
+ /* DSI1_DSIPHY_LN_CFG2 */
+ MIPI_OUTP(MIPI_DSI_BASE + ln_offset + 0x08, 0x0);
+ /* DSI1_DSIPHY_LN_TEST_DATAPATH */
+ MIPI_OUTP(MIPI_DSI_BASE + ln_offset + 0x0c, 0x0);
+ /* DSI1_DSIPHY_LN_TEST_STR0 */
+ MIPI_OUTP(MIPI_DSI_BASE + ln_offset + 0x14, 0x1);
+ /* DSI1_DSIPHY_LN_TEST_STR1 */
+ MIPI_OUTP(MIPI_DSI_BASE + ln_offset + 0x18, 0x66);
+ ln_offset += 0x40;
+ }
+
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0400, 0x40); /* DSI1_DSIPHY_LNCK_CFG0 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0404, 0x67); /* DSI1_DSIPHY_LNCK_CFG1 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0408, 0x0); /* DSI1_DSIPHY_LNCK_CFG2 */
+ /* DSI1_DSIPHY_LNCK_TEST_DATAPATH */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x040c, 0x0);
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0414, 0x1); /* DSI1_DSIPHY_LNCK_TEST_STR0 */
+ /* DSI1_DSIPHY_LNCK_TEST_STR1 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0418, 0x88);
+}
+
+void mipi_dsi_bist_ctrl(void)
+{
+ MIPI_OUTP(MIPI_DSI_BASE + 0x049c, 0x0f); /* DSI1_DSIPHY_BIST_CTRL4 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0490, 0x03); /* DSI1_DSIPHY_BIST_CTRL1 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x048c, 0x03); /* DSI1_DSIPHY_BIST_CTRL0 */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x049c, 0x0); /* DSI1_DSIPHY_BIST_CTRL4 */
+}
+
+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, 0x03);
+
+ /* 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 < 600) {
+ 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 */
+ wmb();
+ usleep(1);
+ MIPI_OUTP(MIPI_DSI_BASE + 0x128, 0x0000);/* end phy w reset */
+ wmb();
+ usleep(1);
+ 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 */
+
+ MIPI_OUTP(MIPI_DSI_BASE + 0x4b0, 0x04);/* DSIPHY_LDO_CNTRL */
+
+ 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();
+ mipi_dsi_lane_cfg(); /* lane cfgs */
+ mipi_dsi_bist_ctrl(); /* bist ctrl */
+
+ 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();
+
+ off = 0x0440; /* phy timing 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 cont_splash_clk_ctrl(int enable)
+{
+ static int cont_splash_clks_enabled;
+ if (enable && !cont_splash_clks_enabled) {
+ clk_prepare_enable(dsi_byte_div_clk);
+ clk_prepare_enable(dsi_esc_clk);
+ cont_splash_clks_enabled = 1;
+ } else if (!enable && cont_splash_clks_enabled) {
+ clk_disable_unprepare(dsi_byte_div_clk);
+ clk_disable_unprepare(dsi_esc_clk);
+ cont_splash_clks_enabled = 0;
+ }
+}
+
+void mipi_dsi_prepare_clocks(void)
+{
+ clk_prepare(amp_pclk);
+ clk_prepare(dsi_m_pclk);
+ clk_prepare(dsi_s_pclk);
+ clk_prepare(dsi_byte_div_clk);
+ clk_prepare(dsi_esc_clk);
+}
+
+void mipi_dsi_unprepare_clocks(void)
+{
+ clk_unprepare(dsi_esc_clk);
+ clk_unprepare(dsi_byte_div_clk);
+ clk_unprepare(dsi_m_pclk);
+ clk_unprepare(dsi_s_pclk);
+ clk_unprepare(amp_pclk);
+}
+
+void mipi_dsi_ahb_ctrl(u32 enable)
+{
+ static int ahb_ctrl_done;
+ if (enable) {
+ if (ahb_ctrl_done) {
+ pr_info("%s: ahb clks already ON\n", __func__);
+ return;
+ }
+ clk_enable(amp_pclk); /* clock for AHB-master to AXI */
+ clk_enable(dsi_m_pclk);
+ clk_enable(dsi_s_pclk);
+ mipi_dsi_ahb_en();
+ mipi_dsi_sfpb_cfg();
+ ahb_ctrl_done = 1;
+ } else {
+ if (ahb_ctrl_done == 0) {
+ pr_info("%s: ahb clks already OFF\n", __func__);
+ return;
+ }
+ clk_disable(dsi_m_pclk);
+ clk_disable(dsi_s_pclk);
+ clk_disable(amp_pclk); /* clock for AHB-master to AXI */
+ ahb_ctrl_done = 0;
+ }
+}
+
+void mipi_dsi_clk_enable(void)
+{
+ u32 pll_ctrl = MIPI_INP(MIPI_DSI_BASE + 0x0200);
+ if (mipi_dsi_clk_on) {
+ pr_info("%s: mipi_dsi_clks already ON\n", __func__);
+ return;
+ }
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0200, pll_ctrl | 0x01);
+ mipi_dsi_phy_rdy_poll();
+
+ 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, esc_byte_ratio) < 0) /* divided by esc */
+ pr_err("%s: dsi_esc_clk - " /* clk ratio */
+ "clk_set_rate failed\n", __func__);
+ mipi_dsi_pclk_ctrl(&dsi_pclk, 1);
+ mipi_dsi_clk_ctrl(&dsicore_clk, 1);
+ clk_enable(dsi_byte_div_clk);
+ clk_enable(dsi_esc_clk);
+ mipi_dsi_clk_on = 1;
+ mdp4_stat.dsi_clk_on++;
+}
+
+void mipi_dsi_clk_disable(void)
+{
+ if (mipi_dsi_clk_on == 0) {
+ pr_info("%s: mipi_dsi_clks already OFF\n", __func__);
+ return;
+ }
+ clk_disable(dsi_esc_clk);
+ clk_disable(dsi_byte_div_clk);
+ mipi_dsi_pclk_ctrl(&dsi_pclk, 0);
+ mipi_dsi_clk_ctrl(&dsicore_clk, 0);
+ /* DSIPHY_PLL_CTRL_0, disable dsi pll */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0200, 0x0);
+ mipi_dsi_clk_on = 0;
+ mdp4_stat.dsi_clk_off++;
+}
+
+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);
+
+ /* disable 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_reset_core(void)
+{
+ hdmi_msm_clk(0);
+ udelay(5);
+ hdmi_msm_clk(1);
+}
+
+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);
+
+ offset = HDMI_PHY_REG_4;
+ while (offset <= HDMI_PHY_REG_11) {
+ HDMI_OUTP(offset, 0x0);
+ offset += 0x4;
+ }
+
+ HDMI_OUTP(HDMI_PHY_REG_3, 0x20);
+}
+
+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..c79c4c7
--- /dev/null
+++ b/drivers/video/msm/msm_dss_io_8x60.c
@@ -0,0 +1,685 @@
+/* Copyright (c) 2008-2012, 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 <mach/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;
+
+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;
+int mipi_dsi_clk_on;
+
+int mipi_dsi_clk_init(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ amp_pclk = clk_get(dev, "arb_clk");
+ if (IS_ERR_OR_NULL(amp_pclk)) {
+ pr_err("can't find amp_pclk\n");
+ amp_pclk = NULL;
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_m_pclk = clk_get(dev, "master_iface_clk");
+ if (IS_ERR_OR_NULL(dsi_m_pclk)) {
+ pr_err("can't find dsi_m_pclk\n");
+ dsi_m_pclk = NULL;
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_s_pclk = clk_get(dev, "slave_iface_clk");
+ if (IS_ERR_OR_NULL(dsi_s_pclk)) {
+ pr_err("can't find dsi_s_pclk\n");
+ dsi_s_pclk = NULL;
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_byte_div_clk = clk_get(dev, "byte_clk");
+ if (IS_ERR_OR_NULL(dsi_byte_div_clk)) {
+ pr_err("can't find dsi_byte_div_clk\n");
+ dsi_byte_div_clk = NULL;
+ goto mipi_dsi_clk_err;
+ }
+
+ dsi_esc_clk = clk_get(dev, "esc_clk");
+ if (IS_ERR_OR_NULL(dsi_esc_clk)) {
+ printk(KERN_ERR "can't find dsi_esc_clk\n");
+ dsi_esc_clk = NULL;
+ goto mipi_dsi_clk_err;
+ }
+
+ return 0;
+
+mipi_dsi_clk_err:
+ mipi_dsi_clk_deinit(NULL);
+ return -EPERM;
+}
+
+void mipi_dsi_clk_deinit(struct device *dev)
+{
+ if (amp_pclk)
+ clk_put(amp_pclk);
+ if (dsi_m_pclk)
+ clk_put(dsi_m_pclk);
+ if (dsi_s_pclk)
+ clk_put(dsi_s_pclk);
+ if (dsi_byte_div_clk)
+ clk_put(dsi_byte_div_clk);
+ if (dsi_esc_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 */
+ wmb();
+ usleep(1);
+ MIPI_OUTP(MIPI_DSI_BASE + 0x128, 0x0000);/* end phy w reset */
+ wmb();
+ usleep(1);
+ 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();
+}
+
+void cont_splash_clk_ctrl(int enable)
+{
+}
+
+void mipi_dsi_prepare_clocks(void)
+{
+ clk_prepare(amp_pclk);
+ clk_prepare(dsi_m_pclk);
+ clk_prepare(dsi_s_pclk);
+ clk_prepare(dsi_byte_div_clk);
+ clk_prepare(dsi_esc_clk);
+}
+
+void mipi_dsi_unprepare_clocks(void)
+{
+ clk_unprepare(dsi_esc_clk);
+ clk_unprepare(dsi_byte_div_clk);
+ clk_unprepare(dsi_m_pclk);
+ clk_unprepare(dsi_s_pclk);
+ clk_unprepare(amp_pclk);
+}
+
+void mipi_dsi_ahb_ctrl(u32 enable)
+{
+ static int ahb_ctrl_done;
+ if (enable) {
+ if (ahb_ctrl_done) {
+ pr_info("%s: ahb clks already ON\n", __func__);
+ return;
+ }
+ clk_enable(amp_pclk); /* clock for AHB-master to AXI */
+ clk_enable(dsi_m_pclk);
+ clk_enable(dsi_s_pclk);
+ mipi_dsi_ahb_en();
+ mipi_dsi_sfpb_cfg();
+ ahb_ctrl_done = 1;
+ } else {
+ if (ahb_ctrl_done == 0) {
+ pr_info("%s: ahb clks already OFF\n", __func__);
+ return;
+ }
+ clk_disable(dsi_m_pclk);
+ clk_disable(dsi_s_pclk);
+ clk_disable(amp_pclk); /* clock for AHB-master to AXI */
+ ahb_ctrl_done = 0;
+ }
+}
+
+void mipi_dsi_clk_enable(void)
+{
+ u32 pll_ctrl = MIPI_INP(MIPI_DSI_BASE + 0x0200);
+ if (mipi_dsi_clk_on) {
+ pr_info("%s: mipi_dsi_clks already ON\n", __func__);
+ return;
+ }
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0200, pll_ctrl | 0x01);
+ mb();
+
+ if (clk_set_rate(dsi_byte_div_clk, 1) < 0) /* divided by 1 */
+ pr_err("%s: clk_set_rate failed\n", __func__);
+ mipi_dsi_pclk_ctrl(&dsi_pclk, 1);
+ mipi_dsi_clk_ctrl(&dsicore_clk, 1);
+ clk_enable(dsi_byte_div_clk);
+ clk_enable(dsi_esc_clk);
+ mipi_dsi_clk_on = 1;
+}
+
+void mipi_dsi_clk_disable(void)
+{
+ if (mipi_dsi_clk_on == 0) {
+ pr_info("%s: mipi_dsi_clks already OFF\n", __func__);
+ return;
+ }
+ clk_disable(dsi_esc_clk);
+ clk_disable(dsi_byte_div_clk);
+
+ mipi_dsi_pclk_ctrl(&dsi_pclk, 0);
+ mipi_dsi_clk_ctrl(&dsicore_clk, 0);
+ /* DSIPHY_PLL_CTRL_0, disable dsi pll */
+ MIPI_OUTP(MIPI_DSI_BASE + 0x0200, 0x40);
+ mipi_dsi_clk_on = 0;
+}
+
+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);
+
+ /* disable 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_reset_core(void)
+{
+ hdmi_msm_clk(0);
+ udelay(5);
+ hdmi_msm_clk(1);
+
+ clk_reset(hdmi_msm_state->hdmi_app_clk, CLK_RESET_ASSERT);
+ udelay(20);
+ clk_reset(hdmi_msm_state->hdmi_app_clk, CLK_RESET_DEASSERT);
+}
+
+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)
+{
+ /* Assert RESET PHY from controller */
+ HDMI_OUTP_ND(0x02D4, 0x4);
+ udelay(10);
+ /* De-assert RESET PHY from controller */
+ HDMI_OUTP_ND(0x02D4, 0x0);
+ /* Turn off Driver */
+ HDMI_OUTP_ND(0x0308, 0x1F);
+ udelay(10);
+ /* 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 1056dc0..773b9bf 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-2012, 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,466 +15,235 @@
* 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/wakelock.h>
-#include <linux/earlysuspend.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>
+
+#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 <mach/debug_display.h>
-#include "mdp_hw.h"
-#ifdef CONFIG_MSM_MDP40
+#include <linux/leds.h>
+#include <linux/pm_runtime.h>
+
+#define MSM_FB_C
+#include "msm_fb.h"
+#include "mddihosti.h"
+#include "tvenc.h"
+#include "mdp.h"
#include "mdp4.h"
+
+#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
+#define MSM_FB_NUM 3
#endif
-static void msmfb_resume_handler(struct early_suspend *h);
-static void msmfb_resume(struct msmfb_info *msmfb);
+static unsigned char *fbram;
+static unsigned char *fbram_phys;
+static int fbram_size;
+static boolean bf_supported;
-#define MSMFB_DEBUG 1
-#ifdef CONFIG_FB_MSM_LOGO
-#define INIT_IMAGE_FILE "/logo.rle"
-#endif
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
-#define PRINT_FPS 0
-#define PRINT_BLIT_TIME 0
+int vsync_mode = 1;
-#define SLEEPING 0x4
-#define UPDATING 0x3
-#define FULL_UPDATE_DONE 0x2
-#define WAKING 0x1
-#define AWAKE 0x0
+#define MAX_BLIT_REQ 256
-#define NONE 0
-#define SUSPEND_RESUME 0x1
-#define FPS 0x2
-#define BLIT_TIME 0x4
-#define SHOW_UPDATES 0x8
+#define MAX_FBI_LIST 32
+static struct fb_info *fbi_list[MAX_FBI_LIST];
+static int fbi_list_index;
-#define DLOG(mask, fmt, args...) \
-do { \
- if ((msmfb_debug_mask | SUSPEND_RESUME) & mask) \
- PR_DISP_INFO("msmfb: "fmt, ##args); \
-} while (0)
-#define BITS_PER_PIXEL(info) (info->fb->var.bits_per_pixel)
-#define BYTES_PER_PIXEL(info) (info->fb->var.bits_per_pixel >> 3)
-static int msmfb_debug_mask;
-module_param_named(msmfb_debug_mask, msmfb_debug_mask, int,
- S_IRUGO | S_IWUSR | S_IWGRP);
+static struct msm_fb_data_type *mfd_list[MAX_FBI_LIST];
+static int mfd_list_index;
-#if defined(CONFIG_USB_FUNCTION_PROJECTOR) || defined(CONFIG_USB_ANDROID_PROJECTOR)
-#define NUM_ALLOC 3
-static void *virt_addr[NUM_ALLOC] = { NULL };
-static void *phys_addr[NUM_ALLOC] = { NULL };
-static struct msmfb_usb_projector_info usb_pjt_info = {0, 0};
-char *get_fb_addr(void)
+static u32 msm_fb_pseudo_palette[16] = {
+ 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
+};
+
+static struct ion_client *iclient;
+
+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);
+static int mdp_bl_scale_config(struct msm_fb_data_type *mfd,
+ struct mdp_bl_scale_data *data);
+static void msm_fb_scale_bl(__u32 *bl_lvl);
+
+#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];
+static int bl_scale, bl_min_lvl;
+
+DEFINE_MUTEX(msm_fb_notify_update_sem);
+void msmfb_no_update_notify_timer_cb(unsigned long data)
{
- int i;
-
- if (!usb_pjt_info.latest_offset)
- return 0;
-
- usb_pjt_info.usb_offset = usb_pjt_info.latest_offset;
-
- for (i=0; i<NUM_ALLOC; i++)
- if (phys_addr[i] == (void *)usb_pjt_info.usb_offset)
- return virt_addr[i];
-
- printk(KERN_ERR "%s: <FATAL> Impossible to be here.\n", __func__);
- return 0;
-}
-#endif
-
-struct mdp_device *mdp;
-#ifdef CONFIG_FB_MSM_OVERLAY
-static atomic_t mdpclk_on = ATOMIC_INIT(1);
-#endif
-
-DECLARE_MUTEX(ov_semaphore);
-static DEFINE_MUTEX(overlay_ioctl_mutex);
-
-#if (defined(CONFIG_USB_FUNCTION_PROJECTOR) || defined(CONFIG_USB_ANDROID_PROJECTOR))
-static DEFINE_SPINLOCK(fb_data_lock);
-static struct msm_fb_info msm_fb_data;
-int msmfb_get_var(struct msm_fb_info *tmp)
-{
- unsigned long flags;
- spin_lock_irqsave(&fb_data_lock, flags);
- memcpy(tmp, &msm_fb_data, sizeof(msm_fb_data));
- spin_unlock_irqrestore(&fb_data_lock, flags);
- 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);
}
-/* projector need this, and very much */
-int msmfb_get_fb_area(void)
+struct dentry *msm_fb_get_debugfs_root(void)
{
- int area;
- unsigned long flags;
- spin_lock_irqsave(&fb_data_lock, flags);
- area = msm_fb_data.msmfb_area;
- spin_unlock_irqrestore(&fb_data_lock, flags);
- return area;
-}
-#endif
+ if (msm_fb_debugfs_root == NULL)
+ msm_fb_debugfs_root = debugfs_create_dir("msm_fb", NULL);
-static int msmfb_open(struct fb_info *info, int user)
-{
- return 0;
+ return msm_fb_debugfs_root;
}
-static int msmfb_release(struct fb_info *info, int user)
+void msm_fb_debugfs_file_create(struct dentry *root, const char *name,
+ u32 *var)
{
- return 0;
-}
-
-int overlay_semaphore_lock(void)
-{
- static struct task_struct last_owner_task = {0};
- static int fail_counter = 0;
- int err = down_timeout(&ov_semaphore, msecs_to_jiffies(1000));
-
- if (!err) {
- /* Got the ownership for this semaphore, record who own it...
- * Then reset the fail ccounter...
- */
- last_owner_task.pid = current->pid;
- last_owner_task.tgid = current->tgid;
- strncpy(last_owner_task.comm, current->comm, (TASK_COMM_LEN-1));
- fail_counter = 0;
- } else {
- /* Fail to get the ownership for this semaphore... */
- if ((fail_counter%10) == 0) {
- PR_DISP_WARN("Semaphore own by [%s](%d, %d), [%s](%d, %d) "
- "want to own it(err=%d)...\n",
- last_owner_task.comm, last_owner_task.pid,
- last_owner_task.tgid, current->comm,
- current->pid, current->tgid, err);
- dump_stack();
- }
- fail_counter++;
- }
-
- return err;
-}
-
-void overlay_semaphore_unlock(void)
-{
- up(&ov_semaphore);
-}
-
-/* Called from dma interrupt handler, must not sleep */
-static void msmfb_handle_dma_interrupt(struct msmfb_callback *callback)
-{
- unsigned long irq_flags = 0;
- struct msmfb_info *msmfb = container_of(callback, struct msmfb_info,
- dma_callback);
-#if PRINT_FPS
- int64_t dt;
- ktime_t now;
- static int64_t frame_count;
- static ktime_t last_sec;
-#endif
-
- overlay_semaphore_unlock();
- 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");
- queue_work(msmfb->resume_workqueue, &msmfb->resume_work);
- }
-#if PRINT_FPS
- now = ktime_get();
- dt = ktime_to_ns(ktime_sub(now, last_sec));
- frame_count++;
- if (dt > NSEC_PER_SEC) {
- int64_t fps = frame_count * NSEC_PER_SEC * 100;
- frame_count = 0;
- last_sec = ktime_get();
- do_div(fps, dt);
- DLOG(FPS, "fps * 100: %llu\n", fps);
- }
-#endif
- 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 = 0;
- 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;
- PR_DISP_WARN("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);
- overlay_semaphore_unlock();
- return -1;
- }
- if (msmfb->sleeping == SLEEPING) {
- DLOG(SUSPEND_RESUME, "tried to start dma while asleep\n");
- spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
- overlay_semaphore_unlock();
- 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)) {
- PR_DISP_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 = ((ALIGN(msmfb->xres, 32) * (yoffset + y) + x) * BYTES_PER_PIXEL(msmfb));
- mdp->dma(mdp, addr + msmfb->fb->fix.smem_start,
- msmfb->xres * BYTES_PER_PIXEL(msmfb), 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);
- overlay_semaphore_unlock();
- 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);
- wake_unlock(&msmfb->idle_lock);
- 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;
-#ifdef CONFIG_PANEL_SELF_REFRESH
- struct mdp_lcdc_info *lcdc = panel_to_lcdc(panel);
-#endif
- unsigned long irq_flags = 0;
- int sleeping;
- int retry = 1;
-#if PRINT_FPS
- ktime_t t1, t2;
- static uint64_t pans;
- static uint64_t dt;
- t1 = ktime_get();
-#endif
- DLOG(SHOW_UPDATES, "update %d %d %d %d %d %d\n",
- left, top, eright, ebottom, yoffset, pan_display);
-
- if (msmfb->sleeping != AWAKE)
- DLOG(SUSPEND_RESUME, "pan_update in state(%d)\n", msmfb->sleeping);
-
-#ifdef CONFIG_PANEL_SELF_REFRESH
- if (lcdc->mdp->mdp_dev.overrides & MSM_MDP_RGB_PANEL_SELE_REFRESH) {
- spin_lock_irqsave(&panel_icm->lock, irq_flags);
- panel_icm->panel_update = 1;
- spin_unlock_irqrestore(&panel_icm->lock, irq_flags);
- wake_up(&panel_update_wait_queue);
- }
-#endif
-
-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);
- /* Shorten delay time when apply vsync recover mechanism*/
- if (panel->recover_vsync) {
- ret = wait_event_interruptible_timeout(msmfb->frame_wq,
- msmfb->frame_done == msmfb->frame_requested &&
- msmfb->sleeping != UPDATING, HZ/3);
+ msm_fb_debugfs_file[msm_fb_debugfs_file_index++] =
+ debugfs_create_u32(name, S_IRUGO | S_IWUSR, root, var);
+}
+#endif
+
+int msm_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+ 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 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 msm_fb_data_type *mfd = dev_get_drvdata(led_cdev->dev->parent);
+ int bl_lvl;
+
+ 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 struct led_classdev backlight_led = {
+ .name = "lcd-backlight",
+ .brightness = MAX_BACKLIGHT_BRIGHTNESS,
+ .brightness_set = msm_fb_set_bl_brightness,
+};
+#endif
+
+static struct msm_fb_platform_data *msm_fb_pdata;
+unsigned char hdmi_prim_display;
+
+int msm_fb_detect_client(const char *name)
+{
+ int ret = 0;
+ u32 len;
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ u32 id;
+#endif
+ if (!msm_fb_pdata)
+ return -EPERM;
+
+ len = strnlen(name, PANEL_NAME_MAX_LEN);
+ if (strnlen(msm_fb_pdata->prim_panel_name, PANEL_NAME_MAX_LEN)) {
+ pr_err("\n name = %s, prim_display = %s",
+ name, msm_fb_pdata->prim_panel_name);
+ if (!strncmp((char *)msm_fb_pdata->prim_panel_name,
+ name, len)) {
+ if (!strncmp((char *)msm_fb_pdata->prim_panel_name,
+ "hdmi_msm", len))
+ hdmi_prim_display = 1;
+ return 0;
} else {
- 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)) {
- wake_lock_timeout(&msmfb->idle_lock, HZ/4);
- panel->request_vsync(panel,
- &msmfb->vsync_callback);
- retry = 0;
- /* FIXME */
- if (panel->recover_vsync)
- panel->recover_vsync(panel);
- PR_DISP_WARN("msmfb_pan_display timeout "
- "rerequest vsync\n");
- } else {
- PR_DISP_WARN("msmfb_pan_display timeout "
- "waiting for frame start, %d %d\n",
- msmfb->frame_requested,
- msmfb->frame_done);
- return;
- }
- }
- goto restart;
- }
-
-#if PRINT_FPS
- t2 = ktime_get();
- if (pan_display) {
- uint64_t temp = ktime_to_ns(ktime_sub(t2, t1));
- do_div(temp, 1000);
- dt += temp;
- pans++;
- if (pans > 1000) {
- do_div(dt, pans);
- DLOG(FPS, "ave_wait_time: %lld\n", dt);
- dt = 0;
- pans = 0;
+ ret = -EPERM;
}
}
+
+ if (strnlen(msm_fb_pdata->ext_panel_name, PANEL_NAME_MAX_LEN)) {
+ pr_err("\n name = %s, ext_display = %s",
+ name, msm_fb_pdata->ext_panel_name);
+ if (!strncmp((char *)msm_fb_pdata->ext_panel_name, name, len))
+ return 0;
+ else
+ ret = -EPERM;
+ }
+
+ if (ret)
+ return ret;
+
+ ret = -EPERM;
+ if (msm_fb_pdata && msm_fb_pdata->detect_client) {
+ ret = msm_fb_pdata->detect_client(name);
+
+ /* if it's non mddi panel, we need to pre-scan
+ mddi client to see if we can disable mddi host */
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ if (!ret && msm_fb_pdata->mddi_prescan)
+ id = mddi_get_client_id();
#endif
-
- 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 */
- overlay_semaphore_lock();
- msmfb->vsync_request_time = ktime_get();
-
-#ifdef CONFIG_MDP4_HW_VSYNC
- msmfb_start_dma(msmfb);
-#else
- if (panel->request_vsync && (sleeping == AWAKE)) {
- wake_lock_timeout(&msmfb->idle_lock, HZ/4);
- 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);
- }
- }
-#endif
-}
-
-static void msmfb_update(struct fb_info *info, uint32_t left, uint32_t top,
- uint32_t eright, uint32_t ebottom)
-{
- msmfb_pan_update(info, left, top, eright, ebottom, 0, 0);
-}
-
-static void power_on_panel(struct work_struct *work)
-{
- struct msmfb_info *msmfb =
- container_of(work, struct msmfb_info, resume_work);
- struct msm_panel_data *panel = msmfb->panel;
- unsigned long irq_flags = 0;
- mutex_lock(&msmfb->panel_init_lock);
- DLOG(SUSPEND_RESUME, "turning on panel\n");
- if (msmfb->sleeping == UPDATING) {
- wake_lock_timeout(&msmfb->idle_lock, HZ);
- if (panel->unblank && panel->unblank(panel)) {
- PR_DISP_INFO("msmfb: panel unblank failed,"
- "not starting drawing\n");
- goto error;
- }
- wake_unlock(&msmfb->idle_lock);
- 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);
+ return ret;
}
static BLOCKING_NOTIFIER_HEAD(display_chain_head);
@@ -482,267 +252,2523 @@
return blocking_notifier_chain_register(&display_chain_head, nb);
}
-static int display_notifier_callback(struct notifier_block *nfb,
- unsigned long action, void *ignored)
+static ssize_t msm_fb_msm_fb_type(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- switch (action) {
- case NOTIFY_MSM_FB:
- PR_DISP_DEBUG("NOTIFY_MSM_FB\n");
+ 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 NOTIFY_POWER:
- /* nothing to do */
+ 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;
+ case MIPI_VIDEO_PANEL:
+ ret = snprintf(buf, PAGE_SIZE, "mipi dsi video panel\n");
+ break;
+ case MIPI_CMD_PANEL:
+ ret = snprintf(buf, PAGE_SIZE, "mipi dsi cmd panel\n");
+ break;
+ case WRITEBACK_PANEL:
+ ret = snprintf(buf, PAGE_SIZE, "writeback panel\n");
break;
default:
- PR_DISP_ERR("%s: unknown action in 0x%lx\n",
- __func__, action);
- return NOTIFY_BAD;
+ ret = snprintf(buf, PAGE_SIZE, "unknown panel\n");
+ break;
}
- return NOTIFY_OK;
+
+ return ret;
}
-/* -------------------------------------------------------------------------- */
-#ifdef CONFIG_HAS_EARLYSUSPEND
-/* turn off the panel */
-static void msmfb_earlier_suspend(struct early_suspend *h)
+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 msm_fb_create_sysfs(struct platform_device *pdev)
{
- struct msmfb_info *msmfb = container_of(h, struct msmfb_info,
- earlier_suspend);
- struct msm_panel_data *panel = msmfb->panel;
- unsigned long irq_flags = 0;
- mutex_lock(&msmfb->panel_init_lock);
- msmfb->sleeping = SLEEPING;
- wake_up(&msmfb->frame_wq);
- spin_lock_irqsave(&msmfb->update_lock, irq_flags);
- spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
- wait_event_timeout(msmfb->frame_wq,
- msmfb->frame_requested == msmfb->frame_done, HZ/10);
-#ifndef CONFIG_MSM_MDP40
- mdp->dma(mdp, virt_to_phys(msmfb->black), 0,
- msmfb->fb->var.xres, msmfb->fb->var.yres, 0, 0,
- NULL, panel->interface_type);
- mdp->dma_wait(mdp, panel->interface_type);
-#endif
- /* turn off the panel */
- panel->blank(panel);
+ 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 void msmfb_suspend(struct early_suspend *h)
+static int msm_fb_probe(struct platform_device *pdev)
{
- struct msmfb_info *msmfb = container_of(h, struct msmfb_info,
- early_suspend);
- struct msm_panel_data *panel = msmfb->panel;
- /* suspend the panel */
- PR_DISP_INFO("%s", __func__);
-#ifdef CONFIG_FB_MSM_OVERLAY
- atomic_set(&mdpclk_on, 0);
-#endif
- panel->suspend(panel);
- msmfb->fb_resumed = 0;
- mutex_unlock(&msmfb->panel_init_lock);
-}
+ struct msm_fb_data_type *mfd;
+ int rc;
+ int err = 0;
-static void msmfb_resume_handler(struct early_suspend *h)
-{
- struct msmfb_info *msmfb = container_of(h, struct msmfb_info,
- early_suspend);
-#ifdef CONFIG_HTC_ONMODE_CHARGING
- if (msmfb->fb_resumed == 1) {
- DLOG(SUSPEND_RESUME, "fb is resumed by onchg. skip resume\n");
- return;
+ 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 = __va(fbram_phys);
+
+ 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);
+
+ iclient = msm_ion_client_create(-1, pdev->name);
+ if (IS_ERR_OR_NULL(iclient)) {
+ pr_err("msm_ion_client_create() return"
+ " error, val %p\n", iclient);
+ iclient = NULL;
+ }
+
+ msm_fb_resource_initialized = 1;
+ return 0;
}
-#endif
- msmfb_resume(msmfb);
-}
-#ifdef CONFIG_HTC_ONMODE_CHARGING
-static void msmfb_onchg_earlier_suspend(struct early_suspend *h)
-{
- struct msmfb_info *msmfb = container_of(h, struct msmfb_info,
- onchg_earlier_suspend);
- struct msm_panel_data *panel = msmfb->panel;
- unsigned long irq_flags = 0;
+ if (!msm_fb_resource_initialized)
+ return -EPERM;
- mutex_lock(&msmfb->panel_init_lock);
- msmfb->sleeping = SLEEPING;
- wake_up(&msmfb->frame_wq);
- spin_lock_irqsave(&msmfb->update_lock, irq_flags);
- spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
- wait_event_timeout(msmfb->frame_wq,
- msmfb->frame_requested == msmfb->frame_done, HZ/10);
-#ifndef CONFIG_MSM_MDP40
- mdp->dma(mdp, virt_to_phys(msmfb->black), 0,
- msmfb->fb->var.xres, msmfb->fb->var.yres, 0, 0,
- NULL, panel->interface_type);
- mdp->dma_wait(mdp, panel->interface_type);
-#endif
- /* turn off the panel */
- panel->blank(panel);
-}
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
-static void msmfb_onchg_suspend(struct early_suspend *h)
-{
- struct msmfb_info *msmfb = container_of(h, struct msmfb_info,
- onchg_suspend);
- struct msm_panel_data *panel = msmfb->panel;
- /* suspend the panel */
-#ifdef CONFIG_FB_MSM_OVERLAY
- atomic_set(&mdpclk_on, 0);
-#endif
- panel->suspend(panel);
- msmfb->fb_resumed = 0;
- mutex_unlock(&msmfb->panel_init_lock);
-}
+ if (!mfd)
+ return -ENODEV;
-static void msmfb_onchg_resume_handler(struct early_suspend *h)
-{
- struct msmfb_info *msmfb = container_of(h, struct msmfb_info,
- onchg_suspend);
- msmfb_resume(msmfb);
-}
-#endif
-
-static void msmfb_resume(struct msmfb_info *msmfb)
-{
- struct msm_panel_data *panel = msmfb->panel;
- unsigned long irq_flags = 0;
- if (panel->resume(panel)) {
- PR_DISP_INFO("msmfb: panel resume failed, not resuming "
- "fb\n");
- return;
- }
- spin_lock_irqsave(&msmfb->update_lock, irq_flags);
- msmfb->frame_requested = msmfb->frame_done = msmfb->update_frame = 0;
- msmfb->sleeping = WAKING;
- DLOG(SUSPEND_RESUME, "ready, waiting for full update\n");
- spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
- msmfb->fb_resumed = 1;
-
-#ifdef CONFIG_FB_MSM_OVERLAY
- atomic_set(&mdpclk_on, 1);
-#endif
-}
-#endif
-
-static int msmfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
- u32 size;
-
- if ((var->xres != info->var.xres) ||
- (var->yres != info->var.yres) ||
- (var->xoffset != info->var.xoffset) ||
- (mdp->check_output_format(mdp, var->bits_per_pixel)) ||
- (var->grayscale != info->var.grayscale))
- return -EINVAL;
-
- size = var->xres_virtual * var->yres_virtual *
- (var->bits_per_pixel >> 3);
- if (size > info->fix.smem_len)
+ if (mfd->key != MFD_KEY)
return -EINVAL;
+
+ if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+ return -ENOMEM;
+
+ vsync_cntrl.dev = mfd->fbi->dev;
+ mfd->panel_info.frame_count = 0;
+ mfd->bl_level = 0;
+ bl_scale = 1024;
+ bl_min_lvl = 255;
+#ifdef CONFIG_FB_MSM_OVERLAY
+ mfd->overlay_play_enable = 1;
+#endif
+
+ bf_supported = mdp4_overlay_borderfill_supported();
+
+ 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 int msmfb_set_par(struct fb_info *info)
+static int msm_fb_remove(struct platform_device *pdev)
{
- struct fb_var_screeninfo *var = &info->var;
- struct fb_fix_screeninfo *fix = &info->fix;
+ struct msm_fb_data_type *mfd;
- /* we only support RGB ordering for now */
- if (var->bits_per_pixel == 32 || var->bits_per_pixel == 24) {
- var->red.offset = 0;
- var->red.length = 8;
- var->green.offset = 8;
- var->green.length = 8;
- var->blue.offset = 16;
- var->blue.length = 8;
- } else if (var->bits_per_pixel == 16) {
- var->red.offset = 11;
- var->red.length = 5;
- var->green.offset = 5;
- var->green.length = 6;
+ 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;
+}
+
+#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;
+ struct msm_fb_panel_data *pdata = NULL;
+
+ if ((!mfd) || (mfd->key != MFD_KEY))
+ return 0;
+
+ pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+
+ /* 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;
+}
+
+#if (defined(CONFIG_SUSPEND) && defined(CONFIG_FB_MSM_HDMI_MSM_PANEL))
+static int msm_fb_ext_suspend(struct device *dev)
+{
+ struct msm_fb_data_type *mfd = dev_get_drvdata(dev);
+ struct msm_fb_panel_data *pdata = NULL;
+ int ret = 0;
+
+ if ((!mfd) || (mfd->key != MFD_KEY))
+ return 0;
+
+ pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+ if (mfd->panel_info.type == HDMI_PANEL ||
+ mfd->panel_info.type == DTV_PANEL) {
+ ret = msm_fb_suspend_sub(mfd);
+
+ /* Turn off the HPD circuitry */
+ if (pdata->power_ctrl) {
+ MSM_FB_INFO("%s: Turning off HPD circuitry\n",
+ __func__);
+ pdata->power_ctrl(FALSE);
+ }
+ }
+
+ return ret;
+}
+
+static int msm_fb_ext_resume(struct device *dev)
+{
+ struct msm_fb_data_type *mfd = dev_get_drvdata(dev);
+ struct msm_fb_panel_data *pdata = NULL;
+ int ret = 0;
+
+ if ((!mfd) || (mfd->key != MFD_KEY))
+ return 0;
+
+ pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+ if (mfd->panel_info.type == HDMI_PANEL ||
+ mfd->panel_info.type == DTV_PANEL) {
+ /* Turn on the HPD circuitry */
+ if (pdata->power_ctrl) {
+ pdata->power_ctrl(TRUE);
+ MSM_FB_INFO("%s: Turning on HPD circuitry\n",
+ __func__);
+ }
+
+ ret = msm_fb_resume_sub(mfd);
+ }
+
+ return ret;
+}
+#endif
+
+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,
+#if (defined(CONFIG_SUSPEND) && defined(CONFIG_FB_MSM_HDMI_MSM_PANEL))
+ .suspend = msm_fb_ext_suspend,
+ .resume = msm_fb_ext_resume,
+#endif
+};
+
+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_MDP303)
+static void memset32_io(u32 __iomem *_ptr, u32 val, size_t count)
+{
+ 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_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);
+}
+
+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
+
+static int unset_bl_level, bl_updated;
+static int bl_level_old;
+static int mdp_bl_scale_config(struct msm_fb_data_type *mfd,
+ struct mdp_bl_scale_data *data)
+{
+ int ret = 0;
+ int curr_bl = mfd->bl_level;
+ bl_scale = data->scale;
+ bl_min_lvl = data->min_lvl;
+ pr_debug("%s: update scale = %d, min_lvl = %d\n", __func__, bl_scale,
+ bl_min_lvl);
+
+ /* update current backlight to use new scaling*/
+ msm_fb_set_backlight(mfd, curr_bl);
+
+ return ret;
+}
+
+static void msm_fb_scale_bl(__u32 *bl_lvl)
+{
+ __u32 temp = *bl_lvl;
+ if (temp >= bl_min_lvl) {
+ /* bl_scale is the numerator of scaling fraction (x/1024)*/
+ temp = ((*bl_lvl) * bl_scale) / 1024;
+
+ /*if less than minimum level, use min level*/
+ if (temp < bl_min_lvl)
+ temp = bl_min_lvl;
+ }
+
+ (*bl_lvl) = temp;
+}
+
+void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl)
+{
+ struct msm_fb_panel_data *pdata;
+ __u32 temp = bkl_lvl;
+ if (!mfd->panel_power_on || !bl_updated) {
+ unset_bl_level = bkl_lvl;
+ return;
+ } else {
+ unset_bl_level = 0;
+ }
+
+ msm_fb_scale_bl(&temp);
+ pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+
+ if ((pdata) && (pdata->set_backlight)) {
+ down(&mfd->sem);
+ if (bl_level_old == temp) {
+ up(&mfd->sem);
+ return;
+ }
+ mfd->bl_level = temp;
+ pdata->set_backlight(mfd);
+ mfd->bl_level = bkl_lvl;
+ bl_level_old = temp;
+ 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;
+ bl_updated = 0;
+
+ msleep(16);
+ ret = pdata->off(mfd->pdev);
+ if (ret)
+ mfd->panel_power_on = curr_pwr_state;
+
+ mfd->op_enable = TRUE;
+ }
+ break;
+ }
+
+ return ret;
+}
+
+int calc_fb_offset(struct msm_fb_data_type *mfd, struct fb_info *fbi, int bpp)
+{
+ struct msm_panel_info *panel_info = &mfd->panel_info;
+ int remainder, yres, offset;
+
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres) & (PAGE_SIZE - 1);
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres) & (PAGE_SIZE - 1);
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
+ if (fbi->var.yoffset < yres) {
+ offset = (fbi->var.xoffset * bpp);
+ /* iBuf->buf += fbi->var.xoffset * bpp + 0 *
+ yres * fbi->fix.line_length; */
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ offset = (fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder);
+ } else {
+ offset = (fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder));
+ }
+ return offset;
+}
+
+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;
+ int remainder, remainder_mode2;
+ static int subsys_id[2] = {MSM_SUBSYSTEM_DISPLAY,
+ MSM_SUBSYSTEM_ROTATOR};
+ unsigned int flags = MSM_SUBSYSTEM_MAP_IOVA;
+
+ /*
+ * 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;
- } else
- return -1;
- mdp->set_output_format(mdp, var->bits_per_pixel);
- fix->line_length = ALIGN(var->xres, 32) * var->bits_per_pixel / 8;
+ 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);
+
+ /* Make sure all buffers can be addressed on a page boundary by an x
+ * and y offset */
+
+ remainder = (fix->line_length * panel_info->yres) & (PAGE_SIZE - 1);
+ /* PAGE_SIZE is a power of 2 */
+ if (!remainder)
+ remainder = PAGE_SIZE;
+ remainder_mode2 = (fix->line_length *
+ panel_info->mode2_yres) & (PAGE_SIZE - 1);
+ if (!remainder_mode2)
+ remainder_mode2 = PAGE_SIZE;
+
+ /*
+ * calculate smem_len based on max size of two supplied modes.
+ * Only fb0 has mem. fb1 and fb2 don't have mem.
+ */
+
+ if (!bf_supported || mfd->index == 0)
+ fix->smem_len = MAX((msm_fb_line_length(mfd->index,
+ panel_info->xres,
+ bpp) *
+ panel_info->yres + PAGE_SIZE -
+ remainder) * mfd->fb_page,
+ (msm_fb_line_length(mfd->index,
+ panel_info->mode2_xres,
+ bpp) *
+ panel_info->mode2_yres + PAGE_SIZE -
+ remainder_mode2) * mfd->fb_page);
+ else if (mfd->index == 1 || mfd->index == 2) {
+ pr_debug("%s:%d no memory is allocated for fb%d!\n",
+ __func__, __LINE__, mfd->index);
+ fix->smem_len = 0;
+ }
+
+ mfd->var_xres = panel_info->xres;
+ mfd->var_yres = panel_info->yres;
+ mfd->var_frame_rate = panel_info->frame_rate;
+
+ 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) {
+ if (panel_info->type == MDDI_PANEL && panel_info->mddi.is_type1)
+ var->reserved[4] = panel_info->lcd.refx100 / (100 * 2);
+ else
+ var->reserved[4] = panel_info->lcd.refx100 / 100;
+ } else {
+ if (panel_info->type == MIPI_VIDEO_PANEL) {
+ var->reserved[4] = panel_info->mipi.frame_rate;
+ } 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));
+ }
+ }
+ pr_debug("reserved[4] %u\n", var->reserved[4]);
+
+ /*
+ * id field for fb app
+ */
+ id = (int *)&mfd->panel;
+
+ switch (mdp_rev) {
+ case MDP_REV_20:
+ snprintf(fix->id, sizeof(fix->id), "msmfb20_%x", (__u32) *id);
+ break;
+ case MDP_REV_22:
+ snprintf(fix->id, sizeof(fix->id), "msmfb22_%x", (__u32) *id);
+ break;
+ case MDP_REV_30:
+ snprintf(fix->id, sizeof(fix->id), "msmfb30_%x", (__u32) *id);
+ break;
+ case MDP_REV_303:
+ snprintf(fix->id, sizeof(fix->id), "msmfb303_%x", (__u32) *id);
+ break;
+ case MDP_REV_31:
+ snprintf(fix->id, sizeof(fix->id), "msmfb31_%x", (__u32) *id);
+ break;
+ case MDP_REV_40:
+ snprintf(fix->id, sizeof(fix->id), "msmfb40_%x", (__u32) *id);
+ break;
+ case MDP_REV_41:
+ snprintf(fix->id, sizeof(fix->id), "msmfb41_%x", (__u32) *id);
+ break;
+ case MDP_REV_42:
+ snprintf(fix->id, sizeof(fix->id), "msmfb42_%x", (__u32) *id);
+ break;
+ case MDP_REV_43:
+ snprintf(fix->id, sizeof(fix->id), "msmfb43_%x", (__u32) *id);
+ break;
+ case MDP_REV_44:
+ snprintf(fix->id, sizeof(fix->id), "msmfb44_%x", (__u32) *id);
+ break;
+ default:
+ snprintf(fix->id, sizeof(fix->id), "msmfb0_%x", (__u32) *id);
+ break;
+ }
+
+ 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 (!bf_supported || mfd->index == 0)
+ if (fbram_size < fix->smem_len) {
+ pr_err("error: no more framebuffer memory!\n");
+ return -ENOMEM;
+ }
+
+ fbi->screen_base = fbram;
+ fbi->fix.smem_start = (unsigned long)fbram_phys;
+
+ mfd->map_buffer = msm_subsystem_map_buffer(
+ fbi->fix.smem_start, fbi->fix.smem_len,
+ flags, subsys_id, 2);
+ if (mfd->map_buffer) {
+ pr_debug("%s(): buf 0x%lx, mfd->map_buffer->iova[0] 0x%lx\n"
+ "mfd->map_buffer->iova[1] 0x%lx", __func__,
+ fbi->fix.smem_start, mfd->map_buffer->iova[0],
+ mfd->map_buffer->iova[1]);
+ }
+ if (!bf_supported || mfd->index == 0)
+ 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
+ /* Flip buffer */
+ if (!load_565rle_image(INIT_IMAGE_FILE, bf_supported))
+ ;
+#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 (info->node == 0 && !(mfd->cont_splash_done)) { /* primary */
+ mfd->ref_cnt++;
+ return 0;
+ }
+
+ if (!mfd->ref_cnt) {
+ if (!bf_supported ||
+ (info->node != 1 && info->node != 2))
+ mdp_set_dma_pan_info(info, NULL, TRUE);
+ else
+ pr_debug("%s:%d no mdp_set_dma_pan_info %d\n",
+ __func__, __LINE__, info->node);
+
+ 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;
}
-int msmfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+static int msm_fb_release(struct fb_info *info, int user)
{
- struct msmfb_info *msmfb = info->par;
- struct msm_panel_data *panel = msmfb->panel;
+ 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;
+}
+
+DECLARE_MUTEX(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;
+ struct msm_fb_panel_data *pdata;
+
+ /*
+ * If framebuffer is 2, io pen display is not allowed.
+ */
+ if (bf_supported && info->node == 2) {
+ pr_err("%s: no pan display for fb%d!",
+ __func__, info->node);
+ return -EPERM;
+ }
+
+ if (info->node != 0 || mfd->cont_splash_done) /* primary */
+ 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 ((panel->caps & MSMFB_CAP_PARTIAL_UPDATES) &&
- (var->reserved[0] == 0x54445055)) {
-#if 0
- PR_DISP_INFO("pan frame %d-%d, rect %d %d %d %d\n",
- msmfb->frame_requested, msmfb->frame_done,
- var->reserved[1] & 0xffff,
- var->reserved[1] >> 16, var->reserved[2] & 0xffff,
- var->reserved[2] >> 16);
-#endif
- 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);
+ 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);
+
+ if (info->node == 0 && !(mfd->cont_splash_done)) { /* primary */
+ mdp_set_dma_pan_info(info, NULL, TRUE);
+ if (msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable)) {
+ pr_err("%s: can't turn on display!\n", __func__);
+ return -EINVAL;
+ }
+ }
+
+ mdp_set_dma_pan_info(info, dirtyPtr,
+ (var->activate == FB_ACTIVATE_VBL));
+ mdp_dma_pan_update(info);
+ up(&msm_fb_pan_sem);
+
+ if (unset_bl_level && !bl_updated) {
+ pdata = (struct msm_fb_panel_data *)mfd->pdev->
+ dev.platform_data;
+ if ((pdata) && (pdata->set_backlight)) {
+ down(&mfd->sem);
+ mfd->bl_level = unset_bl_level;
+ pdata->set_backlight(mfd);
+ bl_level_old = unset_bl_level;
+ up(&mfd->sem);
+ bl_updated = 1;
+ }
+ }
+
+ ++mfd->panel_info.frame_count;
return 0;
}
-static void msmfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+static int msm_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
- cfb_fillrect(p, rect);
- msmfb_update(p, rect->dx, rect->dy, rect->dx + rect->width,
- rect->dy + rect->height);
+ 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 (!bf_supported ||
+ (info->node != 1 && info->node != 2))
+ 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 void msmfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+int msm_fb_check_frame_rate(struct msm_fb_data_type *mfd
+ , struct fb_info *info)
{
- cfb_copyarea(p, area);
- msmfb_update(p, area->dx, area->dy, area->dx + area->width,
- area->dy + area->height);
+ int panel_height, panel_width, var_frame_rate, fps_mod;
+ struct fb_var_screeninfo *var = &info->var;
+ fps_mod = 0;
+ if ((mfd->panel_info.type == DTV_PANEL) ||
+ (mfd->panel_info.type == HDMI_PANEL)) {
+ panel_height = var->yres + var->upper_margin +
+ var->vsync_len + var->lower_margin;
+ panel_width = var->xres + var->right_margin +
+ var->hsync_len + var->left_margin;
+ var_frame_rate = ((var->pixclock)/(panel_height * panel_width));
+ if (mfd->var_frame_rate != var_frame_rate) {
+ fps_mod = 1;
+ mfd->var_frame_rate = var_frame_rate;
+ }
+ }
+ return fps_mod;
}
-static void msmfb_imageblit(struct fb_info *p, const struct fb_image *image)
+static int msm_fb_set_par(struct fb_info *info)
{
- cfb_imageblit(p, image);
- msmfb_update(p, image->dx, image->dy, image->dx + image->width,
- image->dy + image->height);
+ 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) ||
+ (msm_fb_check_frame_rate(mfd, info))))) {
+ 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 msmfb_blit(struct fb_info *info,
- void __user *p)
+static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd)
{
- struct mdp_blit_req req;
- struct mdp_blit_req_list req_list;
- int i;
- int ret, sem_owned;
+ if (mfd->hw_refresh)
+ return -EPERM;
- if (copy_from_user(&req_list, p, sizeof(req_list)))
- return -EFAULT;
+ if (mfd->sw_currently_refreshing) {
+ down(&mfd->sem);
+ mfd->sw_currently_refreshing = FALSE;
+ up(&mfd->sem);
- 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;
- sem_owned = overlay_semaphore_lock();
- ret = mdp->blit(mdp, info, &req);
+ /* wait until the refresher finishes the last job */
+ wait_for_completion_killable(&mfd->refresher_comp);
+ }
- if (sem_owned == 0)
- overlay_semaphore_unlock();
+ 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;
+ if (bf_supported &&
+ (info->node == 1 || info->node == 2)) {
+ pr_err("%s: no pan display for fb%d.",
+ __func__, info->node);
+ return -EPERM;
+ }
+ /* 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;
}
+
+static int msmfb_vsync_ctrl(struct fb_info *info, void __user *argp)
+{
+ int enable, ret;
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ ret = copy_from_user(&enable, argp, sizeof(enable));
+ if (ret) {
+ pr_err("%s:msmfb_overlay_vsync ioctl failed", __func__);
+ return ret;
+ }
+
+ if (mfd->vsync_ctrl)
+ mfd->vsync_ctrl(enable);
+ else {
+ pr_err("%s: Vsync IOCTL not supported", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
#ifdef CONFIG_FB_MSM_OVERLAY
static int msmfb_overlay_get(struct fb_info *info, void __user *p)
{
@@ -752,15 +2778,14 @@
if (copy_from_user(&req, p, sizeof(req)))
return -EFAULT;
- ret = mdp->overlay_get(mdp, info, &req);
-
+ ret = mdp4_overlay_get(info, &req);
if (ret) {
- PR_DISP_ERR("%s: ioctl failed \n",
+ printk(KERN_ERR "%s: ioctl failed \n",
__func__);
return ret;
}
if (copy_to_user(p, &req, sizeof(req))) {
- PR_DISP_ERR("%s: copy2user failed \n",
+ printk(KERN_ERR "%s: copy2user failed \n",
__func__);
return -EFAULT;
}
@@ -771,31 +2796,20 @@
static int msmfb_overlay_set(struct fb_info *info, void __user *p)
{
struct mdp_overlay req;
- int ret, sem_owned;
+ int ret;
if (copy_from_user(&req, p, sizeof(req)))
return -EFAULT;
- PR_DISP_INFO("%s(%d) dst rect info w=%d h=%d x=%d y=%d rotator=%d\n", __func__, __LINE__, req.dst_rect.w, req.dst_rect.h, req.dst_rect.x, req.dst_rect.y, req.user_data[0]);
-
- sem_owned = overlay_semaphore_lock();
- /* Used the following mutex to make sure that overlay play/set will not do at the same time */
- /* It assume overlay play can complete in fixed time */
- mutex_lock(&overlay_ioctl_mutex);
- ret = mdp->overlay_set(mdp, info, &req);
- mutex_unlock(&overlay_ioctl_mutex);
-
- if (sem_owned == 0)
- overlay_semaphore_unlock();
-
+ ret = mdp4_overlay_set(info, &req);
if (ret) {
- PR_DISP_ERR("%s:ioctl failed \n",
- __func__);
+ printk(KERN_ERR "%s: ioctl failed, rc=%d\n",
+ __func__, ret);
return ret;
}
if (copy_to_user(p, &req, sizeof(req))) {
- PR_DISP_ERR("%s: copy2user failed \n",
+ printk(KERN_ERR "%s: copy2user failed \n",
__func__);
return -EFAULT;
}
@@ -805,21 +2819,50 @@
static int msmfb_overlay_unset(struct fb_info *info, unsigned long *argp)
{
- int ret, ndx;
+ int ret, ndx;
ret = copy_from_user(&ndx, argp, sizeof(ndx));
if (ret) {
- PR_DISP_ERR("%s:msmfb_overlay_unset ioctl failed \n",
+ printk(KERN_ERR "%s:msmfb_overlay_unset ioctl failed \n",
__func__);
return ret;
}
- /* Used the following mutex to make sure that overlay play/set/unset will not do at the same time */
- /* Otherwise we met the mdp4_overlay_play()->mdp4_overlay_vg_setup() which try to access the pipe free
- in mdp4_overlay_unset()->mdp4_overlay_*/
- mutex_lock(&overlay_ioctl_mutex);
- ret = mdp->overlay_unset(mdp, info, ndx);
- mutex_unlock(&overlay_ioctl_mutex);
+ return mdp4_overlay_unset(info, ndx);
+}
+
+static int msmfb_overlay_vsync_ctrl(struct fb_info *info, void __user *argp)
+{
+ int ret;
+ int enable;
+
+ ret = copy_from_user(&enable, argp, sizeof(enable));
+ if (ret) {
+ pr_err("%s:msmfb_overlay_vsync ioctl failed", __func__);
+ return ret;
+ }
+
+ ret = mdp4_overlay_vsync_ctrl(info, enable);
+
+ return ret;
+}
+
+static int msmfb_overlay_play_wait(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;
+
+ if (mfd->overlay_play_enable == 0) /* nothing to do */
+ return 0;
+
+ ret = copy_from_user(&req, argp, sizeof(req));
+ if (ret) {
+ pr_err("%s:msmfb_overlay_wait ioctl failed", __func__);
+ return ret;
+ }
+
+ ret = mdp4_overlay_play_wait(info, &req);
return ret;
}
@@ -828,692 +2871,960 @@
{
int ret;
struct msmfb_overlay_data req;
- struct file *p_src_file = 0;
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct msm_fb_panel_data *pdata;
+
+ if (mfd->overlay_play_enable == 0) /* nothing to do */
+ return 0;
ret = copy_from_user(&req, argp, sizeof(req));
if (ret) {
- PR_DISP_ERR("%s:msmfb_overlay_play ioctl failed \n",
+ printk(KERN_ERR "%s:msmfb_overlay_play ioctl failed \n",
__func__);
return ret;
}
- /* Used the following mutex to make sure that overlay play/set will not do at the same time */
- mutex_lock(&overlay_ioctl_mutex);
- ret = mdp->overlay_play(mdp, info, &req, &p_src_file);
- mutex_unlock(&overlay_ioctl_mutex);
+ 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);
- if (p_src_file)
- put_pmem_file(p_src_file);
+ 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);
+
+ if (info->node == 0 && !(mfd->cont_splash_done)) { /* primary */
+ mdp_set_dma_pan_info(info, NULL, TRUE);
+ if (msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable)) {
+ pr_err("%s: can't turn on display!\n", __func__);
+ return -EINVAL;
+ }
+ }
+
+ ret = mdp4_overlay_play(info, &req);
+
+ if (unset_bl_level && !bl_updated) {
+ pdata = (struct msm_fb_panel_data *)mfd->pdev->
+ dev.platform_data;
+ if ((pdata) && (pdata->set_backlight)) {
+ down(&mfd->sem);
+ mfd->bl_level = unset_bl_level;
+ pdata->set_backlight(mfd);
+ bl_level_old = unset_bl_level;
+ up(&mfd->sem);
+ bl_updated = 1;
+ }
+ }
return ret;
}
-#ifdef CONFIG_FB_MSM_WRITE_BACK
+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;
+}
+
static int msmfb_overlay_blt(struct fb_info *info, unsigned long *argp)
{
int ret;
struct msmfb_overlay_blt req;
- struct file *p_src_file = 0;
+
ret = copy_from_user(&req, argp, sizeof(req));
if (ret) {
- PR_DISP_ERR("%s:msmfb_overlay_blt ioctl failed\n",
- __func__);
+ pr_err("%s: failed\n", __func__);
return ret;
}
- ret = mdp4_overlay_blt(mdp, info, &req, &p_src_file);
-
- if (p_src_file)
- put_pmem_file(p_src_file);
+ ret = mdp4_overlay_blt(info, &req);
return ret;
}
+
+#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
+static int msmfb_overlay_ioctl_writeback_init(struct fb_info *info)
+{
+ return mdp4_writeback_init(info);
+}
+static int msmfb_overlay_ioctl_writeback_start(
+ struct fb_info *info)
+{
+ int ret = 0;
+ ret = mdp4_writeback_start(info);
+ if (ret)
+ goto error;
+error:
+ if (ret)
+ pr_err("%s:msmfb_writeback_start "
+ " ioctl failed\n", __func__);
+ return ret;
+}
+
+static int msmfb_overlay_ioctl_writeback_stop(
+ struct fb_info *info)
+{
+ int ret = 0;
+ ret = mdp4_writeback_stop(info);
+ if (ret)
+ goto error;
+
+error:
+ if (ret)
+ pr_err("%s:msmfb_writeback_stop ioctl failed\n",
+ __func__);
+ return ret;
+}
+
+static int msmfb_overlay_ioctl_writeback_queue_buffer(
+ struct fb_info *info, unsigned long *argp)
+{
+ int ret = 0;
+ struct msmfb_data data;
+
+ ret = copy_from_user(&data, argp, sizeof(data));
+ if (ret)
+ goto error;
+
+ ret = mdp4_writeback_queue_buffer(info, &data);
+ if (ret)
+ goto error;
+
+error:
+ if (ret)
+ pr_err("%s:msmfb_writeback_queue_buffer ioctl failed\n",
+ __func__);
+ return ret;
+}
+
+static int msmfb_overlay_ioctl_writeback_dequeue_buffer(
+ struct fb_info *info, unsigned long *argp)
+{
+ int ret = 0;
+ struct msmfb_data data;
+
+ ret = copy_from_user(&data, argp, sizeof(data));
+ if (ret)
+ goto error;
+
+ ret = mdp4_writeback_dequeue_buffer(info, &data);
+ if (ret)
+ goto error;
+
+ ret = copy_to_user(argp, &data, sizeof(data));
+ if (ret)
+ goto error;
+
+error:
+ if (ret)
+ pr_err("%s:msmfb_writeback_dequeue_buffer ioctl failed\n",
+ __func__);
+ return ret;
+}
+static int msmfb_overlay_ioctl_writeback_terminate(struct fb_info *info)
+{
+ return mdp4_writeback_terminate(info);
+}
+
+#else
+static int msmfb_overlay_ioctl_writeback_init(struct fb_info *info)
+{
+ return -ENOTSUPP;
+}
+static int msmfb_overlay_ioctl_writeback_start(
+ struct fb_info *info)
+{
+ return -ENOTSUPP;
+}
+
+static int msmfb_overlay_ioctl_writeback_stop(
+ struct fb_info *info)
+{
+ return -ENOTSUPP;
+}
+
+static int msmfb_overlay_ioctl_writeback_queue_buffer(
+ struct fb_info *info, unsigned long *argp)
+{
+ return -ENOTSUPP;
+}
+
+static int msmfb_overlay_ioctl_writeback_dequeue_buffer(
+ struct fb_info *info, unsigned long *argp)
+{
+ return -ENOTSUPP;
+}
+static int msmfb_overlay_ioctl_writeback_terminate(struct fb_info *info)
+{
+ return -ENOTSUPP;
+}
#endif
-static int msmfb_overlay_change_z_order_vg_pipes(struct fb_info *info, unsigned long *argp)
+static int msmfb_overlay_3d_sbys(struct fb_info *info, unsigned long *argp)
{
int ret;
+ struct msmfb_overlay_3d req;
- ret = mdp4_overlay_change_z_order_vg_pipes(info);
-
+ ret = copy_from_user(&req, argp, sizeof(req));
if (ret) {
- PR_DISP_ERR("%s:msmfb_overlay_change_z_order_vg_pipes ioctl failed \n",
+ pr_err("%s:msmfb_overlay_3d_ctrl ioctl failed\n",
__func__);
return ret;
}
+ ret = mdp4_overlay_3d_sbys(info, &req);
return ret;
}
+
+static int msmfb_mixer_info(struct fb_info *info, unsigned long *argp)
+{
+ int ret, cnt;
+ struct msmfb_mixer_info_req req;
+
+ ret = copy_from_user(&req, argp, sizeof(req));
+ if (ret) {
+ pr_err("%s: failed\n", __func__);
+ return ret;
+ }
+
+ cnt = mdp4_mixer_info(req.mixer_num, req.info);
+ req.cnt = cnt;
+ ret = copy_to_user(argp, &req, sizeof(req));
+ if (ret)
+ pr_err("%s:msmfb_overlay_blt_off ioctl failed\n",
+ __func__);
+
+ return cnt;
+}
+
#endif
DECLARE_MUTEX(msm_fb_ioctl_ppp_sem);
-#if defined(CONFIG_FB_MSM_MDP_ABL)
DEFINE_MUTEX(msm_fb_ioctl_lut_sem);
-DEFINE_MUTEX(msm_fb_ioctl_hist_sem);
-static int msmfb_lut_update(struct fb_info *info, void __user *p)
+/* Set color conversion matrix from user space */
+
+#ifndef CONFIG_FB_MSM_MDP40
+static void msmfb_set_color_conv(struct mdp_ccs *p)
{
- struct fb_cmap cmap;
- int ret;
-
- if (copy_from_user(&cmap, p, sizeof(cmap)))
- return -EFAULT;
-
- mutex_lock(&msm_fb_ioctl_lut_sem);
-
- ret = mdp->lut_update(mdp, info, &cmap);
-
- mutex_unlock(&msm_fb_ioctl_lut_sem);
-
- if (ret) {
- PR_DISP_ERR("%s: ioctl failed \n",
- __func__);
- return ret;
- }
-
- return 0;
-}
-
-static int msmfb_do_histogram(struct fb_info *info, void __user *p)
-{
- struct mdp_histogram hist;
- struct mdp_histogram out;
- int ret;
-
- if (copy_from_user(&hist, p, sizeof(hist)))
- return -EFAULT;
-
- mutex_lock(&msm_fb_ioctl_hist_sem);
- ret = mdp->do_histogram(mdp, &hist, &out);
- mutex_unlock(&msm_fb_ioctl_hist_sem);
-
- if (ret) {
- PR_DISP_ERR("%s: ioctl failed \n",
- __func__);
- return ret;
- }
-
- if (hist.r) {
- ret = copy_to_user(hist.r, out.r, hist.bin_cnt * 4);
- if (ret)
- goto hist_err;
- }
- if (hist.g) {
- ret = copy_to_user(hist.g, out.g, hist.bin_cnt * 4);
- if (ret)
- goto hist_err;
- }
- if (hist.b) {
- ret = copy_to_user(hist.b, out.b, hist.bin_cnt * 4);
- if (ret)
- goto hist_err;
- }
- return 0;
-
-hist_err:
- PR_DISP_ERR("%s: invalid hist buffer\n", __func__);
- return ret;
-
-}
-
-static int msmfb_get_gamma_curvy(struct fb_info *info, void __user *p)
-{
- struct gamma_curvy gc;
- int ret;
-
- if (!mdp->get_gamma_curvy) {
- PR_DISP_INFO("error to get get_gamma_curvy functoin\n");
- return -EFAULT;
- }
-
- if (copy_from_user(&gc, p, sizeof(struct gamma_curvy)))
- return -EFAULT;
-
- ret = mdp->get_gamma_curvy(mdp, &gc);
-
- if (ret) {
- PR_DISP_ERR("%s: ioctl failed \n",
- __func__);
- return ret;
- }
- ret = copy_to_user(p, &gc, sizeof(struct gamma_curvy));
-
- return ret;
-}
-#endif
-
-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 = 0;
-#if PRINT_BLIT_TIME
- ktime_t t1, t2;
-#endif
-
-#if defined(CONFIG_USB_FUNCTION_PROJECTOR) || defined(CONFIG_USB_ANDROID_PROJECTOR)
int i;
- struct msmfb_usb_projector_info tmp_info;
- static int pmem_mapped = 0;
+
+ 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);
+ }
+}
+#else
+static void msmfb_set_color_conv(struct mdp_csc *p)
+{
+ mdp4_vg_csc_update(p);
+}
#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 msmfb_handle_pp_ioctl(struct msm_fb_data_type *mfd,
+ struct msmfb_mdp_pp *pp_ptr)
+{
+ int ret = -1;
+
+ if (!pp_ptr)
+ return ret;
+
+ switch (pp_ptr->op) {
+#ifdef CONFIG_FB_MSM_MDP40
+ case mdp_op_csc_cfg:
+ ret = mdp4_csc_config(&(pp_ptr->data.csc_cfg_data));
+ break;
+
+ case mdp_op_pcc_cfg:
+ ret = mdp4_pcc_cfg(&(pp_ptr->data.pcc_cfg_data));
+ break;
+
+ case mdp_op_lut_cfg:
+ switch (pp_ptr->data.lut_cfg_data.lut_type) {
+ case mdp_lut_igc:
+ ret = mdp4_igc_lut_config(
+ (struct mdp_igc_lut_data *)
+ &pp_ptr->data.lut_cfg_data.data);
+ break;
+
+ case mdp_lut_pgc:
+ ret = mdp4_argc_cfg(
+ &pp_ptr->data.lut_cfg_data.data.pgc_lut_data);
+ break;
+
+ case mdp_lut_hist:
+ ret = mdp_hist_lut_config(
+ (struct mdp_hist_lut_data *)
+ &pp_ptr->data.lut_cfg_data.data);
+ break;
+
+ default:
+ break;
+ }
+ break;
+#endif
+ case mdp_bl_scale_cfg:
+ ret = mdp_bl_scale_config(mfd, (struct mdp_bl_scale_data *)
+ &pp_ptr->data.bl_scale_data);
+ break;
+
+ default:
+ pr_warn("Unsupported request to MDP_PP IOCTL.\n");
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+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_data hist;
+ struct mdp_histogram_start_req hist_req;
+ uint32_t block;
+#ifndef CONFIG_FB_MSM_MDP40
+ struct mdp_ccs ccs_matrix;
+#else
+ struct mdp_csc csc_matrix;
+#endif
+ struct mdp_page_protection fb_page_protection;
+ struct msmfb_mdp_pp mdp_pp;
+ int ret = 0;
+
switch (cmd) {
- case MSMFB_GRP_DISP:
- mdp->set_grp_disp(mdp, arg);
- break;
-#ifdef CONFIG_FB_MSM_WRITE_BACK
- case MSMFB_OVERLAY_BLT:
- down(&msm_fb_ioctl_ppp_sem);
- ret = msmfb_overlay_blt(p, argp);
- up(&msm_fb_ioctl_ppp_sem);
- break;
-#endif
- case MSMFB_BLIT:
-#if PRINT_BLIT_TIME
- t1 = ktime_get();
-#endif
- down(&msm_fb_ioctl_ppp_sem);
- ret = msmfb_blit(p, argp);
- up(&msm_fb_ioctl_ppp_sem);
- if (ret)
- return ret;
-#if PRINT_BLIT_TIME
- t2 = ktime_get();
- DLOG(BLIT_TIME, "total %lld\n",
- ktime_to_ns(t2) - ktime_to_ns(t1));
-#endif
- break;
#ifdef CONFIG_FB_MSM_OVERLAY
case MSMFB_OVERLAY_GET:
- if (!atomic_read(&mdpclk_on)) {
- PR_DISP_WARN("MSMFB_OVERLAY_GET during suspend\n");
- ret = -EINVAL;
- } else {
- down(&msm_fb_ioctl_ppp_sem);
- ret = msmfb_overlay_get(p, argp);
- up(&msm_fb_ioctl_ppp_sem);
- }
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_overlay_get(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
break;
case MSMFB_OVERLAY_SET:
- if (!atomic_read(&mdpclk_on)) {
- PR_DISP_WARN("MSMFB_OVERLAY_SET during suspend\n");
- ret = -EINVAL;
- } else
- ret = msmfb_overlay_set(p, argp);
- PR_DISP_INFO("MSMFB_OVERLAY_SET ret=%d\n", ret);
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_overlay_set(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
break;
case MSMFB_OVERLAY_UNSET:
- ret = msmfb_overlay_unset(p, argp);
- PR_DISP_INFO("MSMFB_OVERLAY_UNSET ret=%d\n", ret);
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_overlay_unset(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
break;
case MSMFB_OVERLAY_PLAY:
- if (!atomic_read(&mdpclk_on)) {
- PR_DISP_ERR("MSMFB_OVERLAY_PLAY during suspend\n");
- ret = -EINVAL;
- } else
- ret = msmfb_overlay_play(p, argp);
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_overlay_play(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
break;
- case MSMFB_OVERLAY_CHANGE_ZORDER_VG_PIPES:
- if (!atomic_read(&mdpclk_on)) {
- PR_DISP_ERR("MSMFB_OVERLAY_CHANGE_ZORDER_VG_PIPES during suspend\n");
- ret = -EINVAL;
- } else {
- down(&msm_fb_ioctl_ppp_sem);
- ret = msmfb_overlay_change_z_order_vg_pipes(p, argp);
- up(&msm_fb_ioctl_ppp_sem);
- }
+ 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_PLAY_WAIT:
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_overlay_play_wait(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_3D:
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_overlay_3d_sbys(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
+ break;
+ case MSMFB_MIXER_INFO:
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_mixer_info(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
+ break;
+ case MSMFB_WRITEBACK_INIT:
+ ret = msmfb_overlay_ioctl_writeback_init(info);
+ break;
+ case MSMFB_WRITEBACK_START:
+ ret = msmfb_overlay_ioctl_writeback_start(
+ info);
+ break;
+ case MSMFB_WRITEBACK_STOP:
+ ret = msmfb_overlay_ioctl_writeback_stop(
+ info);
+ break;
+ case MSMFB_WRITEBACK_QUEUE_BUFFER:
+ ret = msmfb_overlay_ioctl_writeback_queue_buffer(
+ info, argp);
+ break;
+ case MSMFB_WRITEBACK_DEQUEUE_BUFFER:
+ ret = msmfb_overlay_ioctl_writeback_dequeue_buffer(
+ info, argp);
+ break;
+ case MSMFB_WRITEBACK_TERMINATE:
+ ret = msmfb_overlay_ioctl_writeback_terminate(info);
break;
#endif
-#if defined(CONFIG_FB_MSM_MDP_ABL)
+ case MSMFB_VSYNC_CTRL:
+ case MSMFB_OVERLAY_VSYNC_CTRL:
+ down(&msm_fb_ioctl_ppp_sem);
+ if (mdp_rev >= MDP_REV_40)
+ ret = msmfb_overlay_vsync_ctrl(info, argp);
+ else
+ ret = msmfb_vsync_ctrl(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
+ break;
+ 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 = copy_from_user(&csc_matrix, argp, sizeof(csc_matrix));
+ if (ret) {
+ pr_err("%s:MSMFB_SET_CSC_MATRIX ioctl failed\n",
+ __func__);
+ return ret;
+ }
+ down(&msm_fb_ioctl_ppp_sem);
+ msmfb_set_color_conv(&csc_matrix);
+ up(&msm_fb_ioctl_ppp_sem);
+
+#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 = msmfb_lut_update(p, argp);
+ 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:
- ret = msmfb_do_histogram(p, argp);
+ if (!mfd->panel_power_on)
+ return -EPERM;
+
+ if (!mfd->do_histogram)
+ return -ENODEV;
+
+ ret = copy_from_user(&hist, argp, sizeof(hist));
+ if (ret)
+ return ret;
+
+ ret = mfd->do_histogram(info, &hist);
break;
case MSMFB_HISTOGRAM_START:
- ret = mdp->start_histogram(mdp, p);
- break;
+ if (!mfd->panel_power_on)
+ return -EPERM;
+
+ if (!mfd->do_histogram)
+ return -ENODEV;
+
+ ret = copy_from_user(&hist_req, argp, sizeof(hist_req));
+ if (ret)
+ return ret;
+
+ ret = mdp_histogram_start(&hist_req);
+ break;
case MSMFB_HISTOGRAM_STOP:
- ret = mdp->stop_histogram(mdp, p);
- break;
+ if (!mfd->do_histogram)
+ return -ENODEV;
- case MSMFB_GET_GAMMA_CURVY:
- ret = msmfb_get_gamma_curvy(p, argp);
- break;
-#endif
-#if defined(CONFIG_USB_FUNCTION_PROJECTOR) || defined(CONFIG_USB_ANDROID_PROJECTOR)
- case MSMFB_GET_USB_PROJECTOR_INFO:
- ret = copy_to_user(argp, &usb_pjt_info, sizeof(usb_pjt_info));
+ ret = copy_from_user(&block, argp, sizeof(int));
if (ret)
return ret;
+
+ ret = mdp_histogram_stop(info, block);
break;
- case MSMFB_SET_USB_PROJECTOR_INFO:
- ret = copy_from_user(&tmp_info, argp, sizeof(tmp_info));
- usb_pjt_info.latest_offset = tmp_info.latest_offset;
- if (!usb_pjt_info.latest_offset) {
- /* pmem in user space has been freed */
- for (i=0; i<NUM_ALLOC; i++) {
- pmem_mapped = 0;
- phys_addr[i] = 0;
- virt_addr[i] = 0;
- }
- } else {
- if (pmem_mapped < NUM_ALLOC) {
- for (i=0; i<NUM_ALLOC; i++) {
- if (phys_addr[i] == (void *)usb_pjt_info.latest_offset)
- break;
- if (!phys_addr[i]) {
- unsigned long pmem_vbase;
- unsigned long pmem_base;
- unsigned long pmem_size;
- struct file *map_file;
- phys_addr[i] = (void *)usb_pjt_info.latest_offset;
- /* call get_pmem_file only to get information */
- get_pmem_file((unsigned int)phys_addr[i], &pmem_base, &pmem_vbase, &pmem_size, &map_file);
- printk(KERN_ERR "%s: phys %p, virt %p\n",
- __func__, (void *)pmem_base, (void *)pmem_vbase);
- virt_addr[i] = (void*)pmem_vbase;
- pmem_mapped++;
- put_pmem_file(map_file);
- 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;
+
+ case MSMFB_MDP_PP:
+ ret = copy_from_user(&mdp_pp, argp, sizeof(mdp_pp));
if (ret)
return ret;
+
+ ret = msmfb_handle_pp_ioctl(mfd, &mdp_pp);
break;
-#endif
+
default:
- PR_DISP_INFO("msmfb unknown ioctl: %d\n", cmd);
- return -EINVAL;
+ MSM_FB_INFO("MDP: unknown ioctl (cmd=%x) received!\n", cmd);
+ ret = -EINVAL;
+ break;
}
+
return ret;
}
-static struct fb_ops msmfb_ops = {
- .owner = THIS_MODULE,
- .fb_open = msmfb_open,
- .fb_release = msmfb_release,
- .fb_check_var = msmfb_check_var,
- .fb_set_par = msmfb_set_par,
- .fb_pan_display = msmfb_pan_display,
- .fb_fillrect = msmfb_fillrect,
- .fb_copyarea = msmfb_copyarea,
- .fb_imageblit = msmfb_imageblit,
- .fb_ioctl = msmfb_ioctl,
-};
-
-static unsigned PP[16];
-
-
-#if MSMFB_DEBUG
-static ssize_t debug_open(struct inode *inode, struct file *file)
+static int msm_fb_register_driver(void)
{
- file->private_data = inode->i_private;
- return 0;
+ return platform_driver_register(&msm_fb_driver);
}
-
-static ssize_t debug_read(struct file *file, char __user *buf, size_t count,
- loff_t *ppos)
+#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
+struct fb_info *msm_fb_get_writeback_fb(void)
{
- const int debug_bufmax = 4096;
- static char buffer[4096];
- int n = 0;
- struct msmfb_info *msmfb = (struct msmfb_info *)file->private_data;
- unsigned long irq_flags = 0;
+ int c = 0;
+ for (c = 0; c < fbi_list_index; ++c) {
+ struct msm_fb_data_type *mfd;
+ mfd = (struct msm_fb_data_type *)fbi_list[c]->par;
+ if (mfd->panel.type == WRITEBACK_PANEL)
+ return fbi_list[c];
+ }
- spin_lock_irqsave(&msmfb->update_lock, irq_flags);
- n = scnprintf(buffer, debug_bufmax, "yoffset %d\n", msmfb->yoffset);
- n += scnprintf(buffer + n, debug_bufmax, "frame_requested %d\n",
- msmfb->frame_requested);
- n += scnprintf(buffer + n, debug_bufmax, "frame_done %d\n",
- msmfb->frame_done);
- n += scnprintf(buffer + n, debug_bufmax, "sleeping %d\n",
- msmfb->sleeping);
- n += scnprintf(buffer + n, debug_bufmax, "update_frame %d\n",
- msmfb->update_frame);
- spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
- n++;
- buffer[n] = 0;
- return simple_read_from_buffer(buf, count, ppos, buffer, n);
+ return NULL;
}
+EXPORT_SYMBOL(msm_fb_get_writeback_fb);
-static struct file_operations debug_fops = {
- .read = debug_read,
- .open = debug_open,
-};
-#endif
-
-#define BITS_PER_PIXEL_DEF 32
-
-static void setup_fb_info(struct msmfb_info *msmfb)
+int msm_fb_writeback_start(struct fb_info *info)
{
- struct fb_info *fb_info = msmfb->fb;
- int r;
-
- /* 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 = ALIGN(msmfb->xres, 32) * BITS_PER_PIXEL_DEF/8;
-
- 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 = ALIGN(msmfb->xres, 32);
- fb_info->var.yres_virtual = msmfb->yres * 2;
- fb_info->var.bits_per_pixel = BITS_PER_PIXEL_DEF;
- 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. */
-
- /* FIX ME: every panel support partial update?
- 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);
- }
-
- 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;
-
- mdp->set_output_format(mdp, fb_info->var.bits_per_pixel);
- mdp->set_panel_size(mdp, msmfb->xres, msmfb->yres);
-
- r = fb_alloc_cmap(&fb_info->cmap, 16, 0);
- fb_info->pseudo_palette = PP;
-
- PP[0] = 0;
- for (r = 1; r < 16; r++)
- PP[r] = 0xffffffff;
-
- /* Jay add, 7/1/09' */
-#if (defined(CONFIG_USB_FUNCTION_PROJECTOR) || defined(CONFIG_USB_ANDROID_PROJECTOR))
- msm_fb_data.xres = ALIGN(msmfb->xres, 32);
- msm_fb_data.yres = msmfb->yres;
- PR_DISP_INFO("setup_fb_info msmfb->xres %d, msmfb->yres %d\n",
- msmfb->xres, msmfb->yres);
-#endif
+ return mdp4_writeback_start(info);
}
+EXPORT_SYMBOL(msm_fb_writeback_start);
-static int setup_fbmem(struct msmfb_info *msmfb, struct platform_device *pdev)
+int msm_fb_writeback_queue_buffer(struct fb_info *info,
+ struct msmfb_data *data)
{
- struct fb_info *fb = msmfb->fb;
- unsigned long size = msmfb->xres * msmfb->yres *
- BYTES_PER_PIXEL(msmfb) * 2;
- unsigned char *fbram;
- unsigned char *fbram_phys;
- int fbram_size;
- int fbram_offset;
-
- fbram_size = pdev->resource[0].end - pdev->resource[0].start + 1;
- fbram_phys = (char *)pdev->resource[0].start;
- fbram = __va(fbram_phys);
-
- if (!fbram) {
- printk(KERN_ERR "fbram ioremap failed!\n");
- return -ENOMEM;
- }
-
- fbram_offset = PAGE_ALIGN((int)fbram)-(int)fbram;
- fbram += fbram_offset;
- fbram_phys += fbram_offset;
- fbram_size -= fbram_offset;
-
- if (fbram_size < size) {
- printk(KERN_ERR "error: no more framebuffer memory!\n");
- return -ENOMEM;
- }
-
- fb->fix.smem_len = fbram_size;
- fb->screen_base = fbram;
- fb->fix.smem_start = (unsigned long)fbram_phys;
-
- return 0;
+ return mdp4_writeback_queue_buffer(info, data);
}
+EXPORT_SYMBOL(msm_fb_writeback_queue_buffer);
-static int msmfb_probe(struct platform_device *pdev)
+int msm_fb_writeback_dequeue_buffer(struct fb_info *info,
+ struct msmfb_data *data)
{
- struct fb_info *fb;
- struct msmfb_info *msmfb;
- struct msm_panel_data *panel = pdev->dev.platform_data;
- int ret;
+ return mdp4_writeback_dequeue_buffer(info, data);
+}
+EXPORT_SYMBOL(msm_fb_writeback_dequeue_buffer);
- if (!panel) {
- PR_DISP_ERR("msmfb_probe: no platform data\n");
- return -EINVAL;
- }
- if (!panel->fb_data) {
- PR_DISP_ERR("msmfb_probe: no fb_data\n");
- return -EINVAL;
- }
-
- 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;
- msmfb->overrides = panel->fb_data->overrides;
- 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);
- msmfb->resume_workqueue = alloc_workqueue("panel_on", WQ_HIGHPRI | WQ_CPU_INTENSIVE, 1);
- if (msmfb->resume_workqueue == NULL) {
- PR_DISP_ERR("failed to create panel_on workqueue\n");
- ret = -ENOMEM;
- goto error_create_workqueue;
- }
- INIT_WORK(&msmfb->resume_work, power_on_panel);
- msmfb->black = kzalloc(msmfb->fb->var.bits_per_pixel*msmfb->xres,
- GFP_KERNEL);
-
- wake_lock_init(&msmfb->idle_lock, WAKE_LOCK_IDLE, "msmfb_idle_lock");
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
- if (!(msmfb->overrides & MSM_FB_PM_DISABLE)) {
- msmfb->early_suspend.suspend = msmfb_suspend;
- msmfb->early_suspend.resume = msmfb_resume_handler;
- msmfb->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
- register_early_suspend(&msmfb->early_suspend);
-
- msmfb->earlier_suspend.suspend = msmfb_earlier_suspend;
- msmfb->earlier_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
- register_early_suspend(&msmfb->earlier_suspend);
- }
-#ifdef CONFIG_HTC_ONMODE_CHARGING
- if (!(msmfb->overrides & MSM_FB_PM_DISABLE)) {
- msmfb->onchg_suspend.suspend = msmfb_onchg_suspend;
- msmfb->onchg_suspend.resume = msmfb_onchg_resume_handler;
- msmfb->onchg_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
- register_onchg_suspend(&msmfb->onchg_suspend);
-
- msmfb->onchg_earlier_suspend.suspend = msmfb_onchg_earlier_suspend;
- msmfb->onchg_earlier_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
- register_onchg_suspend(&msmfb->onchg_earlier_suspend);
- }
-#endif
+int msm_fb_writeback_stop(struct fb_info *info)
+{
+ return mdp4_writeback_stop(info);
+}
+EXPORT_SYMBOL(msm_fb_writeback_stop);
+int msm_fb_writeback_init(struct fb_info *info)
+{
+ return mdp4_writeback_init(info);
+}
+EXPORT_SYMBOL(msm_fb_writeback_init);
+int msm_fb_writeback_terminate(struct fb_info *info)
+{
+ return mdp4_writeback_terminate(info);
+}
+EXPORT_SYMBOL(msm_fb_writeback_terminate);
#endif
-#if MSMFB_DEBUG
- debugfs_create_file("msm_fb", S_IFREG | S_IRUGO, NULL,
- (void *)fb->par, &debug_fops);
-#endif
+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;
- PR_DISP_INFO("msmfb_probe() installing %d x %d panel\n",
- msmfb->xres, msmfb->yres);
+ if (!pdev)
+ return NULL;
+ id = pdev->id;
- 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);
+ pdata = pdev->dev.platform_data;
+ if (!pdata)
+ return NULL;
+ type = pdata->panel_info.type;
- msmfb->fake_vsync.function = msmfb_fake_vsync;
-
- ret = register_framebuffer(fb);
-
- if (fb->node == 0)
- mdp->fb0 = msmfb->fb;
+#if defined MSM_FB_NUM
+ /*
+ * over written fb_num which defined
+ * at panel_info
+ *
+ */
+ if (type == HDMI_PANEL || type == DTV_PANEL ||
+ type == TV_PANEL || type == WRITEBACK_PANEL) {
+ if (hdmi_prim_display)
+ pdata->panel_info.fb_num = 2;
+ else
+ pdata->panel_info.fb_num = 1;
+ }
else
- mdp->fb1 = msmfb->fb;
+ pdata->panel_info.fb_num = MSM_FB_NUM;
- if (ret)
- goto error_register_framebuffer;
+ 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;
- msmfb->sleeping = WAKING;
+ if (fb_num <= 0)
+ return NULL;
-/* FIXME: Check if deprecated */
-#ifdef CONFIG_FB_MSM_LOGO
- if (!load_565rle_image(INIT_IMAGE_FILE)) {
- /* Flip buffer */
- msmfb->update_info.left = 0;
- msmfb->update_info.top = 0;
- msmfb->update_info.eright = info->var.xres;
- msmfb->update_info.ebottom = info->var.yres;
- msmfb_pan_update(info, 0, 0, fb->var.xres,
- fb->var.yres, 0, 1);
+ if (fbi_list_index >= MAX_FBI_LIST) {
+ printk(KERN_ERR "msm_fb: no more framebuffer info list!\n");
+ return NULL;
}
-#endif
- /* Jay, 29/12/08' */
- display_notifier(display_notifier_callback, NOTIFY_MSM_FB);
+ /*
+ * alloc panel device data
+ */
+ this_dev = msm_fb_device_alloc(pdata, type, id);
-#if defined(CONFIG_FB_MSM_MDP_ABL)
- init_completion(&mdp_hist_comp);
-#endif
+ 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;
+ mfd->iclient = iclient;
+ /* 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,
+ int subsys_id)
+{
+ struct fb_info *info;
+ struct msm_fb_data_type *mfd;
+
+ if (fb_num > MAX_FBI_LIST ||
+ (subsys_id != DISPLAY_SUBSYSTEM_ID &&
+ subsys_id != ROTATOR_SUBSYSTEM_ID)) {
+ pr_err("%s(): Invalid parameters\n", __func__);
+ return -1;
+ }
+
+ info = fbi_list[fb_num];
+ if (!info) {
+ pr_err("%s(): info is NULL\n", __func__);
+ return -1;
+ }
+
+ mfd = (struct msm_fb_data_type *)info->par;
+ if (mfd->map_buffer)
+ *start = mfd->map_buffer->iova[subsys_id];
+ else
+ *start = info->fix.smem_start;
+ *len = info->fix.smem_len;
+
return 0;
-
-error_register_framebuffer:
- wake_lock_destroy(&msmfb->idle_lock);
- destroy_workqueue(msmfb->resume_workqueue);
-error_create_workqueue:
- iounmap(fb->screen_base);
-error_setup_fbmem:
- framebuffer_release(msmfb->fb);
- return ret;
}
+EXPORT_SYMBOL(get_fb_phys_info);
-static void msmfb_shutdown(struct platform_device *pdev)
+int __init msm_fb_init(void)
{
- struct msm_panel_data *panel = pdev->dev.platform_data;
- struct fb_info *fb;
- struct msmfb_info *msmfb;
+ int rc = -ENODEV;
- PR_DISP_INFO("%s\n", __func__);
- fb = registered_fb[0];
- if (!fb) {
- PR_DISP_ERR("fb0 unavailable.\n");
- return;
+ 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);
+ }
}
- msmfb = fb->par;
-
- /* HTC, Change state to SLEEPING to skip pan_update during shutdown */
- msmfb->sleeping = SLEEPING;
-
- if (panel->blank)
- panel->blank(panel);
-
- if (panel->shutdown)
- panel->shutdown(panel);
-}
-
-static struct platform_driver msm_panel_driver = {
- /* need to write remove */
- .probe = msmfb_probe,
- .shutdown = msmfb_shutdown,
- .driver = {.name = "msm_panel"},
-};
-
-int get_fb_phys_info(unsigned long *start, unsigned long *len, int fb_num)
-{
- struct fb_info *fi;
- PR_DISP_DEBUG("%s fb_num %d\n", __func__, fb_num);
-
- if (fb_num >= FB_MAX)
- return -1;
-
- fi = registered_fb[fb_num];
-
- if (!fi)
- return -1;
-
- *start = fi->fix.smem_start;
- *len = fi->fix.smem_len;
-
- if (!*start)
- return -1;
+#endif
return 0;
}
-
-static int msmfb_add_mdp_device(struct device *dev,
- struct class_interface *class_intf)
+/* Called by v4l2 driver to enable/disable overlay pipe */
+int msm_fb_v4l2_enable(struct mdp_overlay *req, bool enable, void **par)
{
- /* might need locking if mulitple mdp devices */
- if (mdp)
- return 0;
- mdp = container_of(dev, struct mdp_device, dev);
- return platform_driver_register(&msm_panel_driver);
-}
+ int err = 0;
+#ifdef CONFIG_FB_MSM_MDP40
+ struct mdp4_overlay_pipe *pipe;
+ if (enable) {
-static void msmfb_remove_mdp_device(struct device *dev,
- struct class_interface *class_intf)
+ err = mdp4_v4l2_overlay_set(fbi_list[0], req, &pipe);
+
+ *(struct mdp4_overlay_pipe **)par = pipe;
+
+ } else {
+ pipe = *(struct mdp4_overlay_pipe **)par;
+ mdp4_v4l2_overlay_clear(pipe);
+ }
+#else
+#ifdef CONFIG_FB_MSM_MDP30
+ if (enable)
+ err = mdp_ppp_v4l2_overlay_set(fbi_list[0], req);
+ else
+ err = mdp_ppp_v4l2_overlay_clear();
+#else
+ err = -EINVAL;
+#endif
+#endif
+
+ return err;
+}
+EXPORT_SYMBOL(msm_fb_v4l2_enable);
+
+/* Called by v4l2 driver to provide a frame for display */
+int msm_fb_v4l2_update(void *par,
+ unsigned long srcp0_addr, unsigned long srcp0_size,
+ unsigned long srcp1_addr, unsigned long srcp1_size,
+ unsigned long srcp2_addr, unsigned long srcp2_size)
{
- /* might need locking if mulitple mdp devices */
- if (dev != &mdp->dev)
- return;
- platform_driver_unregister(&msm_panel_driver);
- mdp = NULL;
+#ifdef CONFIG_FB_MSM_MDP40
+ struct mdp4_overlay_pipe *pipe = (struct mdp4_overlay_pipe *)par;
+ return mdp4_v4l2_overlay_play(fbi_list[0], pipe,
+ srcp0_addr, srcp1_addr,
+ srcp2_addr);
+#else
+#ifdef CONFIG_FB_MSM_MDP30
+ return mdp_ppp_v4l2_overlay_play(fbi_list[0],
+ srcp0_addr, srcp0_size,
+ srcp1_addr, srcp1_size);
+#else
+ return -EINVAL;
+#endif
+#endif
}
+EXPORT_SYMBOL(msm_fb_v4l2_update);
-static struct class_interface msm_fb_interface = {
- .add_dev = &msmfb_add_mdp_device,
- .remove_dev = &msmfb_remove_mdp_device,
-};
-
-static int __init msmfb_init(void)
-{
- return register_mdp_client(&msm_fb_interface);
-}
-
-module_init(msmfb_init);
+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..fcb6d46
--- /dev/null
+++ b/drivers/video/msm/msm_fb.h
@@ -0,0 +1,222 @@
+/* Copyright (c) 2008-2012, 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 <mach/msm_subsystem_map.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>
+#include <linux/list.h>
+#include <linux/types.h>
+
+#include <linux/msm_mdp.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 msmfb_writeback_data_list {
+ struct list_head registered_entry;
+ struct list_head active_entry;
+ void *addr;
+ struct ion_handle *ihdl;
+ struct file *pmem_file;
+ struct msmfb_data buf_info;
+ struct msmfb_img img;
+ int state;
+};
+
+
+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;
+
+ struct device *dev;
+ 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_data *hist);
+ void (*vsync_ctrl) (int enable);
+ 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;
+ __u32 var_frame_rate;
+
+#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 mutex writeback_mutex;
+ struct mutex unregister_mutex;
+ struct list_head writeback_busy_queue;
+ struct list_head writeback_free_queue;
+ struct list_head writeback_register_queue;
+ wait_queue_head_t wait_q;
+ struct ion_client *iclient;
+ struct msm_mapped_buffer *map_buffer;
+ struct mdp_buf_type *ov0_wb_buf;
+ struct mdp_buf_type *ov1_wb_buf;
+ u32 ov_start;
+ u32 mem_hid;
+ u32 mdp_rev;
+ u32 writeback_state;
+ bool writeback_active_cnt;
+ int cont_splash_done;
+};
+
+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);
+struct fb_info *msm_fb_get_writeback_fb(void);
+int msm_fb_writeback_init(struct fb_info *info);
+int msm_fb_writeback_start(struct fb_info *info);
+int msm_fb_writeback_queue_buffer(struct fb_info *info,
+ struct msmfb_data *data);
+int msm_fb_writeback_dequeue_buffer(struct fb_info *info,
+ struct msmfb_data *data);
+int msm_fb_writeback_stop(struct fb_info *info);
+int msm_fb_writeback_terminate(struct fb_info *info);
+int msm_fb_detect_client(const char *name);
+int calc_fb_offset(struct msm_fb_data_type *mfd, struct fb_info *fbi, int bpp);
+
+#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);
+int msm_fb_check_frame_rate(struct msm_fb_data_type *mfd,
+ struct fb_info *info);
+
+#ifdef CONFIG_FB_MSM_LOGO
+#define INIT_IMAGE_FILE "/initlogo.rle"
+int load_565rle_image(char *filename, bool bf_supported);
+#endif
+
+#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..d8eaea2
--- /dev/null
+++ b/drivers/video/msm/msm_fb_panel.c
@@ -0,0 +1,144 @@
+/* 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;
+ case WRITEBACK_PANEL:
+ snprintf(dev_name, sizeof(dev_name), "writeback");
+ 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..51a3f38
--- /dev/null
+++ b/drivers/video/msm/msm_fb_panel.h
@@ -0,0 +1,201 @@
+/* Copyright (c) 2008-2012, 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 */
+#define WRITEBACK_PANEL 10 /* Wifi display */
+#define LVDS_PANEL 11 /* LVDS */
+
+/* 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 */
+ DISPLAY_3, /* attached on third writeback 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;
+ /* Pad width */
+ uint32 xres_pad;
+ /* Pad height */
+ uint32 yres_pad;
+};
+
+struct mddi_panel_info {
+ __u32 vdopkt;
+ boolean is_type1;
+};
+
+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;
+ /* byte to esc clk ratio */
+ uint32 esc_byte_ratio;
+ /* The packet-size should not bet changed */
+ char no_max_pkt_size;
+ /* Clock required during LP commands */
+ char force_clk_lane_hs;
+};
+
+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;
+ __u32 frame_rate;
+
+
+ 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);
+ int (*power_ctrl) (boolean enable);
+ 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..30dc854
--- /dev/null
+++ b/drivers/video/msm/tvenc.c
@@ -0,0 +1,522 @@
+/* Copyright (c) 2008-2012, 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>
+
+#define TVENC_C
+#include "tvenc.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+/* AXI rate in KHz */
+#define MSM_SYSTEM_BUS_RATE 128000000
+
+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_prepare_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_prepare_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_unprepare(tvenc_pclk);
+ clk_disable_unprepare(tvenc_clk);
+ return ret;
+ }
+tvencp_err:
+ clk_disable_unprepare(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_prepare_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_prepare_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_unprepare(mdp_tv_clk);
+ clk_disable_unprepare(tvdac_clk);
+ if (tvenc_pdata->poll)
+ tvenc_set_encoder_clock(CLOCK_OFF);
+ return ret;
+ }
+
+mdptv_err:
+ clk_disable_unprepare(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_unprepare(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_prepare_enable(mfd->ebi1_clk);
+#endif
+ 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, ret;
+ struct clk *ebi1_clk = NULL;
+
+ 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_clk = clk_get(&pdev->dev, "enc_clk");
+ tvdac_clk = clk_get(&pdev->dev, "dac_clk");
+ tvenc_pclk = clk_get(&pdev->dev, "iface_clk");
+ mdp_tv_clk = clk_get(&pdev->dev, "mdp_clk");
+
+#ifndef CONFIG_MSM_BUS_SCALING
+ ebi1_clk = clk_get(&pdev->dev, "mem_clk");
+ if (IS_ERR(ebi1_clk)) {
+ rc = PTR_ERR(ebi1_clk);
+ goto tvenc_probe_err;
+ }
+ clk_set_rate(ebi1_clk, MSM_SYSTEM_BUS_RATE);
+#endif
+
+#ifdef CONFIG_FB_MSM_MDP40
+ tv_src_clk = clk_get(&pdev->dev, "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;
+ }
+ }
+
+ tvenc_pdata = pdev->dev.platform_data;
+ tvenc_resource_initialized = 1;
+ return 0;
+ }
+
+ if (!tvenc_resource_initialized)
+ return -EPERM;
+
+ mfd = platform_get_drvdata(pdev);
+ mfd->ebi1_clk = ebi1_clk;
+
+ 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__);
+ }
+ }
+#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)
+{
+ 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..9ee55cc
--- /dev/null
+++ b/drivers/video/msm/tvout_msm.c
@@ -0,0 +1,652 @@
+/* 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;
+
+ if (msm_fb_detect_client("tvout_msm"))
+ return 0;
+
+ 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..bd37cc0
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
@@ -0,0 +1,721 @@
+/* Copyright (c) 2010-2012, 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;
+ 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);
+ if (res_trk_get_enable_ion()) {
+ DDL_MSG_LOW("ddl_dev_init:ION framework enabled");
+ ddl_context->video_ion_client =
+ res_trk_get_ion_client();
+ if (!ddl_context->video_ion_client) {
+ DDL_MSG_ERROR("ION client create failed");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ }
+ 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 (res_trk_get_firmware_addr(&ddl_context->dram_base_a)) {
+ DDL_MSG_ERROR("firmware allocation failed");
+ ptr = NULL;
+ } else {
+ ptr = (void *)ddl_context->dram_base_a.virtual_base_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) {
+ ddl_context->metadata_shared_input.mem_type = DDL_FW_MEM;
+ 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->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_context->video_ion_client = NULL;
+ 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;
+ }
+ if (res_trk_check_for_sec_session())
+ ddl->shared_mem[0].mem_type = DDL_CMD_MEM;
+ else
+ ddl->shared_mem[0].mem_type = DDL_FW_MEM;
+ ptr = ddl_pmem_alloc(&ddl->shared_mem[0],
+ DDL_FW_AUX_HOST_CMD_SPACE_SIZE, 0);
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ if (!status && ddl_context->frame_channel_depth
+ == VCD_DUAL_FRAME_COMMAND_CHANNEL) {
+ if (res_trk_check_for_sec_session())
+ ddl->shared_mem[1].mem_type = DDL_CMD_MEM;
+ else
+ ddl->shared_mem[1].mem_type = DDL_FW_MEM;
+ ptr = ddl_pmem_alloc(&ddl->shared_mem[1],
+ DDL_FW_AUX_HOST_CMD_SPACE_SIZE, 0);
+ 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 (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
+ encoder->seq_header.mem_type = DDL_MM_MEM;
+ 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;
+ }
+ msm_ion_do_cache_op(ddl_context->video_ion_client,
+ encoder->seq_header.alloc_handle,
+ encoder->seq_header.virtual_base_addr,
+ encoder->seq_header.buffer_size,
+ ION_IOC_CLEAN_INV_CACHES);
+ if (encoder->slice_delivery_info.enable) {
+ DDL_MSG_LOW("%s: slice mode allocate memory for struct\n",
+ __func__);
+ ptr = ddl_pmem_alloc(&encoder->batch_frame.slice_batch_in,
+ DDL_ENC_SLICE_BATCH_INPSTRUCT_SIZE,
+ DDL_LINEAR_BUFFER_ALIGN_BYTES);
+ if (ptr) {
+ ptr = ddl_pmem_alloc(
+ &encoder->batch_frame.slice_batch_out,
+ DDL_ENC_SLICE_BATCH_OUTSTRUCT_SIZE,
+ DDL_LINEAR_BUFFER_ALIGN_BYTES);
+ }
+ if (!ptr) {
+ ddl_pmem_free(&encoder->batch_frame.slice_batch_in);
+ ddl_pmem_free(&encoder->batch_frame.slice_batch_out);
+ ddl_free_enc_hw_buffers(ddl);
+ ddl_pmem_free(&encoder->seq_header);
+ DDL_MSG_ERROR("ddlEncStart:SeqHdrAllocFailed");
+ return VCD_ERR_ALLOC_FAIL;
+ }
+ }
+ 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");
+ 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;
+ struct ddl_encoder_data *encoder =
+ &ddl->codec_data.encoder;
+ u32 vcd_status = VCD_S_SUCCESS;
+
+ struct vcd_transc *transc;
+ transc = (struct vcd_transc *)(ddl->client_data);
+ DDL_MSG_LOW("%s: transc = 0x%x, in_use = %u",
+ __func__, (u32)ddl->client_data, transc->in_use);
+
+ if (encoder->slice_delivery_info.enable) {
+ return ddl_encode_frame_batch(ddl_handle,
+ input_frame,
+ output_bit,
+ 1,
+ encoder->slice_delivery_info.num_slices,
+ client_data);
+ }
+
+ 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_encode_frame_batch(u32 *ddl_handle,
+ struct ddl_frame_data_tag *input_frame,
+ struct ddl_frame_data_tag *output_bit,
+ u32 num_in_frames, u32 num_out_frames,
+ 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;
+ struct ddl_encoder_data *encoder;
+
+ DDL_MSG_LOW("ddl_encode_frame_batch");
+ 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;
+ encoder = &ddl->codec_data.encoder;
+ if (encoder->slice_delivery_info.enable) {
+ DDL_MEMCPY((void *)&(encoder->batch_frame.output_frame[0]),
+ (void *)output_bit,
+ sizeof(struct ddl_frame_data_tag) * num_out_frames);
+ encoder->batch_frame.num_output_frames = num_out_frames;
+ ddl->input_frame = *input_frame;
+ vcd_status = ddl_insert_input_frame_to_pool(ddl, input_frame);
+ if (!vcd_status)
+ ddl_vidc_encode_slice_batch_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");
+ 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");
+ 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..c1c2875
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
@@ -0,0 +1,484 @@
+/* Copyright (c) 2010-2012, 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 <mach/msm_subsystem_map.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)
+
+enum ddl_mem_area {
+ DDL_FW_MEM = 0x0,
+ DDL_MM_MEM = 0x1,
+ DDL_CMD_MEM = 0x2
+};
+
+struct ddl_buf_addr{
+ u8 *virtual_base_addr;
+ u8 *physical_base_addr;
+ u8 *align_physical_addr;
+ u8 *align_virtual_addr;
+ phys_addr_t alloced_phys_addr;
+ struct msm_mapped_buffer *mapped_buffer;
+ struct ion_handle *alloc_handle;
+ u32 buffer_size;
+ enum ddl_mem_area mem_type;
+ void *pil_cookie;
+};
+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_ENCODE_CONTINUE = 0xB,
+ 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_WAIT_FOR_CONTINUE = 0xD,
+ 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_batch_frame_data {
+ struct ddl_buf_addr slice_batch_in;
+ struct ddl_buf_addr slice_batch_out;
+ struct ddl_frame_data_tag input_frame;
+ struct ddl_frame_data_tag output_frame
+ [DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH];
+ u32 num_output_frames;
+ u32 out_frm_next_frmindex;
+};
+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 vcd_property_sps_pps_for_idr_enable sps_pps;
+ 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;
+ u32 closed_gop;
+ struct vcd_property_slice_delivery_info slice_delivery_info;
+ struct ddl_batch_frame_data batch_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;
+ u32 reconfig_detected;
+ u32 dmx_disable;
+};
+union ddl_codec_data{
+ struct ddl_codec_data_hdr hdr;
+ struct ddl_decoder_data decoder;
+ struct ddl_encoder_data encoder;
+};
+struct ddl_context{
+ 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;
+ struct ion_client *video_ion_client;
+ 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);
+ void(*vidc_encode_slice_batch_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_continue(struct ddl_client_context *);
+void ddl_vidc_encode_frame_run(struct ddl_client_context *);
+void ddl_vidc_encode_slice_batch_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_vidc_encode_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_get_stream_buf_from_batch_pool(struct ddl_client_context *ddl,
+ struct ddl_frame_data_tag *stream_buffer);
+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);
+void ddl_fill_dec_desc_buffer(struct ddl_client_context *ddl);
+void ddl_set_vidc_timeout(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(struct ddl_buf_addr *);
+#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..5c1ee21
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h
@@ -0,0 +1,120 @@
+/* Copyright (c) 2010-2012, 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 <media/msm/vcd_api.h>
+#include "vidc.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 vcd_property_slice_delivery_info {
+ u32 enable;
+ u32 num_slices;
+ u32 num_slices_enc;
+};
+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_frame_batch(u32 *ddl_handle,
+ struct ddl_frame_data_tag *input_frame,
+ struct ddl_frame_data_tag *output_bit,
+ u32 num_in_frames, u32 num_out_frames,
+ 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..ddddaa9
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
@@ -0,0 +1,149 @@
+/* Copyright (c) 2010-2012, 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_VIDC_1080P_48MHZ (48000000)
+#define DDL_VIDC_1080P_133MHZ (133330000)
+#define DDL_VIDC_1080P_200MHZ (200000000)
+#define DDL_VIDC_1080P_48MHZ_TIMEOUT_VALUE (0xCB8)
+#define DDL_VIDC_1080P_133MHZ_TIMEOUT_VALUE (0x2355)
+#define DDL_VIDC_1080P_200MHZ_TIMEOUT_VALUE (0x3500)
+
+#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(4))
+#define DDL_FW_INST_GLOBAL_CONTEXT_SPACE_SIZE (DDL_KILO_BYTE(800))
+#define DDL_FW_H264DEC_CONTEXT_SPACE_SIZE (DDL_KILO_BYTE(800))
+#define DDL_FW_H264ENC_CONTEXT_SPACE_SIZE (DDL_KILO_BYTE(20))
+#define DDL_FW_OTHER_CONTEXT_SPACE_SIZE (DDL_KILO_BYTE(20))
+
+#define VCD_DEC_CPB_SIZE (DDL_KILO_BYTE(512))
+#define DDL_DBG_CORE_DUMP_SIZE (DDL_KILO_BYTE(10))
+#define DDL_VIDC_1080P_BASE_OFFSET_SHIFT 11
+
+#define DDL_BUFEND_PAD 256
+#define DDL_ENC_SEQHEADER_SIZE (512+DDL_BUFEND_PAD)
+#define DDL_ENC_SLICE_BATCH_FACTOR 5
+#define DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH 8
+#define DDL_ENC_SLICE_BATCH_INPSTRUCT_SIZE (128 + \
+ 32 * DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH)
+#define DDL_ENC_SLICE_BATCH_OUTSTRUCT_SIZE (64 + \
+ 64 * DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH)
+#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..a2327d5
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c
@@ -0,0 +1,771 @@
+/* Copyright (c) 2010-2012, 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_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_WARN_DEBLOCKING_NOT_DONE:
+ case VIDC_1080P_WARN_INCOMPLETE_FRAME:
+ 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:
+ case VIDC_1080P_WARN_NO_LONG_TERM_REFERENCE:
+ case VIDC_1080P_WARN_NO_SPACE_MPEG2_DATA_DUMP:
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_MISSING_MB:
+ 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_WARN_DEBLOCKING_NOT_DONE:
+ string = "VIDC_1080P_WARN_DEBLOCKING_NOT_DONE";
+ break;
+ case VIDC_1080P_WARN_INCOMPLETE_FRAME:
+ string = "VIDC_1080P_WARN_INCOMPLETE_FRAME";
+ 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;
+ case VIDC_1080P_WARN_NO_LONG_TERM_REFERENCE:
+ string = "VIDC_1080P_WARN_NO_LONG_TERM_REFERENCE";
+ break;
+ case VIDC_1080P_WARN_NO_SPACE_MPEG2_DATA_DUMP:
+ string = "VIDC_1080P_WARN_NO_SPACE_MPEG2_DATA_DUMP";
+ break;
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_MISSING_MB:
+ string = "VIDC_1080P_WARN_METADATA_NO_SPACE_MISSING_MB";
+ 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_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..0acc2f6
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
@@ -0,0 +1,1065 @@
+/* Copyright (c) 2010-2012, 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/ion.h>
+#include <mach/msm_memtypes.h>
+#include "vcd_ddl.h"
+#include "vcd_ddl_shared_mem.h"
+#include "vcd_res_tracker_api.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 (!res_trk_check_for_sec_session() &&
+ frame[i].vcd_frm.virtual) {
+ if (luma_size <= frame[i].vcd_frm.alloc_len) {
+ 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);
+ if (frame[i].vcd_frm.ion_flag == CACHED) {
+ msm_ion_do_cache_op(
+ ddl_context->video_ion_client,
+ frame[i].vcd_frm.buff_ion_handle,
+ (unsigned long *)frame[i].
+ vcd_frm.virtual,
+ (unsigned long)frame[i].
+ vcd_frm.alloc_len,
+ ION_IOC_CLEAN_INV_CACHES);
+ }
+ } else {
+ DDL_MSG_ERROR("luma size error");
+ return VCD_ERR_FAIL;
+ }
+ }
+
+ 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)
+{
+ ddl_pmem_free(&ddl_context->metadata_shared_input);
+ ddl_fw_release(&ddl_context->dram_base_a);
+}
+
+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_pmem_free(&encoder->batch_frame.slice_batch_in);
+ ddl_pmem_free(&encoder->batch_frame.slice_batch_out);
+ 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;
+ struct ddl_context *ddl_context = ddl->ddl_context;
+
+ 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) {
+ dec_bufs->context.mem_type = DDL_MM_MEM;
+ ptr = ddl_pmem_alloc(&dec_bufs->context, buf_size.sz_context,
+ DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ msm_ion_do_cache_op(ddl_context->video_ion_client,
+ dec_bufs->context.alloc_handle,
+ dec_bufs->context.virtual_base_addr,
+ dec_bufs->context.buffer_size,
+ ION_IOC_CLEAN_INV_CACHES);
+ }
+ if (buf_size.sz_nb_ip > 0) {
+ dec_bufs->h264_nb_ip.mem_type = DDL_MM_MEM;
+ 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) {
+ dec_bufs->h264_vert_nb_mv.mem_type = DDL_MM_MEM;
+ 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) {
+ dec_bufs->nb_dcac.mem_type = DDL_MM_MEM;
+ 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) {
+ dec_bufs->upnb_mv.mem_type = DDL_MM_MEM;
+ 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) {
+ dec_bufs->sub_anchor_mv.mem_type = DDL_MM_MEM;
+ 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) {
+ dec_bufs->overlay_xform.mem_type = DDL_MM_MEM;
+ 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) {
+ dec_bufs->bit_plane3.mem_type = DDL_MM_MEM;
+ 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) {
+ dec_bufs->bit_plane2.mem_type = DDL_MM_MEM;
+ 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) {
+ dec_bufs->bit_plane1.mem_type = DDL_MM_MEM;
+ 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) {
+ dec_bufs->stx_parser.mem_type = DDL_MM_MEM;
+ 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) {
+ dec_bufs->desc.mem_type = DDL_MM_MEM;
+ ptr = ddl_pmem_alloc(&dec_bufs->desc, buf_size.sz_desc,
+ DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ else {
+ if (!res_trk_check_for_sec_session()) {
+ memset(dec_bufs->desc.align_virtual_addr,
+ 0, buf_size.sz_desc);
+ msm_ion_do_cache_op(
+ ddl_context->video_ion_client,
+ dec_bufs->desc.alloc_handle,
+ dec_bufs->desc.virtual_base_addr,
+ dec_bufs->desc.buffer_size,
+ ION_IOC_CLEAN_INV_CACHES);
+ }
+ }
+ }
+ 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;
+ sz_context = DDL_FW_OTHER_CONTEXT_SPACE_SIZE;
+ 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 * mb_y * 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));
+ sz_context = DDL_FW_H264ENC_CONTEXT_SPACE_SIZE;
+ 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));
+ }
+ 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;
+ struct ddl_context *ddl_context = ddl->ddl_context;
+
+ 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) {
+ enc_bufs->mv.mem_type = DDL_MM_MEM;
+ 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) {
+ enc_bufs->col_zero.mem_type = DDL_MM_MEM;
+ 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) {
+ enc_bufs->md.mem_type = DDL_MM_MEM;
+ 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) {
+ enc_bufs->pred.mem_type = DDL_MM_MEM;
+ 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) {
+ enc_bufs->nbor_info.mem_type = DDL_MM_MEM;
+ 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) {
+ enc_bufs->acdc_coef.mem_type = DDL_MM_MEM;
+ 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) {
+ enc_bufs->mb_info.mem_type = DDL_MM_MEM;
+ 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) {
+ enc_bufs->context.mem_type = DDL_MM_MEM;
+ ptr = ddl_pmem_alloc(&enc_bufs->context,
+ buf_size.sz_context, DDL_KILO_BYTE(2));
+ if (!ptr)
+ status = VCD_ERR_ALLOC_FAIL;
+ msm_ion_do_cache_op(ddl_context->video_ion_client,
+ enc_bufs->context.alloc_handle,
+ enc_bufs->context.virtual_base_addr,
+ enc_bufs->context.buffer_size,
+ ION_IOC_CLEAN_INV_CACHES);
+ }
+ 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)
+{
+ struct ddl_decoder_data *decoder = &ddl->codec_data.decoder;
+ if ((decoder->cont_mode) &&
+ (res_change == DDL_RESL_CHANGE_DECREASED)) {
+ DDL_MSG_LOW("%s Resolution decreased, continue decoding\n",
+ __func__);
+ vidc_sm_get_min_yc_dpb_sizes(
+ &ddl->shared_mem[ddl->command_channel],
+ &decoder->dpb_buf_size.size_y,
+ &decoder->dpb_buf_size.size_c);
+ DDL_MSG_LOW(" %s Resolution decreased, size_y = %u"
+ " size_c = %u\n",
+ __func__,
+ decoder->dpb_buf_size.size_y,
+ decoder->dpb_buf_size.size_c);
+ ddl_decoder_chroma_dpb_change(ddl);
+ vidc_sm_set_chroma_addr_change(
+ &ddl->shared_mem[ddl->command_channel],
+ true);
+ ddl_vidc_decode_frame_run(ddl);
+ } else {
+ DDL_MSG_LOW("%s Resolution change, start realloc\n",
+ __func__);
+ decoder->reconfig_detected = true;
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_EOS_DONE;
+ ddl->cmd_state = DDL_CMD_EOS;
+ vidc_1080p_frame_start_realloc(ddl->instance_id);
+ }
+}
+
+void ddl_fill_dec_desc_buffer(struct ddl_client_context *ddl)
+{
+ struct ddl_decoder_data *decoder = &ddl->codec_data.decoder;
+ struct vcd_frame_data *ip_bitstream = &(ddl->input_frame.vcd_frm);
+ struct ddl_buf_addr *dec_desc_buf = &(decoder->hw_bufs.desc);
+
+ if (ip_bitstream->desc_buf &&
+ ip_bitstream->desc_size < DDL_KILO_BYTE(128))
+ memcpy(dec_desc_buf->align_virtual_addr,
+ ip_bitstream->desc_buf,
+ ip_bitstream->desc_size);
+}
+
+void ddl_set_vidc_timeout(struct ddl_client_context *ddl)
+{
+ u32 vidc_time_out = 0;
+ if (ddl->codec_data.decoder.idr_only_decoding)
+ vidc_time_out = 2 * DDL_VIDC_1080P_200MHZ_TIMEOUT_VALUE;
+ DDL_MSG_HIGH("%s Video core time out value = 0x%x",
+ __func__, vidc_time_out);
+ vidc_sm_set_video_core_timeout_value(
+ &ddl->shared_mem[ddl->command_channel], vidc_time_out);
+}
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..f9c728a
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
@@ -0,0 +1,1983 @@
+/* Copyright (c) 2010-2012, 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 "vcd_res_tracker_api.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,
+ u32 eos_present);
+static void ddl_handle_slice_done_slice_batch(struct ddl_client_context *ddl);
+static void ddl_handle_enc_frame_done_slice_mode(
+ struct ddl_client_context *ddl, u32 eos_present);
+static void ddl_handle_enc_skipframe_slice_mode(
+ struct ddl_client_context *ddl, u32 eos_present);
+
+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;
+ u8 *fw_ver;
+
+ 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);
+ fw_ver = (u8 *)&ddl_context->fw_version;
+ DDL_MSG_ERROR("fw_version %x:%x:20%x",
+ fw_ver[1]&0xFF, fw_ver[0]&0xFF, fw_ver[2]&0xFF);
+ 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_HIGH("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 (res_trk_get_disable_fullhd() &&
+ (seq_hdr_info.img_size_x * seq_hdr_info.img_size_y >
+ 1280 * 720)) {
+ DDL_MSG_ERROR("FATAL:Resolution greater than 720P HD");
+ ddl_client_fatal_cb(ddl);
+ return process_further;
+ }
+ 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 eos_present = false;
+
+ DDL_MSG_MED("ddl_encoder_frame_run_callback\n");
+ 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);
+
+ 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 (VCD_FRAME_FLAG_EOS & ddl->input_frame.vcd_frm.flags) {
+ DDL_MSG_LOW("%s EOS detected\n", __func__);
+ eos_present = true;
+ }
+
+ 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)) {
+ if (encoder->slice_delivery_info.enable) {
+ if (encoder->enc_frame_info.enc_frame ==
+ VIDC_1080P_ENCODE_FRAMETYPE_SKIPPED)
+ ddl_handle_enc_skipframe_slice_mode(
+ ddl, eos_present);
+ else
+ ddl_handle_enc_frame_done_slice_mode(
+ ddl, eos_present);
+ } else {
+ ddl_handle_enc_frame_done(ddl, eos_present);
+ }
+ 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 if (eos_present &&
+ encoder->slice_delivery_info.enable) {
+ ddl_vidc_encode_eos_run(ddl);
+ } 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;
+ decoder->reconfig_detected = false;
+ 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 =
+ (decoder->reconfig_detected) ?\
+ VIDC_1080P_DEC_TYPE_FRAME_DATA :\
+ 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);
+ DDL_MSG_LOW("ddl_encoder_eos_done\n");
+ if (ddl == NULL) {
+ DDL_MSG_ERROR("NO_DDL_CONTEXT");
+ } else {
+ if (!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);
+ if (!encoder->slice_delivery_info.enable) {
+ ddl_handle_enc_frame_done(ddl, true);
+ ddl->cmd_state = DDL_CMD_INVALID;
+ }
+ DDL_MSG_LOW("encoder_eos_done");
+ 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_slice_done_callback(struct ddl_context *ddl_context)
+{
+ struct ddl_client_context *ddl;
+ u32 channel_inst_id;
+ u32 return_status = true;
+ DDL_MSG_LOW("ddl_sliceDoneCallback");
+ 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 == NULL) {
+ DDL_MSG_ERROR("NO_DDL_CONTEXT");
+ return_status = false;
+ } else if (ddl->cmd_state == DDL_CMD_ENCODE_FRAME) {
+ ddl->cmd_state = DDL_CMD_INVALID;
+ if (DDLCLIENT_STATE_IS(ddl,
+ DDL_CLIENT_WAIT_FOR_FRAME_DONE)) {
+ ddl_handle_slice_done_slice_batch(ddl);
+ } else {
+ DDL_MSG_ERROR("STATE-CRITICAL-ENCFRMRUN : %s\n",
+ __func__);
+ ddl_client_fatal_cb(ddl);
+ }
+ } else {
+ DDL_MSG_ERROR("UNKNOWN_SLICEDONE : %s\n", __func__);
+ }
+ return return_status;
+}
+
+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_SLICE_DONE_RET:
+ ddl_slice_done_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;
+ struct ddl_client_context *ddl;
+ struct ddl_encoder_data *encoder;
+
+ 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);
+ DDL_MSG_LOW("%s vidc_1080p_get_risc2host_cmd cmd = %u"
+ "arg1 = %u arg2 = %u arg3 = %u"
+ "arg4 = %u\n",
+ __func__, ddl_hw_response->cmd,
+ ddl_hw_response->arg1, ddl_hw_response->arg2,
+ ddl_hw_response->arg3,
+ ddl_hw_response->arg4);
+ ddl = ddl_get_current_ddl_client_for_channel_id(ddl_context,
+ ddl_context->response_cmd_ch_id);
+ if (ddl) {
+ encoder = &(ddl->codec_data.encoder);
+ if (encoder && encoder->slice_delivery_info.enable
+ &&
+ ((ddl_hw_response->cmd ==
+ VIDC_1080P_RISC2HOST_CMD_SLICE_DONE_RET)
+ || (ddl_hw_response->cmd ==
+ VIDC_1080P_RISC2HOST_CMD_FRAME_DONE_RET))) {
+ vidc_sm_set_encoder_slice_batch_int_ctrl(
+ &ddl->shared_mem[ddl->command_channel],
+ 1);
+ }
+ }
+ 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_MSG_LOW("%s cmd_err_status = %d\n", __func__,
+ ddl_context->cmd_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);
+ if (dec_disp_info->display_correct ==
+ VIDC_1080P_DECODE_NOT_CORRECT ||
+ dec_disp_info->display_correct ==
+ VIDC_1080P_DECODE_APPROX_CORRECT)
+ output_vcd_frm->flags |=
+ VCD_FRAME_FLAG_DATACORRUPT;
+ } else {
+ if (dec_disp_info->decode_correct ==
+ VIDC_1080P_DECODE_NOT_CORRECT ||
+ dec_disp_info->decode_correct ==
+ VIDC_1080P_DECODE_APPROX_CORRECT)
+ output_vcd_frm->flags |=
+ VCD_FRAME_FLAG_DATACORRUPT;
+ }
+ 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);
+ vidc_sm_get_aspect_ratio_info(
+ &ddl->shared_mem[ddl->command_channel],
+ &output_vcd_frm->aspect_ratio_info);
+ 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,
+ u32 eos_present)
+{
+ 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 = eos_present ?
+ 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);
+}
+
+static void ddl_handle_slice_done_slice_batch(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 = NULL;
+ u32 bottom_frame_tag;
+ struct vidc_1080p_enc_slice_batch_out_param *slice_output = NULL;
+ u32 num_slices_comp = 0;
+ u32 index = 0;
+ u32 start_bfr_idx = 0;
+ u32 actual_idx = 0;
+
+ DDL_MSG_LOW("%s\n", __func__);
+ vidc_sm_get_num_slices_comp(
+ &ddl->shared_mem[ddl->command_channel],
+ &num_slices_comp);
+ slice_output = (struct vidc_1080p_enc_slice_batch_out_param *)
+ (encoder->batch_frame.slice_batch_out.align_virtual_addr);
+ DDL_MSG_LOW(" after get no of slices = %d\n", num_slices_comp);
+ if (slice_output == NULL)
+ DDL_MSG_ERROR(" slice_output is NULL\n");
+ encoder->slice_delivery_info.num_slices_enc += num_slices_comp;
+ if (vidc_msg_timing) {
+ ddl_calc_core_proc_time_cnt(__func__, ENC_SLICE_OP_TIME,
+ num_slices_comp);
+ ddl_set_core_start_time(__func__, ENC_SLICE_OP_TIME);
+ }
+ DDL_MSG_LOW("%s : Slices Completed %d Total slices %d OutBfrInfo:"
+ "Cmd %d Size %d\n",
+ __func__,
+ num_slices_comp,
+ encoder->slice_delivery_info.num_slices_enc,
+ slice_output->cmd_type,
+ slice_output->output_size);
+ start_bfr_idx = encoder->batch_frame.out_frm_next_frmindex;
+ for (index = 0; index < num_slices_comp; index++) {
+ actual_idx =
+ slice_output->slice_info[start_bfr_idx+index].stream_buffer_idx;
+ DDL_MSG_LOW("Slice Info: OutBfrIndex %d SliceSize %d\n",
+ actual_idx,
+ slice_output->slice_info[start_bfr_idx+index].
+ stream_buffer_size);
+ output_frame = &(
+ encoder->batch_frame.output_frame[actual_idx].vcd_frm);
+ DDL_MSG_LOW("OutBfr: vcd_frm 0x%x frmbfr(virtual) 0x%x"
+ "frmbfr(physical) 0x%x\n",
+ &output_frame,
+ output_frame.virtual_base_addr,
+ output_frame.physical_base_addr);
+ 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);
+ ddl_get_encoded_frame(output_frame,
+ encoder->codec.codec,
+ encoder->enc_frame_info.enc_frame);
+ output_frame->data_len =
+ slice_output->slice_info[actual_idx].stream_buffer_size;
+ ddl->output_frame =
+ encoder->batch_frame.output_frame[actual_idx];
+ ddl->output_frame.frm_trans_end = false;
+ 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);
+ ddl->input_frame.frm_trans_end = false;
+ DDL_MSG_LOW("%s Set i/p o/p transactions to false\n", __func__);
+ }
+ encoder->batch_frame.out_frm_next_frmindex = start_bfr_idx + index;
+ ddl->cmd_state = DDL_CMD_ENCODE_FRAME;
+ vidc_sm_set_encoder_slice_batch_int_ctrl(
+ &ddl->shared_mem[ddl->command_channel],
+ 0);
+}
+
+static void ddl_handle_enc_frame_done_slice_mode(
+ struct ddl_client_context *ddl, u32 eos_present)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ struct vcd_frame_data *output_frame = NULL;
+ u32 bottom_frame_tag;
+ u8 *input_buffer_address = NULL;
+ struct vidc_1080p_enc_slice_batch_out_param *slice_output = NULL;
+ u32 num_slices_comp = 0;
+ u32 index = 0;
+ u32 start_bfr_idx = 0;
+ u32 actual_idx = 0;
+ struct vcd_transc *transc;
+
+ DDL_MSG_LOW("%s\n", __func__);
+ vidc_sm_get_num_slices_comp(
+ &ddl->shared_mem[ddl->command_channel],
+ &num_slices_comp);
+ slice_output = (struct vidc_1080p_enc_slice_batch_out_param *)
+ encoder->batch_frame.slice_batch_out.align_virtual_addr;
+ encoder->slice_delivery_info.num_slices_enc += num_slices_comp;
+ if (vidc_msg_timing) {
+ ddl_calc_core_proc_time_cnt(__func__, ENC_OP_TIME,
+ num_slices_comp);
+ }
+ DDL_MSG_LOW("%s Slices Completed %d Total slices done = %d"
+ " OutBfrInfo: Cmd %d Size %d",
+ __func__,
+ num_slices_comp,
+ encoder->slice_delivery_info.num_slices_enc,
+ slice_output->cmd_type,
+ slice_output->output_size);
+ start_bfr_idx = encoder->batch_frame.out_frm_next_frmindex;
+ if ((encoder->slice_delivery_info.num_slices_enc %
+ encoder->batch_frame.num_output_frames) != 0) {
+ DDL_MSG_ERROR("ERROR : %d %d\n",
+ encoder->slice_delivery_info.num_slices_enc,
+ encoder->batch_frame.num_output_frames);
+ }
+ for (index = 0; index < num_slices_comp; index++) {
+ actual_idx =
+ slice_output->slice_info[start_bfr_idx+index]. \
+ stream_buffer_idx;
+ DDL_MSG_LOW("Slice Info: OutBfrIndex %d SliceSize %d",
+ actual_idx,
+ slice_output->slice_info[start_bfr_idx+index]. \
+ stream_buffer_size, 0);
+ output_frame =
+ &(encoder->batch_frame.output_frame[actual_idx].vcd_frm);
+ DDL_MSG_LOW("OutBfr: vcd_frm 0x%x frmbfr(virtual) 0x%x"
+ "frmbfr(physical) 0x%x",
+ &output_frame,
+ output_frame.virtual_base_addr,
+ output_frame.physical_base_addr);
+ 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);
+ ddl_get_encoded_frame(output_frame,
+ encoder->codec.codec,
+ encoder->enc_frame_info.enc_frame);
+ output_frame->data_len =
+ slice_output->slice_info[actual_idx].stream_buffer_size;
+ ddl->output_frame =
+ encoder->batch_frame.output_frame[actual_idx];
+ DDL_MSG_LOW(" %s actual_idx = %d"
+ "encoder->batch_frame.num_output_frames = %d\n", __func__,
+ actual_idx, encoder->batch_frame.num_output_frames);
+ if (encoder->batch_frame.num_output_frames == (actual_idx+1)) {
+ output_frame->flags |= VCD_FRAME_FLAG_ENDOFFRAME;
+ ddl_vidc_encode_dynamic_property(ddl, false);
+ ddl->input_frame.frm_trans_end = true;
+ DDL_MSG_LOW("%s End of frame detected\n", __func__);
+ 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);
+ transc = (struct vcd_transc *)(ddl->client_data);
+ if (eos_present)
+ ddl->output_frame.frm_trans_end = false;
+ else
+ ddl->output_frame.frm_trans_end = true;
+ }
+ DDL_MSG_LOW("%s Before output done cb\n", __func__);
+ transc = (struct vcd_transc *)(ddl->client_data);
+ ddl->output_frame.vcd_frm = *output_frame;
+ 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 (encoder->batch_frame.num_output_frames == (actual_idx+1)) {
+ DDL_MSG_LOW("%s sending input done\n", __func__);
+ 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 ddl_handle_enc_skipframe_slice_mode(
+ struct ddl_client_context *ddl, u32 eos_present)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ struct vcd_frame_data *output_frame = NULL;
+ u32 bottom_frame_tag;
+ u8 *input_buffer_address = NULL;
+ u32 index = 0;
+ DDL_MSG_HIGH("ddl_handle_enc_skipframe_slice_mode: frame skipped");
+ vidc_sm_set_encoder_slice_batch_int_ctrl(
+ &ddl->shared_mem[ddl->command_channel],
+ 1);
+ for (index = 0;
+ index < encoder->batch_frame.num_output_frames;
+ index++) {
+ output_frame =
+ &(encoder->batch_frame.output_frame[index].vcd_frm);
+ DDL_MSG_MED("output buffer: vcd_frm = 0x%x "
+ "frmbfr(virtual) = 0x%x frmbfr(physical) = 0x%x",
+ (u32)output_frame, (u32)output_frame->virtual,
+ (u32)output_frame->physical);
+ vidc_sm_get_frame_tags(
+ &ddl->shared_mem[ddl->command_channel],
+ &output_frame->ip_frm_tag,
+ &bottom_frame_tag);
+ ddl_get_encoded_frame(
+ output_frame,
+ encoder->codec.codec,
+ encoder->enc_frame_info.enc_frame);
+ output_frame->data_len = 0;
+ ddl->output_frame.frm_trans_end = false;
+ if (encoder->batch_frame.num_output_frames ==
+ (index + 1)) {
+ DDL_MSG_MED("last output bfr for skip frame, set EOF");
+ output_frame->flags |= VCD_FRAME_FLAG_ENDOFFRAME;
+ ddl_vidc_encode_dynamic_property(ddl, false);
+ if (eos_present)
+ ddl->output_frame.frm_trans_end = false;
+ else
+ ddl->output_frame.frm_trans_end = true;
+ }
+ ddl->output_frame.vcd_frm = *output_frame;
+ 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 (encoder->batch_frame.num_output_frames ==
+ (index + 1)) {
+ ddl->input_frame.frm_trans_end = false;
+ input_buffer_address =
+ ddl_context->dram_base_a.physical_base_addr +
+ (encoder->enc_frame_info.enc_luma_address);
+ ddl_get_input_frame_from_pool(ddl,
+ input_buffer_address);
+ DDL_MSG_MED("InpBfr: vcd_frm 0x%x frmbfr(virtual) 0x%x"
+ " frmbfr(physical) 0x%x",
+ (u32)&(ddl->input_frame.vcd_frm),
+ (u32)ddl->input_frame.vcd_frm.virtual,
+ (u32)ddl->input_frame.vcd_frm.physical);
+ 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);
+ }
+ }
+}
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..267e924
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c
@@ -0,0 +1,508 @@
+/* Copyright (c) 2010, 2012, 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;
+ encoder->output_buf_req.sz =
+ DDL_ALIGN(encoder->output_buf_req.sz, DDL_KILO_BYTE(4));
+}
+
+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;
+ DDL_MSG_LOW("processing metadata for encoder");
+ 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..db3624a
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
@@ -0,0 +1,2099 @@
+/* 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_res_tracker_api.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);
+ }
+ DDL_MSG_LOW("set VCD_I_FRAME_SIZE width = %d"
+ " height = %d\n",
+ frame_size->width, frame_size->height);
+ 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->dev_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;
+ case VCD_I_DISABLE_DMX:
+ {
+ int disable_dmx_allowed = 0;
+ DDL_MSG_LOW("Set property VCD_I_DISABLE_DMX\n");
+ if (res_trk_get_disable_dmx() &&
+ ((decoder->codec.codec == VCD_CODEC_H264) ||
+ (decoder->codec.codec == VCD_CODEC_VC1) ||
+ (decoder->codec.codec == VCD_CODEC_VC1_RCV)))
+ disable_dmx_allowed = 1;
+
+ if (sizeof(u32) == property_hdr->sz &&
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN) &&
+ disable_dmx_allowed) {
+ decoder->dmx_disable = *(u32 *)property_value;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_REQ_PERF_LEVEL:
+ 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;
+ DDL_MSG_HIGH("VCD_I_MULTI_SLICE eMSliceSel %d nMSliceSize %d"
+ "Tot#of MB %d encoder->frame_size.width = %d"
+ "encoder->frame_size.height = %d",
+ (int)multi_slice->m_slice_sel,
+ multi_slice->m_slice_size,
+ DDL_NO_OF_MB(encoder->frame_size.width,
+ encoder->frame_size.height),
+ encoder->frame_size.width,
+ encoder->frame_size.height);
+ 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));
+ DDL_MSG_LOW("%s encoder->client_output_buf_req.sz"
+ " = %d\n", __func__,
+ encoder->client_output_buf_req.sz);
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_RECON_BUFFERS:
+ {
+ int index, index_hw_bufs = -1;
+ 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) {
+ index_hw_bufs = index;
+ break;
+ } else
+ continue;
+ }
+ if (index_hw_bufs == -1) {
+ DDL_MSG_HIGH("ERROR: value of index_hw_bufs");
+ vcd_status = VCD_ERR_ILLEGAL_PARM;
+ } else {
+ if (property_hdr->sz == sizeof(struct
+ vcd_property_enc_recon_buffer)) {
+ encoder->hw_bufs.dpb_y[index_hw_bufs].
+ align_physical_addr =
+ recon_buffers->dev_addr;
+ encoder->hw_bufs.dpb_y[index_hw_bufs].
+ align_virtual_addr =
+ recon_buffers->kernel_virtual_addr;
+ encoder->hw_bufs.dpb_y[index_hw_bufs].
+ buffer_size = recon_buffers->buffer_size;
+ encoder->hw_bufs.dpb_c[index_hw_bufs].
+ align_physical_addr =
+ recon_buffers->dev_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_hw_bufs].
+ 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_hw_bufs].
+ align_virtual_addr,
+ encoder->hw_bufs.dpb_y[index_hw_bufs].
+ align_physical_addr,
+ encoder->hw_bufs.dpb_c[index_hw_bufs].
+ align_virtual_addr,
+ encoder->hw_bufs.dpb_c[index_hw_bufs].
+ 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_LOW("Meta Data Interface is Requested");
+ if (!res_trk_check_for_sec_session()) {
+ if (!encoder->slice_delivery_info.enable) {
+ vcd_status = ddl_set_metadata_params(ddl,
+ property_hdr, property_value);
+ } else {
+ DDL_MSG_ERROR("Ignoring meta data settting in "
+ "slice mode: %s\n", __func__);
+ vcd_status = VCD_S_SUCCESS;
+ }
+ } else {
+ DDL_MSG_ERROR("Meta Data Interface is not "
+ "supported in secure session");
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ }
+ break;
+ case VCD_I_META_BUFFER_MODE:
+ vcd_status = VCD_S_SUCCESS;
+ break;
+ case VCD_I_ENABLE_SPS_PPS_FOR_IDR:
+ {
+ struct vcd_property_sps_pps_for_idr_enable *sps_pps =
+ (struct vcd_property_sps_pps_for_idr_enable *) property_value;
+
+ if ((sizeof(struct vcd_property_sps_pps_for_idr_enable)) ==
+ property_hdr->sz) {
+ DDL_MSG_LOW("SPS PPS generation for IDR Encode "
+ "is Requested");
+ encoder->sps_pps.sps_pps_for_idr_enable_flag =
+ sps_pps->sps_pps_for_idr_enable_flag;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
+ case VCD_I_SLICE_DELIVERY_MODE:
+ {
+ size_t output_buf_size;
+ u32 num_mb, num_slices;
+ struct vcd_property_hdr slice_property_hdr;
+ struct vcd_property_meta_data_enable slice_meta_data;
+ DDL_MSG_HIGH("Set property VCD_I_SLICE_DELIVERY_MODE\n");
+ if (sizeof(u32) == property_hdr->sz &&
+ encoder->codec.codec == VCD_CODEC_H264 &&
+ encoder->multi_slice.m_slice_sel
+ == VCD_MSLICE_BY_MB_COUNT &&
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)) {
+ encoder->slice_delivery_info.enable
+ = *(u32 *)property_value;
+ DDL_MSG_HIGH("set encoder->slice_delivery_mode = %u\n",
+ encoder->slice_delivery_info.enable);
+ output_buf_size =
+ encoder->client_output_buf_req.sz;
+ num_mb = DDL_NO_OF_MB(encoder->frame_size.width,
+ encoder->frame_size.height);
+ num_slices = num_mb/
+ encoder->multi_slice.m_slice_size;
+ num_slices = ((num_mb - num_slices *
+ encoder->multi_slice.m_slice_size) > 0)
+ ? (num_slices + 1) : num_slices;
+ encoder->slice_delivery_info.num_slices =
+ num_slices;
+ if (num_slices <= DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH) {
+ DDL_MSG_HIGH("%s: currently slice info "
+ "metadata is not supported when slice "
+ "delivery mode is enabled. hence "
+ "disabling slice info metadata.\n",
+ __func__);
+ slice_property_hdr.prop_id =
+ VCD_I_METADATA_ENABLE;
+ slice_property_hdr.sz =
+ sizeof(struct \
+ vcd_property_meta_data_enable);
+ ddl_get_metadata_params(ddl,
+ &slice_property_hdr,
+ &slice_meta_data);
+ slice_meta_data.meta_data_enable_flag
+ &= ~VCD_METADATA_ENC_SLICE;
+ ddl_set_metadata_params(ddl,
+ &slice_property_hdr,
+ &slice_meta_data);
+ encoder->client_output_buf_req.min_count =
+ ((DDL_ENC_SLICE_BATCH_FACTOR * num_slices + 2)
+ > DDL_MAX_BUFFER_COUNT)
+ ? DDL_MAX_BUFFER_COUNT :
+ (DDL_ENC_SLICE_BATCH_FACTOR * num_slices + 2);
+ output_buf_size =
+ encoder->client_output_buf_req.sz/num_slices;
+ encoder->client_output_buf_req.sz =
+ DDL_ALIGN(output_buf_size, DDL_KILO_BYTE(4));
+ encoder->output_buf_req =
+ encoder->client_output_buf_req;
+ DDL_MSG_HIGH("%s num_mb = %u num_slices = %u "
+ "output_buf_count = %u "
+ "output_buf_size = %u aligned size = %u\n",
+ __func__, num_mb, num_slices,
+ encoder->client_output_buf_req.min_count,
+ output_buf_size,
+ encoder->client_output_buf_req.sz);
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ }
+ case VCD_REQ_PERF_LEVEL:
+ 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;
+ case VCD_I_DISABLE_DMX_SUPPORT:
+ if (sizeof(u32) == property_hdr->sz) {
+ *(u32 *)property_value = res_trk_get_disable_dmx();
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_DISABLE_DMX:
+ if (sizeof(u32) == property_hdr->sz) {
+ *(u32 *)property_value = decoder->dmx_disable;
+ 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;
+ DDL_MSG_LOW("%s encoder->client_output_buf_req = %d\n",
+ __func__,
+ encoder->client_output_buf_req.sz);
+ 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;
+ case VCD_I_ENABLE_SPS_PPS_FOR_IDR:
+ if (sizeof(struct vcd_property_sps_pps_for_idr_enable) ==
+ property_hdr->sz) {
+ *(struct vcd_property_sps_pps_for_idr_enable *)
+ property_value = encoder->sps_pps;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_SLICE_DELIVERY_MODE:
+ if (sizeof(struct vcd_property_slice_delivery_info) ==
+ property_hdr->sz) {
+ *(struct vcd_property_slice_delivery_info *)
+ property_value = encoder->slice_delivery_info;
+ 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;
+ decoder->reconfig_detected = false;
+ decoder->dmx_disable = false;
+ 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;
+ if (encoder->codec.codec == VCD_CODEC_MPEG4)
+ encoder->closed_gop = true;
+ ddl_set_default_metadata_flag(ddl);
+ ddl_set_default_encoder_buffer_req(encoder);
+ encoder->slice_delivery_info.enable = 0;
+ encoder->slice_delivery_info.num_slices = 0;
+ encoder->slice_delivery_info.num_slices_enc = 0;
+}
+
+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;
+ DDL_MSG_LOW("%s encoder->client_output_buf_req.sz = %d\n",
+ __func__, encoder->client_output_buf_req.sz);
+}
+
+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;
+ if (estimate) {
+ if (!decoder->cont_mode)
+ min_dpb = ddl_decoder_min_num_dpb(decoder);
+ else
+ min_dpb = 5;
+ 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 {
+ 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;
+ }
+ memset(output_buf_req, 0,
+ sizeof(struct vcd_buffer_requirement));
+ if (!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 * 2);
+ 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");
+ DDL_MSG_ERROR("codec_buf_req: min_cnt=%d, mx_cnt=%d, "
+ "align=%d, sz=%d\n", original_buf_req->min_count,
+ original_buf_req->max_count, original_buf_req->align,
+ original_buf_req->sz);
+ DDL_MSG_ERROR("client_buffs: actual_count=%d, align=%d, "
+ "sz=%d\n", req_buf_req->actual_count,
+ req_buf_req->align, req_buf_req->sz);
+ }
+ 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);
+ encoder->sps_pps.sps_pps_for_idr_enable_flag = false;
+ }
+}
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..7437f94
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
@@ -0,0 +1,876 @@
+/* Copyright (c) 2010-2012, 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_H263_CPCFC_ENABLE_BMSK 0x80
+#define VIDC_SM_ENC_EXT_CTRL_H263_CPCFC_ENABLE_SHFT 7
+#define VIDC_SM_ENC_EXT_CTRL_SPS_PPS_CONTROL_BMSK 0X100
+#define VIDC_SM_ENC_EXT_CTRL_SPS_PPS_CONTROL_SHFT 8
+#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_BATCH_INPUT_ADDR 0x00a4
+#define VIDC_SM_BATCH_INPUT_ADDR_VALUE_BMSK 0xffffffff
+#define VIDC_SM_BATCH_INPUT_ADDRL_VALUE_SHFT 0
+#define VIDC_SM_BATCH_OUTPUT_ADDR 0x00a8
+#define VIDC_SM_BATCH_OUTPUT_ADDR_VALUE_BMSK 0xffffffff
+#define VIDC_SM_BATCH_OUTPUT_ADDR_VALUE_SHFT 0
+#define VIDC_SM_BATCH_OUTPUT_SIZE_ADDR 0x00ac
+#define VIDC_SM_BATCH_OUTPUT_SIZE_VALUE_BMSK 0xffffffff
+#define VIDC_SM_BATCH_OUTPUT_SIZE_VALUE_SHFT 0
+#define VIDC_SM_ENC_SLICE_BATCH_INT_CTRL_ADDR 0x01c8
+#define VIDC_SM_ENC_SLICE_BATCH_INT_CTRL_VALUE_BMSK 0x1
+#define VIDC_SM_ENC_SLICE_BATCH_INT_CTRL_VALUE_SHFT 0
+#define VIDC_SM_ENC_NUM_OF_SLICE_ADDR 0x01cc
+#define VIDC_SM_ENC_NUM_OF_SLICE_VALUE_BMSK 0xffffffff
+#define VIDC_SM_ENC_NUM_OF_SLICE_VALUE_SHFT 0
+#define VIDC_SM_ENC_NUM_OF_SLICE_COMP_ADDR 0x01d0
+#define VIDC_SM_ENC_NUM_OF_SLICE_COMP_VALUE_BMSK 0xffffffff
+#define VIDC_SM_ENC_NUM_OF_SLICE_COMP_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_ASPECT_RATIO_INFO_ADDR 0x00c8
+#define VIDC_SM_MPEG4_ASPECT_RATIO_INFO_BMSK 0xf
+#define VIDC_SM_MPEG4_ASPECT_RATIO_INFO_SHFT 0x0
+#define VIDC_SM_EXTENDED_PAR_ADDR 0x00cc
+#define VIDC_SM_EXTENDED_PAR_WIDTH_BMSK 0xffff0000
+#define VIDC_SM_EXTENDED_PAR_WIDTH_SHFT 0xf
+#define VIDC_SM_EXTENDED_PAR_HEIGHT_BMSK 0x0000ffff
+#define VIDC_SM_EXTENDED_PAR_HEIGHT_SHFT 0x0
+
+#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 VIDC_SM_ERROR_CONCEALMENT_CONFIG_ADDR 0x0154
+
+#define VIDC_SM_ERROR_CONCEALMENT_CONFIG_INTER_SLICE_BMSK 0x0c
+#define VIDC_SM_ERROR_CONCEALMENT_CONFIG_INTER_SLICE_SHFT 2
+#define VIDC_SM_ERROR_CONCEALMENT_CONFIG_INTRA_SLICE_BMSK 0X02
+#define VIDC_SM_ERROR_CONCEALMENT_CONFIG_INTRA_SLICE_SHFT 1
+#define VIDC_SM_ERROR_CONCEALMENT_CONFIG_CONCEAL_ENABLE_BMSK 0x01
+#define VIDC_SM_ERROR_CONCEALMENT_CONFIG_CONCEAL_ENABLE_SHFT 0
+
+#define VIDC_SM_SEI_ENABLE_ADDR 0x0180
+#define VIDC_SM_SEI_ENABLE_RECOVERY_POINT_SEI_BMSK 0x00000001
+#define VIDC_SM_SEI_ENABLE_RECOVERY_POINT_SEI_SHFT 0
+
+#define VIDC_SM_NUM_STUFF_BYTES_CONSUME_ADDR 0X01ac
+
+#define VIDC_SM_TIMEOUT_VALUE_ADDR 0x0158
+#define VIDC_SM_TIMEOUT_VALUE_BMSK 0xffffffff
+#define VIDC_SM_TIMEOUT_VALUE_SHFT 0
+
+#define VIDC_SM_ENC_EXT_CTRL_CLOSED_GOP_ENABLE_BMSK 0x40
+#define VIDC_SM_ENC_EXT_CTRL_CLOSED_GOP_ENABLE_SHFT 6
+
+#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 cpcfc_enable,
+ u32 sps_pps_control, u32 closed_gop_enable)
+{
+ 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) |
+ VIDC_SETFIELD((cpcfc_enable) ? 1 : 0,
+ VIDC_SM_ENC_EXT_CTRL_H263_CPCFC_ENABLE_SHFT,
+ VIDC_SM_ENC_EXT_CTRL_H263_CPCFC_ENABLE_BMSK) |
+ VIDC_SETFIELD((sps_pps_control) ? 1 : 0,
+ VIDC_SM_ENC_EXT_CTRL_SPS_PPS_CONTROL_SHFT,
+ VIDC_SM_ENC_EXT_CTRL_SPS_PPS_CONTROL_BMSK) |
+ VIDC_SETFIELD(closed_gop_enable,
+ VIDC_SM_ENC_EXT_CTRL_CLOSED_GOP_ENABLE_SHFT,
+ VIDC_SM_ENC_EXT_CTRL_CLOSED_GOP_ENABLE_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);
+
+}
+
+void vidc_sm_set_mpeg4_profile_override(struct ddl_buf_addr *shared_mem,
+ enum vidc_sm_mpeg4_profileinfo profile_info)
+{
+ u32 profile_enforce = 0;
+ if (shared_mem != NULL) {
+ profile_enforce = 1;
+ switch (profile_info) {
+ case VIDC_SM_PROFILE_INFO_ASP:
+ profile_enforce |= 4;
+ break;
+ case VIDC_SM_PROFILE_INFO_SP:
+ profile_enforce |= 2;
+ break;
+ case VIDC_SM_PROFILE_INFO_DISABLE:
+ default:
+ profile_enforce = 0;
+ break;
+ }
+ DDL_MEM_WRITE_32(shared_mem, 0x15c, profile_enforce);
+ }
+}
+void vidc_sm_set_decoder_sei_enable(struct ddl_buf_addr *shared_mem,
+ u32 sei_enable)
+{
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_SEI_ENABLE_ADDR, sei_enable);
+}
+
+void vidc_sm_get_decoder_sei_enable(struct ddl_buf_addr *shared_mem,
+ u32 *sei_enable)
+{
+ *sei_enable = DDL_MEM_READ_32(shared_mem, VIDC_SM_SEI_ENABLE_ADDR);
+}
+
+void vidc_sm_set_error_concealment_config(struct ddl_buf_addr *shared_mem,
+ u32 inter_slice, u32 intra_slice, u32 conceal_config_enable)
+{
+ u32 error_conceal_config = 0;
+
+ error_conceal_config = VIDC_SETFIELD(inter_slice,
+ VIDC_SM_ERROR_CONCEALMENT_CONFIG_INTER_SLICE_SHFT,
+ VIDC_SM_ERROR_CONCEALMENT_CONFIG_INTER_SLICE_BMSK);
+
+ error_conceal_config |= VIDC_SETFIELD(intra_slice,
+ VIDC_SM_ERROR_CONCEALMENT_CONFIG_INTRA_SLICE_SHFT,
+ VIDC_SM_ERROR_CONCEALMENT_CONFIG_INTRA_SLICE_BMSK);
+
+ error_conceal_config |= VIDC_SETFIELD(conceal_config_enable,
+ VIDC_SM_ERROR_CONCEALMENT_CONFIG_CONCEAL_ENABLE_SHFT,
+ VIDC_SM_ERROR_CONCEALMENT_CONFIG_CONCEAL_ENABLE_BMSK);
+
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_ERROR_CONCEALMENT_CONFIG_ADDR,
+ error_conceal_config);
+}
+
+void vidc_sm_set_decoder_stuff_bytes_consumption(
+ struct ddl_buf_addr *shared_mem,
+ enum vidc_sm_num_stuff_bytes_consume_info consume_info)
+{
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_NUM_STUFF_BYTES_CONSUME_ADDR,
+ consume_info);
+}
+
+void vidc_sm_set_video_core_timeout_value(struct ddl_buf_addr *shared_mem,
+ u32 timeout)
+{
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_TIMEOUT_VALUE_ADDR,
+ timeout);
+}
+
+void vidc_sm_get_aspect_ratio_info(struct ddl_buf_addr *shared_mem,
+ struct vcd_aspect_ratio *aspect_ratio_info)
+{
+ u32 extended_par_info = 0;
+ aspect_ratio_info->aspect_ratio = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_ASPECT_RATIO_INFO_ADDR);
+
+ if (aspect_ratio_info->aspect_ratio == 0x0f) {
+ extended_par_info = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_EXTENDED_PAR_ADDR);
+ aspect_ratio_info->extended_par_width =
+ VIDC_GETFIELD(extended_par_info,
+ VIDC_SM_EXTENDED_PAR_WIDTH_BMSK,
+ VIDC_SM_EXTENDED_PAR_WIDTH_SHFT);
+ aspect_ratio_info->extended_par_height =
+ VIDC_GETFIELD(extended_par_info,
+ VIDC_SM_EXTENDED_PAR_HEIGHT_BMSK,
+ VIDC_SM_EXTENDED_PAR_HEIGHT_SHFT);
+ }
+}
+
+void vidc_sm_set_encoder_slice_batch_int_ctrl(struct ddl_buf_addr *shared_mem,
+ u32 slice_batch_int_enable)
+{
+ u32 slice_batch_int_ctrl = VIDC_SETFIELD((slice_batch_int_enable) ?
+ 1 : 0,
+ VIDC_SM_ENC_EXT_CTRL_HEC_ENABLE_SHFT,
+ VIDC_SM_ENC_EXT_CTRL_HEC_ENABLE_BMSK);
+ DDL_MEM_WRITE_32(shared_mem,
+ VIDC_SM_ENC_SLICE_BATCH_INT_CTRL_ADDR,
+ slice_batch_int_ctrl);
+}
+
+void vidc_sm_get_num_slices_comp(struct ddl_buf_addr *shared_mem,
+ u32 *num_slices_comp)
+{
+ *num_slices_comp = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_ENC_NUM_OF_SLICE_COMP_ADDR);
+}
+
+void vidc_sm_set_encoder_batch_config(struct ddl_buf_addr *shared_mem,
+ u32 num_slices,
+ u32 input_addr, u32 output_addr,
+ u32 output_buffer_size)
+{
+ DDL_MEM_WRITE_32(shared_mem,
+ VIDC_SM_ENC_NUM_OF_SLICE_ADDR,
+ num_slices);
+ DDL_MEM_WRITE_32(shared_mem,
+ VIDC_SM_BATCH_INPUT_ADDR,
+ input_addr);
+ DDL_MEM_WRITE_32(shared_mem,
+ VIDC_SM_BATCH_OUTPUT_ADDR,
+ output_addr);
+ DDL_MEM_WRITE_32(shared_mem,
+ VIDC_SM_BATCH_OUTPUT_SIZE_ADDR,
+ output_buffer_size);
+}
+
+void vidc_sm_get_encoder_batch_output_size(struct ddl_buf_addr *shared_mem,
+ u32 *output_buffer_size)
+{
+ *output_buffer_size = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_BATCH_OUTPUT_SIZE_ADDR);
+}
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..3bb170e
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
@@ -0,0 +1,197 @@
+/* Copyright (c) 2010-2012, 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)
+
+#define VIDC_SM_RECOVERY_POINT_SEI (1)
+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;
+};
+
+enum vidc_sm_mpeg4_profileinfo {
+ VIDC_SM_PROFILE_INFO_DISABLE = 0,
+ VIDC_SM_PROFILE_INFO_SP = 1,
+ VIDC_SM_PROFILE_INFO_ASP = 2,
+ VIDC_SM_PROFILE_INFO_MAX = 0x7fffffff
+};
+
+enum vidc_sm_num_stuff_bytes_consume_info {
+ VIDC_SM_NUM_STUFF_BYTES_CONSUME_ALL = 0x0,
+ VIDC_SM_NUM_STUFF_BYTES_CONSUME_NONE = 0xffffffff
+};
+
+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, u32 cpcfc_enable, u32 sps_pps_control,
+ u32 closed_gop_enable);
+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);
+void vidc_sm_set_mpeg4_profile_override(struct ddl_buf_addr *shared_mem,
+ enum vidc_sm_mpeg4_profileinfo profile_info);
+void vidc_sm_set_decoder_sei_enable(struct ddl_buf_addr *shared_mem,
+ u32 sei_enable);
+void vidc_sm_get_decoder_sei_enable(struct ddl_buf_addr *shared_mem,
+ u32 *sei_enable);
+void vidc_sm_set_error_concealment_config(struct ddl_buf_addr *shared_mem,
+ u32 inter_slice, u32 intra_slice, u32 conceal_config_enable);
+void vidc_sm_set_decoder_stuff_bytes_consumption(
+ struct ddl_buf_addr *shared_mem,
+ enum vidc_sm_num_stuff_bytes_consume_info consume_info);
+void vidc_sm_set_video_core_timeout_value(struct ddl_buf_addr *shared_mem,
+ u32 timeout);
+void vidc_sm_get_aspect_ratio_info(struct ddl_buf_addr *shared_mem,
+ struct vcd_aspect_ratio *aspect_ratio_info);
+void vidc_sm_set_encoder_slice_batch_int_ctrl(struct ddl_buf_addr *shared_mem,
+ u32 slice_batch_int_enable);
+void vidc_sm_get_num_slices_comp(struct ddl_buf_addr *shared_mem,
+ u32 *num_slices_comp);
+void vidc_sm_set_encoder_batch_config(struct ddl_buf_addr *shared_mem,
+ u32 num_slices,
+ u32 input_addr, u32 output_addr,
+ u32 output_buffer_size);
+void vidc_sm_get_encoder_batch_output_size(struct ddl_buf_addr *shared_mem,
+ u32 *output_buffer_size);
+
+#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..6781e29
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
@@ -0,0 +1,487 @@
+/* Copyright (c) 2011-2012, 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 <mach/msm_subsystem_map.h>
+#include <mach/peripheral-loader.h>
+#include <linux/delay.h>
+#include "vcd_ddl_utils.h"
+#include "vcd_ddl.h"
+#include "vcd_res_tracker_api.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)
+static unsigned int vidc_mmu_subsystem[] = {
+ MSM_SUBSYSTEM_VIDEO, MSM_SUBSYSTEM_VIDEO_FWARE};
+
+#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 ;
+ u32 index = 0;
+ struct ddl_context *ddl_context;
+ struct msm_mapped_buffer *mapped_buffer = NULL;
+ unsigned long iova = 0;
+ unsigned long buffer_size = 0;
+ unsigned long *kernel_vaddr = NULL;
+ unsigned long ionflag = 0;
+ unsigned long flags = 0;
+ int ret = 0;
+ ion_phys_addr_t phyaddr = 0;
+ size_t len = 0;
+ int rc = 0;
+ DBG_PMEM("\n%s() IN: Requested alloc size(%u)", __func__, (u32)sz);
+ if (!addr) {
+ DDL_MSG_ERROR("\n%s() Invalid Parameters", __func__);
+ goto bail_out;
+ }
+ ddl_context = ddl_get_context();
+ res_trk_set_mem_type(addr->mem_type);
+ alloc_size = (sz + alignment);
+ if (res_trk_get_enable_ion()) {
+ if (!ddl_context->video_ion_client)
+ ddl_context->video_ion_client =
+ res_trk_get_ion_client();
+ if (!ddl_context->video_ion_client) {
+ DDL_MSG_ERROR("%s() :DDL ION Client Invalid handle\n",
+ __func__);
+ goto bail_out;
+ }
+ alloc_size = (alloc_size+4095) & ~4095;
+ addr->alloc_handle = ion_alloc(
+ ddl_context->video_ion_client, alloc_size, SZ_4K,
+ res_trk_get_mem_type());
+ if (IS_ERR_OR_NULL(addr->alloc_handle)) {
+ DDL_MSG_ERROR("%s() :DDL ION alloc failed\n",
+ __func__);
+ goto bail_out;
+ }
+ if (res_trk_check_for_sec_session() ||
+ addr->mem_type == DDL_FW_MEM)
+ ionflag = UNCACHED;
+ else
+ ionflag = CACHED;
+ kernel_vaddr = (unsigned long *) ion_map_kernel(
+ ddl_context->video_ion_client,
+ addr->alloc_handle, ionflag);
+ if (IS_ERR_OR_NULL(kernel_vaddr)) {
+ DDL_MSG_ERROR("%s() :DDL ION map failed\n",
+ __func__);
+ goto free_ion_alloc;
+ }
+ addr->virtual_base_addr = (u8 *) kernel_vaddr;
+ if (res_trk_check_for_sec_session()) {
+ rc = ion_phys(ddl_context->video_ion_client,
+ addr->alloc_handle, &phyaddr,
+ &len);
+ if (rc || !phyaddr) {
+ DDL_MSG_ERROR(
+ "%s():DDL ION client physical failed\n",
+ __func__);
+ goto unmap_ion_alloc;
+ }
+ addr->alloced_phys_addr = phyaddr;
+ } else {
+ ret = ion_map_iommu(ddl_context->video_ion_client,
+ addr->alloc_handle,
+ VIDEO_DOMAIN,
+ VIDEO_MAIN_POOL,
+ SZ_4K,
+ 0,
+ &iova,
+ &buffer_size,
+ UNCACHED, 0);
+ if (ret) {
+ DDL_MSG_ERROR(
+ "%s():DDL ION ion map iommu failed\n",
+ __func__);
+ goto unmap_ion_alloc;
+ }
+ addr->alloced_phys_addr = (phys_addr_t) iova;
+ }
+ if (!addr->alloced_phys_addr) {
+ DDL_MSG_ERROR("%s():DDL ION client physical failed\n",
+ __func__);
+ goto unmap_ion_alloc;
+ }
+ addr->mapped_buffer = NULL;
+ addr->physical_base_addr = (u8 *) addr->alloced_phys_addr;
+ 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 = alloc_size;
+ } else {
+ addr->alloced_phys_addr = (phys_addr_t)
+ allocate_contiguous_memory_nomap(alloc_size,
+ res_trk_get_mem_type(), SZ_4K);
+ if (!addr->alloced_phys_addr) {
+ DDL_MSG_ERROR("%s() : acm alloc failed (%d)\n",
+ __func__, alloc_size);
+ goto bail_out;
+ }
+ flags = MSM_SUBSYSTEM_MAP_IOVA | MSM_SUBSYSTEM_MAP_KADDR;
+ if (alignment == DDL_KILO_BYTE(128))
+ index = 1;
+ else if (alignment > SZ_4K)
+ flags |= MSM_SUBSYSTEM_ALIGN_IOVA_8K;
+
+ addr->mapped_buffer =
+ msm_subsystem_map_buffer((unsigned long)addr->alloced_phys_addr,
+ alloc_size, flags, &vidc_mmu_subsystem[index],
+ sizeof(vidc_mmu_subsystem[index])/sizeof(unsigned int));
+ if (IS_ERR(addr->mapped_buffer)) {
+ pr_err(" %s() buffer map failed", __func__);
+ goto free_acm_alloc;
+ }
+ mapped_buffer = addr->mapped_buffer;
+ if (!mapped_buffer->vaddr || !mapped_buffer->iova[0]) {
+ pr_err("%s() map buffers failed\n", __func__);
+ goto free_map_buffers;
+ }
+ addr->physical_base_addr = (u8 *)mapped_buffer->iova[0];
+ addr->virtual_base_addr = mapped_buffer->vaddr;
+ 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;
+ }
+ return addr->virtual_base_addr;
+free_map_buffers:
+ msm_subsystem_unmap_buffer(addr->mapped_buffer);
+ addr->mapped_buffer = NULL;
+free_acm_alloc:
+ free_contiguous_memory_by_paddr(
+ (unsigned long)addr->alloced_phys_addr);
+ addr->alloced_phys_addr = (phys_addr_t)NULL;
+ return NULL;
+unmap_ion_alloc:
+ ion_unmap_kernel(ddl_context->video_ion_client,
+ addr->alloc_handle);
+ addr->virtual_base_addr = NULL;
+ addr->alloced_phys_addr = (phys_addr_t)NULL;
+free_ion_alloc:
+ ion_free(ddl_context->video_ion_client,
+ addr->alloc_handle);
+ addr->alloc_handle = NULL;
+bail_out:
+ return NULL;
+}
+
+void ddl_pmem_free(struct ddl_buf_addr *addr)
+{
+ struct ddl_context *ddl_context;
+ ddl_context = ddl_get_context();
+ if (!addr) {
+ pr_err("%s() invalid args\n", __func__);
+ return;
+ }
+ if (ddl_context->video_ion_client) {
+ if (!IS_ERR_OR_NULL(addr->alloc_handle)) {
+ ion_unmap_kernel(ddl_context->video_ion_client,
+ addr->alloc_handle);
+ if (!res_trk_check_for_sec_session()) {
+ ion_unmap_iommu(ddl_context->video_ion_client,
+ addr->alloc_handle,
+ VIDEO_DOMAIN,
+ VIDEO_MAIN_POOL);
+ }
+ ion_free(ddl_context->video_ion_client,
+ addr->alloc_handle);
+ }
+ } else {
+ if (addr->mapped_buffer)
+ msm_subsystem_unmap_buffer(addr->mapped_buffer);
+ if (addr->alloced_phys_addr)
+ free_contiguous_memory_by_paddr(
+ (unsigned long)addr->alloced_phys_addr);
+ }
+ memset(addr, 0, sizeof(struct ddl_buf_addr));
+}
+
+#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
+
+u32 ddl_fw_init(struct ddl_buf_addr *dram_base)
+{
+ u8 *dest_addr;
+ dest_addr = DDL_GET_ALIGNED_VITUAL(*dram_base);
+ DDL_MSG_LOW("FW Addr / FW Size : %x/%d", (u32)vidc_video_codec_fw,
+ vidc_video_codec_fw_size);
+ if (res_trk_check_for_sec_session() && res_trk_is_cp_enabled()) {
+ if (res_trk_enable_footswitch()) {
+ pr_err("Failed to enable footswitch");
+ return false;
+ }
+ if(res_trk_enable_iommu_clocks()) {
+ res_trk_disable_footswitch();
+ pr_err("Failed to enable iommu clocks\n");
+ return false;
+ }
+ dram_base->pil_cookie = pil_get("vidc");
+ if(res_trk_disable_iommu_clocks())
+ pr_err("Failed to disable iommu clocks\n");
+ if (IS_ERR_OR_NULL(dram_base->pil_cookie)) {
+ pr_err("pil_get failed\n");
+ return false;
+ }
+ } else {
+ if (vidc_video_codec_fw_size > dram_base->buffer_size ||
+ !vidc_video_codec_fw)
+ return false;
+ memcpy(dest_addr, vidc_video_codec_fw,
+ vidc_video_codec_fw_size);
+ }
+ return true;
+}
+
+void ddl_fw_release(struct ddl_buf_addr *dram_base)
+{
+ void *cookie = dram_base->pil_cookie;
+ if (res_trk_is_cp_enabled() &&
+ res_trk_check_for_sec_session()) {
+ res_trk_close_secure_session();
+ if (IS_ERR_OR_NULL(cookie)){
+ pr_err("Invalid params");
+ return;
+ }
+ if (res_trk_enable_footswitch()) {
+ pr_err("Failed to enable footswitch");
+ return;
+ }
+ if(res_trk_enable_iommu_clocks()) {
+ res_trk_disable_footswitch();
+ pr_err("Failed to enable iommu clocks\n");
+ return;
+ }
+ pil_put(cookie);
+ if(res_trk_disable_iommu_clocks())
+ pr_err("Failed to disable iommu clocks\n");
+ if(res_trk_disable_footswitch())
+ pr_err("Failed to disable footswitch\n");
+ } else {
+ if (res_trk_check_for_sec_session())
+ res_trk_close_secure_session();
+ res_trk_release_fw_addr();
+ }
+}
+
+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_calc_core_proc_time_cnt(const char *func_name, u32 index, u32 count)
+{
+ 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 += 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_update_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);
+ time_data->ddl_t1 = act_time;
+ DDL_MSG_LOW("\n%s(): Start time updated Act(%u)",
+ func_name, act_time);
+}
+
+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..13bef35
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
@@ -0,0 +1,77 @@
+/* Copyright (c) 2010-2012, 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 <media/msm/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,
+ ENC_SLICE_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)
+#define DDL_MEMCPY(dest, src, len) memcpy((dest), (src), (len))
+#define DDL_MEMSET(src, value, len) memset((src), (value), (len))
+
+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);
+void ddl_calc_core_proc_time_cnt(const char *func_name, u32 index, u32 count);
+void ddl_update_core_start_time(const char *func_name, 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..c4ab478
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
@@ -0,0 +1,1164 @@
+/* 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
+static unsigned int run_cnt;
+
+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;
+ ddl_context->vidc_encode_slice_batch_start[0] =
+ vidc_1080p_encode_slice_batch_start_ch0;
+ ddl_context->vidc_encode_slice_batch_start[1] =
+ vidc_1080p_encode_slice_batch_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;
+ if ((decoder->codec.codec == VCD_CODEC_MPEG4) ||
+ (decoder->codec.codec == VCD_CODEC_DIVX_4) ||
+ (decoder->codec.codec == VCD_CODEC_DIVX_5) ||
+ (decoder->codec.codec == VCD_CODEC_DIVX_6) ||
+ (decoder->codec.codec == VCD_CODEC_XVID))
+ vidc_sm_set_mpeg4_profile_override(
+ &ddl->shared_mem[ddl->command_channel],
+ VIDC_SM_PROFILE_INFO_ASP);
+ if (VCD_CODEC_H264 == decoder->codec.codec)
+ vidc_sm_set_decoder_sei_enable(
+ &ddl->shared_mem[ddl->command_channel],
+ VIDC_SM_RECOVERY_POINT_SEI);
+ ddl_context->vidc_decode_seq_start[ddl->command_channel](
+ &seq_start_param);
+
+ vidc_sm_set_decoder_stuff_bytes_consumption(
+ &ddl->shared_mem[ddl->command_channel],
+ VIDC_SM_NUM_STUFF_BYTES_CONSUME_NONE);
+}
+
+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_GOB:
+ 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);
+}
+
+static void ddl_vidc_encode_set_batch_slice_info(
+ struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ DDL_MSG_LOW("%s\n", __func__);
+ encoder->batch_frame.slice_batch_out.buffer_size =
+ encoder->output_buf_req.sz;
+ DDL_MSG_LOW("encoder->batch_frame.slice_batch_out.buffer_size = %d\n",
+ encoder->batch_frame.slice_batch_out.buffer_size);
+ vidc_sm_set_encoder_batch_config(
+ &ddl->shared_mem[ddl->command_channel],
+ 1,
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ encoder->batch_frame.slice_batch_in),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ encoder->batch_frame.slice_batch_out),
+ encoder->batch_frame.slice_batch_out.buffer_size);
+ vidc_sm_set_encoder_slice_batch_int_ctrl(
+ &ddl->shared_mem[ddl->command_channel],
+ 0);
+}
+
+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;
+ u32 h263_cpfc_enable = false;
+ u32 scaled_frame_rate;
+
+ 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;
+ scaled_frame_rate = DDL_FRAMERATE_SCALE(encoder->\
+ frame_rate.fps_numerator) /
+ encoder->frame_rate.fps_denominator;
+ if ((encoder->codec.codec == VCD_CODEC_H263) &&
+ (DDL_FRAMERATE_SCALE(DDL_INITIAL_FRAME_RATE)
+ != scaled_frame_rate))
+ h263_cpfc_enable = true;
+ vidc_sm_set_extended_encoder_control(&ddl->shared_mem
+ [ddl->command_channel], hdr_ext_control,
+ r_cframe_skip, false, 0,
+ h263_cpfc_enable, encoder->sps_pps.sps_pps_for_idr_enable_flag,
+ encoder->closed_gop);
+ 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(
+ scaled_frame_rate,
+ 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_MSG_LOW("%s\n", __func__);
+ 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;
+ enc_param.slice_enable = 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);
+}
+
+void ddl_vidc_encode_frame_continue(struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct vcd_frame_data *input_vcd_frm = &(ddl->input_frame.vcd_frm);
+ u32 address_offset;
+ address_offset = (u32)(ddl->output_frame.vcd_frm.physical -
+ ddl_context->dram_base_a.align_physical_addr) >>
+ DDL_VIDC_1080P_BASE_OFFSET_SHIFT;
+ DDL_MSG_LOW("%s\n", __func__);
+ if (VCD_FRAME_FLAG_EOS & input_vcd_frm->flags)
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_EOS_DONE;
+ else
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME_DONE;
+ ddl->cmd_state = DDL_CMD_ENCODE_CONTINUE;
+ vidc_1080p_set_host2risc_cmd(VIDC_1080P_HOST2RISC_CMD_CONTINUE_ENC,
+ address_offset,
+ 0, 0, 0);
+}
+
+void ddl_vidc_encode_slice_batch_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 *input_vcd_frm =
+ &(ddl->input_frame.vcd_frm);
+ u32 dpb_addr_y[4], dpb_addr_c[4];
+ u32 index, y_addr, c_addr;
+ u32 bitstream_size;
+ struct vidc_1080p_enc_slice_batch_in_param *slice_batch_in =
+ (struct vidc_1080p_enc_slice_batch_in_param *)
+ encoder->batch_frame.slice_batch_in.align_virtual_addr;
+ DDL_MSG_LOW("%s\n", __func__);
+ DDL_MEMSET(slice_batch_in, 0,
+ sizeof(struct vidc_1080p_enc_slice_batch_in_param));
+ DDL_MEMSET(encoder->batch_frame.slice_batch_in.align_virtual_addr, 0,
+ sizeof(struct vidc_1080p_enc_slice_batch_in_param));
+ encoder->batch_frame.out_frm_next_frmindex = 0;
+ bitstream_size = encoder->batch_frame.output_frame[0].vcd_frm.alloc_len;
+ encoder->output_buf_req.sz = bitstream_size;
+ 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);
+ enc_param.encode = VIDC_1080P_ENC_TYPE_SLICE_BATCH_START;
+ DDL_MSG_LOW("ddl_state_transition: %s ~~>"
+ "DDL_CLIENT_WAIT_FOR_FRAME_DONE",
+ ddl_get_state_string(ddl->client_state));
+ slice_batch_in->cmd_type = VIDC_1080P_ENC_TYPE_SLICE_BATCH_START;
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME_DONE;
+ ddl->cmd_state = DDL_CMD_ENCODE_FRAME;
+ 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_size = bitstream_size;
+ slice_batch_in->num_stream_buffer =
+ encoder->batch_frame.num_output_frames;
+ slice_batch_in->stream_buffer_size = bitstream_size;
+ DDL_MSG_LOW("%s slice_batch_in->num_stream_buffer = %u size = %u\n",
+ __func__, slice_batch_in->num_stream_buffer,
+ slice_batch_in->stream_buffer_size);
+ for (index = 0; index < encoder->batch_frame.num_output_frames;
+ index++) {
+ slice_batch_in->stream_buffer_addr_offset[index] =
+ ((DDL_OFFSET(ddl_context->dram_base_b.align_physical_addr,
+ encoder->batch_frame.output_frame[index].vcd_frm.physical)) >>
+ DDL_VIDC_1080P_BASE_OFFSET_SHIFT);
+ }
+ slice_batch_in->input_size = VIDC_1080P_SLICE_BATCH_IN_SIZE(index);
+ enc_param.intra_frame = encoder->intra_frame_insertion;
+ if (encoder->intra_frame_insertion)
+ encoder->intra_frame_insertion = false;
+ enc_param.input_flush = false;
+ enc_param.slice_enable =
+ encoder->slice_delivery_info.enable;
+ 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);
+ DDL_MSG_LOW("%sdpb_count = %d\n", __func__, enc_buffers->dpb_count);
+ 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();
+ }
+ if ((!encoder->rc_level.frame_level_rc) &&
+ (!encoder->rc_level.mb_level_rc)) {
+ encoder->session_qp.p_frame_qp++;
+ if (encoder->session_qp.p_frame_qp > encoder->qp_range.max_qp)
+ encoder->session_qp.p_frame_qp =
+ encoder->qp_range.min_qp;
+ 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 (vidc_msg_timing) {
+ if (run_cnt < 2) {
+ ddl_reset_core_time_variables(ENC_OP_TIME);
+ ddl_reset_core_time_variables(ENC_SLICE_OP_TIME);
+ run_cnt++;
+ }
+ ddl_update_core_start_time(__func__, ENC_SLICE_OP_TIME);
+ ddl_set_core_start_time(__func__, ENC_OP_TIME);
+ }
+ ddl_vidc_encode_set_batch_slice_info(ddl);
+ ddl_context->vidc_encode_slice_batch_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;
+ u32 size_y = 0;
+ u32 size_c = 0;
+
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_DPB)) {
+ DDL_MSG_ERROR("STATE-CRITICAL");
+ return VCD_ERR_FAIL;
+ }
+ ddl_set_vidc_timeout(ddl);
+ 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);
+ if (ddl_decoder_dpb_init(ddl) == VCD_ERR_FAIL)
+ return VCD_ERR_FAIL;
+ 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;
+ if (decoder->cont_mode) {
+ size_y = ddl_get_yuv_buf_size(decoder->client_frame_size.width,
+ decoder->client_frame_size.height,
+ DDL_YUV_BUF_TYPE_TILE);
+ size_c = ddl_get_yuv_buf_size(decoder->client_frame_size.width,
+ (decoder->client_frame_size.height >> 1),
+ DDL_YUV_BUF_TYPE_TILE);
+ vidc_sm_set_allocated_dpb_size(
+ &ddl->shared_mem[ddl->command_channel],
+ size_y,
+ size_c);
+ } else {
+ 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;
+ init_buf_param.dmx_disable = decoder->dmx_disable;
+ 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;
+ dec_param.dmx_disable = decoder->dmx_disable;
+ if (decoder->dmx_disable)
+ ddl_fill_dec_desc_buffer(ddl);
+ 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);
+}
+
+void ddl_vidc_encode_eos_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);
+ DDL_MSG_LOW("%s\n", __func__);
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_EOS_DONE;
+ ddl_vidc_encode_dynamic_property(ddl, true);
+ ddl->client_state = DDL_CMD_EOS;
+ DDL_MEMSET(&enc_param, 0, sizeof(enc_param));
+ enc_param.encode = VIDC_1080P_ENC_TYPE_LAST_FRAME_DATA;
+ 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 = 0;
+ enc_param.current_c_addr_offset = 0;
+ enc_param.stream_buffer_size = 0;
+ enc_param.intra_frame = encoder->intra_frame_insertion;
+ vidc_sm_set_frame_tag(&ddl->shared_mem[ddl->command_channel],
+ ddl->input_frame.vcd_frm.ip_frm_tag);
+ ddl_context->vidc_encode_frame_start[ddl->command_channel](
+ &enc_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..d399847
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc.c
@@ -0,0 +1,1108 @@
+/* Copyright (c) 2010-2012, 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_RG7_DISPLAY_CORRECT_MASK 0x00000180
+#define VIDC_1080P_SI_RG7_DISPLAY_CORRECT_SHIFT 7
+#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_SI_RG11_DECODE_CORRECT_MASK 0x00000600
+#define VIDC_1080P_SI_RG11_DECODE_CORRECT_SHIFT 9
+#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_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_BMSK 0x00004000
+#define VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT 14
+#define VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_BMSK 0x80000000
+#define VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT 31
+#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);
+ dec_disp_info->display_correct = VIDC_GETFIELD(display_result,
+ VIDC_1080P_SI_RG7_DISPLAY_CORRECT_MASK,
+ VIDC_1080P_SI_RG7_DISPLAY_CORRECT_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);
+ dec_disp_info->decode_correct = VIDC_GETFIELD(decode_result,
+ VIDC_1080P_SI_RG11_DECODE_CORRECT_MASK,
+ VIDC_1080P_SI_RG11_DECODE_CORRECT_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_404623, 0);
+ 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_404623, 0);
+ 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->dmx_disable,
+ VIDC_1080P_SI_RG10_DMX_DISABLE_SHFT,
+ VIDC_1080P_SI_RG10_DMX_DISABLE_BMSK) |
+ 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->dmx_disable,
+ VIDC_1080P_SI_RG10_DMX_DISABLE_SHFT,
+ VIDC_1080P_SI_RG10_DMX_DISABLE_BMSK) |
+ 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)
+{
+ u32 dpb_config;
+ VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
+ VIDC_HWIO_OUT(REG_666957, VIDC_1080P_INIT_CH_INST_ID);
+ dpb_config = VIDC_SETFIELD(param->dmx_disable,
+ VIDC_1080P_SI_RG10_DMX_DISABLE_SHFT,
+ VIDC_1080P_SI_RG10_DMX_DISABLE_BMSK) |
+ VIDC_SETFIELD(param->dpb_count,
+ VIDC_1080P_SI_RG10_NUM_DPB_SHFT,
+ VIDC_1080P_SI_RG10_NUM_DPB_BMSK);
+ 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, VIDC_1080P_DEC_TYPE_INIT_BUFFERS |
+ param->inst_id);
+}
+
+void vidc_1080p_decode_init_buffers_ch1(
+ struct vidc_1080p_dec_init_buffers_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);
+ dpb_config = VIDC_SETFIELD(param->dmx_disable,
+ VIDC_1080P_SI_RG10_DMX_DISABLE_SHFT,
+ VIDC_1080P_SI_RG10_DMX_DISABLE_BMSK) |
+ VIDC_SETFIELD(param->dpb_count,
+ VIDC_1080P_SI_RG10_NUM_DPB_SHFT,
+ VIDC_1080P_SI_RG10_NUM_DPB_BMSK);
+ 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, 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)
+{
+ u32 input_flush;
+ 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);
+ input_flush = VIDC_SETFIELD(param->input_flush,
+ VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT,
+ VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_BMSK);
+ input_flush |= VIDC_SETFIELD(param->slice_enable,
+ VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT,
+ VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_BMSK);
+ VIDC_HWIO_OUT(REG_404623, 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)
+{
+ u32 input_flush;
+ 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);
+ input_flush = VIDC_SETFIELD(param->input_flush,
+ VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT,
+ VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_BMSK);
+ input_flush |= VIDC_SETFIELD(param->slice_enable,
+ VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT,
+ VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_BMSK);
+
+ VIDC_HWIO_OUT(REG_404623, 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_encode_slice_batch_start_ch0(
+ struct vidc_1080p_enc_frame_start_param *param)
+{
+ u32 input_flush;
+ 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_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);
+ input_flush = VIDC_SETFIELD(param->input_flush,
+ VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT,
+ VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_BMSK);
+ input_flush |= VIDC_SETFIELD(param->slice_enable,
+ VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT,
+ VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_BMSK);
+ VIDC_HWIO_OUT(REG_404623, 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_slice_batch_start_ch1(
+ struct vidc_1080p_enc_frame_start_param *param)
+{
+ u32 input_flush;
+ 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_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);
+ input_flush = VIDC_SETFIELD(param->input_flush,
+ VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT,
+ VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_BMSK);
+ input_flush |= VIDC_SETFIELD(param->slice_enable,
+ VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT,
+ VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_BMSK);
+
+ VIDC_HWIO_OUT(REG_404623, 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..7460ef3
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc.h
@@ -0,0 +1,586 @@
+/* Copyright (c) 2010-2012, 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_SLICE_DONE_RET 6
+#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_BATCH_ENC_RET 14
+#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_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_DEBLOCKING_NOT_DONE 178
+#define VIDC_1080P_WARN_INCOMPLETE_FRAME 179
+#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_WARN_NO_LONG_TERM_REFERENCE 183
+#define VIDC_1080P_WARN_NO_SPACE_MPEG2_DATA_DUMP 190
+#define VIDC_1080P_WARN_METADATA_NO_SPACE_MISSING_MB 191
+
+#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
+#define VIDC_1080P_SLICE_BATCH_MAX_STRM_BFR 8
+#define VIDC_1080P_SLICE_BATCH_IN_SIZE(idx) (4 * sizeof(u32) + \
+ idx * sizeof(u32))
+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_decode_frame_correct_type {
+ VIDC_1080P_DECODE_NOT_CORRECT = 0,
+ VIDC_1080P_DECODE_CORRECT = 1,
+ VIDC_1080P_DECODE_APPROX_CORRECT = 2,
+ VIDC_1080P_DECODE_CORRECTTYPE_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_SLICE_BATCH_START = 0x00070000,
+ 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;
+ u32 dmx_disable;
+ 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;
+ u32 dmx_disable;
+};
+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;
+ u32 slice_enable;
+ 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_enc_slice_batch_in_param {
+ u32 cmd_type;
+ u32 input_size;
+ u32 num_stream_buffer;
+ u32 stream_buffer_size;
+ u32 stream_buffer_addr_offset[VIDC_1080P_SLICE_BATCH_MAX_STRM_BFR];
+};
+struct vidc_1080p_enc_slice_info {
+ u32 stream_buffer_idx;
+ u32 stream_buffer_size;
+};
+struct vidc_1080p_enc_slice_batch_out_param {
+ u32 cmd_type;
+ u32 output_size;
+ struct vidc_1080p_enc_slice_info slice_info
+ [VIDC_1080P_SLICE_BATCH_MAX_STRM_BFR];
+};
+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_correct_type display_correct;
+ enum vidc_1080P_decode_frame_correct_type decode_correct;
+ 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_encode_slice_batch_start_ch0(
+ struct vidc_1080p_enc_frame_start_param *param);
+void vidc_1080p_encode_slice_batch_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..a5a8e57
--- /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) __raw_readl(port)
+#define __outpdw(port, val) __raw_writel(val, port)
+
+#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 100755
index 0000000..7af0de3
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
@@ -0,0 +1,991 @@
+/* Copyright (c) 2010-2012, 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_memtypes.h>
+#include <linux/interrupt.h>
+#include <linux/memory_alloc.h>
+#include <asm/sizes.h>
+#include <media/msm/vidc_init.h>
+#include "vidc.h"
+#include "vcd_res_tracker.h"
+
+#define PIL_FW_BASE_ADDR 0xafe00000
+#define PIL_FW_SIZE 0x200000
+
+static unsigned int vidc_clk_table[4] = {
+ 48000000, 133330000, 200000000, 228570000,
+};
+static unsigned int restrk_mmu_subsystem[] = {
+ MSM_SUBSYSTEM_VIDEO, MSM_SUBSYSTEM_VIDEO_FWARE};
+static struct res_trk_context resource_context;
+
+#define VIDC_FW "vidc_1080p.fw"
+#define VIDC_FW_SIZE SZ_1M
+
+struct res_trk_vidc_mmu_clk {
+ char *mmu_clk_name;
+ struct clk *mmu_clk;
+};
+
+static struct res_trk_vidc_mmu_clk vidc_mmu_clks[] = {
+ {"mdp_iommu_clk"}, {"rot_iommu_clk"},
+ {"vcodec_iommu0_clk"}, {"vcodec_iommu1_clk"},
+ {"smmu_iface_clk"}
+};
+
+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 void *res_trk_pmem_map
+ (struct ddl_buf_addr *addr, size_t sz, u32 alignment)
+{
+ u32 offset = 0, flags = 0;
+ u32 index = 0;
+ struct ddl_context *ddl_context;
+ struct msm_mapped_buffer *mapped_buffer = NULL;
+ int ret = 0;
+ unsigned long iova = 0;
+ unsigned long buffer_size = 0;
+ unsigned long *kernel_vaddr = NULL;
+
+ ddl_context = ddl_get_context();
+ if (res_trk_get_enable_ion() && addr->alloc_handle) {
+ kernel_vaddr = (unsigned long *) ion_map_kernel(
+ ddl_context->video_ion_client,
+ addr->alloc_handle, UNCACHED);
+ if (IS_ERR_OR_NULL(kernel_vaddr)) {
+ DDL_MSG_ERROR("%s():DDL ION client map failed\n",
+ __func__);
+ goto ion_bail_out;
+ }
+ addr->virtual_base_addr = (u8 *) kernel_vaddr;
+ ret = ion_map_iommu(ddl_context->video_ion_client,
+ addr->alloc_handle,
+ VIDEO_DOMAIN,
+ VIDEO_FIRMWARE_POOL,
+ SZ_4K,
+ 0,
+ &iova,
+ &buffer_size,
+ UNCACHED, 0);
+ if (ret) {
+ DDL_MSG_ERROR("%s():DDL ION client iommu map failed\n",
+ __func__);
+ goto ion_unmap_bail_out;
+ }
+ addr->mapped_buffer = NULL;
+ addr->physical_base_addr = (u8 *)iova;
+ 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 = buffer_size;
+ } else {
+ if (!res_trk_check_for_sec_session()) {
+ if (!addr->alloced_phys_addr) {
+ pr_err(" %s() alloced addres NULL", __func__);
+ goto bail_out;
+ }
+ flags = MSM_SUBSYSTEM_MAP_IOVA|MSM_SUBSYSTEM_MAP_KADDR;
+ if (alignment == DDL_KILO_BYTE(128))
+ index = 1;
+ else if (alignment > SZ_4K)
+ flags |= MSM_SUBSYSTEM_ALIGN_IOVA_8K;
+
+ addr->mapped_buffer =
+ msm_subsystem_map_buffer(
+ (unsigned long)addr->alloced_phys_addr,
+ sz, flags, &restrk_mmu_subsystem[index],
+ sizeof(restrk_mmu_subsystem[index])
+ /sizeof(unsigned int));
+ if (IS_ERR(addr->mapped_buffer)) {
+ pr_err(" %s() buffer map failed", __func__);
+ goto bail_out;
+ }
+ mapped_buffer = addr->mapped_buffer;
+ if (!mapped_buffer->vaddr || !mapped_buffer->iova[0]) {
+ pr_err("%s() map buffers failed\n", __func__);
+ goto bail_out;
+ }
+ addr->physical_base_addr = (u8 *)mapped_buffer->iova[0];
+ addr->virtual_base_addr = mapped_buffer->vaddr;
+ } else {
+ addr->physical_base_addr = (u8 *)
+ addr->alloced_phys_addr;
+ addr->virtual_base_addr = (u8 *)
+ addr->alloced_phys_addr;
+ }
+ 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;
+ }
+ return addr->virtual_base_addr;
+bail_out:
+ if (addr->mapped_buffer)
+ msm_subsystem_unmap_buffer(addr->mapped_buffer);
+ return NULL;
+ion_unmap_bail_out:
+ if (!IS_ERR_OR_NULL(addr->alloc_handle)) {
+ ion_unmap_kernel(resource_context.
+ res_ion_client, addr->alloc_handle);
+ }
+ion_bail_out:
+ return NULL;
+}
+
+static void res_trk_pmem_free(struct ddl_buf_addr *addr)
+{
+ /* TODO Pmem*/
+ struct ddl_context *ddl_context;
+ ddl_context = ddl_get_context();
+ if (ddl_context->video_ion_client) {
+ if (addr && addr->alloc_handle) {
+ ion_free(ddl_context->video_ion_client, addr->alloc_handle);
+ addr->alloc_handle = NULL;
+ }
+ }
+}
+static int res_trk_pmem_alloc
+ (struct ddl_buf_addr *addr, size_t sz, u32 alignment)
+{
+ u32 alloc_size;
+ struct ddl_context *ddl_context;
+ int rc = 0;
+ DBG_PMEM("\n%s() IN: Requested alloc size(%u)", __func__, (u32)sz);
+ if (!addr) {
+ DDL_MSG_ERROR("\n%s() Invalid Parameters", __func__);
+ rc = -EINVAL;
+ goto bail_out;
+ }
+ ddl_context = ddl_get_context();
+ res_trk_set_mem_type(addr->mem_type);
+ alloc_size = (sz + alignment);
+ if (res_trk_get_enable_ion()) {
+ if (!res_trk_is_cp_enabled() || !res_trk_check_for_sec_session()) {
+ if (!ddl_context->video_ion_client)
+ ddl_context->video_ion_client =
+ res_trk_get_ion_client();
+ if (!ddl_context->video_ion_client) {
+ DDL_MSG_ERROR("%s() :DDL ION Client Invalid handle\n",
+ __func__);
+ rc = -ENOMEM;
+ goto bail_out;
+ }
+ alloc_size = (alloc_size+4095) & ~4095;
+ addr->alloc_handle = ion_alloc(
+ ddl_context->video_ion_client, alloc_size, SZ_4K,
+ res_trk_get_mem_type());
+ if (IS_ERR_OR_NULL(addr->alloc_handle)) {
+ DDL_MSG_ERROR("%s() :DDL ION alloc failed\n",
+ __func__);
+ rc = -ENOMEM;
+ goto bail_out;
+ }
+ } else {
+ addr->alloc_handle = NULL;
+ addr->alloced_phys_addr = PIL_FW_BASE_ADDR;
+ addr->buffer_size = sz;
+ }
+ } else {
+ addr->alloced_phys_addr = (phys_addr_t)
+ allocate_contiguous_memory_nomap(alloc_size,
+ res_trk_get_mem_type(), SZ_4K);
+ if (!addr->alloced_phys_addr) {
+ DDL_MSG_ERROR("%s() : acm alloc failed (%d)\n",
+ __func__, alloc_size);
+ rc = -ENOMEM;
+ goto bail_out;
+ }
+ addr->buffer_size = sz;
+ return rc;
+ }
+bail_out:
+ return rc;
+}
+
+static void res_trk_pmem_unmap(struct ddl_buf_addr *addr)
+{
+ if (!addr) {
+ pr_err("%s() invalid args\n", __func__);
+ return;
+ }
+ if (!IS_ERR_OR_NULL(addr->alloc_handle)) {
+ if (addr->physical_base_addr) {
+ ion_unmap_kernel(resource_context.res_ion_client,
+ addr->alloc_handle);
+ if (!res_trk_check_for_sec_session()) {
+ ion_unmap_iommu(resource_context.res_ion_client,
+ addr->alloc_handle,
+ VIDEO_DOMAIN,
+ VIDEO_FIRMWARE_POOL);
+ }
+ addr->virtual_base_addr = NULL;
+ addr->physical_base_addr = NULL;
+ }
+ } else if (addr->mapped_buffer)
+ msm_subsystem_unmap_buffer(addr->mapped_buffer);
+ addr->mapped_buffer = NULL;
+}
+
+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,
+ "core_clk");
+ if (IS_ERR(resource_context.vcodec_clk)) {
+ VCDRES_MSG_ERROR("%s(): core_clk get failed\n",
+ __func__);
+ goto bail_out;
+ }
+ resource_context.vcodec_pclk = clk_get(resource_context.device,
+ "iface_clk");
+ if (IS_ERR(resource_context.vcodec_pclk)) {
+ VCDRES_MSG_ERROR("%s(): iface_clk get failed\n",
+ __func__);
+ goto release_vcodec_clk;
+ }
+ 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:
+ clk_put(resource_context.vcodec_pclk);
+ resource_context.vcodec_pclk = 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);
+ 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;
+ }
+
+ 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;
+}
+
+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);
+ 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;
+}
+
+static struct ion_client *res_trk_create_ion_client(void){
+ struct ion_client *video_client;
+ video_client = msm_ion_client_create(-1, "video_client");
+ return video_client;
+}
+
+int res_trk_enable_footswitch(void)
+{
+ int rc = 0;
+ mutex_lock(&resource_context.lock);
+ 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;
+ rc = -EINVAL;
+ } else
+ rc = regulator_enable(resource_context.footswitch);
+ mutex_unlock(&resource_context.lock);
+ return rc;
+}
+
+int res_trk_disable_footswitch(void)
+{
+ mutex_lock(&resource_context.lock);
+ 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;
+ }
+ mutex_unlock(&resource_context.lock);
+ return 0;
+}
+
+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");
+ res_trk_pmem_unmap(&resource_context.firmware_addr);
+ res_trk_pmem_free(&resource_context.firmware_addr);
+#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 if (perf_level <= RESTRK_1080P_MAX_PERF_LEVEL)
+ bus_clk_index = 2;
+ else
+ bus_clk_index = 3;
+
+ if (dev_ctxt->reqd_perf_lvl + dev_ctxt->curr_perf_lvl == 0)
+ bus_clk_index = 2;
+ else if (resource_context.vidc_platform_data->disable_turbo
+ && bus_clk_index == 3) {
+ VCDRES_MSG_ERROR("Warning: Turbo mode not supported "
+ " falling back to 1080p bus\n");
+ 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);
+
+ if (resource_context.vidc_platform_data->disable_turbo
+ && req_perf_lvl > RESTRK_1080P_MAX_PERF_LEVEL) {
+ VCDRES_MSG_ERROR("%s(): Turbo not supported! dev_ctxt(%p)\n",
+ __func__, dev_ctxt);
+ }
+
+#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 if (req_perf_lvl <= RESTRK_1080P_MAX_PERF_LEVEL) {
+ vidc_freq = vidc_clk_table[2];
+ *pn_set_perf_lvl = RESTRK_1080P_MAX_PERF_LEVEL;
+ } else {
+ vidc_freq = vidc_clk_table[3];
+ *pn_set_perf_lvl = RESTRK_1080P_TURBO_PERF_LEVEL;
+ }
+
+ if (resource_context.vidc_platform_data->disable_turbo &&
+ *pn_set_perf_lvl == RESTRK_1080P_TURBO_PERF_LEVEL) {
+ VCDRES_MSG_ERROR("Warning: Turbo mode not supported "
+ " falling back to 1080p clocks\n");
+ 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);
+ mutex_init(&resource_context.secure_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;
+ resource_context.fw_mem_type =
+ resource_context.vidc_platform_data->memtype;
+ resource_context.cmd_mem_type =
+ resource_context.vidc_platform_data->memtype;
+ if (resource_context.vidc_platform_data->enable_ion) {
+ resource_context.res_ion_client =
+ res_trk_create_ion_client();
+ if (!(resource_context.res_ion_client)) {
+ VCDRES_MSG_ERROR("%s()ION createfail\n",
+ __func__);
+ return;
+ }
+ resource_context.fw_mem_type =
+ ION_MM_FIRMWARE_HEAP_ID;
+ resource_context.cmd_mem_type =
+ ION_CP_MFC_HEAP_ID;
+ }
+ resource_context.disable_dmx =
+ resource_context.vidc_platform_data->disable_dmx;
+ resource_context.disable_fullhd =
+ resource_context.vidc_platform_data->disable_fullhd;
+#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.disable_dmx = 0;
+ }
+ resource_context.core_type = VCD_CORE_1080P;
+ resource_context.firmware_addr.mem_type = DDL_FW_MEM;
+ }
+}
+
+u32 res_trk_get_core_type(void){
+ return resource_context.core_type;
+}
+
+u32 res_trk_get_firmware_addr(struct ddl_buf_addr *firm_addr)
+{
+ int rc = 0;
+ size_t size= 0;
+ if (!firm_addr || resource_context.firmware_addr.mapped_buffer) {
+ pr_err("%s() invalid params", __func__);
+ return -EINVAL;
+ }
+ if (res_trk_is_cp_enabled() && res_trk_check_for_sec_session())
+ size = PIL_FW_SIZE;
+ else
+ size = VIDC_FW_SIZE;
+
+ if (res_trk_pmem_alloc(&resource_context.firmware_addr,
+ size, DDL_KILO_BYTE(128))) {
+ pr_err("%s() Firmware buffer allocation failed",
+ __func__);
+ memset(&resource_context.firmware_addr, 0,
+ sizeof(resource_context.firmware_addr));
+ rc = -ENOMEM;
+ goto fail_alloc;
+ }
+ if (!res_trk_pmem_map(&resource_context.firmware_addr,
+ resource_context.firmware_addr.buffer_size,
+ DDL_KILO_BYTE(128))) {
+ pr_err("%s() Firmware buffer mapping failed",
+ __func__);
+ rc = -ENOMEM;
+ goto fail_map;
+ }
+ memcpy(firm_addr, &resource_context.firmware_addr,
+ sizeof(struct ddl_buf_addr));
+ return 0;
+fail_map:
+ res_trk_pmem_free(&resource_context.firmware_addr);
+fail_alloc:
+ return rc;
+}
+
+void res_trk_release_fw_addr(void)
+{
+ res_trk_pmem_unmap(&resource_context.firmware_addr);
+ res_trk_pmem_free(&resource_context.firmware_addr);
+}
+
+int res_trk_check_for_sec_session(void)
+{
+ int rc;
+ mutex_lock(&resource_context.secure_lock);
+ rc = resource_context.secure_session;
+ mutex_unlock(&resource_context.secure_lock);
+ return rc;
+}
+
+int res_trk_get_mem_type(void)
+{
+ int mem_type = -1;
+ switch (resource_context.res_mem_type) {
+ case DDL_FW_MEM:
+ mem_type = ION_HEAP(resource_context.fw_mem_type);
+ return mem_type;
+ case DDL_MM_MEM:
+ mem_type = resource_context.memtype;
+ break;
+ case DDL_CMD_MEM:
+ if (res_trk_check_for_sec_session())
+ mem_type = resource_context.cmd_mem_type;
+ else
+ mem_type = resource_context.memtype;
+ break;
+ default:
+ return mem_type;
+ }
+ if (resource_context.vidc_platform_data->enable_ion) {
+ if (res_trk_check_for_sec_session()) {
+ mem_type = ION_HEAP(mem_type);
+ if(resource_context.res_mem_type != DDL_FW_MEM)
+ mem_type |= ION_SECURE;
+ else if (res_trk_is_cp_enabled())
+ mem_type |= ION_SECURE;
+ }
+ else
+ mem_type = (ION_HEAP(mem_type) |
+ ION_HEAP(ION_IOMMU_HEAP_ID));
+ }
+ return mem_type;
+}
+
+u32 res_trk_is_cp_enabled(void)
+{
+ if (resource_context.vidc_platform_data->cp_enabled)
+ return 1;
+ else
+ return 0;
+}
+
+u32 res_trk_get_enable_ion(void)
+{
+ if (resource_context.vidc_platform_data->enable_ion)
+ return 1;
+ else
+ return 0;
+}
+
+struct ion_client *res_trk_get_ion_client(void)
+{
+ return resource_context.res_ion_client;
+}
+
+u32 res_trk_get_disable_dmx(void){
+ return resource_context.disable_dmx;
+}
+
+void res_trk_set_mem_type(enum ddl_mem_area mem_type)
+{
+ resource_context.res_mem_type = mem_type;
+ return;
+}
+
+u32 res_trk_get_disable_fullhd(void)
+{
+ return resource_context.disable_fullhd;
+}
+
+int res_trk_enable_iommu_clocks(void)
+{
+ int ret = 0, i;
+ if (resource_context.mmu_clks_on) {
+ pr_err(" %s: Clocks are already on", __func__);
+ return -EINVAL;
+ }
+ resource_context.mmu_clks_on = 1;
+ for (i = 0; i < ARRAY_SIZE(vidc_mmu_clks); i++) {
+ vidc_mmu_clks[i].mmu_clk = clk_get(resource_context.device,
+ vidc_mmu_clks[i].mmu_clk_name);
+ if (IS_ERR(vidc_mmu_clks[i].mmu_clk)) {
+ pr_err(" %s: Get failed for clk %s", __func__,
+ vidc_mmu_clks[i].mmu_clk_name);
+ ret = PTR_ERR(vidc_mmu_clks[i].mmu_clk);
+ }
+ if (!ret) {
+ ret = clk_enable(vidc_mmu_clks[i].mmu_clk);
+ if (ret) {
+ clk_put(vidc_mmu_clks[i].mmu_clk);
+ vidc_mmu_clks[i].mmu_clk = NULL;
+ }
+ }
+ if (ret) {
+ for (i--; i >= 0; i--) {
+ clk_disable(vidc_mmu_clks[i].mmu_clk);
+ clk_put(vidc_mmu_clks[i].mmu_clk);
+ vidc_mmu_clks[i].mmu_clk = NULL;
+ }
+ resource_context.mmu_clks_on = 0;
+ pr_err("%s() clocks enable failed", __func__);
+ break;
+ }
+ }
+ return ret;
+}
+
+int res_trk_disable_iommu_clocks(void)
+{
+ int i;
+ if (!resource_context.mmu_clks_on) {
+ pr_err(" %s: clks are already off", __func__);
+ return -EINVAL;
+ }
+ resource_context.mmu_clks_on = 0;
+ for (i = 0; i < ARRAY_SIZE(vidc_mmu_clks); i++) {
+ clk_disable(vidc_mmu_clks[i].mmu_clk);
+ clk_put(vidc_mmu_clks[i].mmu_clk);
+ vidc_mmu_clks[i].mmu_clk = NULL;
+ }
+ return 0;
+}
+
+void res_trk_secure_unset(void)
+{
+ mutex_lock(&resource_context.secure_lock);
+ resource_context.secure_session--;
+ mutex_unlock(&resource_context.secure_lock);
+}
+
+void res_trk_secure_set(void)
+{
+ mutex_lock(&resource_context.secure_lock);
+ resource_context.secure_session++;
+ mutex_unlock(&resource_context.secure_lock);
+}
+
+int res_trk_open_secure_session()
+{
+ int rc;
+
+ if (res_trk_check_for_sec_session() == 1) {
+ mutex_lock(&resource_context.secure_lock);
+ pr_err("Securing...\n");
+ rc = res_trk_enable_iommu_clocks();
+ if (rc) {
+ pr_err("IOMMU clock enabled failed while open");
+ goto error_open;
+ }
+ msm_ion_secure_heap(ION_HEAP(resource_context.memtype));
+ msm_ion_secure_heap(ION_HEAP(resource_context.cmd_mem_type));
+ res_trk_disable_iommu_clocks();
+ mutex_unlock(&resource_context.secure_lock);
+ }
+ return 0;
+error_open:
+ mutex_unlock(&resource_context.secure_lock);
+ return rc;
+}
+
+int res_trk_close_secure_session()
+{
+ int rc;
+ if (res_trk_check_for_sec_session() == 1) {
+ pr_err("Unsecuring....\n");
+ mutex_lock(&resource_context.secure_lock);
+ rc = res_trk_enable_iommu_clocks();
+ if (rc) {
+ pr_err("IOMMU clock enabled failed while close");
+ goto error_close;
+ }
+ msm_ion_unsecure_heap(ION_HEAP(resource_context.cmd_mem_type));
+ msm_ion_unsecure_heap(ION_HEAP(resource_context.memtype));
+ res_trk_disable_iommu_clocks();
+ mutex_unlock(&resource_context.secure_lock);
+ }
+ return 0;
+error_close:
+ mutex_unlock(&resource_context.secure_lock);
+ return rc;
+}
+
+u32 get_res_trk_perf_level(enum vcd_perf_level perf_level)
+{
+ u32 res_trk_perf_level;
+ switch (perf_level) {
+ case VCD_PERF_LEVEL0:
+ res_trk_perf_level = RESTRK_1080P_VGA_PERF_LEVEL;
+ break;
+ case VCD_PERF_LEVEL1:
+ res_trk_perf_level = RESTRK_1080P_720P_PERF_LEVEL;
+ break;
+ case VCD_PERF_LEVEL2:
+ res_trk_perf_level = RESTRK_1080P_MAX_PERF_LEVEL;
+ break;
+ case VCD_PERF_LEVEL_TURBO:
+ res_trk_perf_level = RESTRK_1080P_TURBO_PERF_LEVEL;
+ break;
+ default:
+ VCD_MSG_ERROR("Invalid perf level: %d\n", perf_level);
+ res_trk_perf_level = -EINVAL;
+ }
+ return res_trk_perf_level;
+}
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..d5e656b
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h
@@ -0,0 +1,78 @@
+/* Copyright (c) 2010-2012, 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 <linux/ion.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
+#define RESTRK_1080P_TURBO_PERF_LEVEL (RESTRK_1080P_MAX_PERF_LEVEL + 1)
+
+struct res_trk_context {
+ struct device *device;
+ u32 irq_num;
+ struct mutex lock;
+ struct clk *vcodec_clk;
+ struct clk *vcodec_pclk;
+ 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;
+ int fw_mem_type;
+ int cmd_mem_type;
+#ifdef CONFIG_MSM_BUS_SCALING
+ struct msm_bus_scale_pdata *vidc_bus_client_pdata;
+ uint32_t pcl;
+#endif
+ u32 core_type;
+ struct ddl_buf_addr firmware_addr;
+ struct ion_client *res_ion_client;
+ u32 disable_dmx;
+ u32 disable_fullhd;
+ enum ddl_mem_area res_mem_type;
+ u32 mmu_clks_on;
+ u32 secure_session;
+ struct mutex secure_lock;
+};
+
+#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..3fbbb38
--- /dev/null
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h
@@ -0,0 +1,51 @@
+/* Copyright (c) 2010-2012, 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"
+#include "vcd_ddl.h"
+#include "vcd_ddl_utils.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_firmware_addr(struct ddl_buf_addr *firm_addr);
+int res_trk_get_mem_type(void);
+u32 res_trk_get_enable_ion(void);
+u32 res_trk_is_cp_enabled(void);
+u32 res_trk_get_disable_fullhd(void);
+struct ion_client *res_trk_get_ion_client(void);
+u32 res_trk_get_disable_dmx(void);
+void res_trk_set_mem_type(enum ddl_mem_area mem_type);
+int res_trk_enable_iommu_clocks(void);
+int res_trk_disable_iommu_clocks(void);
+int res_trk_check_for_sec_session(void);
+int res_trk_open_secure_session(void);
+int res_trk_close_secure_session(void);
+void res_trk_secure_set(void);
+void res_trk_secure_unset(void);
+u32 get_res_trk_perf_level(enum vcd_perf_level);
+int res_trk_enable_footswitch(void);
+int res_trk_disable_footswitch(void);
+void res_trk_release_fw_addr(void);
+u32 res_trk_get_clk_rate(unsigned long *phclk_rate);
+#endif
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c
index b53a354..a144e06 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -9,16 +9,12 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
-#include "vidc_type.h"
+#include <media/msm/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)
@@ -46,9 +42,22 @@
}
DDL_MEMSET(ddl_context, 0, sizeof(struct ddl_context));
-
DDL_BUSY(ddl_context);
+ if (res_trk_get_enable_ion()) {
+ VIDC_LOGERR_STRING("ddl_dev_init: ION framework enabled");
+ ddl_context->video_ion_client =
+ res_trk_get_ion_client();
+ if (!ddl_context->video_ion_client) {
+ VIDC_LOGERR_STRING("ION client create failed");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ }
+ 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 =
@@ -161,7 +170,7 @@
VIDC_LOG_STRING("FW_ENDDONE");
ddl_release_context_buffers(ddl_context);
-
+ ddl_context->video_ion_client = NULL;
DDL_IDLE(ddl_context);
return VCD_S_SUCCESS;
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
index 34b522a..e6d3527 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
@@ -1,33 +1,18 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012 Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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 <mach/msm_subsystem_map.h>
#include "vcd_ddl_api.h"
#include "vcd_ddl_utils.h"
#include "vcd_ddl_firmware.h"
@@ -82,12 +67,19 @@
#define DDL_DEC_REQ_OUTPUT_FLUSH 0x1
+enum ddl_mem_area {
+ DDL_MM_MEM = 0x0
+};
+
struct ddl_buf_addr {
u32 *physical_base_addr;
u32 *virtual_base_addr;
u32 *align_physical_addr;
u32 *align_virtual_addr;
+ struct msm_mapped_buffer *mapped_buffer;
+ struct ion_handle *alloc_handle;
u32 buffer_size;
+ enum ddl_mem_area mem_type;
};
enum ddl_cmd_state {
@@ -209,6 +201,7 @@
struct vcd_buffer_requirement actual_output_buf_req;
struct vcd_buffer_requirement min_output_buf_req;
struct vcd_buffer_requirement client_output_buf_req;
+ u32 idr_only_decoding;
};
union ddl_codec_data {
@@ -218,6 +211,7 @@
};
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);
@@ -232,6 +226,7 @@
struct ddl_buf_addr dbg_core_dump;
u32 enable_dbg_core_dump;
struct ddl_client_context *ddl_clients[VCD_MAX_NO_CLIENT];
+ struct ion_client *video_ion_client;
u32 device_state;
u32 ddl_busy;
u32 intr_status;
@@ -294,4 +289,6 @@
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);
+void ddl_pmem_alloc(struct ddl_buf_addr *addr, size_t sz, u32 alignment);
+void ddl_pmem_free(struct ddl_buf_addr *addr);
#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
index 444bb6f..53cc93e 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_api.h
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_api.h
@@ -1,29 +1,13 @@
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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_
@@ -31,6 +15,7 @@
#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,
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_core.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_core.h
index b4e4c39..9fdb668 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_core.h
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_core.h
@@ -1,29 +1,13 @@
/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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_
@@ -43,6 +27,8 @@
#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
@@ -70,7 +56,7 @@
#define DDL_MPEG_REFBUF_COUNT 2
#define DDL_MPEG_COMV_BUF_NO 2
-#define DDL_H263_COMV_BUF_NO 0
+#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
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c
index 9ce7233..ac5bce9 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c
@@ -9,14 +9,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd_ddl_utils.h"
#include "vcd_ddl.h"
@@ -365,6 +360,11 @@
case ACTIVE_SPS_NOT_PRESENT:
case ACTIVE_PPS_NOT_PRESENT:
{
+ if (ddl->codec_data.decoder.idr_only_decoding) {
+ DBG("Consider warnings as errors in idr mode");
+ ddl_client_fatal_cb(ddl_context);
+ return true;
+ }
vcd_status = VCD_ERR_BITSTREAM_ERR;
break;
}
@@ -555,11 +555,23 @@
DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_INITCODECDONE)) {
switch (ddl_context->cmd_err_status) {
case UNSUPPORTED_FEATURE_IN_PROFILE:
- case RESOLUTION_NOT_SUPPORTED:
case HEADER_NOT_FOUND:
case INVALID_SPS_ID:
case INVALID_PPS_ID:
+ case RESOLUTION_NOT_SUPPORTED:
+ case PROFILE_UNKOWN:
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,
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.c
index 1a9552e..965c3aa 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -9,14 +9,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd_ddl_firmware.h"
#include "vcd_ddl_utils.h"
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.h
index 533e945..a136de8 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.h
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.h
@@ -1,34 +1,18 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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"
+#include <media/msm/vcd_property.h>
#define VCD_FW_BIG_ENDIAN 0x0
#define VCD_FW_LITTLE_ENDIAN 0x1
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c
index 0ae12d3..6a69955 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -9,14 +9,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd_ddl_utils.h"
#include "vcd_ddl_metadata.h"
@@ -812,8 +807,13 @@
}
case VCD_CODEC_H264:
{
- comv_buf_no =
- decoder->client_output_buf_req.actual_count;
+ if (decoder->idr_only_decoding)
+ comv_buf_no = decoder->min_dpb_num;
+ else
+ comv_buf_no =
+ decoder->
+ client_output_buf_req.
+ actual_count;
break;
}
}
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c
index 2debffa..15adf21 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -9,14 +9,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd_ddl_utils.h"
DDL_INLINE struct ddl_context *ddl_get_context(void)
@@ -129,6 +124,7 @@
u32 loopc;
struct ddl_frame_data_tag *found_frame = NULL;
struct ddl_mask *dpb_mask = &decoder->dpb_mask;
+ u32 temp_mask;
switch (operation) {
case DDL_DPB_OP_MARK_BUSY:
@@ -150,13 +146,17 @@
if (found_frame) {
if (operation == DDL_DPB_OP_MARK_BUSY) {
- dpb_mask->hw_mask &=
- (~(0x1 << loopc));
+ temp_mask = (~(0x1 << loopc));
+ if (decoder->idr_only_decoding)
+ temp_mask = ~(0xffffffff);
+ dpb_mask->hw_mask &= temp_mask;
*in_out_frame = *found_frame;
} else if (operation ==
DDL_DPB_OP_MARK_FREE) {
- dpb_mask->client_mask |=
- (0x1 << loopc);
+ temp_mask = (0x1 << loopc);
+ if (decoder->idr_only_decoding)
+ temp_mask = 0xffffffff;
+ dpb_mask->client_mask |= temp_mask;
*found_frame = *in_out_frame;
}
} else {
@@ -177,29 +177,35 @@
}
case DDL_DPB_OP_INIT:
{
- u32 dpb_size;
+ u32 dpb_size, index, num_dpb;
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,
+ if (decoder->idr_only_decoding)
+ num_dpb = decoder->min_dpb_num;
+ else
+ num_dpb = decoder->dp_buf.no_of_dec_pic_buf;
+ vidc_720p_decode_set_dpb_details(
+ num_dpb,
dpb_size,
decoder->ref_buffer.
align_physical_addr);
- for (loopc = 0;
- loopc < decoder->dp_buf.no_of_dec_pic_buf;
- ++loopc) {
+ for (loopc = 0; loopc < num_dpb; ++loopc) {
+ if (decoder->idr_only_decoding)
+ index = 0;
+ else
+ index = loopc;
vidc_720p_decode_set_dpb_buffers(loopc,
(u32 *)
decoder->
dp_buf.
dec_pic_buffers
- [loopc].
+ [index].
vcd_frm.
physical);
- VIDC_LOG1("DEC_DPB_BUFn_SIZE",
+ VIDC_LOG1("DEC_DPB_BUFn_SIZE=%d",
decoder->dp_buf.
- dec_pic_buffers[loopc].vcd_frm.
+ dec_pic_buffers[index].vcd_frm.
alloc_len);
}
break;
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
index 81879cb..7e201cf 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h
@@ -1,34 +1,18 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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"
+#include <media/msm/vcd_api.h>
#define VCD_EVT_RESP_DDL_BASE 0x3000
#define VCD_EVT_RESP_DEVICE_INIT (VCD_EVT_RESP_DDL_BASE + 0x1)
@@ -73,6 +57,12 @@
u32 activity_region_flag;
};
+struct vcd_property_slice_delivery_info {
+ u32 enable;
+ u32 num_slices;
+ u32 num_slices_enc;
+};
+
struct ddl_frame_data_tag;
struct ddl_property_dec_pic_buffers {
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
index 2584417..fe71dc1 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_interrupt_handler.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_interrupt_handler.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -9,14 +9,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vidc.h"
#include "vcd_ddl_utils.h"
#include "vcd_ddl_metadata.h"
@@ -235,6 +230,14 @@
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
@@ -287,13 +290,14 @@
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 ||
+ 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,
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.c
index bbf97df..2a74da8 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -9,14 +9,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd_ddl_utils.h"
#include "vcd_ddl_metadata.h"
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.h
index 9d9f3fc..ed43861 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.h
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.h
@@ -1,29 +1,13 @@
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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_
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c
index 4bc97c0..3aebdaf 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -9,14 +9,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd_ddl_utils.h"
#include "vcd_ddl_metadata.h"
@@ -239,6 +234,10 @@
&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;
@@ -255,6 +254,10 @@
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;
@@ -362,6 +365,18 @@
}
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_FRAME_RATE:
{
vcd_status = VCD_S_SUCCESS;
@@ -790,6 +805,10 @@
&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;
@@ -806,6 +825,10 @@
) {
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;
@@ -840,12 +863,24 @@
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;
@@ -886,15 +921,10 @@
{
if (sizeof(struct vcd_buffer_requirement) ==
property_hdr->sz) {
- if (decoder->
- client_input_buf_req.sz) {
- *(struct vcd_buffer_requirement *)
- property_value =
- decoder->client_input_buf_req;
- vcd_status = VCD_S_SUCCESS;
- } else {
- vcd_status = VCD_ERR_ILLEGAL_OP;
- }
+ *(struct vcd_buffer_requirement *)
+ property_value =
+ decoder->client_input_buf_req;
+ vcd_status = VCD_S_SUCCESS;
}
break;
}
@@ -902,14 +932,10 @@
{
if (sizeof(struct vcd_buffer_requirement) ==
property_hdr->sz) {
- if (decoder->client_output_buf_req.sz) {
- *(struct vcd_buffer_requirement *)
- property_value =
- decoder->client_output_buf_req;
- vcd_status = VCD_S_SUCCESS;
- } else {
- vcd_status = VCD_ERR_ILLEGAL_OP;
- }
+ *(struct vcd_buffer_requirement *)
+ property_value =
+ decoder->client_output_buf_req;
+ vcd_status = VCD_S_SUCCESS;
}
break;
}
@@ -917,14 +943,9 @@
{
if (sizeof(struct vcd_property_codec) ==
property_hdr->sz) {
- if (decoder->codec.codec) {
- *(struct vcd_property_codec *)
- property_value =
- decoder->codec;
- vcd_status = VCD_S_SUCCESS;
- } else {
- vcd_status = VCD_ERR_ILLEGAL_OP;
- }
+ *(struct vcd_property_codec *)
+ property_value = decoder->codec;
+ vcd_status = VCD_S_SUCCESS;
}
break;
}
@@ -959,9 +980,7 @@
}
case DDL_I_FRAME_PROC_UNITS:
{
- if (sizeof(u32) == property_hdr->sz &&
- decoder->client_frame_size.width &&
- decoder->client_frame_size.height) {
+ if (sizeof(u32) == property_hdr->sz) {
struct vcd_property_frame_size frame_sz =
decoder->client_frame_size;
ddl_calculate_stride(&frame_sz,
@@ -1279,14 +1298,10 @@
{
if (sizeof(struct vcd_buffer_requirement) ==
property_hdr->sz) {
- if (encoder->output_buf_req.sz) {
- *(struct vcd_buffer_requirement *)
- property_value =
- encoder->client_input_buf_req;
- vcd_status = VCD_S_SUCCESS;
- } else {
- vcd_status = VCD_ERR_ILLEGAL_OP;
- }
+ *(struct vcd_buffer_requirement *)
+ property_value =
+ encoder->client_input_buf_req;
+ vcd_status = VCD_S_SUCCESS;
}
break;
}
@@ -1294,14 +1309,10 @@
{
if (sizeof(struct vcd_buffer_requirement) ==
property_hdr->sz) {
- if (encoder->output_buf_req.sz) {
- *(struct vcd_buffer_requirement *)
- property_value =
- encoder->client_output_buf_req;
- vcd_status = VCD_S_SUCCESS;
- } else {
- vcd_status = VCD_ERR_ILLEGAL_OP;
- }
+ *(struct vcd_buffer_requirement *)
+ property_value =
+ encoder->client_output_buf_req;
+ vcd_status = VCD_S_SUCCESS;
}
break;
}
@@ -1317,9 +1328,7 @@
}
case DDL_I_FRAME_PROC_UNITS:
{
- if (sizeof(u32) == property_hdr->sz &&
- encoder->frame_size.width &&
- encoder->frame_size.height) {
+ if (sizeof(u32) == property_hdr->sz) {
*(u32 *) property_value =
((encoder->frame_size.width >> 4) *
(encoder->frame_size.height >> 4)
@@ -1377,7 +1386,8 @@
(struct vcd_property_target_bitrate *)
property_value;
if (sizeof(struct vcd_property_target_bitrate) ==
- property_hdr->sz) {
+ 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;
@@ -1458,8 +1468,8 @@
{
struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
- if (decoder->codec.codec == VCD_CODEC_MPEG4 ||
- decoder->codec.codec == VCD_CODEC_MPEG2)
+ if (decoder->codec.codec >= VCD_CODEC_MPEG2 &&
+ decoder->codec.codec <= VCD_CODEC_XVID)
decoder->post_filter.post_filter = true;
else
decoder->post_filter.post_filter = false;
@@ -1469,6 +1479,7 @@
decoder->client_frame_size.stride = 176;
decoder->client_frame_size.scan_lines = 144;
decoder->progressive_only = 1;
+ decoder->idr_only_decoding = 0;
decoder->profile.profile = VCD_PROFILE_UNKNOWN;
decoder->level.level = VCD_LEVEL_UNKNOWN;
decoder->output_order = VCD_DEC_ORDER_DISPLAY;
@@ -1538,9 +1549,12 @@
static void ddl_set_default_enc_vop_timing
(struct ddl_encoder_data *encoder)
{
- encoder->vop_timing.vop_time_resolution =
- (2 * encoder->frame_rate.fps_numerator) /
- encoder->frame_rate.fps_denominator;
+ 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(
@@ -1693,18 +1707,24 @@
min_dpb = decoder->min_dpb_num;
}
+ if (decoder->idr_only_decoding)
+ min_dpb = 1;
+
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;
-
+ if (decoder->idr_only_decoding) {
+ output_buf_req->actual_count = output_buf_req->min_count;
+ } else {
+ 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)
@@ -1722,7 +1742,7 @@
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) >> 2;
+ 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;
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
index f984292..580d428 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -9,15 +9,11 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
-
-#include "vidc_type.h"
+#include <linux/memory_alloc.h>
+#include <media/msm/vidc_type.h>
#include "vcd_ddl_utils.h"
+#include "vcd_res_tracker_api.h"
#if DEBUG
#define DBG(x...) printk(KERN_DEBUG x)
@@ -91,91 +87,183 @@
void ddl_pmem_alloc(struct ddl_buf_addr *buff_addr, size_t sz, u32 align)
{
u32 guard_bytes, align_mask;
- s32 physical_addr;
+ u32 physical_addr;
u32 align_offset;
+ u32 alloc_size, flags = 0;
+ struct ddl_context *ddl_context;
+ struct msm_mapped_buffer *mapped_buffer = NULL;
+ unsigned long *kernel_vaddr = NULL;
+ ion_phys_addr_t phyaddr = 0;
+ size_t len = 0;
+ int ret = -EINVAL;
- DBG_PMEM("\n%s() IN: Requested alloc size(%u)", __func__, (u32)sz);
-
+ if (!buff_addr) {
+ ERR("\n%s() Invalid Parameters\n", __func__);
+ return;
+ }
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;
}
-
- physical_addr = pmem_kalloc((sz + guard_bytes),
- PMEM_MEMTYPE_EBI1 | PMEM_ALIGNMENT_4K);
- buff_addr->physical_base_addr = (u32 *)physical_addr;
-
- if (IS_ERR((void *)physical_addr)) {
- pr_err("%s(): could not allocte in kernel pmem buffers\n",
- __func__);
- goto bailout;
+ ddl_context = ddl_get_context();
+ alloc_size = sz + guard_bytes;
+ if (res_trk_get_enable_ion()) {
+ if (!ddl_context->video_ion_client)
+ ddl_context->video_ion_client =
+ res_trk_get_ion_client();
+ if (!ddl_context->video_ion_client) {
+ ERR("\n%s(): DDL ION Client Invalid handle\n",
+ __func__);
+ goto bailout;
+ }
+ buff_addr->mem_type = res_trk_get_mem_type();
+ buff_addr->alloc_handle = ion_alloc(
+ ddl_context->video_ion_client,
+ alloc_size,
+ SZ_4K,
+ buff_addr->mem_type);
+ if (!buff_addr->alloc_handle) {
+ ERR("\n%s(): DDL ION alloc failed\n",
+ __func__);
+ goto bailout;
+ }
+ ret = ion_phys(ddl_context->video_ion_client,
+ buff_addr->alloc_handle,
+ &phyaddr,
+ &len);
+ if (ret || !phyaddr) {
+ ERR("\n%s(): DDL ION client physical failed\n",
+ __func__);
+ goto free_ion_buffer;
+ }
+ buff_addr->physical_base_addr = (u32 *)phyaddr;
+ kernel_vaddr = (unsigned long *) ion_map_kernel(
+ ddl_context->video_ion_client,
+ buff_addr->alloc_handle,
+ UNCACHED);
+ if (IS_ERR_OR_NULL(kernel_vaddr)) {
+ ERR("\n%s(): DDL ION map failed\n", __func__);
+ goto unmap_ion_buffer;
+ }
+ buff_addr->virtual_base_addr = (u32 *)kernel_vaddr;
+ DBG("ddl_ion_alloc: handle(0x%x), mem_type(0x%x), "\
+ "phys(0x%x), virt(0x%x), size(%u), align(%u), "\
+ "alloced_len(%u)", (u32)buff_addr->alloc_handle,
+ (u32)buff_addr->mem_type,
+ (u32)buff_addr->physical_base_addr,
+ (u32)buff_addr->virtual_base_addr,
+ alloc_size, align, len);
+ } else {
+ physical_addr = (u32)
+ allocate_contiguous_memory_nomap(alloc_size,
+ ddl_context->memtype, SZ_4K);
+ if (!physical_addr) {
+ ERR("\n%s(): DDL pmem allocate failed\n",
+ __func__);
+ goto bailout;
+ }
+ buff_addr->physical_base_addr = (u32 *) physical_addr;
+ flags = MSM_SUBSYSTEM_MAP_KADDR;
+ buff_addr->mapped_buffer =
+ msm_subsystem_map_buffer((unsigned long)physical_addr,
+ alloc_size, flags, NULL, 0);
+ if (IS_ERR(buff_addr->mapped_buffer)) {
+ ERR("\n%s() buffer map failed\n", __func__);
+ goto free_pmem_buffer;
+ }
+ mapped_buffer = buff_addr->mapped_buffer;
+ if (!mapped_buffer->vaddr) {
+ ERR("\n%s() mapped virtual address is NULL\n",
+ __func__);
+ goto unmap_pmem_buffer;
+ }
+ buff_addr->virtual_base_addr = mapped_buffer->vaddr;
+ DBG("ddl_pmem_alloc: mem_type(0x%x), phys(0x%x),"\
+ " virt(0x%x), sz(%u), align(%u)",
+ (u32)buff_addr->mem_type,
+ (u32)buff_addr->physical_base_addr,
+ (u32)buff_addr->virtual_base_addr,
+ alloc_size, SZ_4K);
}
- 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__);
- pmem_kfree(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_physical_addr = (u32 *)
+ (((u32)buff_addr->physical_base_addr + guard_bytes) &
+ align_mask);
+ align_offset = (u32) (buff_addr->align_physical_addr) -
+ (u32)buff_addr->physical_base_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);
-
+ DBG("%s(): phys(0x%x) align_phys(0x%x), virt(0x%x),"\
+ " align_virt(0x%x)", __func__,
+ (u32)buff_addr->physical_base_addr,
+ (u32)buff_addr->align_physical_addr,
+ (u32)buff_addr->virtual_base_addr,
+ (u32)buff_addr->align_virtual_addr);
return;
+
+unmap_pmem_buffer:
+ if (buff_addr->mapped_buffer)
+ msm_subsystem_unmap_buffer(buff_addr->mapped_buffer);
+free_pmem_buffer:
+ if (buff_addr->physical_base_addr)
+ free_contiguous_memory_by_paddr((unsigned long)
+ buff_addr->physical_base_addr);
+ memset(buff_addr, 0, sizeof(struct ddl_buf_addr));
+ return;
+
+unmap_ion_buffer:
+ if (ddl_context->video_ion_client) {
+ if (buff_addr->alloc_handle)
+ ion_unmap_kernel(ddl_context->video_ion_client,
+ buff_addr->alloc_handle);
+ }
+free_ion_buffer:
+ if (ddl_context->video_ion_client) {
+ if (buff_addr->alloc_handle)
+ ion_free(ddl_context->video_ion_client,
+ buff_addr->alloc_handle);
+ }
bailout:
- buff_addr->physical_base_addr = NULL;
- buff_addr->virtual_base_addr = NULL;
- buff_addr->buffer_size = 0;
+ memset(buff_addr, 0, sizeof(struct ddl_buf_addr));
}
void ddl_pmem_free(struct ddl_buf_addr *buff_addr)
{
+ struct ddl_context *ddl_context;
+ ddl_context = ddl_get_context();
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,
+ DBG("ddl_pmem_free: phys(0x%x) align_phys(0x%x), "\
+ "virt(0x%x), align_virt(0x%x), size(%u)",
+ (u32)buff_addr->physical_base_addr,
+ (u32)buff_addr->align_physical_addr,
+ (u32)buff_addr->virtual_base_addr,
+ (u32)buff_addr->align_virtual_addr,
buff_addr->buffer_size);
-
- if (buff_addr->virtual_base_addr)
- iounmap((void *)buff_addr->virtual_base_addr);
-
- if ((buff_addr->physical_base_addr) &&
- pmem_kfree((s32) buff_addr->physical_base_addr)) {
- ERR("\n %s(): Error in Freeing ddl_pmem_free "
- "Physical Address %p", __func__,
- buff_addr->physical_base_addr);
+ if (ddl_context->video_ion_client) {
+ if (buff_addr->alloc_handle) {
+ ion_unmap_kernel(ddl_context->video_ion_client,
+ buff_addr->alloc_handle);
+ ion_free(ddl_context->video_ion_client,
+ buff_addr->alloc_handle);
+ }
+ } else {
+ if (buff_addr->mapped_buffer)
+ msm_subsystem_unmap_buffer(
+ buff_addr->mapped_buffer);
+ 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;
+ memset(buff_addr, 0, sizeof(struct ddl_buf_addr));
}
#endif
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.h
index 81e8b21..539f753 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.h
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.h
@@ -1,29 +1,13 @@
/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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_
@@ -56,10 +40,6 @@
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);
diff --git a/drivers/video/msm/vidc/720p/ddl/vidc.c b/drivers/video/msm/vidc/720p/ddl/vidc.c
index eacfbca..de6cbbb 100644
--- a/drivers/video/msm/vidc/720p/ddl/vidc.c
+++ b/drivers/video/msm/vidc/720p/ddl/vidc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -9,16 +9,11 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
#include <linux/unistd.h>
+#include <media/msm/vidc_type.h>
#include "vidc.h"
-#include "vidc_type.h"
#if DEBUG
#define DBG(x...) printk(KERN_DEBUG x)
@@ -228,6 +223,9 @@
/*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 ;
}
diff --git a/drivers/video/msm/vidc/720p/ddl/vidc.h b/drivers/video/msm/vidc/720p/ddl/vidc.h
index 03232b9..509482b 100644
--- a/drivers/video/msm/vidc/720p/ddl/vidc.h
+++ b/drivers/video/msm/vidc/720p/ddl/vidc.h
@@ -1,29 +1,13 @@
/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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
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
index 6387325..a636196 100644
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -9,25 +9,19 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
#include <linux/firmware.h>
-#include <linux/pm_qos_params.h>
#include <linux/clk.h>
#include <linux/delay.h>
-#include <mach/internal_power_rail.h>
+#include <linux/regulator/consumer.h>
#include <mach/clk.h>
-#include <mach/msm_reqs.h>
#include <linux/interrupt.h>
-#include "vidc_type.h"
+#include <media/msm/vidc_init.h>
+#include <media/msm/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)
@@ -37,23 +31,12 @@
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;
@@ -86,23 +69,48 @@
unsigned char *vidc_vc1_dec_fw;
u32 vidc_vc1_dec_fw_size;
-static u32 res_trk_disable_pwr_rail(void)
+static u32 res_trk_disable_videocore(void)
{
int rc = -1;
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);
- }
-
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) {
@@ -112,19 +120,48 @@
}
msleep(20);
- rc = internal_pwr_rail_ctl(PWR_RAIL_MFC_CLK, 0);
- if (rc) {
- VCDRES_MSG_ERROR("\n clk_reset failed %d\n", rc);
- mutex_unlock(&resource_context.lock);
- return false;
- }
+ 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)
@@ -224,80 +261,107 @@
return true;
}
-static u32 res_trk_enable_pwr_rail(void)
+static u32 res_trk_enable_videocore(void)
{
mutex_lock(&resource_context.lock);
if (!resource_context.rail_enabled) {
int rc = -1;
- rc = internal_pwr_rail_mode(PWR_RAIL_MFC_CLK,
- PWR_RAIL_CTL_MANUAL);
+
+ rc = regulator_enable(resource_context.regulator);
if (rc) {
- VCDRES_MSG_ERROR("%s(): internal_pwr_rail_mode \
- failed %d\n", __func__, rc);
- mutex_unlock(&resource_context.lock);
- return false;
+ VCDRES_MSG_ERROR("%s(): regulator_enable failed %d\n",
+ __func__, rc);
+ goto bail_out;
}
- VCDRES_MSG_LOW("%s(): internal_pwr_rail_mode Success %d\n",
- __func__, rc);
+ VCDRES_MSG_LOW("%s(): regulator enable Success %d\n",
+ __func__, rc);
resource_context.pclk = clk_get(resource_context.device,
- "mfc_pclk");
+ "iface_clk");
if (IS_ERR(resource_context.pclk)) {
- VCDRES_MSG_ERROR("%s(): mfc_pclk get failed\n"
+ VCDRES_MSG_ERROR("%s(): iface_clk get failed\n"
, __func__);
-
- mutex_unlock(&resource_context.lock);
- return false;
+ goto disable_regulator;
}
resource_context.hclk = clk_get(resource_context.device,
- "mfc_clk");
+ "core_clk");
if (IS_ERR(resource_context.hclk)) {
- VCDRES_MSG_ERROR("%s(): mfc_clk get failed\n"
+ VCDRES_MSG_ERROR("%s(): core_clk get failed\n"
, __func__);
- clk_put(resource_context.pclk);
- mutex_unlock(&resource_context.lock);
- return false;
+ goto release_pclk;
}
resource_context.hclk_div2 =
- clk_get(resource_context.device, "mfc_div2_clk");
+ clk_get(resource_context.device, "core_div2_clk");
- if (IS_ERR(resource_context.pclk)) {
- VCDRES_MSG_ERROR("%s(): mfc_div2_clk get failed\n"
+ if (IS_ERR(resource_context.hclk_div2)) {
+ VCDRES_MSG_ERROR("%s(): core_div2_clk get failed\n"
, __func__);
-
- clk_put(resource_context.pclk);
- clk_put(resource_context.hclk);
- mutex_unlock(&resource_context.lock);
- return false;
+ goto release_hclk_pclk;
}
- rc = internal_pwr_rail_ctl(PWR_RAIL_MFC_CLK, 1);
- if (rc) {
- VCDRES_MSG_ERROR("\n internal_pwr_rail_ctl failed %d\n"
- , rc);
- mutex_unlock(&resource_context.lock);
- return false;
+ 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;
}
- VCDRES_MSG_LOW("%s(): internal_pwr_rail_ctl Success %d\n"
- , __func__, rc);
- msleep(20);
+
+ 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);
- mutex_unlock(&resource_context.lock);
- return false;
+ 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)
@@ -333,9 +397,7 @@
return (u32)freq;
}
-#ifdef AXI_CLK_SCALING
-static struct pm_qos_request_list *qos_req_list;
-#endif
+static struct clk *ebi1_clk;
u32 res_trk_power_up(void)
{
@@ -345,18 +407,18 @@
{
VCDRES_MSG_MED("\n res_trk_power_up():: "
"Calling AXI add requirement\n");
- qos_req_list = pm_qos_add_request(PM_QOS_SYSTEM_BUS_FREQ,
- PM_QOS_DEFAULT_VALUE);
- if (IS_ERR_OR_NULL(qos_req_list)) {
+ ebi1_clk = clk_get(resource_context.device, "mem_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_pwr_rail();
+ return res_trk_enable_videocore();
}
u32 res_trk_power_down(void)
@@ -365,11 +427,12 @@
#ifdef AXI_CLK_SCALING
VCDRES_MSG_MED("\n res_trk_power_down()::"
"Calling AXI remove requirement\n");
- pm_qos_remove_request(qos_req_list);
+ clk_disable(ebi1_clk);
+ clk_put(ebi1_clk);
#endif
VCDRES_MSG_MED("\n res_trk_power_down():: Calling "
- "res_trk_disable_pwr_rail()\n");
- return res_trk_disable_pwr_rail();
+ "res_trk_disable_videocore()\n");
+ return res_trk_disable_videocore();
}
u32 res_trk_get_max_perf_level(u32 *pn_max_perf_lvl)
@@ -458,8 +521,7 @@
if (req_perf_lvl != VCD_RESTRK_MIN_PERF_LEVEL) {
VCDRES_MSG_MED("\n %s(): Setting AXI freq to %u",
__func__, axi_freq);
- pm_qos_update_request(qos_req_list,
- axi_freq);
+ clk_set_rate(ebi1_clk, axi_freq * 1000);
}
#endif
@@ -615,8 +677,16 @@
return false;
}
+static struct ion_client *res_trk_create_ion_client(void){
+ struct ion_client *video_client;
+ VCDRES_MSG_LOW("%s", __func__);
+ video_client = msm_ion_client_create(-1, "video_client");
+ return video_client;
+}
+
void res_trk_init(struct device *device, u32 irq)
{
+ VCDRES_MSG_LOW("%s", __func__);
if (resource_context.device || resource_context.irq_num ||
!device) {
VCDRES_MSG_ERROR("%s() Resource Tracker Init error\n",
@@ -628,8 +698,100 @@
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;
+ VCDRES_MSG_LOW("%s(): resource_context.memtype = 0x%x",
+ __func__, (u32)resource_context.memtype);
+ if (resource_context.vidc_platform_data->enable_ion) {
+ resource_context.res_ion_client =
+ res_trk_create_ion_client();
+ if (!(resource_context.res_ion_client)) {
+ VCDRES_MSG_ERROR("%s()ION createfail\n",
+ __func__);
+ return;
+ }
+ VCDRES_MSG_LOW("%s(): ion_client = 0x%x", __func__,
+ (u32)resource_context.res_ion_client);
+ } else {
+ VCDRES_MSG_ERROR("%s(): ION not disabled\n",
+ __func__);
+ }
+ } else {
+ resource_context.memtype = -1;
+ VCDRES_MSG_ERROR("%s(): vidc_platform_data is NULL",
+ __func__);
+ }
}
u32 res_trk_get_core_type(void){
return resource_context.core_type;
}
+
+u32 res_trk_get_enable_ion(void)
+{
+ if (resource_context.vidc_platform_data->enable_ion)
+ return 1;
+ else
+ return 0;
+}
+
+struct ion_client *res_trk_get_ion_client(void)
+{
+ return resource_context.res_ion_client;
+}
+
+u32 res_trk_get_mem_type(void)
+{
+ u32 mem_type = ION_HEAP(resource_context.memtype);
+ return mem_type;
+}
+
+void res_trk_set_mem_type(enum ddl_mem_area mem_type)
+{
+ return;
+}
+
+u32 res_trk_get_disable_fullhd(void)
+{
+ return 0;
+}
+
+int res_trk_check_for_sec_session()
+{
+ return 0;
+}
+
+void res_trk_secure_unset(void)
+{
+ return;
+}
+
+void res_trk_secure_set(void)
+{
+ return;
+}
+
+int res_trk_open_secure_session()
+{
+ return -EINVAL;
+}
+
+int res_trk_close_secure_session()
+{
+ return 0;
+}
+u32 get_res_trk_perf_level(enum vcd_perf_level perf_level)
+{
+ return -ENOTSUPP;
+}
+u32 res_trk_is_cp_enabled(void)
+{
+ if (resource_context.vidc_platform_data->cp_enabled)
+ return 1;
+ else
+ return 0;
+}
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
index 63d3399..f8d9053 100644
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.h
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.h
@@ -1,34 +1,19 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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 <linux/ion.h>
#include "vcd_res_tracker_api.h"
#define VCD_RESTRK_MIN_PERF_LEVEL 37900
@@ -47,7 +32,13 @@
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;
+ u32 secure_session;
+ struct ion_client *res_ion_client;
+ enum ddl_mem_area res_mem_type;
};
#if DEBUG
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
index 57d3638..4b77576 100644
--- 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
@@ -1,35 +1,20 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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"
+#include "vcd_ddl.h"
void res_trk_init(struct device *device, u32 irq);
u32 res_trk_power_up(void);
@@ -42,5 +27,16 @@
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);
+u32 res_trk_get_disable_fullhd(void);
+u32 res_trk_get_enable_ion(void);
+u32 res_trk_is_cp_enabled(void);
+struct ion_client *res_trk_get_ion_client(void);
+void res_trk_set_mem_type(enum ddl_mem_area mem_type);
+int res_trk_check_for_sec_session(void);
+int res_trk_open_secure_session(void);
+int res_trk_close_secure_session(void);
+void res_trk_secure_set(void);
+void res_trk_secure_unset(void);
+u32 get_res_trk_perf_level(enum vcd_perf_level perf_level);
#endif
diff --git a/drivers/video/msm/vidc/Kconfig b/drivers/video/msm/vidc/Kconfig
index aae34a7..9ffcb15 100644
--- a/drivers/video/msm/vidc/Kconfig
+++ b/drivers/video/msm/vidc/Kconfig
@@ -3,7 +3,7 @@
#
menuconfig MSM_VIDC
bool "Video Core Driver"
- depends on ARCH_MSM8X60 || ARCH_MSM7X30
+ depends on ARCH_MSM8X60 || ARCH_MSM7X30 || ARCH_MSM8960
default y
---help---
Say Y here to see options for video device drivers.
@@ -18,7 +18,7 @@
config MSM_VIDC_1080P
bool "1080P Video Core"
- depends on MSM_VIDC && ARCH_MSM8X60
+ depends on MSM_VIDC && (ARCH_MSM8X60 || ARCH_MSM8960)
default y
help
This option enables support for Video core.
diff --git a/drivers/video/msm/vidc/Makefile b/drivers/video/msm/vidc/Makefile
index c1331d2..af41f18 100644
--- a/drivers/video/msm/vidc/Makefile
+++ b/drivers/video/msm/vidc/Makefile
@@ -48,6 +48,7 @@
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
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
old mode 100644
new mode 100755
index 7cb3990..8772f23
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -9,11 +9,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
#include <linux/cdev.h>
@@ -33,11 +28,12 @@
#include <linux/android_pmem.h>
#include <linux/clk.h>
#include <linux/timer.h>
-
-#include "vidc_type.h"
-#include "vcd_api.h"
+#include <mach/msm_subsystem_map.h>
+#include <media/msm/vidc_type.h>
+#include <media/msm/vcd_api.h>
+#include <media/msm/vidc_init.h>
+#include "vcd_res_tracker_api.h"
#include "vdec_internal.h"
-#include "vidc_init.h"
@@ -45,11 +41,15 @@
#define INFO(x...) pr_info(x)
#define ERR(x...) pr_err(x)
-#define VID_DEC_NAME "msm_vidc_dec"
+#define VID_DEC_NAME "msm_vidc_dec"
+static char *node_name[2] = {"", "_sec"};
static struct vid_dec_dev *vid_dec_device_p;
static dev_t vid_dec_dev_num;
static struct class *vid_dec_class;
+
+static unsigned int vidc_mmu_subsystem[] = {
+ MSM_SUBSYSTEM_VIDEO};
static s32 vid_dec_get_empty_client_index(void)
{
u32 i, found = false;
@@ -187,6 +187,10 @@
return;
}
+ kfree(vcd_frame_data->desc_buf);
+ vcd_frame_data->desc_buf = NULL;
+ vcd_frame_data->desc_size = 0;
+
vdec_msg = kzalloc(sizeof(struct vid_dec_msg), GFP_KERNEL);
if (!vdec_msg) {
ERR("vid_dec_input_frame_done(): cannot allocate vid_dec_msg "
@@ -205,8 +209,9 @@
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\n");
- return;
+ 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 =
@@ -230,6 +235,9 @@
struct file *file;
s32 buffer_index = -1;
enum vdec_picture pic_type;
+ u32 ion_flag = 0;
+ struct ion_handle *buff_handle = NULL;
+ struct vdec_output_frameinfo *output_frame;
if (!client_ctx || !vcd_frame_data) {
ERR("vid_dec_input_frame_done() NULL pointer\n");
@@ -248,12 +256,12 @@
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\n");
- return;
+ 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;
@@ -263,7 +271,6 @@
&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;
@@ -292,6 +299,15 @@
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:
@@ -314,13 +330,31 @@
}
vdec_msg->vdec_msg_info.msgdata.output_frame.pic_type =
pic_type;
+ output_frame = &vdec_msg->vdec_msg_info.msgdata.output_frame;
+ output_frame->aspect_ratio_info.aspect_ratio =
+ vcd_frame_data->aspect_ratio_info.aspect_ratio;
+ output_frame->aspect_ratio_info.par_width =
+ vcd_frame_data->aspect_ratio_info.extended_par_width;
+ output_frame->aspect_ratio_info.par_height =
+ vcd_frame_data->aspect_ratio_info.extended_par_height;
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;
}
-
+ if (vcd_frame_data->data_len > 0) {
+ ion_flag = vidc_get_fd_info(client_ctx, BUFFER_TYPE_OUTPUT,
+ pmem_fd, kernel_vaddr, buffer_index,
+ &buff_handle);
+ if (ion_flag == CACHED) {
+ msm_ion_do_cache_op(client_ctx->user_ion_client,
+ buff_handle,
+ (unsigned long *) kernel_vaddr,
+ (unsigned long)vcd_frame_data->data_len,
+ ION_IOC_INV_CACHES);
+ }
+ }
mutex_lock(&client_ctx->msg_queue_lock);
list_add_tail(&vdec_msg->list, &client_ctx->msg_queue);
mutex_unlock(&client_ctx->msg_queue_lock);
@@ -644,6 +678,57 @@
return true;
}
+static u32 vid_dec_get_disable_dmx_support(struct video_client_ctx *client_ctx,
+ u32 *disable_dmx)
+{
+
+ struct vcd_property_hdr vcd_property_hdr;
+ if (!client_ctx || !disable_dmx)
+ return false;
+ vcd_property_hdr.prop_id = VCD_I_DISABLE_DMX_SUPPORT;
+ vcd_property_hdr.sz = sizeof(u32);
+ if (vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ disable_dmx))
+ return false;
+ else
+ return true;
+}
+static u32 vid_dec_get_disable_dmx(struct video_client_ctx *client_ctx,
+ u32 *disable_dmx)
+{
+
+ struct vcd_property_hdr vcd_property_hdr;
+ if (!client_ctx || !disable_dmx)
+ return false;
+ vcd_property_hdr.prop_id = VCD_I_DISABLE_DMX;
+ vcd_property_hdr.sz = sizeof(u32);
+ if (vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ disable_dmx))
+ return false;
+ else
+ return true;
+}
+
+static u32 vid_dec_set_disable_dmx(struct video_client_ctx *client_ctx)
+{
+
+ struct vcd_property_hdr vcd_property_hdr;
+ u32 vcd_disable_dmx;
+ if (!client_ctx)
+ return false;
+ vcd_property_hdr.prop_id = VCD_I_DISABLE_DMX;
+ vcd_property_hdr.sz = sizeof(u32);
+ vcd_disable_dmx = true;
+ DBG("%s() : Setting Disable DMX: %d\n",
+ __func__, vcd_disable_dmx);
+
+ if (vcd_set_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ &vcd_disable_dmx))
+ return false;
+ else
+ return true;
+}
+
static u32 vid_dec_set_picture_order(struct video_client_ctx *client_ctx,
u32 *picture_order)
{
@@ -733,44 +818,129 @@
struct vdec_h264_mv *mv_data)
{
struct vcd_property_hdr vcd_property_hdr;
- struct vcd_property_h264_mv_buffer vcd_h264_mv_buffer;
+ struct vcd_property_h264_mv_buffer *vcd_h264_mv_buffer = NULL;
+ struct msm_mapped_buffer *mapped_buffer = NULL;
u32 vcd_status = VCD_ERR_FAIL;
- u32 len;
+ u32 len = 0, flags = 0;
struct file *file;
+ int rc = 0;
+ unsigned long ionflag = 0;
+ unsigned long buffer_size = 0;
+ unsigned long iova = 0;
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);
+ vcd_h264_mv_buffer = &client_ctx->vcd_h264_mv_buffer;
- memset(&vcd_h264_mv_buffer, 0,
+ memset(&client_ctx->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;
+ 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;
+ if (!vcd_get_ion_status()) {
+ 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);
+ flags = MSM_SUBSYSTEM_MAP_IOVA;
+ mapped_buffer = msm_subsystem_map_buffer(
+ (unsigned long)vcd_h264_mv_buffer->physical_addr, len,
+ flags, vidc_mmu_subsystem,
+ sizeof(vidc_mmu_subsystem)/
+ sizeof(unsigned int));
+ if (IS_ERR(mapped_buffer)) {
+ pr_err("buffer map failed");
+ return false;
+ }
+ vcd_h264_mv_buffer->client_data = (void *) mapped_buffer;
+ vcd_h264_mv_buffer->dev_addr = (u8 *)mapped_buffer->iova[0];
+ } else {
+ client_ctx->h264_mv_ion_handle = ion_import_fd(
+ client_ctx->user_ion_client,
+ vcd_h264_mv_buffer->pmem_fd);
+ if (!client_ctx->h264_mv_ion_handle) {
+ ERR("%s(): get_ION_handle failed\n", __func__);
+ goto import_ion_error;
+ }
+ rc = ion_handle_get_flags(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle,
+ &ionflag);
+ if (rc) {
+ ERR("%s():get_ION_flags fail\n",
+ __func__);
+ goto import_ion_error;
+ }
+ vcd_h264_mv_buffer->kernel_virtual_addr = (u8 *) ion_map_kernel(
+ client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle,
+ ionflag);
+ if (!vcd_h264_mv_buffer->kernel_virtual_addr) {
+ ERR("%s(): get_ION_kernel virtual addr failed\n",
+ __func__);
+ goto import_ion_error;
+ }
+ if (res_trk_check_for_sec_session() ||
+ (res_trk_get_core_type() == (u32)VCD_CORE_720P)) {
+ rc = ion_phys(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle,
+ (unsigned long *) (&(vcd_h264_mv_buffer->
+ physical_addr)), &len);
+ if (rc) {
+ ERR("%s():get_ION_kernel physical addr fail\n",
+ __func__);
+ goto ion_map_error;
+ }
+ vcd_h264_mv_buffer->client_data = NULL;
+ vcd_h264_mv_buffer->dev_addr = (u8 *)
+ vcd_h264_mv_buffer->physical_addr;
+ } else {
+ rc = ion_map_iommu(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle,
+ VIDEO_DOMAIN, VIDEO_MAIN_POOL,
+ SZ_4K, 0, (unsigned long *)&iova,
+ (unsigned long *)&buffer_size,
+ UNCACHED, 0);
+ if (rc) {
+ ERR("%s():get_ION_kernel physical addr fail\n",
+ __func__);
+ goto ion_map_error;
+ }
+ vcd_h264_mv_buffer->physical_addr = (u8 *) iova;
+ vcd_h264_mv_buffer->client_data = NULL;
+ vcd_h264_mv_buffer->dev_addr = (u8 *) iova;
+ }
}
- 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);
-
+ DBG("Virt: %p, Phys %p, fd: %d", vcd_h264_mv_buffer->
+ kernel_virtual_addr, vcd_h264_mv_buffer->physical_addr,
+ vcd_h264_mv_buffer->pmem_fd);
+ DBG("Dev addr %p", vcd_h264_mv_buffer->dev_addr);
vcd_status = vcd_set_property(client_ctx->vcd_handle,
- &vcd_property_hdr, &vcd_h264_mv_buffer);
+ &vcd_property_hdr, vcd_h264_mv_buffer);
if (vcd_status)
return false;
else
return true;
+ion_map_error:
+ if (vcd_h264_mv_buffer->kernel_virtual_addr)
+ ion_unmap_kernel(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle);
+ if (client_ctx->h264_mv_ion_handle)
+ ion_free(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle);
+import_ion_error:
+ return false;
}
static u32 vid_dec_set_cont_on_reconfig(struct video_client_ctx *client_ctx)
@@ -827,12 +997,30 @@
if (!client_ctx)
return false;
+ if (client_ctx->vcd_h264_mv_buffer.client_data)
+ msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
+ client_ctx->vcd_h264_mv_buffer.client_data);
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 (client_ctx->h264_mv_ion_handle != NULL) {
+ ion_unmap_kernel(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle);
+ if (!res_trk_check_for_sec_session() &&
+ (res_trk_get_core_type() != (u32)VCD_CORE_720P)) {
+ ion_unmap_iommu(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle,
+ VIDEO_DOMAIN,
+ VIDEO_MAIN_POOL);
+ }
+ ion_free(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle);
+ }
+
if (vcd_status)
return false;
else
@@ -878,7 +1066,7 @@
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;
+ unsigned long kernel_vaddr, buf_adr_offset = 0, length;
if (!client_ctx || !buffer_info)
return false;
@@ -888,17 +1076,16 @@
buffer = VCD_BUFFER_OUTPUT;
buf_adr_offset = (unsigned long)buffer_info->buffer.offset;
}
-
+ length = buffer_info->buffer.buffer_len;
/*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)) {
+ buf_adr_offset, MAX_VIDEO_NUM_OF_BUFF, length)) {
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);
@@ -925,6 +1112,7 @@
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,
@@ -933,7 +1121,6 @@
__func__, buffer_info->buffer.bufferaddr);
return true;
}
-
vcd_status = vcd_free_buffer(client_ctx->vcd_handle, buffer,
(u8 *)kernel_vaddr);
@@ -1035,7 +1222,8 @@
}
static u32 vid_dec_decode_frame(struct video_client_ctx *client_ctx,
- struct vdec_input_frameinfo *input_frame_info)
+ struct vdec_input_frameinfo *input_frame_info,
+ u8 *desc_buf, u32 desc_size)
{
struct vcd_frame_data vcd_input_buffer;
unsigned long kernel_vaddr, phy_addr, user_vaddr;
@@ -1043,6 +1231,8 @@
struct file *file;
s32 buffer_index = -1;
u32 vcd_status = VCD_ERR_FAIL;
+ u32 ion_flag = 0;
+ struct ion_handle *buff_handle = NULL;
if (!client_ctx || !input_frame_info)
return false;
@@ -1068,7 +1258,23 @@
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_input_buffer.desc_buf = desc_buf;
+ vcd_input_buffer.desc_size = desc_size;
+ if (vcd_input_buffer.data_len > 0) {
+ ion_flag = vidc_get_fd_info(client_ctx,
+ BUFFER_TYPE_INPUT,
+ pmem_fd,
+ kernel_vaddr,
+ buffer_index,
+ &buff_handle);
+ if (ion_flag == CACHED) {
+ msm_ion_do_cache_op(client_ctx->user_ion_client,
+ buff_handle,
+ (unsigned long *)kernel_vaddr,
+ (unsigned long) vcd_input_buffer.data_len,
+ ION_IOC_CLEAN_CACHES);
+ }
+ }
vcd_status = vcd_decode_frame(client_ctx->vcd_handle,
&vcd_input_buffer);
if (!vcd_status)
@@ -1093,6 +1299,7 @@
struct file *file;
s32 buffer_index = -1;
u32 vcd_status = VCD_ERR_FAIL;
+ struct ion_handle *buff_handle = NULL;
struct vcd_frame_data vcd_frame;
@@ -1111,7 +1318,12 @@
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_frame.ion_flag = vidc_get_fd_info(client_ctx,
+ BUFFER_TYPE_OUTPUT,
+ pmem_fd, kernel_vaddr,
+ buffer_index,
+ &buff_handle);
+ vcd_frame.buff_ion_handle = buff_handle;
vcd_status = vcd_fill_output_buffer(client_ctx->vcd_handle,
&vcd_frame);
if (!vcd_status)
@@ -1220,16 +1432,19 @@
return 0;
}
-static int vid_dec_ioctl(struct inode *inode, struct file *file,
+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;
+ unsigned long ker_vaddr;
struct file *pmem_file;
u32 result = true;
void __user *arg = (void __user *)u_arg;
+ int rc = 0;
+ size_t ion_len;
DBG("%s\n", __func__);
if (_IOC_TYPE(cmd) != VDEC_IOCTL_MAGIC)
@@ -1430,17 +1645,38 @@
case VDEC_IOCTL_DECODE_FRAME:
{
struct vdec_input_frameinfo input_frame_info;
+ u8 *desc_buf = NULL;
+ u32 desc_size = 0;
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;
+ if (client_ctx->dmx_disable) {
+ if (input_frame_info.desc_addr) {
+ desc_size = input_frame_info.desc_size;
+ desc_buf = kzalloc(desc_size, GFP_KERNEL);
+ if (desc_buf) {
+ if (copy_from_user(desc_buf,
+ input_frame_info.desc_addr,
+ desc_size)) {
+ kfree(desc_buf);
+ desc_buf = NULL;
+ return -EFAULT;
+ }
+ }
+ } else
+ return -EINVAL;
+ }
+ result = vid_dec_decode_frame(client_ctx, &input_frame_info,
+ desc_buf, desc_size);
- result = vid_dec_decode_frame(client_ctx, &input_frame_info);
-
- if (!result)
+ if (!result) {
+ kfree(desc_buf);
+ desc_buf = NULL;
return -EIO;
+ }
break;
}
case VDEC_IOCTL_FILL_OUTPUT_BUFFER:
@@ -1497,6 +1733,7 @@
{
struct vdec_seqheader seq_header;
struct vcd_sequence_hdr vcd_seq_hdr;
+ unsigned long ionflag;
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");
@@ -1512,13 +1749,56 @@
return -EFAULT;
}
- if (get_pmem_file(seq_header.pmem_fd,
+ if (!vcd_get_ion_status()) {
+ 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;
+ ERR("%s(): get_pmem_file failed\n", __func__);
+ return false;
+ }
+ put_pmem_file(pmem_file);
+ } else {
+ client_ctx->seq_hdr_ion_handle = ion_import_fd(
+ client_ctx->user_ion_client,
+ seq_header.pmem_fd);
+ if (!client_ctx->seq_hdr_ion_handle) {
+ ERR("%s(): get_ION_handle failed\n", __func__);
+ return false;
+ }
+ rc = ion_handle_get_flags(client_ctx->user_ion_client,
+ client_ctx->seq_hdr_ion_handle,
+ &ionflag);
+ if (rc) {
+ ERR("%s():get_ION_flags fail\n",
+ __func__);
+ ion_free(client_ctx->user_ion_client,
+ client_ctx->seq_hdr_ion_handle);
+ return false;
+ }
+ ker_vaddr = (unsigned long) ion_map_kernel(
+ client_ctx->user_ion_client,
+ client_ctx->seq_hdr_ion_handle, ionflag);
+ if (!ker_vaddr) {
+ ERR("%s():get_ION_kernel virtual addr fail\n",
+ __func__);
+ ion_free(client_ctx->user_ion_client,
+ client_ctx->seq_hdr_ion_handle);
+ return false;
+ }
+ kernel_vaddr = ker_vaddr;
+ rc = ion_phys(client_ctx->user_ion_client,
+ client_ctx->seq_hdr_ion_handle,
+ &phy_addr, &ion_len);
+ if (rc) {
+ ERR("%s():get_ION_kernel physical addr fail\n",
+ __func__);
+ ion_unmap_kernel(client_ctx->user_ion_client,
+ client_ctx->seq_hdr_ion_handle);
+ ion_free(client_ctx->user_ion_client,
+ client_ctx->seq_hdr_ion_handle);
+ return false;
+ }
+ len = ion_len;
}
- 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;
@@ -1539,6 +1819,14 @@
ERR("Set Seq Header status is failed");
return -EFAULT;
}
+ if (vcd_get_ion_status()) {
+ if (client_ctx->seq_hdr_ion_handle) {
+ ion_unmap_kernel(client_ctx->user_ion_client,
+ client_ctx->seq_hdr_ion_handle);
+ ion_free(client_ctx->user_ion_client,
+ client_ctx->seq_hdr_ion_handle);
+ }
+ }
break;
}
case VDEC_IOCTL_GET_NUMBER_INSTANCES:
@@ -1570,6 +1858,48 @@
return -EIO;
break;
}
+
+ case VDEC_IOCTL_GET_DISABLE_DMX_SUPPORT:
+ {
+ u32 disable_dmx;
+ DBG("VDEC_IOCTL_GET_DISABLE_DMX_SUPPORT\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+ result = vid_dec_get_disable_dmx_support(client_ctx,
+ &disable_dmx);
+ if (result) {
+ if (copy_to_user(vdec_msg.out, &disable_dmx,
+ sizeof(u32)))
+ return -EFAULT;
+ } else
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_GET_DISABLE_DMX:
+ {
+ u32 disable_dmx;
+ DBG("VDEC_IOCTL_GET_DISABLE_DMX\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+ result = vid_dec_get_disable_dmx(client_ctx,
+ &disable_dmx);
+ if (result) {
+ if (copy_to_user(vdec_msg.out, &disable_dmx,
+ sizeof(u32)))
+ return -EFAULT;
+ } else
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_SET_DISABLE_DMX:
+ {
+ DBG("VDEC_IOCTL_SET_DISABLE_DMX\n");
+ result = vid_dec_set_disable_dmx(client_ctx);
+ if (!result)
+ return -EIO;
+ client_ctx->dmx_disable = 1;
+ break;
+ }
case VDEC_IOCTL_SET_PICTURE_ORDER:
{
u32 picture_order;
@@ -1717,69 +2047,146 @@
mutex_unlock(&vid_dec_device_p->lock);
return false;
}
+ client_ctx->user_ion_client = NULL;
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)
+int vid_dec_open_client(struct video_client_ctx **vid_clnt_ctx, int flags)
{
+ int rc = 0;
s32 client_index;
- struct video_client_ctx *client_ctx;
- u32 vcd_status = VCD_ERR_FAIL;
- u8 client_count = 0;
+ struct video_client_ctx *client_ctx = NULL;
+ u8 client_count;
- DBG("msm_vidc_dec: Inside %s()", __func__);
- mutex_lock(&vid_dec_device_p->lock);
-
+ if (!vid_clnt_ctx) {
+ ERR("Invalid input\n");
+ return -EINVAL;
+ }
+ *vid_clnt_ctx = NULL;
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;
+ "limit reached\n");
+ rc = -ENOMEM;
+ goto client_failure;
}
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;
+ if (!vidc_load_firmware()) {
+ rc = -ENOMEM;
+ goto client_failure;
+ }
}
client_index = vid_dec_get_empty_client_index();
- if (client_index < 0) {
+ if (client_index == -1) {
ERR("%s() : No free clients client_index == -1\n", __func__);
- return -ENODEV;
+ rc = -ENOMEM;
+ goto client_failure;
}
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);
+ mutex_init(&client_ctx->enrty_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) {
+ client_ctx->dmx_disable = 0;
+ if (vcd_get_ion_status()) {
+ client_ctx->user_ion_client = vcd_get_ion_client();
+ if (!client_ctx->user_ion_client) {
+ ERR("vcd_open ion client get failed");
+ rc = -ENOMEM;
+ goto client_failure;
+ }
+ }
+ rc = vcd_open(vid_dec_device_p->device_handle, true,
+ vid_dec_vcd_cb, client_ctx, flags);
+ if (!rc) {
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;
+ rc = -ENODEV;
+ goto client_failure;
}
} else {
- ERR("vcd_open returned error: %u", vcd_status);
- mutex_unlock(&vid_dec_device_p->lock);
- return -EFAULT;
+ ERR("vcd_open returned error: %u", rc);
+ goto client_failure;
+ }
+ client_ctx->seq_header_set = false;
+ *vid_clnt_ctx = client_ctx;
+client_failure:
+ return rc;
+}
+
+static int vid_dec_open_secure(struct inode *inode, struct file *file)
+{
+ int rc = 0;
+ struct video_client_ctx *client_ctx;
+ mutex_lock(&vid_dec_device_p->lock);
+ rc = vid_dec_open_client(&client_ctx, VCD_CP_SESSION);
+ if (rc)
+ goto error;
+ if (!client_ctx) {
+ rc = -ENOMEM;
+ goto error;
}
- client_ctx->seq_header_set = false;
+ file->private_data = client_ctx;
+ if (res_trk_open_secure_session()) {
+ ERR("Secure session operation failure\n");
+ rc = -EACCES;
+ goto error;
+ }
+ mutex_unlock(&vid_dec_device_p->lock);
+ return 0;
+error:
+ mutex_unlock(&vid_dec_device_p->lock);
+ return rc;
+}
+
+static int vid_dec_open(struct inode *inode, struct file *file)
+{
+ int rc = 0;
+ struct video_client_ctx *client_ctx;
+ INFO("msm_vidc_dec: Inside %s()", __func__);
+ mutex_lock(&vid_dec_device_p->lock);
+ rc = vid_dec_open_client(&client_ctx, 0);
+ if (rc) {
+ mutex_unlock(&vid_dec_device_p->lock);
+ return rc;
+ }
+ if (!client_ctx) {
+ mutex_unlock(&vid_dec_device_p->lock);
+ return -ENOMEM;
+ }
+
file->private_data = client_ctx;
mutex_unlock(&vid_dec_device_p->lock);
+ return rc;
+}
+
+static int vid_dec_release_secure(struct inode *inode, struct file *file)
+{
+ struct video_client_ctx *client_ctx = file->private_data;
+
+ INFO("msm_vidc_dec: Inside %s()", __func__);
+ vidc_cleanup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT);
+ vidc_cleanup_addr_table(client_ctx, BUFFER_TYPE_INPUT);
+ 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;
}
@@ -1787,21 +2194,32 @@
{
struct video_client_ctx *client_ctx = file->private_data;
- DBG("msm_vidc_dec: Inside %s()", __func__);
+ INFO("msm_vidc_dec: Inside %s()", __func__);
+ vidc_cleanup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT);
+ vidc_cleanup_addr_table(client_ctx, BUFFER_TYPE_INPUT);
vid_dec_close_client(client_ctx);
vidc_release_firmware();
#ifndef USE_RES_TRACKER
vidc_disable_clk();
#endif
- DBG("msm_vidc_dec: Return from %s()", __func__);
+ 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,
- .ioctl = vid_dec_ioctl,
+static const struct file_operations vid_dec_fops[2] = {
+ {
+ .owner = THIS_MODULE,
+ .open = vid_dec_open,
+ .release = vid_dec_release,
+ .unlocked_ioctl = vid_dec_ioctl,
+ },
+ {
+ .owner = THIS_MODULE,
+ .open = vid_dec_open_secure,
+ .release = vid_dec_release_secure,
+ .unlocked_ioctl = vid_dec_ioctl,
+ },
+
};
void vid_dec_interrupt_deregister(void)
@@ -1867,7 +2285,7 @@
static int __init vid_dec_init(void)
{
- int rc = 0;
+ int rc = 0, i = 0, j = 0;
struct device *class_devp;
DBG("msm_vidc_dec: Inside %s()", __func__);
@@ -1878,7 +2296,8 @@
return -ENOMEM;
}
- rc = alloc_chrdev_region(&vid_dec_dev_num, 0, 1, VID_DEC_NAME);
+ rc = alloc_chrdev_region(&vid_dec_dev_num, 0, NUM_OF_DRIVER_NODES,
+ VID_DEC_NAME);
if (rc < 0) {
ERR("%s: alloc_chrdev_region Failed rc = %d\n",
__func__, rc);
@@ -1893,49 +2312,59 @@
goto error_vid_dec_class_create;
}
+ for (i = 0; i < NUM_OF_DRIVER_NODES; i++) {
+ class_devp = device_create(vid_dec_class, NULL,
+ (vid_dec_dev_num + i),
+ NULL, VID_DEC_NAME "%s",
+ node_name[i]);
- 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);
+ if (!i)
+ goto error_vid_dec_class_device_create;
+ else
+ goto error_vid_dec_cdev_add;
+ }
- 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[i] = class_devp;
- vid_dec_device_p->device = class_devp;
+ cdev_init(&vid_dec_device_p->cdev[i], &vid_dec_fops[i]);
+ vid_dec_device_p->cdev[i].owner = THIS_MODULE;
+ rc = cdev_add(&(vid_dec_device_p->cdev[i]),
+ (vid_dec_dev_num+i), 1);
- 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;
+ 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:
+ for (j = i-1; j >= 0; j--)
+ cdev_del(&(vid_dec_device_p->cdev[j]));
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);
+ unregister_chrdev_region(vid_dec_dev_num, NUM_OF_DRIVER_NODES);
error_vid_dec_alloc_chrdev_region:
kfree(vid_dec_device_p);
-
return rc;
}
static void __exit vid_dec_exit(void)
{
- DBG("msm_vidc_dec: Inside %s()", __func__);
- cdev_del(&(vid_dec_device_p->cdev));
+ int i = 0;
+ INFO("msm_vidc_dec: Inside %s()", __func__);
+ for (i = 0; i < NUM_OF_DRIVER_NODES; i++)
+ cdev_del(&(vid_dec_device_p->cdev[i]));
device_destroy(vid_dec_class, vid_dec_dev_num);
class_destroy(vid_dec_class);
- unregister_chrdev_region(vid_dec_dev_num, 1);
+ unregister_chrdev_region(vid_dec_dev_num, NUM_OF_DRIVER_NODES);
kfree(vid_dec_device_p);
DBG("msm_vidc_dec: Return from %s()", __func__);
}
diff --git a/drivers/video/msm/vidc/common/dec/vdec_internal.h b/drivers/video/msm/vidc/common/dec/vdec_internal.h
index 48ba65f..89da9a2 100644
--- a/drivers/video/msm/vidc/common/dec/vdec_internal.h
+++ b/drivers/video/msm/vidc/common/dec/vdec_internal.h
@@ -1,29 +1,13 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010, 2012, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
*
*/
@@ -32,7 +16,9 @@
#include <linux/msm_vidc_dec.h>
#include <linux/cdev.h>
-#include "vidc_init.h"
+#include <media/msm/vidc_init.h>
+
+#define NUM_OF_DRIVER_NODES 2
struct vid_dec_msg {
struct list_head list;
@@ -40,8 +26,8 @@
};
struct vid_dec_dev {
- struct cdev cdev;
- struct device *device;
+ struct cdev cdev[NUM_OF_DRIVER_NODES];
+ struct device *device[NUM_OF_DRIVER_NODES];
resource_size_t phys_base;
void __iomem *virt_base;
unsigned int irq;
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index a3684ef..ff4bc6b 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -9,11 +9,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
#include <linux/cdev.h>
@@ -32,11 +27,12 @@
#include <linux/workqueue.h>
#include <linux/android_pmem.h>
#include <linux/clk.h>
+#include <media/msm/vidc_type.h>
+#include <media/msm/vcd_api.h>
+#include <media/msm/vidc_init.h>
-#include "vidc_type.h"
-#include "vcd_api.h"
#include "venc_internal.h"
-#include "vidc_init.h"
+#include "vcd_res_tracker_api.h"
#define VID_ENC_NAME "msm_vidc_enc"
@@ -52,7 +48,7 @@
static struct vid_enc_dev *vid_enc_device_p;
static dev_t vid_enc_dev_num;
static struct class *vid_enc_class;
-static int vid_enc_ioctl(struct inode *inode, struct file *file,
+static long vid_enc_ioctl(struct file *file,
unsigned cmd, unsigned long arg);
static int stop_cmd;
@@ -163,18 +159,22 @@
venc_msg->venc_msg_info.statuscode = vid_enc_get_status(status);
- if (event == VCD_EVT_RESP_INPUT_DONE) {
- venc_msg->venc_msg_info.msgcode =
- VEN_MSG_INPUT_BUFFER_DONE;
- DBG("Send INPUT_DON message to client = %p\n",
+ 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);
- } else if (event == VCD_EVT_RESP_INPUT_FLUSHED) {
- venc_msg->venc_msg_info.msgcode = VEN_MSG_INPUT_BUFFER_DONE;
+ break;
+ case VCD_EVT_RESP_INPUT_FLUSHED:
DBG("Send INPUT_FLUSHED message to client = %p\n",
client_ctx);
- } else {
- ERR("vid_enc_input_frame_done(): invalid event type\n");
- return;
+ 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 =
@@ -197,6 +197,8 @@
int pmem_fd;
struct file *file;
s32 buffer_index = -1;
+ u32 ion_flag = 0;
+ struct ion_handle *buff_handle = NULL;
if (!client_ctx || !vcd_frame_data) {
ERR("vid_enc_input_frame_done() NULL pointer\n");
@@ -212,17 +214,21 @@
}
venc_msg->venc_msg_info.statuscode = vid_enc_get_status(status);
+ venc_msg->venc_msg_info.msgcode = VEN_MSG_OUTPUT_BUFFER_DONE;
- if (event == VCD_EVT_RESP_OUTPUT_DONE)
- venc_msg->venc_msg_info.msgcode =
- VEN_MSG_OUTPUT_BUFFER_DONE;
-
- else if (event == VCD_EVT_RESP_OUTPUT_FLUSHED)
- venc_msg->venc_msg_info.msgcode =
- VEN_MSG_OUTPUT_BUFFER_DONE;
- else {
- ERR("QVD: vid_enc_output_frame_done invalid cmd type\n");
- return;
+ 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 =
@@ -255,7 +261,18 @@
venc_msg->venc_msg_info.statuscode =
VEN_S_EFATAL;
}
-
+ if (venc_msg->venc_msg_info.buf.len > 0) {
+ ion_flag = vidc_get_fd_info(client_ctx, BUFFER_TYPE_OUTPUT,
+ pmem_fd, kernel_vaddr, buffer_index,
+ &buff_handle);
+ if (ion_flag == CACHED) {
+ msm_ion_do_cache_op(client_ctx->user_ion_client,
+ buff_handle,
+ (unsigned long *) kernel_vaddr,
+ (unsigned long)venc_msg->venc_msg_info.buf.len,
+ ION_IOC_CLEAN_INV_CACHES);
+ }
+ }
mutex_lock(&client_ctx->msg_queue_lock);
list_add_tail(&venc_msg->list, &client_ctx->msg_queue);
mutex_unlock(&client_ctx->msg_queue_lock);
@@ -490,7 +507,6 @@
mutex_unlock(&vid_enc_device_p->lock);
return false;
}
-
memset((void *)client_ctx, 0,
sizeof(struct video_client_ctx));
@@ -505,7 +521,7 @@
{
s32 client_index;
struct video_client_ctx *client_ctx;
- u32 vcd_status = VCD_ERR_FAIL;
+ int rc = 0;
u8 client_count = 0;
INFO("\n msm_vidc_enc: Inside %s()", __func__);
@@ -529,7 +545,7 @@
client_index = vid_enc_get_empty_client_index();
- if (client_index < 0) {
+ if (client_index == -1) {
ERR("%s() : No free clients client_index == -1\n",
__func__);
return -ENODEV;
@@ -541,13 +557,21 @@
init_completion(&client_ctx->event);
mutex_init(&client_ctx->msg_queue_lock);
+ mutex_init(&client_ctx->enrty_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);
+ if (vcd_get_ion_status()) {
+ client_ctx->user_ion_client = vcd_get_ion_client();
+ if (!client_ctx->user_ion_client) {
+ ERR("vcd_open ion get client failed");
+ return -EFAULT;
+ }
+ }
+ rc = vcd_open(vid_enc_device_p->device_handle, false,
+ vid_enc_vcd_cb, client_ctx, 0);
client_ctx->stop_msg = 0;
- if (!vcd_status) {
+ if (!rc) {
wait_for_completion(&client_ctx->event);
if (client_ctx->event_status) {
ERR("callback for vcd_open returned error: %u",
@@ -556,13 +580,13 @@
return -EFAULT;
}
} else {
- ERR("vcd_open returned error: %u", vcd_status);
+ ERR("vcd_open returned error: %u", rc);
mutex_unlock(&vid_enc_device_p->lock);
- return -EFAULT;
+ return rc;
}
file->private_data = client_ctx;
mutex_unlock(&vid_enc_device_p->lock);
- return 0;
+ return rc;
}
static int vid_enc_release(struct inode *inode, struct file *file)
@@ -582,7 +606,7 @@
.owner = THIS_MODULE,
.open = vid_enc_open,
.release = vid_enc_release,
- .ioctl = vid_enc_ioctl
+ .unlocked_ioctl = vid_enc_ioctl,
};
void vid_enc_interrupt_deregister(void)
@@ -720,7 +744,7 @@
kfree(vid_enc_device_p);
INFO("\n msm_vidc_enc: Return from %s()", __func__);
}
-static int vid_enc_ioctl(struct inode *inode, struct file *file,
+static long vid_enc_ioctl(struct file *file,
unsigned cmd, unsigned long u_arg)
{
struct video_client_ctx *client_ctx = NULL;
@@ -963,8 +987,15 @@
}
case VEN_IOCTL_FREE_RECON_BUFFER:
{
+ struct venc_recon_addr venc_recon;
DBG("VEN_IOCTL_FREE_RECON_BUFFER\n");
- result = vid_enc_free_recon_buffers(client_ctx);
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ if (copy_from_user(&venc_recon, venc_msg.in,
+ sizeof(venc_recon)))
+ return -EFAULT;
+ result = vid_enc_free_recon_buffers(client_ctx,
+ &venc_recon);
if (!result) {
ERR("VEN_IOCTL_FREE_RECON_BUFFER failed\n");
return -EIO;
@@ -1284,7 +1315,6 @@
case VEN_IOCTL_GET_SEQUENCE_HDR:
{
struct venc_seqheader seq_header, seq_header_user;
- memset(&seq_header, 0, sizeof(struct venc_seqheader));
if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
return -EFAULT;
@@ -1548,6 +1578,48 @@
}
break;
}
+ case VEN_IOCTL_SET_EXTRADATA:
+ case VEN_IOCTL_GET_EXTRADATA:
+ {
+ u32 extradata_flag;
+ DBG("VEN_IOCTL_(G)SET_EXTRADATA\n");
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ if (cmd == VEN_IOCTL_SET_EXTRADATA) {
+ if (copy_from_user(&extradata_flag, venc_msg.in,
+ sizeof(u32)))
+ return -EFAULT;
+ result = vid_enc_set_get_extradata(client_ctx,
+ &extradata_flag, true);
+ } else {
+ result = vid_enc_set_get_extradata(client_ctx,
+ &extradata_flag, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out, &extradata_flag,
+ sizeof(u32)))
+ return -EFAULT;
+ }
+ }
+ if (!result) {
+ ERR("setting VEN_IOCTL_(G)SET_LIVE_MODE failed\n");
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_SLICE_DELIVERY_MODE:
+ {
+ struct vcd_property_hdr vcd_property_hdr;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 enable = true;
+ vcd_property_hdr.prop_id = VCD_I_SLICE_DELIVERY_MODE;
+ vcd_property_hdr.sz = sizeof(u32);
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &enable);
+ if (vcd_status) {
+ pr_err(" Setting slice delivery mode failed");
+ return -EIO;
+ }
+ break;
+ }
case VEN_IOCTL_SET_AC_PREDICTION:
case VEN_IOCTL_GET_AC_PREDICTION:
case VEN_IOCTL_SET_RVLC:
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.c b/drivers/video/msm/vidc/common/enc/venc_internal.c
index 1298ff4..58be91a 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.c
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -9,11 +9,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
#include <linux/cdev.h>
@@ -32,11 +27,12 @@
#include <linux/workqueue.h>
#include <linux/android_pmem.h>
#include <linux/clk.h>
-
-#include "vidc_type.h"
-#include "vcd_api.h"
+#include <mach/msm_subsystem_map.h>
+#include <media/msm/vidc_type.h>
+#include <media/msm/vcd_api.h>
+#include <media/msm/vidc_init.h>
+#include "vcd_res_tracker_api.h"
#include "venc_internal.h"
-#include "vidc_init.h"
#if DEBUG
#define DBG(x...) printk(KERN_DEBUG x)
@@ -45,6 +41,9 @@
#endif
#define ERR(x...) printk(KERN_ERR x)
+static unsigned int vidc_mmu_subsystem[] = {
+ MSM_SUBSYSTEM_VIDEO};
+
u32 vid_enc_set_get_base_cfg(struct video_client_ctx *client_ctx,
struct venc_basecfg *base_config, u32 set_flag)
@@ -318,6 +317,42 @@
return true;
}
+u32 vid_enc_set_get_extradata(struct video_client_ctx *client_ctx,
+ u32 *extradata_flag, u32 set_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);
+ if (set_flag) {
+ DBG("vcd_set_property: VCD_I_METADATA_ENABLE = %d\n",
+ *extradata_flag);
+ 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) {
+ ERR("%s(): Set VCD_I_METADATA_ENABLE Failed\n",
+ __func__);
+ return false;
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_meta_data);
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_METADATA_ENABLE Failed\n",
+ __func__);
+ return false;
+ }
+ *extradata_flag = vcd_meta_data.meta_data_enable_flag;
+ DBG("vcd_get_property: VCD_I_METADATA_ENABLE = %d\n",
+ *extradata_flag);
+ }
+ return true;
+}
+
u32 vid_enc_set_get_framerate(struct video_client_ctx *client_ctx,
struct venc_framerate *frame_rate, u32 set_flag)
{
@@ -1496,6 +1531,11 @@
venc_buf_req->alignment = buffer_req.align;
venc_buf_req->bufpoolid = buffer_req.buf_pool_id;
venc_buf_req->suffixsize = 0;
+ DBG("%s: actual_count=%d, align=%d, sz=%d, min_count=%d, "
+ "max_count=%d, buf_pool_id=%d\n", __func__,
+ buffer_req.actual_count, buffer_req.align,
+ buffer_req.sz, buffer_req.min_count,
+ buffer_req.max_count, buffer_req.buf_pool_id);
}
return status;
}
@@ -1523,6 +1563,11 @@
buffer_req.align = venc_buf_req->alignment;
buffer_req.buf_pool_id = 0;
+ DBG("%s: actual_count=%d, align=%d, sz=%d, min_count=%d, "
+ "max_count=%d, buf_pool_id=%d\n", __func__,
+ buffer_req.actual_count, buffer_req.align, buffer_req.sz,
+ buffer_req.min_count, buffer_req.max_count,
+ buffer_req.buf_pool_id);
vcd_status = vcd_set_buffer_requirements(client_ctx->vcd_handle,
buffer, &buffer_req);
@@ -1538,7 +1583,7 @@
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;
+ unsigned long kernel_vaddr, length = 0;
if (!client_ctx || !buffer_info)
return false;
@@ -1547,14 +1592,14 @@
dir_buffer = BUFFER_TYPE_OUTPUT;
vcd_buffer_t = VCD_BUFFER_OUTPUT;
}
-
+ length = buffer_info->sz;
/*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)) {
+ VID_ENC_MAX_NUM_OF_BUFF, length)) {
DBG("%s() : user_virt_addr = %p cannot be set.",
__func__, buffer_info->pbuffer);
return false;
@@ -1594,7 +1639,6 @@
__func__, buffer_info->pbuffer);
return true;
}
-
vcd_status = vcd_free_buffer(client_ctx->vcd_handle, buffer_vcd,
(u8 *)kernel_vaddr);
@@ -1612,6 +1656,8 @@
int pmem_fd;
struct file *file;
s32 buffer_index = -1;
+ u32 ion_flag = 0;
+ struct ion_handle *buff_handle = NULL;
u32 vcd_status = VCD_ERR_FAIL;
@@ -1643,6 +1689,21 @@
/* Rely on VCD using the same flags as OMX */
vcd_input_buffer.flags = input_frame_info->flags;
+ ion_flag = vidc_get_fd_info(client_ctx, BUFFER_TYPE_INPUT,
+ pmem_fd, kernel_vaddr, buffer_index,
+ &buff_handle);
+
+ if (vcd_input_buffer.data_len > 0) {
+ if (ion_flag == CACHED) {
+ msm_ion_do_cache_op(
+ client_ctx->user_ion_client,
+ buff_handle,
+ (unsigned long *) vcd_input_buffer.virtual,
+ (unsigned long) vcd_input_buffer.data_len,
+ ION_IOC_CLEAN_CACHES);
+ }
+ }
+
vcd_status = vcd_encode_frame(client_ctx->vcd_handle,
&vcd_input_buffer);
if (!vcd_status)
@@ -1705,55 +1766,200 @@
struct venc_recon_addr *venc_recon)
{
u32 vcd_status = VCD_ERR_FAIL;
- u32 len;
+ u32 len, i, flags = 0;
struct file *file;
struct vcd_property_hdr vcd_property_hdr;
- struct vcd_property_enc_recon_buffer control;
+ struct vcd_property_enc_recon_buffer *control = NULL;
+ struct msm_mapped_buffer *mapped_buffer = NULL;
+ int rc = -1;
+ unsigned long ionflag = 0;
+ unsigned long iova = 0;
+ unsigned long buffer_size = 0;
+ size_t ion_len = -1;
+ unsigned long phy_addr;
- 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;
+ if (!client_ctx || !venc_recon) {
+ pr_err("%s() Invalid params", __func__);
+ return false;
+ }
+ len = sizeof(client_ctx->recon_buffer)/
+ sizeof(struct vcd_property_enc_recon_buffer);
+ for (i = 0; i < len; i++) {
+ if (!client_ctx->recon_buffer[i].kernel_virtual_addr) {
+ control = &client_ctx->recon_buffer[i];
+ break;
}
- put_pmem_file(file);
- DBG("Virt: %p, Phys %p, fd: %d", control.kernel_virtual_addr,
- control.physical_addr, control.pmem_fd);
+ }
+ if (!control) {
+ pr_err("Exceeded max recon buffer setting");
+ return false;
+ }
+ 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;
+ control->user_virtual_addr = venc_recon->pbuffer;
- 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;
+ if (!vcd_get_ion_status()) {
+ 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);
+ flags = MSM_SUBSYSTEM_MAP_IOVA;
+ mapped_buffer = msm_subsystem_map_buffer(
+ (unsigned long)control->physical_addr, len,
+ flags, vidc_mmu_subsystem,
+ sizeof(vidc_mmu_subsystem)/sizeof(unsigned int));
+ if (IS_ERR(mapped_buffer)) {
+ pr_err("buffer map failed");
+ return false;
+ }
+ control->client_data = (void *) mapped_buffer;
+ control->dev_addr = (u8 *)mapped_buffer->iova[0];
+ } else {
+ client_ctx->recon_buffer_ion_handle[i] = ion_import_fd(
+ client_ctx->user_ion_client, control->pmem_fd);
+ if (IS_ERR_OR_NULL(client_ctx->recon_buffer_ion_handle[i])) {
+ ERR("%s(): get_ION_handle failed\n", __func__);
+ goto import_ion_error;
+ }
+ rc = ion_handle_get_flags(client_ctx->user_ion_client,
+ client_ctx->recon_buffer_ion_handle[i],
+ &ionflag);
+ if (rc) {
+ ERR("%s():get_ION_flags fail\n",
+ __func__);
+ goto import_ion_error;
+ }
+ control->kernel_virtual_addr = (u8 *) ion_map_kernel(
+ client_ctx->user_ion_client,
+ client_ctx->recon_buffer_ion_handle[i],
+ ionflag);
+ if (!control->kernel_virtual_addr) {
+ ERR("%s(): get_ION_kernel virtual addr fail\n",
+ __func__);
+ goto import_ion_error;
+ }
+ if (res_trk_check_for_sec_session() ||
+ (res_trk_get_core_type() == (u32)VCD_CORE_720P)) {
+ rc = ion_phys(client_ctx->user_ion_client,
+ client_ctx->recon_buffer_ion_handle[i],
+ &phy_addr, &ion_len);
+ if (rc) {
+ ERR("%s():get_ION_kernel physical addr fail\n",
+ __func__);
+ goto map_ion_error;
+ }
+ control->physical_addr = (u8 *) phy_addr;
+ len = (unsigned long) ion_len;
+ control->client_data = NULL;
+ control->dev_addr = (u8 *)control->physical_addr;
} else {
- ERR("%s(): vid_enc_set_recon_buffers failed = %u\n",
- __func__, vcd_status);
- return false;
+ rc = ion_map_iommu(client_ctx->user_ion_client,
+ client_ctx->recon_buffer_ion_handle[i],
+ VIDEO_DOMAIN,
+ VIDEO_MAIN_POOL,
+ SZ_4K,
+ 0,
+ (unsigned long *)&iova,
+ (unsigned long *)&buffer_size,
+ UNCACHED, 0);
+ if (rc) {
+ ERR("%s():ION map iommu addr fail\n",
+ __func__);
+ goto map_ion_error;
+ }
+ control->physical_addr = (u8 *) iova;
+ len = buffer_size;
+ control->client_data = NULL;
+ control->dev_addr = (u8 *)iova;
}
+ }
+
+ 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;
+ }
+map_ion_error:
+ if (control->kernel_virtual_addr)
+ ion_unmap_kernel(client_ctx->user_ion_client,
+ client_ctx->recon_buffer_ion_handle[i]);
+ if (client_ctx->recon_buffer_ion_handle[i])
+ ion_free(client_ctx->user_ion_client,
+ client_ctx->recon_buffer_ion_handle[i]);
+ client_ctx->recon_buffer_ion_handle[i] = NULL;
+import_ion_error:
+ return false;
}
-u32 vid_enc_free_recon_buffers(struct video_client_ctx *client_ctx)
+u32 vid_enc_free_recon_buffers(struct video_client_ctx *client_ctx,
+ struct venc_recon_addr *venc_recon)
{
u32 vcd_status = VCD_ERR_FAIL;
struct vcd_property_hdr vcd_property_hdr;
- struct vcd_property_enc_recon_buffer control;
+ struct vcd_property_enc_recon_buffer *control = NULL;
+ u32 len = 0, i;
+
+ if (!client_ctx || !venc_recon) {
+ pr_err("%s() Invalid params", __func__);
+ return false;
+ }
+ len = sizeof(client_ctx->recon_buffer)/
+ sizeof(struct vcd_property_enc_recon_buffer);
+ pr_err(" %s() address %p", __func__,
+ venc_recon->pbuffer);
+ for (i = 0; i < len; i++) {
+ if (client_ctx->recon_buffer[i].user_virtual_addr
+ == venc_recon->pbuffer) {
+ control = &client_ctx->recon_buffer[i];
+ break;
+ }
+ }
+ if (!control) {
+ pr_err(" %s() address not found %p", __func__,
+ venc_recon->pbuffer);
+ return false;
+ }
+ if (control->client_data)
+ msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
+ control->client_data);
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);
+ &vcd_property_hdr, control);
+ if (vcd_get_ion_status()) {
+ if (client_ctx->recon_buffer_ion_handle[i]) {
+ ion_unmap_kernel(client_ctx->user_ion_client,
+ client_ctx->recon_buffer_ion_handle[i]);
+ if (!res_trk_check_for_sec_session() &&
+ (res_trk_get_core_type() != (u32)VCD_CORE_720P)) {
+ ion_unmap_iommu(client_ctx->user_ion_client,
+ client_ctx->recon_buffer_ion_handle[i],
+ VIDEO_DOMAIN,
+ VIDEO_MAIN_POOL);
+ }
+ ion_free(client_ctx->user_ion_client,
+ client_ctx->recon_buffer_ion_handle[i]);
+ client_ctx->recon_buffer_ion_handle[i] = NULL;
+ }
+ }
+ memset(control, 0, sizeof(struct vcd_property_enc_recon_buffer));
return true;
}
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.h b/drivers/video/msm/vidc/common/enc/venc_internal.h
index e7b7ff3..8a07fdb 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.h
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.h
@@ -1,29 +1,13 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
*
*/
@@ -32,8 +16,7 @@
#include <linux/msm_vidc_enc.h>
#include <linux/cdev.h>
-
-#include "vidc_init.h"
+#include <media/msm/vidc_init.h>
#define VID_ENC_MAX_NUM_OF_BUFF 100
@@ -85,6 +68,9 @@
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_extradata(struct video_client_ctx *client_ctx,
+ u32 *extradata_flag, u32 set_flag);
+
u32 vid_enc_set_get_short_header(struct video_client_ctx *client_ctx,
struct venc_switch *encoder_switch, u32 set_flag);
@@ -159,7 +145,8 @@
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_free_recon_buffers(struct video_client_ctx *client_ctx,
+ struct venc_recon_addr *venc_recon);
u32 vid_enc_get_recon_buffer_size(struct video_client_ctx *client_ctx,
struct venc_recon_buff_size *venc_recon_size);
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.c b/drivers/video/msm/vidc/common/init/vidc_init.c
old mode 100644
new mode 100755
index b9581a9..6226c79
--- a/drivers/video/msm/vidc/common/init/vidc_init.c
+++ b/drivers/video/msm/vidc/common/init/vidc_init.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -9,11 +9,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
#include <linux/cdev.h>
@@ -33,13 +28,12 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/debugfs.h>
-#include <mach/internal_power_rail.h>
#include <mach/clk.h>
#include <linux/pm_runtime.h>
-
-#include "vcd_api.h"
+#include <mach/msm_subsystem_map.h>
+#include <media/msm/vcd_api.h>
+#include <media/msm/vidc_init.h>
#include "vidc_init_internal.h"
-#include "vidc_init.h"
#include "vcd_res_tracker_api.h"
#if DEBUG
@@ -55,12 +49,13 @@
static struct vidc_dev *vidc_device_p;
static dev_t vidc_dev_num;
static struct class *vidc_class;
+static unsigned int vidc_mmu_subsystem[] = {MSM_SUBSYSTEM_VIDEO};
static const struct file_operations vidc_fops = {
.owner = THIS_MODULE,
.open = NULL,
.release = NULL,
- .ioctl = NULL,
+ .unlocked_ioctl = NULL,
};
struct workqueue_struct *vidc_wq;
@@ -68,7 +63,7 @@
static irqreturn_t vidc_isr(int irq, void *dev);
static spinlock_t vidc_spin_lock;
-u32 vidc_msg_timing, vidc_msg_pmem;
+u32 vidc_msg_timing, vidc_msg_pmem, vidc_msg_register;
#ifdef VIDC_ENABLE_DBGFS
struct dentry *vidc_debugfs_root;
@@ -84,7 +79,7 @@
u32 *var)
{
struct dentry *vidc_debugfs_file =
- debugfs_create_u32(name, S_IRUGO | S_IWUSR, root, var);
+ debugfs_create_u32(name, S_IRUGO | S_IWUSR, root, var);
if (!vidc_debugfs_file)
ERR("%s(): Error creating/opening file %s\n", __func__, name);
}
@@ -157,8 +152,8 @@
ERR("%s(): Invalid resource\n", __func__);
return -ENXIO;
}
- if (resource && resource->start)
- vidc_device_p->phys_base = resource->start;
+
+ vidc_device_p->phys_base = resource->start;
vidc_device_p->virt_base = ioremap(resource->start,
resource->end - resource->start + 1);
@@ -290,14 +285,14 @@
if (unlikely(rc)) {
ERR("%s() :request_irq failed\n", __func__);
- goto error_vidc_platfom_register;
+ goto error_vidc_request_irq;
}
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;
+ goto error_vidc_create_workqueue;
}
DBG("Disabling IRQ in %s()\n", __func__);
disable_irq_nosync(vidc_device_p->irq);
@@ -316,10 +311,16 @@
(u32 *) &vidc_msg_timing);
vidc_debugfs_file_create(root, "vidc_msg_pmem",
(u32 *) &vidc_msg_pmem);
+ vidc_debugfs_file_create(root, "vidc_msg_register",
+ (u32 *) &vidc_msg_register);
}
#endif
return 0;
+error_vidc_create_workqueue:
+ free_irq(vidc_device_p->irq, vidc_device_p->device);
+error_vidc_request_irq:
+ platform_driver_unregister(&msm_vidc_720p_platform_driver);
error_vidc_platfom_register:
cdev_del(&(vidc_device_p->cdev));
error_vidc_cdev_add:
@@ -344,31 +345,133 @@
{
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++;
+ if (!res_trk_check_for_sec_session()) {
+ 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);
+ 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);
+ if (!res_trk_check_for_sec_session()) {
+ 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_get_fd_info(struct video_client_ctx *client_ctx,
+ enum buffer_dir buffer, int pmem_fd,
+ unsigned long kvaddr, int index,
+ struct ion_handle **buff_handle)
+{
+ struct buf_addr_table *buf_addr_table;
+ u32 rc = 0;
+ if (!client_ctx)
+ return false;
+ if (buffer == BUFFER_TYPE_INPUT)
+ buf_addr_table = client_ctx->input_buf_addr_table;
+ else
+ buf_addr_table = client_ctx->output_buf_addr_table;
+ if (buf_addr_table[index].pmem_fd == pmem_fd) {
+ if (buf_addr_table[index].kernel_vaddr == kvaddr)
+ rc = buf_addr_table[index].buff_ion_flag;
+ *buff_handle = buf_addr_table[index].buff_ion_handle;
+ }
+ return rc;
+}
+EXPORT_SYMBOL(vidc_get_fd_info);
+
+void vidc_cleanup_addr_table(struct video_client_ctx *client_ctx,
+ enum buffer_dir buffer)
+{
+ u32 *num_of_buffers = NULL;
+ u32 i = 0;
+ struct buf_addr_table *buf_addr_table;
+ 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)
+ goto bail_out_cleanup;
+ if (!client_ctx->user_ion_client)
+ goto bail_out_cleanup;
+ for (i = 0; i < *num_of_buffers; ++i) {
+ if (buf_addr_table[i].client_data) {
+ msm_subsystem_unmap_buffer(
+ (struct msm_mapped_buffer *)
+ buf_addr_table[i].client_data);
+ buf_addr_table[i].client_data = NULL;
+ }
+ if (!IS_ERR_OR_NULL(buf_addr_table[i].buff_ion_handle)) {
+ if (!IS_ERR_OR_NULL(client_ctx->user_ion_client)) {
+ ion_unmap_kernel(client_ctx->user_ion_client,
+ buf_addr_table[i].
+ buff_ion_handle);
+ if (!res_trk_check_for_sec_session() &&
+ (res_trk_get_core_type() !=
+ (u32)VCD_CORE_720P)) {
+ ion_unmap_iommu(
+ client_ctx->user_ion_client,
+ buf_addr_table[i].
+ buff_ion_handle,
+ VIDEO_DOMAIN,
+ VIDEO_MAIN_POOL);
+ }
+ ion_free(client_ctx->user_ion_client,
+ buf_addr_table[i].
+ buff_ion_handle);
+ buf_addr_table[i].buff_ion_handle = NULL;
+ }
+ }
+ }
+ if (client_ctx->vcd_h264_mv_buffer.client_data) {
+ msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
+ client_ctx->vcd_h264_mv_buffer.client_data);
+ client_ctx->vcd_h264_mv_buffer.client_data = NULL;
+ }
+ if (!IS_ERR_OR_NULL(client_ctx->h264_mv_ion_handle)) {
+ if (!IS_ERR_OR_NULL(client_ctx->user_ion_client)) {
+ ion_unmap_kernel(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle);
+ if (!res_trk_check_for_sec_session() &&
+ (res_trk_get_core_type() != (u32)VCD_CORE_720P)) {
+ ion_unmap_iommu(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle,
+ VIDEO_DOMAIN,
+ VIDEO_MAIN_POOL);
+ }
+ ion_free(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle);
+ client_ctx->h264_mv_ion_handle = NULL;
+ }
+ }
+bail_out_cleanup:
+ return;
+}
+EXPORT_SYMBOL(vidc_cleanup_addr_table);
+
u32 vidc_lookup_addr_table(struct video_client_ctx *client_ctx,
enum buffer_dir buffer,
u32 search_with_user_vaddr,
@@ -384,7 +487,7 @@
if (!client_ctx)
return false;
-
+ mutex_lock(&client_ctx->enrty_queue_lock);
if (buffer == BUFFER_TYPE_INPUT) {
buf_addr_table = client_ctx->input_buf_addr_table;
num_of_buffers = client_ctx->num_of_input_buffers;
@@ -419,7 +522,7 @@
}
if (found) {
- *phy_addr = buf_addr_table[i].phy_addr;
+ *phy_addr = buf_addr_table[i].dev_addr;
*pmem_fd = buf_addr_table[i].pmem_fd;
*file = buf_addr_table[i].file;
*buffer_index = i;
@@ -434,6 +537,7 @@
" pmem_fd = %d, struct *file = %p "
"buffer_index = %d\n", *user_vaddr, *phy_addr,
*pmem_fd, *file, *buffer_index);
+ mutex_unlock(&client_ctx->enrty_queue_lock);
return true;
} else {
if (search_with_user_vaddr)
@@ -443,6 +547,7 @@
DBG("%s() : client_ctx = %p kernel_virt_addr = 0x%08lx"
" Not Found.\n", __func__, client_ctx,
*kernel_vaddr);
+ mutex_unlock(&client_ctx->enrty_queue_lock);
return false;
}
}
@@ -451,17 +556,188 @@
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 buffer_addr_offset, unsigned int max_num_buffers,
+ unsigned long length)
{
unsigned long len, phys_addr;
- struct file *file;
+ struct file *file = NULL;
+ u32 *num_of_buffers = NULL;
+ u32 i, flags;
+ struct buf_addr_table *buf_addr_table;
+ struct msm_mapped_buffer *mapped_buffer = NULL;
+ struct ion_handle *buff_ion_handle = NULL;
+ unsigned long ionflag = 0;
+ unsigned long iova = 0;
+ int ret = 0;
+ unsigned long buffer_size = 0;
+ size_t ion_len;
+
+ if (!client_ctx || !length)
+ return false;
+ mutex_lock(&client_ctx->enrty_queue_lock);
+ 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);
+ length = length * 2; /* workaround for iommu video h/w bug */
+ }
+
+ if (*num_of_buffers == max_num_buffers) {
+ ERR("%s(): Num of buffers reached max value : %d",
+ __func__, max_num_buffers);
+ goto bail_out_add;
+ }
+
+ 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);
+ goto bail_out_add;
+ } else {
+ if (!vcd_get_ion_status()) {
+ if (get_pmem_file(pmem_fd, &phys_addr,
+ kernel_vaddr, &len, &file)) {
+ ERR("%s(): get_pmem_file failed\n", __func__);
+ goto bail_out_add;
+ }
+ put_pmem_file(file);
+ flags = (buffer == BUFFER_TYPE_INPUT)
+ ? MSM_SUBSYSTEM_MAP_IOVA :
+ MSM_SUBSYSTEM_MAP_IOVA|MSM_SUBSYSTEM_ALIGN_IOVA_8K;
+ mapped_buffer = msm_subsystem_map_buffer(phys_addr,
+ length, flags, vidc_mmu_subsystem,
+ sizeof(vidc_mmu_subsystem)/sizeof(unsigned int));
+ if (IS_ERR(mapped_buffer)) {
+ pr_err("buffer map failed");
+ goto bail_out_add;
+ }
+ buf_addr_table[*num_of_buffers].client_data = (void *)
+ mapped_buffer;
+ buf_addr_table[*num_of_buffers].dev_addr =
+ mapped_buffer->iova[0];
+ } else {
+ buff_ion_handle = ion_import_fd(
+ client_ctx->user_ion_client, pmem_fd);
+ if (IS_ERR_OR_NULL(buff_ion_handle)) {
+ ERR("%s(): get_ION_handle failed\n",
+ __func__);
+ goto bail_out_add;
+ }
+ if (ion_handle_get_flags(client_ctx->user_ion_client,
+ buff_ion_handle,
+ &ionflag)) {
+ ERR("%s():ION flags fail\n",
+ __func__);
+ goto bail_out_add;
+ }
+ *kernel_vaddr = (unsigned long)
+ ion_map_kernel(
+ client_ctx->user_ion_client,
+ buff_ion_handle,
+ ionflag);
+ if (IS_ERR_OR_NULL((void *)*kernel_vaddr)) {
+ ERR("%s():ION virtual addr fail\n",
+ __func__);
+ *kernel_vaddr = (unsigned long)NULL;
+ goto ion_free_error;
+ }
+ if (res_trk_check_for_sec_session() ||
+ (res_trk_get_core_type() == (u32)VCD_CORE_720P)) {
+ if (ion_phys(client_ctx->user_ion_client,
+ buff_ion_handle,
+ &phys_addr, &ion_len)) {
+ ERR("%s():ION physical addr fail\n",
+ __func__);
+ goto ion_map_error;
+ }
+ len = (unsigned long) ion_len;
+ buf_addr_table[*num_of_buffers].client_data =
+ NULL;
+ buf_addr_table[*num_of_buffers].dev_addr =
+ phys_addr;
+ } else {
+ ret = ion_map_iommu(client_ctx->user_ion_client,
+ buff_ion_handle,
+ VIDEO_DOMAIN,
+ VIDEO_MAIN_POOL,
+ SZ_8K,
+ length,
+ (unsigned long *) &iova,
+ (unsigned long *) &buffer_size,
+ UNCACHED,
+ ION_IOMMU_UNMAP_DELAYED);
+ if (ret) {
+ ERR("%s():ION iommu map fail\n",
+ __func__);
+ goto ion_map_error;
+ }
+ phys_addr = iova;
+ buf_addr_table[*num_of_buffers].client_data =
+ NULL;
+ buf_addr_table[*num_of_buffers].dev_addr =
+ iova;
+ }
+ }
+ 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;
+ buf_addr_table[*num_of_buffers].buff_ion_handle =
+ buff_ion_handle;
+ buf_addr_table[*num_of_buffers].buff_ion_flag =
+ ionflag;
+ *num_of_buffers = *num_of_buffers + 1;
+ DBG("%s() : client_ctx = %p, user_virt_addr = 0x%08lx, "
+ "kernel_vaddr = 0x%08lx phys_addr=%lu inserted!",
+ __func__, client_ctx, user_vaddr, *kernel_vaddr,
+ phys_addr);
+ }
+ mutex_unlock(&client_ctx->enrty_queue_lock);
+ return true;
+ion_map_error:
+ if (*kernel_vaddr && buff_ion_handle)
+ ion_unmap_kernel(client_ctx->user_ion_client, buff_ion_handle);
+ion_free_error:
+ if (!IS_ERR_OR_NULL(buff_ion_handle))
+ ion_free(client_ctx->user_ion_client, buff_ion_handle);
+bail_out_add:
+ mutex_unlock(&client_ctx->enrty_queue_lock);
+ return false;
+}
+EXPORT_SYMBOL(vidc_insert_addr_table);
+
+/*
+ * Similar to vidc_insert_addr_table except intended for in-kernel
+ * use where buffers have already been alloced and mapped properly
+ */
+u32 vidc_insert_addr_table_kernel(struct video_client_ctx *client_ctx,
+ enum buffer_dir buffer, unsigned long user_vaddr,
+ unsigned long kernel_vaddr, unsigned long phys_addr,
+ unsigned int max_num_buffers,
+ unsigned long length)
+{
u32 *num_of_buffers = NULL;
u32 i;
struct buf_addr_table *buf_addr_table;
+ struct msm_mapped_buffer *mapped_buffer = NULL;
- if (!client_ctx)
+ if (!client_ctx || !length || !kernel_vaddr || !phys_addr)
return false;
-
+ mutex_lock(&client_ctx->enrty_queue_lock);
if (buffer == BUFFER_TYPE_INPUT) {
buf_addr_table = client_ctx->input_buf_addr_table;
num_of_buffers = &client_ctx->num_of_input_buffers;
@@ -478,40 +754,42 @@
if (*num_of_buffers == max_num_buffers) {
ERR("%s(): Num of buffers reached max value : %d",
__func__, max_num_buffers);
- return false;
+ goto bail_out_add;
}
i = 0;
while (i < *num_of_buffers &&
- user_vaddr != buf_addr_table[i].user_vaddr)
+ 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;
+ goto bail_out_add;
} 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;
+ mapped_buffer = NULL;
+ buf_addr_table[*num_of_buffers].client_data = (void *)
+ mapped_buffer;
+ buf_addr_table[*num_of_buffers].dev_addr = phys_addr;
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].kernel_vaddr = kernel_vaddr;
+ buf_addr_table[*num_of_buffers].pmem_fd = -1;
+ buf_addr_table[*num_of_buffers].file = NULL;
buf_addr_table[*num_of_buffers].phy_addr = phys_addr;
+ buf_addr_table[*num_of_buffers].buff_ion_handle = NULL;
*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);
+ "kernel_vaddr = 0x%08lx inserted!", __func__,
+ client_ctx, user_vaddr, kernel_vaddr);
}
+ mutex_unlock(&client_ctx->enrty_queue_lock);
return true;
+bail_out_add:
+ mutex_unlock(&client_ctx->enrty_queue_lock);
+ return false;
}
-EXPORT_SYMBOL(vidc_insert_addr_table);
+EXPORT_SYMBOL(vidc_insert_addr_table_kernel);
u32 vidc_delete_addr_table(struct video_client_ctx *client_ctx,
enum buffer_dir buffer,
@@ -524,33 +802,54 @@
if (!client_ctx)
return false;
-
+ mutex_lock(&client_ctx->enrty_queue_lock);
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;
+ goto bail_out_del;
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."
+ pr_err("%s() : client_ctx = %p."
" user_virt_addr = 0x%08lx NOT found",
__func__, client_ctx, user_vaddr);
- return false;
+ goto bail_out_del;
+ }
+ if (buf_addr_table[i].client_data) {
+ msm_subsystem_unmap_buffer(
+ (struct msm_mapped_buffer *)buf_addr_table[i].client_data);
+ buf_addr_table[i].client_data = NULL;
}
*kernel_vaddr = buf_addr_table[i].kernel_vaddr;
+ if (buf_addr_table[i].buff_ion_handle) {
+ ion_unmap_kernel(client_ctx->user_ion_client,
+ buf_addr_table[i].buff_ion_handle);
+ if (!res_trk_check_for_sec_session() &&
+ (res_trk_get_core_type() != (u32)VCD_CORE_720P)) {
+ ion_unmap_iommu(client_ctx->user_ion_client,
+ buf_addr_table[i].buff_ion_handle,
+ VIDEO_DOMAIN,
+ VIDEO_MAIN_POOL);
+ }
+ ion_free(client_ctx->user_ion_client,
+ buf_addr_table[i].buff_ion_handle);
+ buf_addr_table[i].buff_ion_handle = NULL;
+ }
if (i < (*num_of_buffers - 1)) {
+ buf_addr_table[i].client_data =
+ buf_addr_table[*num_of_buffers - 1].client_data;
+ buf_addr_table[i].dev_addr =
+ buf_addr_table[*num_of_buffers - 1].dev_addr;
buf_addr_table[i].user_vaddr =
buf_addr_table[*num_of_buffers - 1].user_vaddr;
buf_addr_table[i].kernel_vaddr =
@@ -561,12 +860,18 @@
buf_addr_table[*num_of_buffers - 1].pmem_fd;
buf_addr_table[i].file =
buf_addr_table[*num_of_buffers - 1].file;
+ buf_addr_table[i].buff_ion_handle =
+ buf_addr_table[*num_of_buffers - 1].buff_ion_handle;
}
*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);
+ mutex_unlock(&client_ctx->enrty_queue_lock);
return true;
+bail_out_del:
+ mutex_unlock(&client_ctx->enrty_queue_lock);
+ return false;
}
EXPORT_SYMBOL(vidc_delete_addr_table);
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.h b/drivers/video/msm/vidc/common/init/vidc_init.h
deleted file mode 100644
index 0bd0ede..0000000
--- a/drivers/video/msm/vidc/common/init/vidc_init.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#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
index 9d26d92..1d903ad 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init_internal.h
+++ b/drivers/video/msm/vidc/common/init/vidc_init_internal.h
@@ -1,29 +1,13 @@
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
*
*/
diff --git a/drivers/video/msm/vidc/common/vcd/vcd.h b/drivers/video/msm/vidc/common/vcd/vcd.h
index a1206e5..e557dab 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd.h
@@ -1,38 +1,22 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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 <media/msm/vcd_api.h>
+#include "vcd_util.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"
@@ -406,4 +390,9 @@
void vcd_handle_ind_info_output_reconfig
(struct vcd_clnt_ctxt *cctxt, u32 status);
+u32 vcd_req_perf_level(struct vcd_clnt_ctxt *cctxt,
+ struct vcd_property_perf_level *);
+
+u32 vcd_set_num_slices(struct vcd_clnt_ctxt *cctxt);
+
#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_api.c b/drivers/video/msm/vidc/common/vcd/vcd_api.c
index ac9459c..172107e 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_api.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_api.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -9,14 +9,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd.h"
u32 vcd_init(struct vcd_init_config *config, s32 *driver_handle)
@@ -79,22 +74,105 @@
}
EXPORT_SYMBOL(vcd_term);
+struct client_security_info {
+ int secure_enc;
+ int secure_dec;
+ int non_secure_enc;
+ int non_secure_dec;
+};
+
+static int vcd_get_clients_security_info(struct client_security_info *sec_info)
+{
+ struct vcd_drv_ctxt *drv_ctxt;
+ struct vcd_clnt_ctxt *cctxt;
+ int count = 0;
+ if (!sec_info) {
+ VCD_MSG_ERROR("Invalid argument\n");
+ return -EINVAL;
+ }
+ memset(sec_info, 0 , sizeof(*sec_info));
+ drv_ctxt = vcd_get_drv_context();
+ mutex_lock(&drv_ctxt->dev_mutex);
+ cctxt = drv_ctxt->dev_ctxt.cctxt_list_head;
+ while (cctxt) {
+ if (cctxt->secure && cctxt->decoding)
+ sec_info->secure_dec++;
+ else if (cctxt->secure && !cctxt->decoding)
+ sec_info->secure_enc++;
+ else if (!cctxt->secure && cctxt->decoding)
+ sec_info->non_secure_dec++;
+ else
+ sec_info->non_secure_enc++;
+ count++;
+ cctxt = cctxt->next;
+ }
+ mutex_unlock(&drv_ctxt->dev_mutex);
+ return count;
+}
+
+static int is_session_invalid(u32 decoding, u32 flags) {
+ int is_secure;
+ struct client_security_info sec_info;
+ int client_count = 0;
+ int secure_session_running = 0;
+ is_secure = (flags & VCD_CP_SESSION) ? 1:0;
+ client_count = vcd_get_clients_security_info(&sec_info);
+ secure_session_running = (sec_info.secure_enc > 0) ||
+ (sec_info.secure_dec > 0);
+ if (!decoding && is_secure) {
+ if ((sec_info.secure_dec == 1))
+ VCD_MSG_LOW("SE-SD: SUCCESS\n");
+ else {
+ VCD_MSG_LOW("SE is permitted only with SD: FAILURE\n");
+ return -EACCES;
+ }
+ } else if (!decoding && !is_secure) {
+ if (secure_session_running) {
+ VCD_MSG_LOW("SD-NSE: FAILURE\n");
+ VCD_MSG_LOW("SE-NSE: FAILURE\n");
+ return -EACCES;
+ }
+ } else if (decoding && is_secure) {
+ if (client_count > 0) {
+ VCD_MSG_LOW("S/NS-SD: FAILURE\n");
+ if (sec_info.secure_enc > 0 ||
+ sec_info.non_secure_enc > 0) {
+ return -EAGAIN;
+ }
+ return -EACCES;
+ }
+ } else {
+ if (sec_info.secure_dec > 0) {
+ VCD_MSG_LOW("SD-NSD: FAILURE\n");
+ return -EACCES;
+ }
+ }
+ return 0;
+}
+
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)
+ void *client_data, int flags)
{
- u32 rc = VCD_S_SUCCESS;
+ u32 rc = 0;
struct vcd_drv_ctxt *drv_ctxt;
-
+ struct vcd_clnt_ctxt *cctxt;
+ int is_secure = (flags & VCD_CP_SESSION) ? 1:0;
VCD_MSG_MED("vcd_open:");
if (!callback) {
VCD_MSG_ERROR("Bad parameters");
-
- return VCD_ERR_ILLEGAL_PARM;
+ return -EINVAL;
}
-
+ rc = is_session_invalid(decoding, flags);
+ if (rc) {
+ VCD_MSG_ERROR("Invalid Session: is_decoder: %d, secure: %d\n",
+ decoding, flags);
+ return rc;
+ }
+ if (is_secure)
+ res_trk_secure_set();
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
@@ -102,17 +180,22 @@
rc = drv_ctxt->dev_state.state_table->ev_hdlr.
open(drv_ctxt, driver_handle, decoding, callback,
client_data);
+ if (rc) {
+ rc = -ENODEV;
+ }
} else {
VCD_MSG_ERROR("Unsupported API in device state %d",
drv_ctxt->dev_state.state);
-
- rc = VCD_ERR_BAD_STATE;
+ rc = -EPERM;
}
+ if (!rc) {
+ cctxt = drv_ctxt->dev_ctxt.cctxt_list_head;
+ cctxt->secure = is_secure;
+ } else if (is_secure)
+ res_trk_secure_unset();
mutex_unlock(&drv_ctxt->dev_mutex);
-
return rc;
-
}
EXPORT_SYMBOL(vcd_open);
@@ -122,7 +205,7 @@
(struct vcd_clnt_ctxt *)handle;
struct vcd_drv_ctxt *drv_ctxt;
u32 rc;
-
+ int is_secure = 0;
VCD_MSG_MED("vcd_close:");
if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
@@ -131,6 +214,7 @@
return VCD_ERR_BAD_HANDLE;
}
+ is_secure = cctxt->secure;
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (drv_ctxt->dev_state.state_table->ev_hdlr.close) {
@@ -143,6 +227,8 @@
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
+ if (is_secure)
+ res_trk_secure_unset();
return rc;
}
@@ -882,5 +968,18 @@
EXPORT_SYMBOL(vcd_get_num_of_clients);
+u32 vcd_get_ion_status(void)
+{
+ return res_trk_get_enable_ion();
+}
+EXPORT_SYMBOL(vcd_get_ion_status);
+
+struct ion_client *vcd_get_ion_client(void)
+{
+ return res_trk_get_ion_client();
+}
+EXPORT_SYMBOL(vcd_get_ion_client);
+
+
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
index 97207d4..07c7347 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -9,14 +9,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd.h"
static const struct vcd_clnt_state_table *vcd_clnt_state_table[];
@@ -347,6 +342,7 @@
static u32 vcd_flush_in_eos(struct vcd_clnt_ctxt *cctxt,
u32 mode)
{
+ u32 rc = VCD_S_SUCCESS;
VCD_MSG_LOW("vcd_flush_in_eos:");
if (mode > VCD_FLUSH_ALL || !mode) {
@@ -356,10 +352,18 @@
}
VCD_MSG_MED("Flush mode requested %d", mode);
+ if (!(cctxt->status.frame_submitted) &&
+ (!cctxt->decoding)) {
+ 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);
- cctxt->status.mask |= (mode & VCD_FLUSH_ALL);
-
- return VCD_S_SUCCESS;
+ return rc;
}
static u32 vcd_flush_in_invalid(struct vcd_clnt_ctxt *cctxt,
@@ -498,7 +502,12 @@
}
rc = ddl_set_property(cctxt->ddl_handle, prop_hdr, prop_val);
- VCD_FAILED_RETURN(rc, "Failed: ddl_set_property");
+ if (rc) {
+ /* Some properties aren't known to ddl that we can handle */
+ if (prop_hdr->prop_id != VCD_I_VOP_TIMING_CONSTANT_DELTA)
+ VCD_FAILED_RETURN(rc, "Failed: ddl_set_property");
+ }
+
switch (prop_hdr->prop_id) {
case VCD_I_META_BUFFER_MODE:
{
@@ -539,6 +548,24 @@
cctxt->bframe = iperiod->b_frames;
break;
}
+ case VCD_REQ_PERF_LEVEL:
+ rc = vcd_req_perf_level(cctxt,
+ (struct vcd_property_perf_level *)prop_val);
+ break;
+ case VCD_I_VOP_TIMING_CONSTANT_DELTA:
+ {
+ struct vcd_property_vop_timing_constant_delta *delta =
+ (struct vcd_property_vop_timing_constant_delta *)
+ prop_val;
+ if (delta->constant_delta > 0) {
+ cctxt->time_frame_delta = delta->constant_delta;
+ rc = VCD_S_SUCCESS;
+ } else {
+ VCD_MSG_ERROR("Frame delta must be positive");
+ rc = VCD_ERR_ILLEGAL_PARM;
+ }
+ break;
+ }
default:
{
break;
@@ -551,6 +578,7 @@
(struct vcd_clnt_ctxt *cctxt,
struct vcd_property_hdr *prop_hdr, void *prop_val)
{
+ int rc;
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) {
@@ -558,7 +586,24 @@
return VCD_ERR_ILLEGAL_PARM;
}
- return ddl_get_property(cctxt->ddl_handle, prop_hdr, prop_val);
+ rc = ddl_get_property(cctxt->ddl_handle, prop_hdr, prop_val);
+ if (rc) {
+ /* Some properties aren't known to ddl that we can handle */
+ if (prop_hdr->prop_id != VCD_I_VOP_TIMING_CONSTANT_DELTA)
+ VCD_FAILED_RETURN(rc, "Failed: ddl_set_property");
+ }
+
+ switch (prop_hdr->prop_id) {
+ case VCD_I_VOP_TIMING_CONSTANT_DELTA:
+ {
+ struct vcd_property_vop_timing_constant_delta *delta =
+ (struct vcd_property_vop_timing_constant_delta *)
+ prop_val;
+ delta->constant_delta = cctxt->time_frame_delta;
+ rc = VCD_S_SUCCESS;
+ }
+ }
+ return rc;
}
static u32 vcd_set_buffer_requirements_cmn
@@ -709,10 +754,24 @@
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;
@@ -1558,18 +1617,14 @@
VCD_MSG_ERROR("Bad parameters. cctxt=%p, to_state=%d",
cctxt, to_state);
}
-
- if (!cctxt)
- return;
state_ctxt = &cctxt->clnt_state;
- if (state_ctxt->state) {
- if (state_ctxt->state == to_state) {
- VCD_MSG_HIGH("Client already in requested to_state=%d",
- to_state);
- return;
- }
+ 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",
@@ -1628,9 +1683,9 @@
NULL,
NULL,
NULL,
+ vcd_get_property_cmn,
NULL,
- NULL,
- NULL,
+ vcd_get_buffer_requirements_cmn,
NULL,
NULL,
NULL,
@@ -1677,10 +1732,10 @@
NULL,
vcd_flush_in_flushing,
NULL,
+ vcd_set_property_cmn,
+ vcd_get_property_cmn,
NULL,
- NULL,
- NULL,
- NULL,
+ vcd_get_buffer_requirements_cmn,
NULL,
NULL,
NULL,
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.h b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.h
index 6520fb8..9f2d63d 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.h
@@ -1,34 +1,18 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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 <media/msm/vcd_api.h>
#include "vcd_ddl_api.h"
struct vcd_clnt_state_table;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_core.h b/drivers/video/msm/vidc/common/vcd/vcd_core.h
index 47c517b..9014921 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_core.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_core.h
@@ -1,35 +1,20 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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 <linux/ion.h>
+#include <media/msm/vcd_api.h>
#include "vcd_ddl_api.h"
#include "vcd_util.h"
@@ -76,8 +61,8 @@
};
enum vcd_core_type {
- VCD_CORE_1080P,
- VCD_CORE_720P,
+ VCD_CORE_1080P,
+ VCD_CORE_720P
};
struct vcd_cmd_q_element {
@@ -172,7 +157,7 @@
u32 int_field_cnt;
s64 first_ts;
s64 prev_ts;
- u32 time_elapsed;
+ 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;
@@ -200,11 +185,13 @@
u32 live;
u32 decoding;
u32 bframe;
+ u32 num_slices;
struct vcd_property_frame_rate frm_rate;
u32 frm_p_units;
u32 reqd_perf_lvl;
u32 time_resoln;
+ u32 time_frame_delta;
struct vcd_buffer_pool in_buf_pool;
struct vcd_buffer_pool out_buf_pool;
@@ -220,9 +207,12 @@
struct vcd_sequence_hdr seq_hdr;
u8 *seq_hdr_phy_addr;
struct vcd_clnt_status status;
-
+ struct ion_client *vcd_ion_client;
+ u32 vcd_enable_ion;
struct vcd_clnt_ctxt *next;
u32 meta_mode;
+ int secure;
+ int perf_set_by_client;
};
#define VCD_BUFFERPOOL_INUSE_DECREMENT(val) \
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
index 2faab76..d517028 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -9,14 +9,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd.h"
static const struct vcd_dev_state_table *vcd_dev_state_table[];
@@ -42,18 +37,14 @@
VCD_MSG_ERROR("Bad parameters. drv_ctxt=%p, to_state=%d",
drv_ctxt, to_state);
}
-
- if (!drv_ctxt)
- return;
state_ctxt = &drv_ctxt->dev_state;
- if (state_ctxt->state) {
- if (state_ctxt->state == to_state) {
- VCD_MSG_HIGH("Device already in requested to_state=%d",
- to_state);
- return;
- }
+ 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",
@@ -138,10 +129,16 @@
{
transc = (struct vcd_transc *)client_data;
- if (!transc || !transc->in_use
- || !transc->cctxt) {
+ if (!transc || !transc->in_use || !transc->cctxt) {
VCD_MSG_ERROR("Invalid clientdata "
- "received from DDL ");
+ "received from DDL, transc = 0x%x\n",
+ (u32)transc);
+ if (transc) {
+ VCD_MSG_ERROR("transc->in_use = %u, "
+ "transc->cctxt = 0x%x\n",
+ transc->in_use,
+ (u32)transc->cctxt);
+ }
} else {
cctxt = transc->cctxt;
@@ -532,8 +529,8 @@
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");
+ VCD_MSG_HIGH("Device config mismatch. "
+ "VCD will be using config from 1st vcd_init");
}
*driver_handle = 0;
@@ -927,7 +924,6 @@
if (dev_ctxt->pwr_state == VCD_PWR_STATE_ON)
vcd_pause_all_sessions(dev_ctxt);
dev_ctxt->pwr_state = VCD_PWR_STATE_SLEEP;
-
break;
}
@@ -964,6 +960,9 @@
u32 rc = VCD_S_SUCCESS;
u32 client_inited = false;
u32 fail_all_open = false;
+ struct ddl_context *ddl_context;
+
+ ddl_context = ddl_get_context();
VCD_MSG_LOW("vcd_dev_cb_in_initing:");
@@ -1037,6 +1036,8 @@
tmp_client = client;
client = client->next;
+ if (tmp_client == dev_ctxt->cctxt_list_head)
+ fail_all_open = true;
vcd_destroy_client_context(tmp_client);
}
@@ -1045,6 +1046,10 @@
if (!client_inited || fail_all_open) {
VCD_MSG_ERROR("All client open requests failed");
+ DDL_IDLE(ddl_context);
+
+ vcd_handle_device_init_failed(drv_ctxt,
+ DEVICE_STATE_EVENT_NUMBER(close));
dev_ctxt->pending_cmd = VCD_CMD_DEVICE_TERM;
} else {
if (vcd_power_event(dev_ctxt, NULL,
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.h b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.h
index 787b462..2443c33 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.h
@@ -1,35 +1,19 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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 <media/msm/vcd_api.h>
#include "vcd_ddl_api.h"
#include "vcd_core.h"
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
index 202e3f7..01bd931 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -9,14 +9,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd_power_sm.h"
#include "vcd_core.h"
#include "vcd.h"
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_power_sm.h b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.h
index 26558ca..26ce019 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_power_sm.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.h
@@ -1,29 +1,13 @@
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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_
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c b/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c
index 2ef953d..ab21bac 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -9,14 +9,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd.h"
#define NORMALIZATION_FACTOR 3600
@@ -107,9 +102,10 @@
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;
+ if (!cctxt->perf_set_by_client)
+ 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,
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 67af827..759989d 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -9,54 +9,218 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
-
+#include <linux/memory_alloc.h>
+#include <mach/msm_subsystem_map.h>
#include <asm/div64.h>
-
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd.h"
#include "vdec_internal.h"
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
+#define MAP_TABLE_SZ 64
+#define VCD_ENC_MAX_OUTBFRS_PER_FRAME 8
-static int vcd_pmem_alloc(size_t sz, u8 **kernel_vaddr, u8 **phy_addr)
+struct vcd_msm_map_buffer {
+ phys_addr_t phy_addr;
+ struct msm_mapped_buffer *mapped_buffer;
+ struct ion_handle *alloc_handle;
+ u32 in_use;
+};
+static struct vcd_msm_map_buffer msm_mapped_buffer_table[MAP_TABLE_SZ];
+static unsigned int vidc_mmu_subsystem[] = {MSM_SUBSYSTEM_VIDEO};
+
+static int vcd_pmem_alloc(size_t sz, u8 **kernel_vaddr, u8 **phy_addr,
+ struct vcd_clnt_ctxt *cctxt)
{
- *phy_addr =
- (u8 *) pmem_kalloc(sz, PMEM_MEMTYPE | PMEM_ALIGNMENT_4K);
+ u32 memtype, i = 0, flags = 0;
+ struct vcd_msm_map_buffer *map_buffer = NULL;
+ struct msm_mapped_buffer *mapped_buffer = NULL;
+ unsigned long iova = 0;
+ unsigned long buffer_size = 0;
+ int ret = 0;
+ unsigned long ionflag = 0;
+ ion_phys_addr_t phyaddr = 0;
+ size_t len = 0;
- if (!IS_ERR((void *)*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__);
- pmem_kfree((s32) *phy_addr);
- return -ENOMEM;
+ if (!kernel_vaddr || !phy_addr || !cctxt) {
+ pr_err("\n%s: Invalid parameters", __func__);
+ goto bailout;
+ }
+ *phy_addr = NULL;
+ *kernel_vaddr = NULL;
+ for (i = 0; i < MAP_TABLE_SZ; i++) {
+ if (!msm_mapped_buffer_table[i].in_use) {
+ map_buffer = &msm_mapped_buffer_table[i];
+ map_buffer->in_use = 1;
+ break;
}
- pr_debug("write buf: phy addr 0x%08x kernel addr 0x%08x\n",
- (u32) *phy_addr, (u32) *kernel_vaddr);
- return 0;
+ }
+ if (!map_buffer) {
+ pr_err("%s() map table is full", __func__);
+ goto bailout;
+ }
+ res_trk_set_mem_type(DDL_MM_MEM);
+ memtype = res_trk_get_mem_type();
+ if (!cctxt->vcd_enable_ion) {
+ map_buffer->phy_addr = (phys_addr_t)
+ allocate_contiguous_memory_nomap(sz, memtype, SZ_4K);
+ if (!map_buffer->phy_addr) {
+ pr_err("%s() acm alloc failed", __func__);
+ goto free_map_table;
+ }
+ flags = MSM_SUBSYSTEM_MAP_IOVA | MSM_SUBSYSTEM_MAP_KADDR;
+ map_buffer->mapped_buffer =
+ msm_subsystem_map_buffer((unsigned long)map_buffer->phy_addr,
+ sz, flags, vidc_mmu_subsystem,
+ sizeof(vidc_mmu_subsystem)/sizeof(unsigned int));
+ if (IS_ERR(map_buffer->mapped_buffer)) {
+ pr_err(" %s() buffer map failed", __func__);
+ goto free_acm_alloc;
+ }
+ mapped_buffer = map_buffer->mapped_buffer;
+ if (!mapped_buffer->vaddr || !mapped_buffer->iova[0]) {
+ pr_err("%s() map buffers failed", __func__);
+ goto free_map_buffers;
+ }
+ *phy_addr = (u8 *) mapped_buffer->iova[0];
+ *kernel_vaddr = (u8 *) mapped_buffer->vaddr;
+ VCD_MSG_LOW("vcd_pmem_alloc: phys(0x%x), virt(0x%x), "\
+ "sz(%u), flags(0x%x)", (u32)*phy_addr,
+ (u32)*kernel_vaddr, sz, (u32)flags);
} else {
- pr_err("%s: could not allocte in kernel pmem buffers\n",
- __func__);
- return -ENOMEM;
+ map_buffer->alloc_handle = ion_alloc(
+ cctxt->vcd_ion_client, sz, SZ_4K,
+ memtype);
+ if (!map_buffer->alloc_handle) {
+ pr_err("%s() ION alloc failed", __func__);
+ goto bailout;
+ }
+ if (ion_handle_get_flags(cctxt->vcd_ion_client,
+ map_buffer->alloc_handle,
+ &ionflag)) {
+ pr_err("%s() ION get flag failed", __func__);
+ goto bailout;
+ }
+ *kernel_vaddr = (u8 *) ion_map_kernel(
+ cctxt->vcd_ion_client,
+ map_buffer->alloc_handle,
+ ionflag);
+ if (!(*kernel_vaddr)) {
+ pr_err("%s() ION map failed", __func__);
+ goto ion_free_bailout;
+ }
+ if (res_trk_get_core_type() != (u32)VCD_CORE_720P) {
+ ret = ion_map_iommu(cctxt->vcd_ion_client,
+ map_buffer->alloc_handle,
+ VIDEO_DOMAIN,
+ VIDEO_MAIN_POOL,
+ SZ_4K,
+ 0,
+ (unsigned long *)&iova,
+ (unsigned long *)&buffer_size,
+ UNCACHED, 0);
+ if (ret) {
+ pr_err("%s() ION iommu map failed", __func__);
+ goto ion_map_bailout;
+ }
+ map_buffer->phy_addr = iova;
+ } else {
+ ret = ion_phys(cctxt->vcd_ion_client,
+ map_buffer->alloc_handle,
+ &phyaddr,
+ &len);
+ if (ret) {
+ pr_err("%s() ion_phys failed", __func__);
+ goto ion_map_bailout;
+ }
+ map_buffer->phy_addr = phyaddr;
+ }
+ if (!map_buffer->phy_addr) {
+ pr_err("%s() acm alloc failed", __func__);
+ goto free_map_table;
+ }
+ *phy_addr = (u8 *)map_buffer->phy_addr;
+ mapped_buffer = NULL;
+ map_buffer->mapped_buffer = NULL;
+ VCD_MSG_LOW("vcd_ion_alloc: phys(0x%x), virt(0x%x), "\
+ "sz(%u), ionflags(0x%x)", (u32)*phy_addr,
+ (u32)*kernel_vaddr, sz, (u32)ionflag);
}
+ return 0;
+
+free_map_buffers:
+ if (map_buffer->mapped_buffer)
+ msm_subsystem_unmap_buffer(map_buffer->mapped_buffer);
+free_acm_alloc:
+ if (!cctxt->vcd_enable_ion) {
+ free_contiguous_memory_by_paddr(
+ (unsigned long)map_buffer->phy_addr);
+ }
+ return -ENOMEM;
+ion_map_bailout:
+ ion_unmap_kernel(cctxt->vcd_ion_client, map_buffer->alloc_handle);
+ion_free_bailout:
+ ion_free(cctxt->vcd_ion_client, map_buffer->alloc_handle);
+free_map_table:
+ map_buffer->in_use = 0;
+bailout:
+ return -ENOMEM;
}
-static int vcd_pmem_free(u8 *kernel_vaddr, u8 *phy_addr)
+static int vcd_pmem_free(u8 *kernel_vaddr, u8 *phy_addr,
+ struct vcd_clnt_ctxt *cctxt)
{
- iounmap((void *)kernel_vaddr);
- pmem_kfree((s32) phy_addr);
+ u32 i = 0;
+ struct vcd_msm_map_buffer *map_buffer = NULL;
+
+ if (!kernel_vaddr || !phy_addr || !cctxt) {
+ pr_err("\n%s: Invalid parameters", __func__);
+ goto bailout;
+ }
+ for (i = 0; i < MAP_TABLE_SZ; i++) {
+ if (msm_mapped_buffer_table[i].in_use &&
+ (msm_mapped_buffer_table[i]
+ .mapped_buffer->vaddr == kernel_vaddr)) {
+ map_buffer = &msm_mapped_buffer_table[i];
+ map_buffer->in_use = 0;
+ break;
+ }
+ }
+ if (!map_buffer) {
+ pr_err("%s() Entry not found", __func__);
+ goto bailout;
+ }
+ if (map_buffer->mapped_buffer)
+ msm_subsystem_unmap_buffer(map_buffer->mapped_buffer);
+ if (cctxt->vcd_enable_ion) {
+ VCD_MSG_LOW("vcd_ion_free: phys(0x%x), virt(0x%x)",
+ (u32)phy_addr, (u32)kernel_vaddr);
+ if (map_buffer->alloc_handle) {
+ ion_unmap_kernel(cctxt->vcd_ion_client,
+ map_buffer->alloc_handle);
+ if (res_trk_get_core_type() != (u32)VCD_CORE_720P)
+ ion_unmap_iommu(cctxt->vcd_ion_client,
+ map_buffer->alloc_handle,
+ VIDEO_DOMAIN,
+ VIDEO_MAIN_POOL);
+ ion_free(cctxt->vcd_ion_client,
+ map_buffer->alloc_handle);
+ }
+ } else {
+ VCD_MSG_LOW("vcd_pmem_free: phys(0x%x), virt(0x%x)",
+ (u32)phy_addr, (u32)kernel_vaddr);
+ free_contiguous_memory_by_paddr(
+ (unsigned long)map_buffer->phy_addr);
+ }
+bailout:
+ kernel_vaddr = NULL;
+ phy_addr = NULL;
return 0;
}
+
u8 *vcd_pmem_get_physical(struct video_client_ctx *client_ctx,
unsigned long kernel_vaddr)
{
@@ -83,6 +247,42 @@
}
+u32 vcd_get_ion_flag(struct video_client_ctx *client_ctx,
+ unsigned long kernel_vaddr,
+ struct ion_handle **buff_ion_handle)
+{
+ unsigned long phy_addr, user_vaddr;
+ int pmem_fd;
+ struct file *file;
+ s32 buffer_index = -1;
+ u32 ion_flag = 0;
+ struct ion_handle *buff_handle = NULL;
+
+ if (vidc_lookup_addr_table(client_ctx, BUFFER_TYPE_INPUT,
+ false, &user_vaddr, &kernel_vaddr,
+ &phy_addr, &pmem_fd, &file,
+ &buffer_index)) {
+
+ ion_flag = vidc_get_fd_info(client_ctx, BUFFER_TYPE_INPUT,
+ pmem_fd, kernel_vaddr, buffer_index,
+ &buff_handle);
+ *buff_ion_handle = buff_handle;
+ return ion_flag;
+ } else if (vidc_lookup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT,
+ false, &user_vaddr, &kernel_vaddr, &phy_addr, &pmem_fd, &file,
+ &buffer_index)) {
+ ion_flag = vidc_get_fd_info(client_ctx, BUFFER_TYPE_OUTPUT,
+ pmem_fd, kernel_vaddr, buffer_index,
+ &buff_handle);
+ *buff_ion_handle = buff_handle;
+ return ion_flag;
+ } else {
+ VCD_MSG_ERROR("Couldn't get ion flag");
+ return 0;
+ }
+
+}
+
void vcd_reset_device_channels(struct vcd_dev_ctxt *dev_ctxt)
{
dev_ctxt->ddl_frame_ch_free = dev_ctxt->ddl_frame_ch_depth;
@@ -418,6 +618,8 @@
{
struct vcd_buffer_entry *buf_entry;
u8 *physical;
+ u32 ion_flag = 0;
+ struct ion_handle *buff_handle = NULL;
buf_entry = vcd_find_buffer_pool_entry(buf_pool, buffer);
if (buf_entry) {
@@ -429,6 +631,9 @@
physical = (u8 *) vcd_pmem_get_physical(
cctxt->client_data, (unsigned long)buffer);
+ ion_flag = vcd_get_ion_flag(cctxt->client_data,
+ (unsigned long)buffer,
+ &buff_handle);
if (!physical) {
VCD_MSG_ERROR("Couldn't get physical address");
return VCD_ERR_BAD_POINTER;
@@ -443,7 +648,6 @@
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;
@@ -452,6 +656,8 @@
buf_entry->frame.virtual = buf_entry->virtual;
buf_entry->frame.physical = buf_entry->physical;
+ buf_entry->frame.ion_flag = ion_flag;
+ buf_entry->frame.buff_ion_handle = buff_handle;
buf_pool->validated++;
@@ -481,7 +687,7 @@
buf_size += buf_req->align;
rc = vcd_pmem_alloc(buf_size, &buf_entry->alloc,
- &buf_entry->physical);
+ &buf_entry->physical, cctxt);
if (rc < 0) {
VCD_MSG_ERROR("Buffer allocation failed");
@@ -563,7 +769,8 @@
return VCD_ERR_ILLEGAL_PARM;
}
if (buf_entry->in_use) {
- VCD_MSG_ERROR("\n Buffer is in use and is not flushed");
+ VCD_MSG_ERROR("Buffer is in use and is not flushed: %p, %d\n",
+ buf_entry, buf_entry->in_use);
return VCD_ERR_ILLEGAL_OP;
}
@@ -571,7 +778,7 @@
buf_entry->virtual, buf_entry->allocated);
if (buf_entry->allocated) {
- vcd_pmem_free(buf_entry->alloc, buf_entry->physical);
+ vcd_pmem_free(buf_entry->alloc, buf_entry->physical, cctxt);
buf_pool->allocated--;
}
@@ -598,7 +805,7 @@
buf_pool->entries[i].allocated) {
vcd_pmem_free(buf_pool->entries[i].alloc,
buf_pool->entries[i].
- physical);
+ physical, cctxt);
}
}
@@ -762,7 +969,6 @@
list_del(&entry->list);
pool->q_len--;
}
-
return entry;
}
@@ -862,6 +1068,7 @@
{
u32 rc = VCD_S_SUCCESS;
struct vcd_buffer_entry *buf_entry;
+ struct vcd_buffer_entry *orig_frame = NULL;
VCD_MSG_LOW("vcd_flush_buffers:");
@@ -885,9 +1092,19 @@
vcd_frame_data),
cctxt,
cctxt->client_data);
+ orig_frame = vcd_find_buffer_pool_entry(
+ &cctxt->in_buf_pool,
+ buf_entry->virtual);
}
- buf_entry->in_use = false;
+ if (orig_frame) {
+ orig_frame->in_use--;
+ if (orig_frame != buf_entry)
+ kfree(buf_entry);
+ } else {
+ buf_entry->in_use = false;
+ VCD_MSG_ERROR("Original frame not found in buffer pool\n");
+ }
VCD_BUFFERPOOL_INUSE_DECREMENT(
cctxt->in_buf_pool.in_use);
buf_entry = NULL;
@@ -925,6 +1142,14 @@
VCD_MSG_LOW("vcd_init_client_context:");
rc = ddl_open(&cctxt->ddl_handle, cctxt->decoding);
VCD_FAILED_RETURN(rc, "Failed: ddl_open");
+ cctxt->vcd_enable_ion = res_trk_get_enable_ion();
+ if (cctxt->vcd_enable_ion) {
+ cctxt->vcd_ion_client = res_trk_get_ion_client();
+ if (!cctxt->vcd_ion_client) {
+ VCD_MSG_LOW("vcd_init_ion_get_client_failed:");
+ return -EINVAL;
+ }
+ }
cctxt->ddl_hdl_valid = true;
cctxt->clnt_state.state = VCD_CLIENT_STATE_OPEN;
cctxt->clnt_state.state_table =
@@ -934,6 +1159,7 @@
cctxt->bframe = 0;
cctxt->cmd_q.pending_cmd = VCD_CMD_NONE;
cctxt->status.last_evt = VCD_EVT_RESP_BASE;
+ cctxt->num_slices = 1;
return rc;
}
@@ -983,7 +1209,7 @@
if (cctxt->seq_hdr.sequence_header) {
vcd_pmem_free(cctxt->seq_hdr.sequence_header,
- cctxt->seq_hdr_phy_addr);
+ cctxt->seq_hdr_phy_addr, cctxt);
cctxt->seq_hdr.sequence_header = NULL;
}
@@ -1001,7 +1227,7 @@
cctxt->signature = 0;
cctxt->clnt_state.state = VCD_CLIENT_STATE_NULL;
cctxt->clnt_state.state_table = NULL;
-
+ cctxt->vcd_ion_client = NULL;
kfree(cctxt);
}
@@ -1105,6 +1331,7 @@
}
} else {
+ vcd_set_num_slices(transc->cctxt);
rc = ddl_encode_start(transc->cctxt->ddl_handle,
(void *)transc);
}
@@ -1304,7 +1531,8 @@
u32 rc = VCD_S_SUCCESS;
u32 evcode = 0;
struct ddl_frame_data_tag ddl_ip_frm;
- struct ddl_frame_data_tag ddl_op_frm;
+ struct ddl_frame_data_tag *ddl_op_frm;
+ u32 out_buf_cnt = 0;
VCD_MSG_LOW("vcd_submit_frame:");
cctxt = transc->cctxt;
@@ -1316,34 +1544,52 @@
transc->flags = ip_frm_entry->flags;
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);
+ (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 {
+ ddl_op_frm = (struct ddl_frame_data_tag *)
+ kmalloc((sizeof(struct ddl_frame_data_tag) *
+ VCD_ENC_MAX_OUTBFRS_PER_FRAME), GFP_KERNEL);
+ if (!ddl_op_frm) {
+ VCD_MSG_ERROR("Memory allocation failure");
+ return VCD_ERR_ALLOC_FAIL;
+ }
+ memset(ddl_op_frm, 0, (sizeof(struct ddl_frame_data_tag) *
+ VCD_ENC_MAX_OUTBFRS_PER_FRAME));
+ for (out_buf_cnt = 0; out_buf_cnt < cctxt->num_slices ;
+ out_buf_cnt++) {
+ 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;
+ break;
+ }
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);
+ ddl_op_frm[out_buf_cnt].vcd_frm = op_buf_entry->frame;
+ VCD_MSG_LOW("%s : buffer_cnt = %d framebfr(virtual)"
+ " 0x%p", __func__, out_buf_cnt,
+ op_buf_entry->frame.virtual);
+ VCD_MSG_LOW("framebfr(physical) 0x%p bfrlength %d",
+ op_buf_entry->frame.physical,
+ op_buf_entry->frame.alloc_len);
}
+ ddl_ip_frm.vcd_frm = *ip_frm_entry;
+ ddl_ip_frm.frm_delta =
+ vcd_calculate_frame_delta(cctxt,
+ ip_frm_entry);
+ evcode = CLIENT_STATE_EVENT_NUMBER(encode_frame);
+
+ if (!VCD_FAILED(rc)) {
+ rc = ddl_encode_frame(cctxt->ddl_handle,
+ &ddl_ip_frm, &ddl_op_frm[0], (void *) transc);
+ }
+ kfree(ddl_op_frm);
}
ip_frm_entry->ip_frm_tag = transc->ip_frm_tag;
if (!VCD_FAILED(rc)) {
@@ -1678,17 +1924,21 @@
} else {
memset(&dev_ctxt->trans_tbl[i], 0,
sizeof(struct vcd_transc));
-
dev_ctxt->trans_tbl[i].in_use = true;
-
+ VCD_MSG_LOW("%s: Get transc = 0x%x, in_use = %u\n",
+ __func__, (u32)(&dev_ctxt->trans_tbl[i]),
+ dev_ctxt->trans_tbl[i].in_use);
return &dev_ctxt->trans_tbl[i];
}
}
void vcd_release_trans_tbl_entry(struct vcd_transc *trans_entry)
{
- if (trans_entry)
+ if (trans_entry) {
trans_entry->in_use = false;
+ VCD_MSG_LOW("%s: Free transc = 0x%x, in_use = %u\n",
+ __func__, (u32)trans_entry, trans_entry->in_use);
+ }
}
u32 vcd_handle_input_done(
@@ -1700,6 +1950,7 @@
(struct ddl_frame_data_tag *) payload;
struct vcd_buffer_entry *orig_frame = NULL;
u32 rc;
+ VCD_MSG_LOW("%s\n", __func__);
if (!cctxt->status.frame_submitted &&
!cctxt->status.frame_delayed) {
@@ -1747,8 +1998,11 @@
transc->ip_buf_entry = NULL;
transc->input_done = true;
- if (transc->input_done && transc->frame_done)
+ if (transc->input_done && transc->frame_done) {
+ VCD_MSG_LOW("%s Calling vcd_release_trans_tbl_entry\n",
+ __func__);
vcd_release_trans_tbl_entry(transc);
+ }
if (VCD_FAILED(status)) {
VCD_MSG_ERROR("INPUT_DONE returned err = 0x%x", status);
@@ -1787,6 +2041,7 @@
(struct ddl_frame_data_tag *) payload;
u32 rc = VCD_ERR_FAIL, codec_config = false;
u32 core_type = res_trk_get_core_type();
+ VCD_MSG_LOW("%s\n", __func__);
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);
@@ -1892,6 +2147,7 @@
struct ddl_frame_data_tag *frame =
(struct ddl_frame_data_tag *)payload;
u32 rc = VCD_S_SUCCESS;
+ VCD_MSG_LOW("%s\n", __func__);
if (!cctxt->status.frame_submitted &&
!cctxt->status.frame_delayed) {
@@ -1952,6 +2208,7 @@
struct vcd_transc *transc;
struct ddl_frame_data_tag *frame =
(struct ddl_frame_data_tag *)payload;
+ VCD_MSG_LOW("%s\n", __func__);
rc = vcd_validate_io_done_pyld(cctxt, payload, VCD_S_SUCCESS);
if (rc == VCD_ERR_CLIENT_FATAL)
@@ -1985,6 +2242,7 @@
struct vcd_transc *transc;
u32 rc;
s64 time_stamp;
+ VCD_MSG_LOW("%s\n", __func__);
rc = vcd_validate_io_done_pyld(cctxt, payload, status);
if (rc == VCD_ERR_CLIENT_FATAL)
@@ -2074,7 +2332,7 @@
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:");
+ VCD_MSG_LOW("%s\n", __func__);
rc = vcd_validate_io_done_pyld(cctxt, payload, status);
if (rc == VCD_ERR_CLIENT_FATAL)
vcd_handle_clnt_fatal(cctxt, frame->frm_trans_end);
@@ -2155,6 +2413,7 @@
u32 rc, seqhdr_present = 0;
struct vcd_property_hdr prop_hdr;
struct vcd_sequence_hdr seq_hdr;
+ struct vcd_property_sps_pps_for_idr_enable idr_enable;
struct vcd_property_codec codec;
*handled = true;
prop_hdr.prop_id = DDL_I_SEQHDR_PRESENT;
@@ -2171,29 +2430,64 @@
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;
+ /*
+ * The seq. header is stored in a seperate internal
+ * buffer and is memcopied into the output buffer
+ * that we provide. In secure sessions, we aren't
+ * allowed to touch these buffers. In these cases
+ * seq. headers are returned to client as part of
+ * I-frames. So for secure session, just return
+ * empty buffer.
+ */
+ if (!cctxt->secure) {
+ 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;
+ } else
+ VCD_MSG_ERROR("rc = 0x%x. Failed:"
+ "ddl_get_property: VCD_I_SEQ_HEADER",
+ rc);
+ } else {
+ /*
+ * First check that the proper props are enabled
+ * so client can get the proper info eventually
+ */
+ prop_hdr.prop_id = VCD_I_ENABLE_SPS_PPS_FOR_IDR;
+ prop_hdr.sz = sizeof(idr_enable);
+ rc = ddl_get_property(cctxt->ddl_handle,
+ &prop_hdr, &idr_enable);
+ if (!VCD_FAILED(rc)) {
+ if (!idr_enable.
+ sps_pps_for_idr_enable_flag) {
+ VCD_MSG_ERROR("SPS/PPS per IDR "
+ "needs to be enabled");
+ rc = VCD_ERR_BAD_STATE;
+ } else {
+ /* Send zero len frame */
+ frm_entry->data_len = 0;
+ frm_entry->time_stamp = 0;
+ frm_entry->flags = 0;
+ }
+ }
+
+ }
+
+ if (!VCD_FAILED(rc))
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);
+ VCD_S_SUCCESS, frm_entry,
+ sizeof(struct vcd_frame_data),
+ cctxt,
+ cctxt->client_data);
} else
VCD_MSG_LOW("Codec Type is H.263\n");
} else
@@ -2666,7 +2960,7 @@
VCD_MSG_HIGH("Old seq hdr detected");
vcd_pmem_free(cctxt->seq_hdr.sequence_header,
- cctxt->seq_hdr_phy_addr);
+ cctxt->seq_hdr_phy_addr, cctxt);
cctxt->seq_hdr.sequence_header = NULL;
}
@@ -2686,7 +2980,7 @@
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));
+ &(cctxt->seq_hdr_phy_addr), cctxt);
if (ret < 0) {
VCD_MSG_ERROR("Seq hdr allocation failed");
@@ -2734,6 +3028,30 @@
return rc;
}
+u32 vcd_req_perf_level(
+ struct vcd_clnt_ctxt *cctxt,
+ struct vcd_property_perf_level *perf_level)
+{
+ u32 rc;
+ u32 res_trk_perf_level;
+ if (!perf_level) {
+ VCD_MSG_ERROR("Invalid parameters\n");
+ return -EINVAL;
+ }
+ res_trk_perf_level = get_res_trk_perf_level(perf_level->level);
+ if (res_trk_perf_level < 0) {
+ rc = -ENOTSUPP;
+ goto perf_level_not_supp;
+ }
+ rc = vcd_set_perf_level(cctxt->dev_ctxt, res_trk_perf_level);
+ if (!rc) {
+ cctxt->reqd_perf_lvl = res_trk_perf_level;
+ cctxt->perf_set_by_client = 1;
+ }
+perf_level_not_supp:
+ return rc;
+}
+
u32 vcd_set_frame_size(
struct vcd_clnt_ctxt *cctxt,
struct vcd_property_frame_size *frm_size)
@@ -2742,7 +3060,12 @@
u32 rc;
u32 frm_p_units;
(void)frm_size;
-
+ if (res_trk_get_disable_fullhd() && frm_size &&
+ (frm_size->width * frm_size->height > 1280 * 720)) {
+ VCD_MSG_ERROR("Frame size = %dX%d greater than 1280X720 not"
+ "supported", frm_size->width, frm_size->height);
+ return VCD_ERR_FAIL;
+ }
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);
@@ -2791,13 +3114,15 @@
u32 frm_delta;
u64 temp, max = ~((u64)0);
- if (frame->time_stamp >= cctxt->status.prev_ts)
+ if (cctxt->time_frame_delta)
+ temp = cctxt->time_frame_delta;
+ else 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",
+ VCD_MSG_LOW("Curr_ts=%lld Prev_ts=%lld Diff=%llu\n",
frame->time_stamp, cctxt->status.prev_ts, temp);
temp *= cctxt->time_resoln;
@@ -3109,3 +3434,23 @@
0, cctxt, cctxt->client_data);
}
}
+
+u32 vcd_set_num_slices(struct vcd_clnt_ctxt *cctxt)
+{
+ struct vcd_property_hdr prop_hdr;
+ struct vcd_property_slice_delivery_info slice_delivery_info;
+ u32 rc = VCD_S_SUCCESS;
+ prop_hdr.prop_id = VCD_I_SLICE_DELIVERY_MODE;
+ prop_hdr.sz = sizeof(struct vcd_property_slice_delivery_info);
+ rc = ddl_get_property(cctxt->ddl_handle, &prop_hdr,
+ &slice_delivery_info);
+ VCD_FAILED_RETURN(rc, "Failed: Get VCD_I_SLICE_DELIVERY_MODE");
+ if (slice_delivery_info.enable) {
+ cctxt->num_slices = slice_delivery_info.num_slices;
+ VCD_MSG_LOW("%s slice delivery mode num_slices = %u\n",
+ __func__, cctxt->num_slices);
+ } else {
+ cctxt->num_slices = 1;
+ }
+ return rc;
+}
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_util.c b/drivers/video/msm/vidc/common/vcd/vcd_util.c
index b638359..ba991f1 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_util.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_util.c
@@ -9,11 +9,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
*/
#include "vidc_type.h"
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_util.h b/drivers/video/msm/vidc/common/vcd/vcd_util.h
index 631f18c..7164029 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_util.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_util.h
@@ -1,35 +1,19 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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"
+#include <media/msm/vidc_type.h>
+#include <media/msm/vcd_api.h>
#if DEBUG
diff --git a/drivers/video/msm/vidc/common/vcd/vidc_type.h b/drivers/video/msm/vidc/common/vcd/vidc_type.h
deleted file mode 100644
index c3c1b95..0000000
--- a/drivers/video/msm/vidc/common/vcd/vidc_type.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-#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
-
-#ifdef CONFIG_KERNEL_PMEM_SMI_REGION
-#define PMEM_MEMTYPE PMEM_MEMTYPE_SMI
-#else
-#define PMEM_MEMTYPE PMEM_MEMTYPE_EBI1
-#endif
-
-#endif
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 1d37f42..b9d46fa 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -11,6 +11,8 @@
#ifndef __LINUX_CLK_H
#define __LINUX_CLK_H
+#include <linux/kernel.h>
+
struct device;
/*
@@ -41,11 +43,31 @@
struct clk *clk_get(struct device *dev, const char *id);
/**
+ * clk_prepare - prepare a clock source
+ * @clk: clock source
+ *
+ * This prepares the clock source for use.
+ *
+ * Must not be called from within atomic context.
+ */
+#ifdef CONFIG_HAVE_CLK_PREPARE
+int clk_prepare(struct clk *clk);
+#else
+static inline int clk_prepare(struct clk *clk)
+{
+ might_sleep();
+ return 0;
+}
+#endif
+
+/**
* clk_enable - inform the system when the clock source should be running.
* @clk: clock source
*
* If the clock can not be enabled/disabled, this should return success.
*
+ * May be called from atomic contexts.
+ *
* Returns success (0) or negative errno.
*/
int clk_enable(struct clk *clk);
@@ -57,6 +79,8 @@
* Inform the system that a clock source is no longer required by
* a driver and may be shut down.
*
+ * May be called from atomic contexts.
+ *
* Implementation detail: if the clock source is shared between
* multiple drivers, clk_enable() calls must be balanced by the
* same number of clk_disable() calls for the clock source to be
@@ -64,6 +88,47 @@
*/
void clk_disable(struct clk *clk);
+
+/**
+ * clk_unprepare - undo preparation of a clock source
+ * @clk: clock source
+ *
+ * This undoes a previously prepared clock. The caller must balance
+ * the number of prepare and unprepare calls.
+ *
+ * Must not be called from within atomic context.
+ */
+#ifdef CONFIG_HAVE_CLK_PREPARE
+void clk_unprepare(struct clk *clk);
+#else
+static inline void clk_unprepare(struct clk *clk)
+{
+ might_sleep();
+}
+#endif
+
+/* clk_prepare_enable helps cases using clk_enable in non-atomic context. */
+static inline int clk_prepare_enable(struct clk *clk)
+{
+ int ret;
+
+ ret = clk_prepare(clk);
+ if (ret)
+ return ret;
+ ret = clk_enable(clk);
+ if (ret)
+ clk_unprepare(clk);
+
+ return ret;
+}
+
+/* clk_disable_unprepare helps cases using clk_disable in non-atomic context. */
+static inline void clk_disable_unprepare(struct clk *clk)
+{
+ clk_disable(clk);
+ clk_unprepare(clk);
+}
+
/**
* clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
* This is only valid once the clock source has been enabled.
diff --git a/include/linux/ion.h b/include/linux/ion.h
index a2dbbd4..d9443ff 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -2,6 +2,7 @@
* include/linux/ion.h
*
* Copyright (C) 2011 Google, Inc.
+ * Copyright (c) 2011-2012, 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
@@ -29,12 +30,18 @@
* @ION_HEAP_TYPE_CARVEOUT: memory allocated from a prereserved
* carveout heap, allocations are physically
* contiguous
- * @ION_HEAP_END: helper for iterating over heaps
+ * @ION_HEAP_TYPE_IOMMU: IOMMU memory
+ * @ION_HEAP_TYPE_CP: memory allocated from a prereserved
+ * carveout heap, allocations are physically
+ * contiguous. Used for content protection.
+ * @ION_HEAP_END: helper for iterating over heaps
*/
enum ion_heap_type {
ION_HEAP_TYPE_SYSTEM,
ION_HEAP_TYPE_SYSTEM_CONTIG,
ION_HEAP_TYPE_CARVEOUT,
+ ION_HEAP_TYPE_IOMMU,
+ ION_HEAP_TYPE_CP,
ION_HEAP_TYPE_CUSTOM, /* must be last so device specific heaps always
are at the end of this enum */
ION_NUM_HEAPS,
@@ -43,6 +50,7 @@
#define ION_HEAP_SYSTEM_MASK (1 << ION_HEAP_TYPE_SYSTEM)
#define ION_HEAP_SYSTEM_CONTIG_MASK (1 << ION_HEAP_TYPE_SYSTEM_CONTIG)
#define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT)
+#define ION_HEAP_CP_MASK (1 << ION_HEAP_TYPE_CP)
/**
@@ -50,24 +58,56 @@
* The ids listed are the order in which allocation will be attempted
* if specified. Don't swap the order of heap ids unless you know what
* you are doing!
+ * Id's are spaced by purpose to allow new Id's to be inserted in-between (for
+ * possible fallbacks)
*/
enum ion_heap_ids {
- ION_HEAP_SYSTEM_ID,
- ION_HEAP_SYSTEM_CONTIG_ID,
- ION_HEAP_EBI_ID,
- ION_HEAP_SMI_ID,
- ION_HEAP_ADSP_ID,
- ION_HEAP_AUDIO_ID,
- ION_HEAP_ADSP2_ID,
+ INVALID_HEAP_ID = -1,
+ ION_CP_MM_HEAP_ID = 8,
+ ION_CP_MFC_HEAP_ID = 12,
+ ION_CP_WB_HEAP_ID = 16, /* 8660 only */
+ ION_CAMERA_HEAP_ID = 20, /* 8660 only */
+ ION_SF_HEAP_ID = 24,
+ ION_IOMMU_HEAP_ID = 25,
+ ION_QSECOM_HEAP_ID = 27,
+ ION_AUDIO_HEAP_ID = 28,
+
+ ION_MM_FIRMWARE_HEAP_ID = 29,
+ ION_SYSTEM_HEAP_ID = 30,
+
+ ION_HEAP_ID_RESERVED = 31 /** Bit reserved for ION_SECURE flag */
};
-#define ION_KMALLOC_HEAP_NAME "kmalloc"
+enum ion_fixed_position {
+ NOT_FIXED,
+ FIXED_LOW,
+ FIXED_MIDDLE,
+ FIXED_HIGH,
+};
+
+/**
+ * Flag to use when allocating to indicate that a heap is secure.
+ */
+#define ION_SECURE (1 << ION_HEAP_ID_RESERVED)
+
+/**
+ * Macro should be used with ion_heap_ids defined above.
+ */
+#define ION_HEAP(bit) (1 << (bit))
+
#define ION_VMALLOC_HEAP_NAME "vmalloc"
-#define ION_EBI1_HEAP_NAME "EBI1"
-#define ION_ADSP_HEAP_NAME "adsp"
-#define ION_ADSP2_HEAP_NAME "adsp2"
-#define ION_SMI_HEAP_NAME "smi"
+#define ION_AUDIO_HEAP_NAME "audio"
+#define ION_SF_HEAP_NAME "sf"
+#define ION_MM_HEAP_NAME "mm"
+#define ION_CAMERA_HEAP_NAME "camera_preview"
+#define ION_IOMMU_HEAP_NAME "iommu"
+#define ION_MFC_HEAP_NAME "mfc"
+#define ION_WB_HEAP_NAME "wb"
+#define ION_MM_FIRMWARE_HEAP_NAME "mm_fw"
+#define ION_QSECOM_HEAP_NAME "qsecom"
+#define ION_FMEM_HEAP_NAME "fmem"
+
#define CACHED 1
#define UNCACHED 0
@@ -77,6 +117,12 @@
#define ION_IS_CACHED(__flags) ((__flags) & (1 << ION_CACHE_SHIFT))
+/*
+ * This flag allows clients when mapping into the IOMMU to specify to
+ * defer un-mapping from the IOMMU until the buffer memory is freed.
+ */
+#define ION_IOMMU_UNMAP_DELAYED 1
+
#ifdef __KERNEL__
#include <linux/err.h>
#include <mach/ion.h>
@@ -91,17 +137,19 @@
be converted to phys_addr_t. For the time being many kernel interfaces
do not accept phys_addr_t's that would have to */
#define ion_phys_addr_t unsigned long
+#define ion_virt_addr_t unsigned long
/**
* struct ion_platform_heap - defines a heap in the given platform
* @type: type of the heap from ion_heap_type enum
- * @id: unique identifier for heap. When allocating (lower numbers
+ * @id: unique identifier for heap. When allocating (lower numbers
* will be allocated from first)
* @name: used for debug purposes
* @base: base address of heap in physical memory if applicable
* @size: size of the heap in bytes if applicable
- *
- * Provided by the board file.
+ * @memory_type:Memory type used for the heap
+ * @has_outer_cache: set to 1 if outer cache is used, 0 otherwise.
+ * @extra_data: Extra data specific to each heap type
*/
struct ion_platform_heap {
enum ion_heap_type type;
@@ -110,10 +158,79 @@
ion_phys_addr_t base;
size_t size;
enum ion_memory_types memory_type;
+ unsigned int has_outer_cache;
+ void *extra_data;
+};
+
+/**
+ * struct ion_cp_heap_pdata - defines a content protection heap in the given
+ * platform
+ * @permission_type: Memory ID used to identify the memory to TZ
+ * @align: Alignment requirement for the memory
+ * @secure_base: Base address for securing the heap.
+ * Note: This might be different from actual base address
+ * of this heap in the case of a shared heap.
+ * @secure_size: Memory size for securing the heap.
+ * Note: This might be different from actual size
+ * of this heap in the case of a shared heap.
+ * @reusable Flag indicating whether this heap is reusable of not.
+ * (see FMEM)
+ * @mem_is_fmem Flag indicating whether this memory is coming from fmem
+ * or not.
+ * @fixed_position If nonzero, position in the fixed area.
+ * @virt_addr: Virtual address used when using fmem.
+ * @iommu_map_all: Indicates whether we should map whole heap into IOMMU.
+ * @iommu_2x_map_domain: Indicates the domain to use for overmapping.
+ * @request_region: function to be called when the number of allocations
+ * goes from 0 -> 1
+ * @release_region: function to be called when the number of allocations
+ * goes from 1 -> 0
+ * @setup_region: function to be called upon ion registration
+ *
+ */
+struct ion_cp_heap_pdata {
+ enum ion_permission_type permission_type;
+ unsigned int align;
+ ion_phys_addr_t secure_base; /* Base addr used when heap is shared */
+ size_t secure_size; /* Size used for securing heap when heap is shared*/
+ int reusable;
+ int mem_is_fmem;
+ enum ion_fixed_position fixed_position;
+ int iommu_map_all;
+ int iommu_2x_map_domain;
+ ion_virt_addr_t *virt_addr;
+ int (*request_region)(void *);
+ int (*release_region)(void *);
+ void *(*setup_region)(void);
+};
+
+/**
+ * struct ion_co_heap_pdata - defines a carveout heap in the given platform
+ * @adjacent_mem_id: Id of heap that this heap must be adjacent to.
+ * @align: Alignment requirement for the memory
+ * @mem_is_fmem Flag indicating whether this memory is coming from fmem
+ * or not.
+ * @fixed_position If nonzero, position in the fixed area.
+ * @request_region: function to be called when the number of allocations
+ * goes from 0 -> 1
+ * @release_region: function to be called when the number of allocations
+ * goes from 1 -> 0
+ * @setup_region: function to be called upon ion registration
+ *
+ */
+struct ion_co_heap_pdata {
+ int adjacent_mem_id;
+ unsigned int align;
+ int mem_is_fmem;
+ enum ion_fixed_position fixed_position;
+ int (*request_region)(void *);
+ int (*release_region)(void *);
+ void *(*setup_region)(void);
};
/**
* struct ion_platform_data - array of platform heaps passed from board file
+ * @has_outer_cache: set to 1 if outer cache is used, 0 otherwise.
* @nr: number of structures in the array
* @request_region: function to be called when the number of allocations goes
* from 0 -> 1
@@ -125,9 +242,10 @@
* Provided by the board file in the form of platform data to a platform device.
*/
struct ion_platform_data {
+ unsigned int has_outer_cache;
int nr;
- void (*request_region)(void *);
- void (*release_region)(void *);
+ int (*request_region)(void *);
+ int (*release_region)(void *);
void *(*setup_region)(void);
struct ion_platform_heap heaps[];
};
@@ -299,6 +417,125 @@
int ion_handle_get_flags(struct ion_client *client, struct ion_handle *handle,
unsigned long *flags);
+
+/**
+ * ion_map_iommu - map the given handle into an iommu
+ *
+ * @client - client who allocated the handle
+ * @handle - handle to map
+ * @domain_num - domain number to map to
+ * @partition_num - partition number to allocate iova from
+ * @align - alignment for the iova
+ * @iova_length - length of iova to map. If the iova length is
+ * greater than the handle length, the remaining
+ * address space will be mapped to a dummy buffer.
+ * @iova - pointer to store the iova address
+ * @buffer_size - pointer to store the size of the buffer
+ * @flags - flags for options to map
+ * @iommu_flags - flags specific to the iommu.
+ *
+ * Maps the handle into the iova space specified via domain number. Iova
+ * will be allocated from the partition specified via partition_num.
+ * Returns 0 on success, negative value on error.
+ */
+int ion_map_iommu(struct ion_client *client, struct ion_handle *handle,
+ int domain_num, int partition_num, unsigned long align,
+ unsigned long iova_length, unsigned long *iova,
+ unsigned long *buffer_size,
+ unsigned long flags, unsigned long iommu_flags);
+
+
+/**
+ * ion_handle_get_size - get the allocated size of a given handle
+ *
+ * @client - client who allocated the handle
+ * @handle - handle to get the size
+ * @size - pointer to store the size
+ *
+ * gives the allocated size of a handle. returns 0 on success, negative
+ * value on error
+ *
+ * NOTE: This is intended to be used only to get a size to pass to map_iommu.
+ * You should *NOT* rely on this for any other usage.
+ */
+
+int ion_handle_get_size(struct ion_client *client, struct ion_handle *handle,
+ unsigned long *size);
+
+/**
+ * ion_unmap_iommu - unmap the handle from an iommu
+ *
+ * @client - client who allocated the handle
+ * @handle - handle to unmap
+ * @domain_num - domain to unmap from
+ * @partition_num - partition to unmap from
+ *
+ * Decrement the reference count on the iommu mapping. If the count is
+ * 0, the mapping will be removed from the iommu.
+ */
+void ion_unmap_iommu(struct ion_client *client, struct ion_handle *handle,
+ int domain_num, int partition_num);
+
+
+/**
+ * ion_secure_heap - secure a heap
+ *
+ * @client - a client that has allocated from the heap heap_id
+ * @heap_id - heap id to secure.
+ *
+ * Secure a heap
+ * Returns 0 on success
+ */
+int ion_secure_heap(struct ion_device *dev, int heap_id);
+
+/**
+ * ion_unsecure_heap - un-secure a heap
+ *
+ * @client - a client that has allocated from the heap heap_id
+ * @heap_id - heap id to un-secure.
+ *
+ * Un-secure a heap
+ * Returns 0 on success
+ */
+int ion_unsecure_heap(struct ion_device *dev, int heap_id);
+
+/**
+ * msm_ion_secure_heap - secure a heap. Wrapper around ion_secure_heap.
+ *
+ * @heap_id - heap id to secure.
+ *
+ * Secure a heap
+ * Returns 0 on success
+ */
+int msm_ion_secure_heap(int heap_id);
+
+/**
+ * msm_ion_unsecure_heap - unsecure a heap. Wrapper around ion_unsecure_heap.
+ *
+ * @heap_id - heap id to secure.
+ *
+ * Un-secure a heap
+ * Returns 0 on success
+ */
+int msm_ion_unsecure_heap(int heap_id);
+
+/**
+ * msm_ion_do_cache_op - do cache operations.
+ *
+ * @client - pointer to ION client.
+ * @handle - pointer to buffer handle.
+ * @vaddr - virtual address to operate on.
+ * @len - Length of data to do cache operation on.
+ * @cmd - Cache operation to perform:
+ * ION_IOC_CLEAN_CACHES
+ * ION_IOC_INV_CACHES
+ * ION_IOC_CLEAN_INV_CACHES
+ *
+ * Returns 0 on success
+ */
+int msm_ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
+ void *vaddr, unsigned long len, unsigned int cmd);
+
#else
static inline struct ion_client *ion_client_create(struct ion_device *dev,
unsigned int heap_mask, const char *name)
@@ -371,6 +608,54 @@
{
return -ENODEV;
}
+
+static inline int ion_map_iommu(struct ion_client *client,
+ struct ion_handle *handle, int domain_num,
+ int partition_num, unsigned long align,
+ unsigned long iova_length, unsigned long *iova,
+ unsigned long *buffer_size,
+ unsigned long flags,
+ unsigned long iommu_flags)
+{
+ return -ENODEV;
+}
+
+static inline void ion_unmap_iommu(struct ion_client *client,
+ struct ion_handle *handle, int domain_num,
+ int partition_num)
+{
+ return;
+}
+
+static inline int ion_secure_heap(struct ion_device *dev, int heap_id)
+{
+ return -ENODEV;
+
+}
+
+static inline int ion_unsecure_heap(struct ion_device *dev, int heap_id)
+{
+ return -ENODEV;
+}
+
+static inline int msm_ion_secure_heap(int heap_id)
+{
+ return -ENODEV;
+
+}
+
+static inline int msm_ion_unsecure_heap(int heap_id)
+{
+ return -ENODEV;
+}
+
+static inline int msm_ion_do_cache_op(struct ion_client *client,
+ struct ion_handle *handle, void *vaddr,
+ unsigned long len, unsigned int cmd)
+{
+ return -ENODEV;
+}
+
#endif /* CONFIG_ION */
#endif /* __KERNEL__ */
@@ -439,6 +724,7 @@
/* struct ion_flush_data - data passed to ion for flushing caches
*
* @handle: handle with data to flush
+ * @fd: fd to flush
* @vaddr: userspace virtual address mapped with mmap
* @offset: offset into the handle to flush
* @length: length of handle to flush
@@ -449,6 +735,7 @@
*/
struct ion_flush_data {
struct ion_handle *handle;
+ int fd;
void *vaddr;
unsigned int offset;
unsigned int length;
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 3ff2347..baef1cc 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -151,21 +151,14 @@
#define KGSL_2D1_REG_MEMORY "kgsl_2d1_reg_memory"
#define KGSL_2D1_IRQ "kgsl_2d1_irq"
-struct kgsl_grp_clk_name {
- const char *clk;
- const char *pclk;
-};
-
struct kgsl_device_platform_data {
struct kgsl_pwrlevel pwrlevel[KGSL_MAX_PWRLEVELS];
int init_level;
int num_levels;
int (*set_grp_async)(void);
unsigned int idle_timeout;
- bool strtstp_sleepwake;
unsigned int nap_allowed;
- struct kgsl_grp_clk_name clk;
- struct kgsl_grp_clk_name imem_clk_name;
+ unsigned int clk_map;
unsigned int idle_needed;
struct msm_bus_scale_pdata *bus_scale_table;
const char *iommu_user_ctx_name;
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 219caa6..e051640 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -1,6 +1,7 @@
/* include/linux/msm_mdp.h
*
* Copyright (C) 2007 Google Incorporated
+ * Copyright (c) 2012 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
@@ -24,15 +25,18 @@
#define MSMFB_RESUME_SW_REFRESHER _IOW(MSMFB_IOCTL_MAGIC, 129, unsigned int)
#define MSMFB_CURSOR _IOW(MSMFB_IOCTL_MAGIC, 130, struct fb_cursor)
#define MSMFB_SET_LUT _IOW(MSMFB_IOCTL_MAGIC, 131, struct fb_cmap)
-#define MSMFB_HISTOGRAM _IOWR(MSMFB_IOCTL_MAGIC, 132, struct mdp_histogram)
+#define MSMFB_HISTOGRAM _IOWR(MSMFB_IOCTL_MAGIC, 132, struct mdp_histogram_data)
/* new ioctls's for set/get ccs matrix */
#define MSMFB_GET_CCS_MATRIX _IOWR(MSMFB_IOCTL_MAGIC, 133, struct mdp_ccs)
#define MSMFB_SET_CCS_MATRIX _IOW(MSMFB_IOCTL_MAGIC, 134, struct mdp_ccs)
#define MSMFB_OVERLAY_SET _IOWR(MSMFB_IOCTL_MAGIC, 135, \
struct mdp_overlay)
#define MSMFB_OVERLAY_UNSET _IOW(MSMFB_IOCTL_MAGIC, 136, unsigned int)
+
#define MSMFB_OVERLAY_PLAY _IOW(MSMFB_IOCTL_MAGIC, 137, \
struct msmfb_overlay_data)
+#define MSMFB_OVERLAY_QUEUE MSMFB_OVERLAY_PLAY
+
#define MSMFB_GET_PAGE_PROTECTION _IOR(MSMFB_IOCTL_MAGIC, 138, \
struct mdp_page_protection)
#define MSMFB_SET_PAGE_PROTECTION _IOW(MSMFB_IOCTL_MAGIC, 139, \
@@ -43,8 +47,9 @@
#define MSMFB_OVERLAY_BLT _IOWR(MSMFB_IOCTL_MAGIC, 142, \
struct msmfb_overlay_blt)
#define MSMFB_OVERLAY_BLT_OFFSET _IOW(MSMFB_IOCTL_MAGIC, 143, unsigned int)
-#define MSMFB_HISTOGRAM_START _IO(MSMFB_IOCTL_MAGIC, 144)
-#define MSMFB_HISTOGRAM_STOP _IO(MSMFB_IOCTL_MAGIC, 145)
+#define MSMFB_HISTOGRAM_START _IOR(MSMFB_IOCTL_MAGIC, 144, \
+ struct mdp_histogram_start_req)
+#define MSMFB_HISTOGRAM_STOP _IOR(MSMFB_IOCTL_MAGIC, 145, unsigned int)
#define MSMFB_NOTIFY_UPDATE _IOW(MSMFB_IOCTL_MAGIC, 146, unsigned int)
#define MSMFB_OVERLAY_3D _IOWR(MSMFB_IOCTL_MAGIC, 147, \
@@ -54,17 +59,9 @@
struct msmfb_mixer_info_req)
#define MSMFB_OVERLAY_PLAY_WAIT _IOWR(MSMFB_IOCTL_MAGIC, 149, \
struct msmfb_overlay_data)
-
#define MSMFB_WRITEBACK_INIT _IO(MSMFB_IOCTL_MAGIC, 150)
-
-/* The QCT latest code base is used, adding on 2/9/2012 */
#define MSMFB_WRITEBACK_START _IO(MSMFB_IOCTL_MAGIC, 151)
#define MSMFB_WRITEBACK_STOP _IO(MSMFB_IOCTL_MAGIC, 152)
-
-#define MSMFB_WRITEBACK_REGISTER_BUFFER _IOW(MSMFB_IOCTL_MAGIC, 151, \
- struct msmfb_writeback_data)
-#define MSMFB_WRITEBACK_UNREGISTER_BUFFER _IOW(MSMFB_IOCTL_MAGIC, 152, \
- struct msmfb_writeback_data)
#define MSMFB_WRITEBACK_QUEUE_BUFFER _IOW(MSMFB_IOCTL_MAGIC, 153, \
struct msmfb_data)
#define MSMFB_WRITEBACK_DEQUEUE_BUFFER _IOW(MSMFB_IOCTL_MAGIC, 154, \
@@ -72,29 +69,23 @@
#define MSMFB_WRITEBACK_TERMINATE _IO(MSMFB_IOCTL_MAGIC, 155)
#define MSMFB_MDP_PP _IOWR(MSMFB_IOCTL_MAGIC, 156, struct msmfb_mdp_pp)
-/* HTC: Define custom ioctl started from 200 */
-#define MSMFB_OVERLAY_CHANGE_ZORDER_VG_PIPES _IOW(MSMFB_IOCTL_MAGIC, 200, unsigned int)
-#define MSMFB_GET_GAMMA_CURVY _IOWR(MSMFB_IOCTL_MAGIC, 201, struct gamma_curvy)
-
+#define MSMFB_OVERLAY_VSYNC_CTRL _IOW(MSMFB_IOCTL_MAGIC, 160, unsigned int)
+#define MSMFB_VSYNC_CTRL _IOW(MSMFB_IOCTL_MAGIC, 161, unsigned int)
#define FB_TYPE_3D_PANEL 0x10101010
#define MDP_IMGTYPE2_START 0x10000
#define MSMFB_DRIVER_VERSION 0xF9E8D701
-#define MSMFB_GET_USB_PROJECTOR_INFO _IOR(MSMFB_IOCTL_MAGIC, 301, struct msmfb_usb_projector_info)
-#define MSMFB_SET_USB_PROJECTOR_INFO _IOW(MSMFB_IOCTL_MAGIC, 302, struct msmfb_usb_projector_info)
-
enum {
NOTIFY_UPDATE_START,
NOTIFY_UPDATE_STOP,
- NOTIFY_TERMINATE_BLOCKING,
- NOTIFY_NUM,
};
enum {
MDP_RGB_565, /* RGB 565 planer */
MDP_XRGB_8888, /* RGB 888 padded */
MDP_Y_CBCR_H2V2, /* Y and CbCr, pseudo planer w/ Cb is in MSB */
+ MDP_Y_CBCR_H2V2_ADRENO,
MDP_ARGB_8888, /* ARGB 888 */
MDP_RGB_888, /* RGB 888 planer */
MDP_Y_CRCB_H2V2, /* Y and CrCb, pseudo planer w/ Cr is in MSB */
@@ -111,7 +102,10 @@
MDP_Y_CB_CR_H2V2, /* Y, Cb and Cr, planar */
MDP_Y_CRCB_H1V1, /* Y and CrCb, pseduo planer w/ Cr is in MSB */
MDP_Y_CBCR_H1V1, /* Y and CbCr, pseduo planer w/ Cb is in MSB */
+ MDP_YCRCB_H1V1, /* YCrCb interleave */
+ MDP_YCBCR_H1V1, /* YCbCr interleave */
MDP_IMGTYPE_LIMIT,
+ MDP_RGB_BORDERFILL, /* border fill pipe */
MDP_BGR_565 = MDP_IMGTYPE2_START, /* BGR 565 planer */
MDP_FB_FORMAT, /* framebuffer format */
MDP_IMGTYPE_LIMIT2 /* Non valid image type after this enum */
@@ -155,8 +149,8 @@
#define MDP_DEINTERLACE_ODD 0x00400000
#define MDP_OV_PLAY_NOWAIT 0x00200000
#define MDP_SOURCE_ROTATED_90 0x00100000
-#define MDP_MEMORY_ID_TYPE_FB 0x00001000
#define MDP_DPP_HSIC 0x00080000
+#define MDP_BACKEND_COMPOSITION 0x00040000
#define MDP_BORDERFILL_SUPPORTED 0x00010000
#define MDP_SECURE_OVERLAY_SESSION 0x00008000
#define MDP_MEMORY_ID_TYPE_FB 0x00001000
@@ -254,11 +248,9 @@
struct msmfb_overlay_data {
uint32_t id;
struct msmfb_data data;
-#ifndef CONFIG_FB_MSM_OVERLAY_LEGACY
uint32_t version_key;
struct msmfb_data plane1_data;
struct msmfb_data plane2_data;
-#endif
};
struct msmfb_img {
@@ -295,9 +287,7 @@
uint32_t flags;
uint32_t id;
uint32_t user_data[8];
-#ifndef CONFIG_FB_MSM_OVERLAY_LEGACY
struct dpp_ctrl dpp;
-#endif
};
struct msmfb_overlay_3d {
@@ -345,9 +335,40 @@
MDP_BLOCK_DMA_P,
MDP_BLOCK_DMA_S,
MDP_BLOCK_DMA_E,
+ MDP_BLOCK_OVERLAY_2,
MDP_BLOCK_MAX,
};
+/*
+mdp_histogram_start_req is used to provide the parameters for
+histogram start request
+*/
+
+struct mdp_histogram_start_req {
+ uint32_t block;
+ uint8_t frame_cnt;
+ uint8_t bit_mask;
+ uint8_t num_bins;
+};
+
+
+/*
+
+ mdp_histogram_data is used to return the histogram data, once
+ the histogram is done/stopped/cance
+
+ */
+
+
+struct mdp_histogram_data {
+ uint32_t block;
+ uint8_t bin_cnt;
+ uint32_t *c0;
+ uint32_t *c1;
+ uint32_t *c2;
+ uint32_t *extra_info;
+};
+
struct mdp_pcc_coeff {
uint32_t c, r, g, b, rr, gg, bb, rg, gb, rb, rgb_0, rgb_1;
};
@@ -358,6 +379,10 @@
struct mdp_pcc_coeff r, g, b;
};
+#define MDP_CSC_FLAG_ENABLE 0x1
+#define MDP_CSC_FLAG_YUV_IN 0x2
+#define MDP_CSC_FLAG_YUV_OUT 0x4
+
struct mdp_csc_cfg {
/* flags for enable CSC, toggling RGB,YUV input/output */
uint32_t flags;
@@ -413,7 +438,6 @@
uint32_t *data;
};
-
struct mdp_lut_cfg_data {
uint32_t lut_type;
union {
@@ -423,10 +447,16 @@
} data;
};
+struct mdp_bl_scale_data {
+ uint32_t min_lvl;
+ uint32_t scale;
+};
+
enum {
mdp_op_pcc_cfg,
mdp_op_csc_cfg,
mdp_op_lut_cfg,
+ mdp_bl_scale_cfg,
mdp_op_max,
};
@@ -436,6 +466,7 @@
struct mdp_pcc_cfg_data pcc_cfg_data;
struct mdp_csc_cfg_data csc_cfg_data;
struct mdp_lut_cfg_data lut_cfg_data;
+ struct mdp_bl_scale_data bl_scale_data;
} data;
};
@@ -461,30 +492,24 @@
struct mdp_mixer_info info[MAX_PIPE_PER_MIXER];
};
-struct msmfb_usb_projector_info {
- int usb_offset;
- int latest_offset;
+enum {
+ DISPLAY_SUBSYSTEM_ID,
+ ROTATOR_SUBSYSTEM_ID,
};
#ifdef __KERNEL__
/* get the framebuffer physical address information */
-int get_fb_phys_info(unsigned long *start, unsigned long *len, int fb_num);
+int get_fb_phys_info(unsigned long *start, unsigned long *len, int fb_num,
+ int subsys_id);
struct fb_info *msm_fb_get_writeback_fb(void);
int msm_fb_writeback_init(struct fb_info *info);
-
-/* The QCT latest code base is used, adding on 2/9/2012 */
int msm_fb_writeback_start(struct fb_info *info);
-int msm_fb_writeback_stop(struct fb_info *info);
-
-int msm_fb_writeback_register_buffer(struct fb_info *info,
- struct msmfb_writeback_data *data);
int msm_fb_writeback_queue_buffer(struct fb_info *info,
struct msmfb_data *data);
int msm_fb_writeback_dequeue_buffer(struct fb_info *info,
struct msmfb_data *data);
-int msm_fb_writeback_unregister_buffer(struct fb_info *info,
- struct msmfb_writeback_data *data);
+int msm_fb_writeback_stop(struct fb_info *info);
int msm_fb_writeback_terminate(struct fb_info *info);
#endif
diff --git a/include/linux/msm_vidc_dec.h b/include/linux/msm_vidc_dec.h
index 4db94be..0c03e13 100644
--- a/include/linux/msm_vidc_dec.h
+++ b/include/linux/msm_vidc_dec.h
@@ -514,6 +514,12 @@
uint32_t bottom;
};
+struct vdec_aspectratioinfo {
+ uint32_t aspect_ratio;
+ uint32_t par_width;
+ uint32_t par_height;
+};
+
struct vdec_output_frameinfo {
void __user *bufferaddr;
size_t offset;
@@ -524,6 +530,8 @@
void *client_data;
void *input_frame_clientdata;
struct vdec_framesize framesize;
+ enum vdec_interlaced_format interlaced_format;
+ struct vdec_aspectratioinfo aspect_ratio_info;
};
union vdec_msgdata {
diff --git a/include/linux/msm_vidc_enc.h b/include/linux/msm_vidc_enc.h
index bf149eb..519c537 100644
--- a/include/linux/msm_vidc_enc.h
+++ b/include/linux/msm_vidc_enc.h
@@ -454,6 +454,10 @@
#define VEN_IOCTL_GET_EXTRADATA \
_IOR(VEN_IOCTLBASE_ENC, 49, struct venc_ioctl_msg)
+/*IOCTL params:SET: InputData - NULL, OutputData - NULL.*/
+#define VEN_IOCTL_SET_SLICE_DELIVERY_MODE \
+ _IO(VEN_IOCTLBASE_ENC, 50)
+
struct venc_switch{
unsigned char status;
};
diff --git a/include/linux/pm_qos_params.h b/include/linux/pm_qos_params.h
index 8f2190e..a846644 100644
--- a/include/linux/pm_qos_params.h
+++ b/include/linux/pm_qos_params.h
@@ -1,3 +1,5 @@
+#ifndef _LINUX_PM_QOS_PARAMS_H
+#define _LINUX_PM_QOS_PARAMS_H
/* interface for the pm_qos_power infrastructure of the linux kernel.
*
* Mark Gross <mgross@linux.intel.com>
@@ -15,7 +17,19 @@
#define PM_QOS_NUM_CLASSES 5
#define PM_QOS_DEFAULT_VALUE -1
-struct pm_qos_request_list;
+#define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC)
+#define PM_QOS_NETWORK_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC)
+#define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE 0
+
+struct pm_qos_request_list {
+ struct list_head list;
+ union {
+ s32 value;
+ s32 usec;
+ s32 kbps;
+ };
+ int pm_qos_class;
+};
struct pm_qos_request_list *pm_qos_add_request(int pm_qos_class, s32 value);
void pm_qos_update_request(struct pm_qos_request_list *pm_qos_req,
@@ -25,4 +39,6 @@
int pm_qos_request(int pm_qos_class);
int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier);
int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier);
+int pm_qos_request_active(struct pm_qos_request_list *req);
+#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_api.h b/include/media/msm/vcd_api.h
similarity index 68%
rename from drivers/video/msm/vidc/common/vcd/vcd_api.h
rename to include/media/msm/vcd_api.h
index 1a530f9..c93b696 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_api.h
+++ b/include/media/msm/vcd_api.h
@@ -1,29 +1,13 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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_
@@ -69,13 +53,20 @@
VCD_PWR_STATE_SLEEP,
};
+struct vcd_aspect_ratio {
+ u32 aspect_ratio;
+ u32 extended_par_width;
+ u32 extended_par_height;
+};
+
struct vcd_frame_data {
u8 *virtual;
u8 *physical;
+ u32 ion_flag;
u32 alloc_len;
u32 data_len;
u32 offset;
- s64 time_stamp;
+ s64 time_stamp; /* in usecs*/
u32 flags;
u32 frm_clnt_data;
struct vcd_property_dec_output_buffer dec_op_prop;
@@ -83,6 +74,10 @@
enum vcd_frame frame;
u32 ip_frm_tag;
u32 intrlcd_ip_frm_tag;
+ u8 *desc_buf;
+ u32 desc_size;
+ struct ion_handle *buff_ion_handle;
+ struct vcd_aspect_ratio aspect_ratio_info;
};
struct vcd_sequence_hdr {
@@ -121,11 +116,14 @@
void (*timer_stop) (void *timer_handle);
};
+/*Flags passed to vcd_open*/
+#define VCD_CP_SESSION 0x00000001
+
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);
+ void *handle, void *const client_data), void *client_data, int flags);
u32 vcd_close(void *handle);
u32 vcd_encode_start(void *handle);
u32 vcd_encode_frame(void *handle, struct vcd_frame_data *input_frame);
@@ -155,5 +153,6 @@
void vcd_read_and_clear_interrupt(void);
void vcd_response_handler(void);
u8 vcd_get_num_of_clients(void);
-
+u32 vcd_get_ion_status(void);
+struct ion_client *vcd_get_ion_client(void);
#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_property.h b/include/media/msm/vcd_property.h
similarity index 63%
rename from drivers/video/msm/vidc/common/vcd/vcd_property.h
rename to include/media/msm/vcd_property.h
index 228b36d..b5417ff 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_property.h
+++ b/include/media/msm/vcd_property.h
@@ -1,29 +1,13 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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_
@@ -64,6 +48,12 @@
#define VCD_I_DEC_PICTYPE (VCD_START_BASE + 0x20)
#define VCD_I_CONT_ON_RECONFIG (VCD_START_BASE + 0x21)
#define VCD_I_META_BUFFER_MODE (VCD_START_BASE + 0x22)
+#define VCD_I_DISABLE_DMX (VCD_START_BASE + 0x23)
+#define VCD_I_DISABLE_DMX_SUPPORT (VCD_START_BASE + 0x24)
+#define VCD_I_ENABLE_SPS_PPS_FOR_IDR (VCD_START_BASE + 0x25)
+#define VCD_REQ_PERF_LEVEL (VCD_START_BASE + 0x26)
+#define VCD_I_VOP_TIMING_CONSTANT_DELTA (VCD_START_BASE + 0x27)
+#define VCD_I_SLICE_DELIVERY_MODE (VCD_START_BASE + 0x28)
#define VCD_START_REQ (VCD_START_BASE + 0x1000)
#define VCD_I_REQ_IFRAME (VCD_START_REQ + 0x1)
@@ -105,6 +95,12 @@
u32 scan_lines;
};
+enum vcd_perf_level {
+ VCD_PERF_LEVEL0,
+ VCD_PERF_LEVEL1,
+ VCD_PERF_LEVEL2,
+ VCD_PERF_LEVEL_TURBO,
+};
#define VCD_METADATA_DATANONE 0x001
#define VCD_METADATA_QCOMFILLER 0x002
@@ -136,6 +132,10 @@
u32 target_bitrate;
};
+struct vcd_property_perf_level {
+ enum vcd_perf_level level;
+};
+
enum vcd_yuv_buffer_format {
VCD_BUFFER_FORMAT_NV12 = 0x1,
VCD_BUFFER_FORMAT_TILE_4x2 = 0x2,
@@ -171,60 +171,60 @@
};
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
+ 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 {
@@ -302,6 +302,10 @@
u32 vop_time_resolution;
};
+struct vcd_property_vop_timing_constant_delta {
+ u32 constant_delta; /*In usecs */
+};
+
struct vcd_property_short_header {
u32 short_header;
};
@@ -314,11 +318,11 @@
u32 req_i_frame;
};
-struct vcd_frame_rect{
- u32 left;
- u32 top;
- u32 right;
- u32 bottom;
+struct vcd_frame_rect {
+ u32 left;
+ u32 top;
+ u32 right;
+ u32 bottom;
};
struct vcd_property_dec_output_buffer {
@@ -327,33 +331,42 @@
};
enum vcd_output_order {
- VCD_DEC_ORDER_DISPLAY = 0x0,
- VCD_DEC_ORDER_DECODE = 0x1
+ VCD_DEC_ORDER_DISPLAY = 0x0,
+ VCD_DEC_ORDER_DECODE = 0x1
};
-struct vcd_property_enc_recon_buffer{
+struct vcd_property_enc_recon_buffer {
+ u8 *user_virtual_addr;
u8 *kernel_virtual_addr;
u8 *physical_addr;
+ u8 *dev_addr;
u32 buffer_size;
u32 ysize;
int pmem_fd;
u32 offset;
+ void *client_data;
};
-struct vcd_property_h264_mv_buffer{
+struct vcd_property_h264_mv_buffer {
u8 *kernel_virtual_addr;
u8 *physical_addr;
u32 size;
u32 count;
int pmem_fd;
u32 offset;
+ u8 *dev_addr;
+ void *client_data;
};
-struct vcd_property_buffer_size{
+struct vcd_property_buffer_size {
int width;
int height;
int size;
int alignment;
};
+struct vcd_property_sps_pps_for_idr_enable {
+ u32 sps_pps_for_idr_enable_flag;
+};
+
#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_status.h b/include/media/msm/vcd_status.h
similarity index 62%
rename from drivers/video/msm/vidc/common/vcd/vcd_status.h
rename to include/media/msm/vcd_status.h
index 6fba334..7e8ec0b 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_status.h
+++ b/include/media/msm/vcd_status.h
@@ -1,29 +1,13 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
*
*/
diff --git a/include/media/msm/vidc_init.h b/include/media/msm/vidc_init.h
new file mode 100644
index 0000000..c681213
--- /dev/null
+++ b/include/media/msm/vidc_init.h
@@ -0,0 +1,100 @@
+/* Copyright (c) 2010-2012, 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 <linux/ion.h>
+#include <media/msm/vidc_type.h>
+#include <media/msm/vcd_property.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;
+ unsigned long buff_ion_flag;
+ struct ion_handle *buff_ion_handle;
+ int pmem_fd;
+ struct file *file;
+ unsigned long dev_addr;
+ void *client_data;
+};
+
+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;
+ struct mutex enrty_queue_lock;
+ wait_queue_head_t msg_wait;
+ struct completion event;
+ struct vcd_property_h264_mv_buffer vcd_h264_mv_buffer;
+ struct vcd_property_enc_recon_buffer recon_buffer[4];
+ u32 event_status;
+ u32 seq_header_set;
+ u32 stop_msg;
+ u32 stop_called;
+ u32 stop_sync_cb;
+ struct ion_client *user_ion_client;
+ struct ion_handle *seq_hdr_ion_handle;
+ struct ion_handle *h264_mv_ion_handle;
+ struct ion_handle *recon_buffer_ion_handle[4];
+ u32 dmx_disable;
+};
+
+void __iomem *vidc_get_ioaddr(void);
+int vidc_load_firmware(void);
+void vidc_release_firmware(void);
+u32 vidc_get_fd_info(struct video_client_ctx *client_ctx,
+ enum buffer_dir buffer, int pmem_fd,
+ unsigned long kvaddr, int index,
+ struct ion_handle **buff_handle);
+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, unsigned long length);
+u32 vidc_insert_addr_table_kernel(struct video_client_ctx *client_ctx,
+ enum buffer_dir buffer, unsigned long user_vaddr,
+ unsigned long kernel_vaddr, unsigned long phys_addr,
+ unsigned int max_num_buffers,
+ unsigned long length);
+u32 vidc_delete_addr_table(struct video_client_ctx *client_ctx,
+ enum buffer_dir buffer, unsigned long user_vaddr,
+ unsigned long *kernel_vaddr);
+void vidc_cleanup_addr_table(struct video_client_ctx *client_ctx,
+ enum buffer_dir buffer);
+
+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/include/media/msm/vidc_type.h b/include/media/msm/vidc_type.h
new file mode 100644
index 0000000..d4db0a0
--- /dev/null
+++ b/include/media/msm/vidc_type.h
@@ -0,0 +1,30 @@
+/* Copyright (c) 2010-2012, 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
diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c
index 2622509..f48d643 100644
--- a/kernel/pm_qos_params.c
+++ b/kernel/pm_qos_params.c
@@ -48,15 +48,6 @@
* or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock
* held, taken with _irqsave. One lock to rule them all
*/
-struct pm_qos_request_list {
- struct list_head list;
- union {
- s32 value;
- s32 usec;
- s32 kbps;
- };
- int pm_qos_class;
-};
static s32 max_compare(s32 v1, s32 v2);
static s32 min_compare(s32 v1, s32 v2);