Merge "msm_fb: display: enable sending uevent as default" into msm-3.4
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
new file mode 100644
index 0000000..6db1150
--- /dev/null
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -0,0 +1,140 @@
+Qualcomm mdss-dsi-panel
+
+mdss-dsi-panel is a dsi panel driver which supports panels that
+are compatable with MIPI display serial interface specification.
+
+Required properties:
+- compatible: Must be "qcom,mdss-dsi-panel"
+- status: A string that has to be set to "okay/ok" to enable
+ the panel driver. By default this property will be
+ set to "disable". Will be set to "ok/okay" status
+ for specific platforms.
+- qcom,mdss-pan-res: A two dimensional array that specifies the panel
+ resolution.
+- qcom,mdss-pan-bpp: Specifies the panel bits per pixel. Default value is 24(rgb888).
+ 18 = for rgb666
+ 16 = for rgb565
+- qcom,mdss-panel-on-cmds: An array of variable length that lists the init commands
+ of the panel. Each command will have the format specified
+ as below:
+ --> data type of the command
+ --> specifies whether this command packet is last.
+ --> virtual channel
+ --> Needs acknowledge from the panel or not.
+ --> wait time after the command is transmitter.
+ --> size of payload
+ --> payload.
+- qcom,mdss-panel-off-cmds: An array of variable length that lists the panel off
+ commands. Each command will have the format specified
+ as below:
+ --> data type of the command
+ --> specifies whether this command packet is last.
+ --> virtual channel
+ --> Needs acknowledge from the panel or not.
+ --> wait time after the command is transmitter.
+ --> size of payload
+ --> payload.
+
+Required structure:
+- A qcom,mdss-dsi-panel node must be a child of an mdss-dsi controller node that links to
+ one of the two DSI controllers.
+
+
+Optional properties:
+- label: A string used as a descriptive name of the panel
+- qcom,mdss-pan-porch-values: An array of size 6 that specifies the panel blanking values.
+- qcom,mdss-pan-underflow-clr: Specifies the controller settings for the panel underflow clear
+ settings. Default value is 0xff.
+- qcom,mdss-pan-bl-levels: Specifies the backlight levels supported by the panel.
+ Default range is 1 to 255.
+
+- qcom,mdss-pan-dsi-mode: Specifies the panel operating mode.
+ 0 = enable video mode(default mode).
+ 1 = enable command mode.
+- qcom,mdss-pan-dsi-h-pulse-mode: Specifies the pulse mode option for the panel.
+ 0 = Don't send hsa/he following vs/ve packet(default)
+ 1 = Send hsa/he following vs/ve packet
+- qcom,mdss-pan-dsi-h-power-stop: An Array of size 3 that specifies the power mode
+ during horizontal porch and sync periods of the panel.
+ 0 = high speed mode(default mode).
+ 1 = Low power mode for horizontal porches and sync pulse.
+- qcom,mdss-pan-dsi-bllp-power-stop: An Array of size 2 that specifies the power mode
+ during blanking period and after EOF(end of frame).
+ 0 = high speed mode(default mode).
+ 1 = Low power mode during blanking and EOF.
+- qcom,mdss-pan-dsi-traffic-mode: Specifies the panel traffic mode.
+ 0 = non burst with sync pulses (default mode).
+ 1 = non burst with sync start event.
+ 2 = burst mode.
+- qcom,mdss-pan-dsi-dst-format: Specifies the destination format.
+ 0 = DSI_VIDEO_DST_FORMAT_RGB565.
+ 1 = DSI_VIDEO_DST_FORMAT_RGB666.
+ 2 = DSI_VIDEO_DST_FORMAT_RGB666_LOOSE.
+ 3 = DSI_VIDEO_DST_FORMAT_RGB888 (Default format)
+ 6 = DSI_CMD_DST_FORMAT_RGB565
+ 7 = DSI_CMD_DST_FORMAT_RGB666
+ 8 = DSI_CMD_DST_FORMAT_RGB888
+- qcom,mdss-pan-dsi-vc: Specifies the virtual channel identefier.
+ 0 = default value.
+- qcom,mdss-pan-dsi-rgb-swap: Specifies the R, G and B channel ordering.
+ 0 = DSI_RGB_SWAP_RGB (default value)
+ 1 = DSI_RGB_SWAP_RBG
+ 2 = DSI_RGB_SWAP_BGR
+ 3 = DSI_RGB_SWAP_BRG
+ 4 = DSI_RGB_SWAP_GRB
+ 5 = DSI_RGB_SWAP_GBR
+- qcom,mdss-pan-dsi-data-lanes: An array that specifies the data lanes enabled.
+ <1 1 0 0> = data lanes 1 and 2 are enabled.(default).
+- qcom,mdss-pan-dsi-t-clk: An array that specifies the byte clock cycles
+ before and after each mode switch.
+- qcom,mdss-pan-dsi-stream: Specifies the packet stream to be used.
+ 0 = stream 0 (default)
+ 1 = stream 1
+- qcom,mdss-pan-dsi-mdp-tr: Specifies the trigger mechanism to be used for MDP path.
+ 0 = no trigger
+ 2 = Tear check signal line used for trigger
+ 4 = Triggered by software (default mode)
+ 6 = Software trigger and TE
+- qcom,mdss-pan-dsi-dma-tr: Specifies the trigger mechanism to be used for DMA path.
+ 0 = no trigger
+ 2 = Tear check signal line used for trigger
+ 4 = Triggered by software (default mode)
+ 5 = Software trigger and start/end of frame trigger.
+ 6 = Software trigger and TE
+- qcom,mdss-pan-dsi-frame-rate: Specifies the frame rate for the panel.
+ 60 = 60 frames per second (default)
+
+Note, if a given optional qcom,* binding is not present, then the driver will configure
+the default values specified.
+
+Example:
+ qcom,mdss_dsi@fd922800 {
+
+ qcom,mdss_dsi_sim_video {
+ compatible = "qcom,mdss-dsi-panel";
+ label = "simulator video mode dsi panel";
+ status = "disable";
+ qcom,mdss-pan-res = <640 480>;
+ qcom,mdss-pan-bpp = <24>;
+ qcom,mdss-pan-porch-values = <6 2 6 6 2 6>;
+ qcom,mdss-pan-underflow-clr = <0xff>;
+ qcom,mdss-pan-bl-levels = <1 15>;
+ qcom,mdss-pan-dsi-mode = <0>;
+ qcom,mdss-pan-dsi-h-pulse-mode = <1>;
+ qcom,mdss-pan-dsi-h-power-stop = <1 1 1>;
+ qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
+ qcom,mdss-pan-dsi-traffic-mode = <0>;
+ qcom,mdss-pan-dsi-dst-format = <3>;
+ qcom,mdss-pan-dsi-vc = <0>;
+ qcom,mdss-pan-dsi-rgb-swap = <0>;
+ qcom,mdss-pan-dsi-data-lanes = <1 1 0 0>;
+ qcom,mdss-pan-dsi-t-clk = <0x24 0x03>;
+ qcom,mdss-pan-dsi-stream = <0>;
+ qcom,mdss-pan-dsi-mdp-tr = <0x04>;
+ qcom,mdss-pan-dsi-dma-tr = <0x04>;
+ qcom,mdss-pan-frame-rate = <60>;
+ qcom,panel-on-cmds = [32 01 00 00 00 02 00 00];
+ qcom,panel-off-cmds = [22 01 00 00 00 00 00];
+ };
+
+ };
diff --git a/arch/arm/boot/dts/msm8974-ion.dtsi b/arch/arm/boot/dts/msm8974-ion.dtsi
new file mode 100644
index 0000000..1893ae4
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-ion.dtsi
@@ -0,0 +1,76 @@
+/* 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.
+ */
+
+/ {
+ qcom,ion {
+ compatible = "qcom,msm-ion";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,ion-heap@30 { /* SYSTEM HEAP */
+ reg = <30>;
+ };
+
+ qcom,ion-heap@8 { /* CP_MM HEAP */
+ compatible = "qcom,msm-ion-reserve";
+ reg = <8>;
+ qcom,heap-align = <0x1000>;
+ qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
+ qcom,memory-reservation-size = <0x7800000>;
+ };
+
+ qcom,ion-heap@29 { /* FIRMWARE HEAP */
+ compatible = "qcom,msm-ion-reserve";
+ reg = <29>;
+ qcom,heap-align = <0x20000>;
+ qcom,heap-adjacent = <8>;
+ qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
+ qcom,memory-reservation-size = <0xA00000>;
+ };
+
+ qcom,ion-heap@12 { /* MFC HEAP */
+ compatible = "qcom,msm-ion-reserve";
+ reg = <12>;
+ qcom,heap-align = <0x1000>;
+ qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
+ qcom,memory-reservation-size = <0x2000>;
+ };
+
+ qcom,ion-heap@24 { /* SF HEAP */
+ compatible = "qcom,msm-ion-reserve";
+ reg = <24>;
+ qcom,heap-align = <0x1000>;
+ qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
+ qcom,memory-reservation-size = <0x2800000>;
+ };
+
+ qcom,ion-heap@25 { /* IOMMU HEAP */
+ reg = <25>;
+ };
+
+ qcom,ion-heap@27 { /* QSECOM HEAP */
+ compatible = "qcom,msm-ion-reserve";
+ reg = <27>;
+ qcom,heap-align = <0x1000>;
+ qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
+ qcom,memory-reservation-size = <0x600000>;
+ };
+
+ qcom,ion-heap@28 { /* AUDIO HEAP */
+ compatible = "qcom,msm-ion-reserve";
+ reg = <28>;
+ qcom,heap-align = <0x1000>;
+ qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
+ qcom,memory-reservation-size = <0x2B4000>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index de1d54f..f144421 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -15,6 +15,7 @@
/include/ "msm8974-iommu.dtsi"
/include/ "msm8974-camera.dtsi"
/include/ "msm-gdsc.dtsi"
+/include/ "msm8974-ion.dtsi"
/include/ "msm8974-gpu.dtsi"
/ {
@@ -215,6 +216,7 @@
interrupts = <0 163 0 0 164 0>;
interrupt-names = "slimbus_irq", "slimbus_bam_irq";
qcom,min-clk-gear = <10>;
+ qcom,rxreg-access;
};
spmi_bus: qcom,spmi@fc4c0000 {
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 314f91b..00325c9 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -218,7 +218,6 @@
# CONFIG_SERIAL_MSM_CLOCK_CONTROL is not set
CONFIG_DIAG_CHAR=y
# CONFIG_HW_RANDOM is not set
-CONFIG_DCC_TTY=y
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
# CONFIG_I2C_MSM is not set
diff --git a/arch/arm/configs/msm7630_defconfig b/arch/arm/configs/msm7630_defconfig
index aad13b8..5c5a152 100644
--- a/arch/arm/configs/msm7630_defconfig
+++ b/arch/arm/configs/msm7630_defconfig
@@ -238,7 +238,6 @@
CONFIG_SERIAL_MSM_HS=y
CONFIG_DIAG_CHAR=y
# CONFIG_HW_RANDOM is not set
-CONFIG_DCC_TTY=y
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_QUP=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index 5d19237..0efe658 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -282,7 +282,6 @@
CONFIG_DIAG_CHAR=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_MSM=y
-CONFIG_DCC_TTY=y
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
# CONFIG_I2C_MSM is not set
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 28d6e60..ca3e996 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -651,7 +651,8 @@
cpumask_copy(&mask, cpu_online_mask);
cpumask_clear_cpu(smp_processor_id(), &mask);
- smp_cross_call(&mask, IPI_CPU_STOP);
+ if (!cpumask_empty(&mask))
+ smp_cross_call(&mask, IPI_CPU_STOP);
/* Wait up to one second for other CPUs to stop */
timeout = USEC_PER_SEC;
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index b939dc2..240e094 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -20,9 +20,6 @@
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/of_irq.h>
-#ifdef CONFIG_ION_MSM
-#include <linux/ion.h>
-#endif
#include <linux/memory.h>
#ifdef CONFIG_ANDROID_PMEM
#include <linux/android_pmem.h>
@@ -52,17 +49,6 @@
#include "lpm_resources.h"
#define MSM_KERNEL_EBI1_MEM_SIZE 0x280000
-#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
-#define MSM_ION_SF_SIZE 0x4000000 /* 64 Mbytes */
-#else
-#define MSM_ION_SF_SIZE 0x2800000 /* 40 Mbytes */
-#endif
-#define MSM_ION_MM_FW_SIZE 0xa00000 /* (10MB) */
-#define MSM_ION_MM_SIZE 0x7800000 /* (120MB) */
-#define MSM_ION_QSECOM_SIZE 0x600000 /* (6MB) */
-#define MSM_ION_MFC_SIZE SZ_8K
-#define MSM_ION_AUDIO_SIZE 0x2B4000
-#define MSM_ION_HEAP_NUM 8
#ifdef CONFIG_KERNEL_PMEM_EBI_REGION
static unsigned kernel_ebi1_mem_size = MSM_KERNEL_EBI1_MEM_SIZE;
@@ -90,121 +76,12 @@
return MEMTYPE_EBI1;
}
-#ifdef CONFIG_ION_MSM
-static struct ion_cp_heap_pdata cp_mm_ion_pdata = {
- .permission_type = IPT_TYPE_MM_CARVEOUT,
- .align = PAGE_SIZE,
-};
-
-static struct ion_cp_heap_pdata cp_mfc_ion_pdata = {
- .permission_type = IPT_TYPE_MFC_SHAREDMEM,
- .align = PAGE_SIZE,
-};
-
-static struct ion_co_heap_pdata co_ion_pdata = {
- .adjacent_mem_id = INVALID_HEAP_ID,
- .align = PAGE_SIZE,
-};
-
-static struct ion_co_heap_pdata fw_co_ion_pdata = {
- .adjacent_mem_id = ION_CP_MM_HEAP_ID,
- .align = SZ_128K,
-};
-
-/**
- * These heaps are listed in the order they will be allocated. Due to
- * video hardware restrictions and content protection the FW heap has to
- * be allocated adjacent (below) the MM heap and the MFC heap has to be
- * allocated after the MM heap to ensure MFC heap is not more than 256MB
- * away from the base address of the FW heap.
- * However, the order of FW heap and MM heap doesn't matter since these
- * two heaps are taken care of by separate code to ensure they are adjacent
- * to each other.
- * Don't swap the order unless you know what you are doing!
- */
-static struct ion_platform_data ion_pdata = {
- .nr = MSM_ION_HEAP_NUM,
- .heaps = {
- {
- .id = ION_SYSTEM_HEAP_ID,
- .type = ION_HEAP_TYPE_SYSTEM,
- .name = ION_VMALLOC_HEAP_NAME,
- },
- {
- .id = ION_CP_MM_HEAP_ID,
- .type = ION_HEAP_TYPE_CP,
- .name = ION_MM_HEAP_NAME,
- .size = MSM_ION_MM_SIZE,
- .memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &cp_mm_ion_pdata,
- },
- {
- .id = ION_MM_FIRMWARE_HEAP_ID,
- .type = ION_HEAP_TYPE_CARVEOUT,
- .name = ION_MM_FIRMWARE_HEAP_NAME,
- .size = MSM_ION_MM_FW_SIZE,
- .memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &fw_co_ion_pdata,
- },
- {
- .id = ION_CP_MFC_HEAP_ID,
- .type = ION_HEAP_TYPE_CP,
- .name = ION_MFC_HEAP_NAME,
- .size = MSM_ION_MFC_SIZE,
- .memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &cp_mfc_ion_pdata,
- },
- {
- .id = ION_SF_HEAP_ID,
- .type = ION_HEAP_TYPE_CARVEOUT,
- .name = ION_SF_HEAP_NAME,
- .size = MSM_ION_SF_SIZE,
- .memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &co_ion_pdata,
- },
- {
- .id = ION_IOMMU_HEAP_ID,
- .type = ION_HEAP_TYPE_IOMMU,
- .name = ION_IOMMU_HEAP_NAME,
- },
- {
- .id = ION_QSECOM_HEAP_ID,
- .type = ION_HEAP_TYPE_CARVEOUT,
- .name = ION_QSECOM_HEAP_NAME,
- .size = MSM_ION_QSECOM_SIZE,
- .memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &co_ion_pdata,
- },
- {
- .id = ION_AUDIO_HEAP_ID,
- .type = ION_HEAP_TYPE_CARVEOUT,
- .name = ION_AUDIO_HEAP_NAME,
- .size = MSM_ION_AUDIO_SIZE,
- .memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &co_ion_pdata,
- },
- }
-};
-
-static struct platform_device ion_dev = {
- .name = "ion-msm",
- .id = 1,
- .dev = { .platform_data = &ion_pdata },
-};
-
-static void __init reserve_ion_memory(void)
+static void __init reserve_ebi_memory(void)
{
- msm_8974_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_SIZE;
- msm_8974_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_FW_SIZE;
- msm_8974_reserve_table[MEMTYPE_EBI1].size += MSM_ION_SF_SIZE;
- msm_8974_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MFC_SIZE;
- msm_8974_reserve_table[MEMTYPE_EBI1].size += MSM_ION_QSECOM_SIZE;
- msm_8974_reserve_table[MEMTYPE_EBI1].size += MSM_ION_AUDIO_SIZE;
#ifdef CONFIG_KERNEL_PMEM_EBI_REGION
msm_8974_reserve_table[MEMTYPE_EBI1].size += kernel_ebi1_mem_size;
#endif
}
-#endif
static struct resource smd_resource[] = {
{
@@ -370,9 +247,7 @@
static void __init msm_8974_calculate_reserve_sizes(void)
{
-#ifdef CONFIG_ION_MSM
- reserve_ion_memory();
-#endif
+ reserve_ebi_memory();
}
static struct reserve_info msm_8974_reserve_info __initdata = {
@@ -535,9 +410,6 @@
void __init msm_8974_add_devices(void)
{
-#ifdef CONFIG_ION_MSM
- platform_device_register(&ion_dev);
-#endif
platform_device_register(&msm_device_smd_8974);
platform_device_register(&android_usb_device);
platform_add_devices(msm_8974_stub_regulator_devices,
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 658b3dc..7dd3829 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -4960,14 +4960,19 @@
CLK_LOOKUP("osr_clk", audio_core_lpaif_quad_osr_clk.c, ""),
CLK_LOOKUP("ebit_clk", audio_core_lpaif_quad_ebit_clk.c, ""),
CLK_LOOKUP("ibit_clk", audio_core_lpaif_quad_ibit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_pcm0_clk_src.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_pcm0_clk_src.c,
+ "msm-dai-q6.4106"),
CLK_LOOKUP("ebit_clk", audio_core_lpaif_pcm0_ebit_clk.c, ""),
+ CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm0_ibit_clk.c,
+ "msm-dai-q6.4106"),
CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm0_ibit_clk.c, ""),
CLK_LOOKUP("core_clk", audio_core_lpaif_pcm1_clk_src.c, ""),
CLK_LOOKUP("ebit_clk", audio_core_lpaif_pcm1_ebit_clk.c, ""),
CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm1_ibit_clk.c, ""),
- CLK_LOOKUP("core_clk_src", audio_core_lpaif_pcmoe_clk_src.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_pcmoe_clk.c, ""),
+ CLK_LOOKUP("core_oe_src_clk", audio_core_lpaif_pcmoe_clk_src.c,
+ "msm-dai-q6.4106"),
+ CLK_LOOKUP("core_oe_clk", audio_core_lpaif_pcmoe_clk.c,
+ "msm-dai-q6.4106"),
CLK_LOOKUP("core_clk", mss_xo_q6_clk.c, "pil-q6v5-mss"),
CLK_LOOKUP("bus_clk", mss_bus_q6_clk.c, "pil-q6v5-mss"),
diff --git a/arch/arm/mach-msm/include/mach/cpuidle.h b/arch/arm/mach-msm/include/mach/cpuidle.h
index 2a5aa97..8566e7f 100644
--- a/arch/arm/mach-msm/include/mach/cpuidle.h
+++ b/arch/arm/mach-msm/include/mach/cpuidle.h
@@ -25,12 +25,16 @@
enum msm_pm_sleep_mode mode_nr;
};
-#ifdef CONFIG_CPU_IDLE
+#ifdef CONFIG_PM
s32 msm_cpuidle_get_deep_idle_latency(void);
+#else
+static inline s32 msm_cpuidle_get_deep_idle_latency(void) { return 0; }
+#endif
+
+#ifdef CONFIG_CPU_IDLE
int msm_cpuidle_init(void);
#else
static inline int msm_cpuidle_init(void) { return -ENOSYS; }
-static inline s32 msm_cpuidle_get_deep_idle_latency(void) { return 0; }
#endif
#ifdef CONFIG_MSM_SLEEP_STATS
diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c
index e74af2e..07f3efc 100644
--- a/arch/arm/mach-msm/mdm2.c
+++ b/arch/arm/mach-msm/mdm2.c
@@ -44,7 +44,7 @@
#define MDM_PBLRDY_CNT 20
-static int mdm_debug_on;
+static int mdm_debug_mask;
static int power_on_count;
static int hsic_peripheral_status;
static DEFINE_MUTEX(hsic_status_lock);
@@ -234,7 +234,7 @@
static void debug_state_changed(int value)
{
- mdm_debug_on = value;
+ mdm_debug_mask = value;
}
static void mdm_status_changed(struct mdm_modem_drv *mdm_drv, int value)
diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c
index d1865e4..6ca9045 100644
--- a/arch/arm/mach-msm/mdm_common.c
+++ b/arch/arm/mach-msm/mdm_common.c
@@ -49,10 +49,11 @@
#define MDM_RDUMP_TIMEOUT 120000L
#define MDM2AP_STATUS_TIMEOUT_MS 60000L
-static int mdm_debug_on;
+static unsigned int mdm_debug_mask;
static struct workqueue_struct *mdm_queue;
static struct workqueue_struct *mdm_sfr_queue;
static unsigned int dump_timeout_ms;
+static int vddmin_gpios_sent;
#define EXTERNAL_MODEM "external_modem"
@@ -100,6 +101,7 @@
if (!vddmin_res)
return;
+ pr_info("Enabling vddmin logging\n");
req.id = vddmin_res->rpm_id;
req.value = ((uint32_t)vddmin_res->ap2mdm_vddmin_gpio & 0x0000FFFF)
<< 16;
@@ -108,7 +110,7 @@
msm_rpm_set(MSM_RPM_CTX_SET_0, &req, 1);
- /* Monitor low power gpio from mdm */
+ /* Start monitoring low power gpio from mdm */
irq = MSM_GPIO_TO_INT(vddmin_res->mdm2ap_vddmin_gpio);
if (irq < 0) {
pr_err("%s: could not get LPM POWER IRQ resource.\n",
@@ -478,23 +480,33 @@
.name = EXTERNAL_MODEM,
};
-static int mdm_debug_on_set(void *data, u64 val)
+/* Once the gpios are sent to RPM and debugging
+ * starts, there is no way to stop it without
+ * rebooting the device.
+ */
+static int mdm_debug_mask_set(void *data, u64 val)
{
- mdm_debug_on = val;
+ if (!vddmin_gpios_sent &&
+ (val & MDM_DEBUG_MASK_VDDMIN_SETUP)) {
+ mdm_setup_vddmin_gpios();
+ vddmin_gpios_sent = 1;
+ }
+
+ mdm_debug_mask = val;
if (mdm_drv->ops->debug_state_changed_cb)
- mdm_drv->ops->debug_state_changed_cb(mdm_debug_on);
+ mdm_drv->ops->debug_state_changed_cb(mdm_debug_mask);
return 0;
}
-static int mdm_debug_on_get(void *data, u64 *val)
+static int mdm_debug_mask_get(void *data, u64 *val)
{
- *val = mdm_debug_on;
+ *val = mdm_debug_mask;
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(mdm_debug_on_fops,
- mdm_debug_on_get,
- mdm_debug_on_set, "%llu\n");
+DEFINE_SIMPLE_ATTRIBUTE(mdm_debug_mask_fops,
+ mdm_debug_mask_get,
+ mdm_debug_mask_set, "%llu\n");
static int mdm_debugfs_init(void)
{
@@ -504,8 +516,8 @@
if (IS_ERR(dent))
return PTR_ERR(dent);
- debugfs_create_file("debug_on", 0644, dent, NULL,
- &mdm_debug_on_fops);
+ debugfs_create_file("debug_mask", 0644, dent, NULL,
+ &mdm_debug_mask_fops);
return 0;
}
@@ -601,7 +613,7 @@
mdm_modem_initialize_data(pdev, p_mdm_cb);
if (mdm_drv->ops->debug_state_changed_cb)
- mdm_drv->ops->debug_state_changed_cb(mdm_debug_on);
+ mdm_drv->ops->debug_state_changed_cb(mdm_debug_mask);
gpio_request(mdm_drv->ap2mdm_status_gpio, "AP2MDM_STATUS");
gpio_request(mdm_drv->ap2mdm_errfatal_gpio, "AP2MDM_ERRFATAL");
@@ -737,8 +749,6 @@
*/
if (mdm_drv->ap2mdm_pmic_pwr_en_gpio > 0)
gpio_direction_output(mdm_drv->ap2mdm_pmic_pwr_en_gpio, 1);
- /* Register VDDmin gpios with RPM */
- mdm_setup_vddmin_gpios();
/* Perform early powerup of the external modem in order to
* allow tabla devices to be found.
diff --git a/arch/arm/mach-msm/mdm_private.h b/arch/arm/mach-msm/mdm_private.h
index 7aba83d..d1e85d3 100644
--- a/arch/arm/mach-msm/mdm_private.h
+++ b/arch/arm/mach-msm/mdm_private.h
@@ -13,6 +13,7 @@
#ifndef _ARCH_ARM_MACH_MSM_MDM_PRIVATE_H
#define _ARCH_ARM_MACH_MSM_MDM_PRIVATE_H
+#define MDM_DEBUG_MASK_VDDMIN_SETUP (0x00000002)
struct mdm_modem_drv;
struct mdm_ops {
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 95a85f2a..0febaf3 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -251,6 +251,7 @@
int logging_mode;
int mask_check;
int logging_process_id;
+ struct task_struct *socket_process;
#ifdef CONFIG_DIAG_SDIO_PIPE
unsigned char *buf_in_sdio;
unsigned char *usb_buf_mdm_out;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 240a514..30504bc 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -230,6 +230,13 @@
* This call will remove any pending registrations of such client
*/
diagchar_ioctl(NULL, DIAG_IOCTL_DCI_DEINIT, 0);
+
+ /* If the exiting process is the socket process */
+ if (driver->socket_process &&
+ (driver->socket_process->tgid == current->tgid)) {
+ driver->socket_process = NULL;
+ }
+
#ifdef CONFIG_DIAG_OVER_USB
/* If the SD logging process exits, change logging to USB mode */
if (driver->logging_process_id == current->tgid) {
@@ -344,6 +351,7 @@
void *temp_buf;
uint16_t support_list = 0;
struct dci_notification_tbl *notify_params;
+ int status;
if (iocmd == DIAG_IOCTL_COMMAND_REG) {
struct bindpkt_params_per_process *pkt_params =
@@ -480,12 +488,32 @@
mutex_lock(&driver->diagchar_mutex);
temp = driver->logging_mode;
driver->logging_mode = (int)ioarg;
- if (driver->logging_mode == MEMORY_DEVICE_MODE)
+ if (driver->logging_mode == MEMORY_DEVICE_MODE) {
driver->mask_check = 1;
+ if (driver->socket_process) {
+ /*
+ * Notify the socket logging process that we
+ * are switching to MEMORY_DEVICE_MODE
+ */
+ status = send_sig(SIGCONT,
+ driver->socket_process, 0);
+ if (status) {
+ pr_err("diag: %s, Error notifying ",
+ __func__);
+ pr_err("socket process, status: %d\n",
+ status);
+ }
+ }
+ }
if (driver->logging_mode == UART_MODE) {
driver->mask_check = 0;
driver->logging_mode = MEMORY_DEVICE_MODE;
}
+ if (driver->logging_mode == SOCKET_MODE) {
+ driver->socket_process = current;
+ driver->mask_check = 0;
+ driver->logging_mode = MEMORY_DEVICE_MODE;
+ }
driver->logging_process_id = current->tgid;
mutex_unlock(&driver->diagchar_mutex);
if (temp == MEMORY_DEVICE_MODE && driver->logging_mode
@@ -1251,6 +1279,7 @@
driver->poolsize_write_struct = poolsize_write_struct;
driver->num_clients = max_clients;
driver->logging_mode = USB_MODE;
+ driver->socket_process = NULL;
driver->mask_check = 0;
mutex_init(&driver->diagchar_mutex);
init_waitqueue_head(&driver->wait_q);
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 86fe3f5..5ba3778 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1822,7 +1822,8 @@
if (state) {
adreno_regwrite(device, REG_RBBM_INT_CNTL, RBBM_INT_MASK);
adreno_regwrite(device, REG_CP_INT_CNTL, CP_INT_MASK);
- adreno_regwrite(device, MH_INTERRUPT_MASK, KGSL_MMU_INT_MASK);
+ adreno_regwrite(device, MH_INTERRUPT_MASK,
+ kgsl_mmu_get_int_mask());
} else {
adreno_regwrite(device, REG_RBBM_INT_CNTL, 0);
adreno_regwrite(device, REG_CP_INT_CNTL, 0);
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index bc6ec8e..5293d66 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -299,4 +299,14 @@
(gpuaddr < (KGSL_PAGETABLE_BASE + kgsl_mmu_get_ptsize())));
}
+static inline unsigned int kgsl_mmu_get_int_mask(void)
+{
+ /* Dont enable gpummu interrupts, if iommu is enabled */
+ if (KGSL_MMU_TYPE_GPU == kgsl_mmu_get_mmutype())
+ return KGSL_MMU_INT_MASK;
+ else
+ return (MH_INTERRUPT_MASK__AXI_READ_ERROR |
+ MH_INTERRUPT_MASK__AXI_WRITE_ERROR);
+}
+
#endif /* __KGSL_MMU_H */
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 6efba45..3504dfc 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -892,7 +892,8 @@
if (state) {
z180_regwrite(device, (ADDR_VGC_IRQENABLE >> 2), 3);
- z180_regwrite(device, MH_INTERRUPT_MASK, KGSL_MMU_INT_MASK);
+ z180_regwrite(device, MH_INTERRUPT_MASK,
+ kgsl_mmu_get_int_mask());
} else {
z180_regwrite(device, (ADDR_VGC_IRQENABLE >> 2), 0);
z180_regwrite(device, MH_INTERRUPT_MASK, 0);
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
index 2cc61a1..7d58091 100644
--- a/drivers/media/video/msm/server/msm_cam_server.c
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -1565,11 +1565,16 @@
int rc = -EINVAL;
uint32_t mctl_handle = 0;
struct msm_cam_media_controller *p_mctl = NULL;
+ int is_gesture_evt =
+ (notification == NOTIFY_GESTURE_EVT)
+ || (notification == NOTIFY_GESTURE_CAM_EVT);
- mctl_handle = msm_camera_server_find_mctl(notification, arg);
- if (mctl_handle < 0) {
- pr_err("%s: Couldn't find mctl instance!\n", __func__);
- return;
+ if (!is_gesture_evt) {
+ mctl_handle = msm_camera_server_find_mctl(notification, arg);
+ if (mctl_handle < 0) {
+ pr_err("%s: Couldn't find mctl instance!\n", __func__);
+ return;
+ }
}
switch (notification) {
case NOTIFY_ISP_MSG_EVT:
@@ -2283,12 +2288,17 @@
int *p_active)
{
int rc = 0;
+ int i = 0;
struct msm_cam_media_controller *pmctl = NULL;
*p_active = 0;
- if (g_server_dev.pcam_active[pcam->server_queue_idx]) {
- D("%s: Active camera present return", __func__);
- return 0;
+
+ for (i = 0; i < MAX_NUM_ACTIVE_CAMERA; i++) {
+ if (NULL != g_server_dev.pcam_active[i]) {
+ pr_info("%s: Active camera present return", __func__);
+ return 0;
+ }
}
+
rc = msm_cam_server_open_session(&g_server_dev, pcam);
if (rc < 0) {
pr_err("%s: cam_server_open_session failed %d\n",
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index e87b4bd..352e60e 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -76,12 +76,29 @@
if (psy->set_property)
return psy->set_property(psy, POWER_SUPPLY_PROP_SCOPE,
&ret);
-
return -ENXIO;
}
EXPORT_SYMBOL_GPL(power_supply_set_scope);
/**
+ * power_supply_set_supply_type - set type of the power supply
+ * @psy: the power supply to control
+ * @supply_type: sets type property of power supply
+ */
+int power_supply_set_supply_type(struct power_supply *psy,
+ enum power_supply_type supply_type)
+{
+ const union power_supply_propval ret = {supply_type,};
+
+ if (psy->set_property)
+ return psy->set_property(psy, POWER_SUPPLY_PROP_TYPE,
+ &ret);
+
+ return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(power_supply_set_supply_type);
+
+/**
* power_supply_set_charge_type - set charge type of the power supply
* @psy: the power supply to control
* @enable: sets charge type property of power supply
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 75d92f1..5879530 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -2928,30 +2928,32 @@
int mdp4_overlay_wait4vsync(struct fb_info *info, long long *vtime)
{
- if (info->node == 0) {
+ 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 (info->node == 1)
+ } 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)
{
- if (info->node == 0) {
+ if (!hdmi_prim_display && info->node == 0) {
if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
mdp4_dsi_video_vsync_ctrl(0, enable);
else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
mdp4_dsi_cmd_vsync_ctrl(0, enable);
else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
mdp4_lcdc_vsync_ctrl(0, enable);
- } else if (info->node == 1)
+ } else if (hdmi_prim_display || info->node == 1) {
mdp4_dtv_vsync_ctrl(0, enable);
+ }
return 0;
}
diff --git a/drivers/video/msm/mdss/Makefile b/drivers/video/msm/mdss/Makefile
index 492437e..b6294f4 100644
--- a/drivers/video/msm/mdss/Makefile
+++ b/drivers/video/msm/mdss/Makefile
@@ -7,4 +7,10 @@
mdss-mdp-objs += mdss_mdp_wb.o
obj-$(CONFIG_FB_MSM_MDSS) += mdss-mdp.o
obj-$(CONFIG_FB_MSM_MDSS) += mdss_fb.o
+
+mdss-dsi-objs := mdss_dsi.o mdss_dsi_host.o
+mdss-dsi-objs += mdss_dsi_panel.o
+mdss-dsi-objs += msm_mdss_io_8974.o
+obj-$(CONFIG_FB_MSM_MDSS) += mdss-dsi.o
+
obj-$(CONFIG_FB_MSM_MDSS_WRITEBACK) += mdss_wb.o
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index a58c3e6..6145d67 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -22,6 +22,7 @@
#define MDSS_REG_READ(addr) readl_relaxed(mdss_reg_base + addr)
extern unsigned char *mdss_reg_base;
+extern spinlock_t dsi_clk_lock;
enum mdss_mdp_clk_type {
MDSS_CLK_AHB,
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
new file mode 100644
index 0000000..d051828
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -0,0 +1,383 @@
+/* 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 <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of_device.h>
+
+#include "mdss.h"
+#include "mdss_panel.h"
+#include "mdss_dsi.h"
+
+static struct mdss_panel_common_pdata *panel_pdata;
+
+static unsigned char *mdss_dsi_base;
+
+static int mdss_dsi_off(struct mdss_panel_data *pdata)
+{
+ int ret = 0;
+ struct mdss_panel_info *pinfo;
+
+ pinfo = &pdata->panel_info;
+
+ if (pdata->panel_info.type == MIPI_VIDEO_PANEL)
+ mdss_dsi_controller_cfg(0, pdata);
+
+ mdss_dsi_op_mode_config(DSI_CMD_MODE, pdata);
+
+ ret = panel_pdata->off(pdata);
+ if (ret) {
+ pr_err("%s: Panel OFF failed\n", __func__);
+ return ret;
+ }
+
+ spin_lock_bh(&dsi_clk_lock);
+ mdss_dsi_clk_disable();
+
+ /* disable dsi engine */
+ MIPI_OUTP(mdss_dsi_base + 0x0004, 0);
+
+ spin_unlock_bh(&dsi_clk_lock);
+
+ mdss_dsi_unprepare_clocks();
+
+ pr_debug("%s-:\n", __func__);
+
+ return ret;
+}
+
+static int mdss_dsi_on(struct mdss_panel_data *pdata)
+{
+ int ret = 0;
+ u32 clk_rate;
+ struct mdss_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;
+
+ pinfo = &pdata->panel_info;
+
+ cont_splash_clk_ctrl(0);
+ mdss_dsi_prepare_clocks();
+
+ spin_lock_bh(&dsi_clk_lock);
+
+ MIPI_OUTP(mdss_dsi_base + 0x118, 1);
+ MIPI_OUTP(mdss_dsi_base + 0x118, 0);
+
+ mdss_dsi_clk_enable();
+ spin_unlock_bh(&dsi_clk_lock);
+
+ clk_rate = pdata->panel_info.clk_rate;
+ clk_rate = min(clk_rate, pdata->panel_info.clk_max);
+
+ hbp = pdata->panel_info.lcdc.h_back_porch;
+ hfp = pdata->panel_info.lcdc.h_front_porch;
+ vbp = pdata->panel_info.lcdc.v_back_porch;
+ vfp = pdata->panel_info.lcdc.v_front_porch;
+ hspw = pdata->panel_info.lcdc.h_pulse_width;
+ vspw = pdata->panel_info.lcdc.v_pulse_width;
+ width = pdata->panel_info.xres;
+ height = pdata->panel_info.yres;
+
+ mipi = &pdata->panel_info.mipi;
+ if (pdata->panel_info.type == MIPI_VIDEO_PANEL) {
+ dummy_xres = pdata->panel_info.lcdc.xres_pad;
+ dummy_yres = pdata->panel_info.lcdc.yres_pad;
+
+ MIPI_OUTP(mdss_dsi_base + 0x24,
+ ((hspw + hbp + width + dummy_xres) << 16 |
+ (hspw + hbp)));
+ MIPI_OUTP(mdss_dsi_base + 0x28,
+ ((vspw + vbp + height + dummy_yres) << 16 |
+ (vspw + vbp)));
+ MIPI_OUTP(mdss_dsi_base + 0x2C,
+ (vspw + vbp + height + dummy_yres +
+ vfp - 1) << 16 | (hspw + hbp +
+ width + dummy_xres + hfp - 1));
+
+ MIPI_OUTP(mdss_dsi_base + 0x30, (hspw << 16));
+ MIPI_OUTP(mdss_dsi_base + 0x34, 0);
+ MIPI_OUTP(mdss_dsi_base + 0x38, (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(mdss_dsi_base + 0x60, data);
+ MIPI_OUTP(mdss_dsi_base + 0x58, data);
+
+ /* DSI_COMMAND_MODE_MDP_STREAM_TOTAL */
+ data = height << 16 | width;
+ MIPI_OUTP(mdss_dsi_base + 0x64, data);
+ MIPI_OUTP(mdss_dsi_base + 0x5C, data);
+ }
+
+ mdss_dsi_host_init(mipi, pdata);
+
+ if (mipi->force_clk_lane_hs) {
+ u32 tmp;
+
+ tmp = MIPI_INP(mdss_dsi_base + 0xac);
+ tmp |= (1<<28);
+ MIPI_OUTP(mdss_dsi_base + 0xac, tmp);
+ wmb();
+ }
+
+ ret = panel_pdata->on(pdata);
+ if (ret) {
+ pr_err("%s: unable to initialize the panel\n", __func__);
+ return ret;
+ }
+
+ mdss_dsi_op_mode_config(mipi->mode, pdata);
+
+ pr_debug("%s-:\n", __func__);
+ return ret;
+}
+
+unsigned char *mdss_dsi_get_base_adr(void)
+{
+ return mdss_dsi_base;
+}
+
+unsigned char *mdss_dsi_get_clk_base(void)
+{
+ return mdss_dsi_base;
+}
+
+static int mdss_dsi_resource_initialized;
+
+static int __devinit mdss_dsi_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+ pr_debug("%s\n", __func__);
+
+ if (pdev->dev.of_node && !mdss_dsi_resource_initialized) {
+ struct resource *mdss_dsi_mres;
+ pdev->id = 1;
+ mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mdss_dsi_mres) {
+ pr_err("%s:%d unable to get the MDSS resources",
+ __func__, __LINE__);
+ return -ENOMEM;
+ }
+ if (mdss_dsi_mres) {
+ mdss_dsi_base = ioremap(mdss_dsi_mres->start,
+ resource_size(mdss_dsi_mres));
+ if (!mdss_dsi_base) {
+ pr_err("%s:%d unable to remap dsi resources",
+ __func__, __LINE__);
+ return -ENOMEM;
+ }
+ }
+
+ if (mdss_dsi_clk_init(pdev)) {
+ iounmap(mdss_dsi_base);
+ return -EPERM;
+ }
+
+ rc = of_platform_populate(pdev->dev.of_node,
+ NULL, NULL, &pdev->dev);
+ if (rc) {
+ dev_err(&pdev->dev,
+ "%s: failed to add child nodes, rc=%d\n",
+ __func__, rc);
+ iounmap(mdss_dsi_base);
+ return rc;
+ }
+
+ mdss_dsi_resource_initialized = 1;
+ }
+
+ if (!mdss_dsi_resource_initialized)
+ return -EPERM;
+
+ return 0;
+}
+
+static int __devexit mdss_dsi_remove(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+
+ mfd = platform_get_drvdata(pdev);
+ iounmap(mdss_dsi_base);
+ return 0;
+}
+
+struct device dsi_dev;
+
+int dsi_panel_device_register(struct platform_device *pdev,
+ struct mdss_panel_common_pdata *panel_data)
+{
+ struct mipi_panel_info *mipi;
+ int rc;
+ u8 lanes = 0, bpp;
+ u32 h_period, v_period, dsi_pclk_rate;
+ struct mdss_panel_data *pdata = NULL;
+
+ panel_pdata = panel_data;
+
+ h_period = ((panel_pdata->panel_info.lcdc.h_pulse_width)
+ + (panel_pdata->panel_info.lcdc.h_back_porch)
+ + (panel_pdata->panel_info.xres)
+ + (panel_pdata->panel_info.lcdc.h_front_porch));
+
+ v_period = ((panel_pdata->panel_info.lcdc.v_pulse_width)
+ + (panel_pdata->panel_info.lcdc.v_back_porch)
+ + (panel_pdata->panel_info.yres)
+ + (panel_pdata->panel_info.lcdc.v_front_porch));
+
+ mipi = &panel_pdata->panel_info.mipi;
+
+ panel_pdata->panel_info.type =
+ ((mipi->mode == DSI_VIDEO_MODE)
+ ? MIPI_VIDEO_PANEL : MIPI_CMD_PANEL);
+
+ 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 (panel_pdata->panel_info.type == MIPI_VIDEO_PANEL &&
+ !panel_pdata->panel_info.clk_rate) {
+ h_period += panel_pdata->panel_info.lcdc.xres_pad;
+ v_period += panel_pdata->panel_info.lcdc.yres_pad;
+
+ if (lanes > 0) {
+ panel_pdata->panel_info.clk_rate =
+ ((h_period * v_period * (mipi->frame_rate) * bpp * 8)
+ / lanes);
+ } else {
+ pr_err("%s: forcing mdss_dsi lanes to 1\n", __func__);
+ panel_pdata->panel_info.clk_rate =
+ (h_period * v_period
+ * (mipi->frame_rate) * bpp * 8);
+ }
+ }
+ pll_divider_config.clk_rate = panel_pdata->panel_info.clk_rate;
+
+ rc = mdss_dsi_clk_div_config(bpp, lanes, &dsi_pclk_rate);
+ if (rc) {
+ pr_err("%s: unable to initialize the clk dividers\n", __func__);
+ return rc;
+ }
+
+ if ((dsi_pclk_rate < 3300000) || (dsi_pclk_rate > 103300000))
+ dsi_pclk_rate = 35000000;
+ mipi->dsi_pclk_rate = dsi_pclk_rate;
+
+ /*
+ * data chain
+ */
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ pdata->on = mdss_dsi_on;
+ pdata->off = mdss_dsi_off;
+ memcpy(&(pdata->panel_info), &(panel_pdata->panel_info),
+ sizeof(struct mdss_panel_info));
+
+ pdata->dsi_base = mdss_dsi_base;
+
+ /*
+ * register in mdp driver
+ */
+ rc = mdss_register_panel(pdata);
+ if (rc) {
+ dev_err(&pdev->dev, "unable to register MIPI DSI panel\n");
+ devm_kfree(&pdev->dev, pdata);
+ return rc;
+ }
+
+ pr_debug("%s: Panal data initialized\n", __func__);
+ return 0;
+}
+
+static const struct of_device_id msm_mdss_dsi_dt_match[] = {
+ {.compatible = "qcom,msm-mdss-dsi"},
+ {}
+};
+MODULE_DEVICE_TABLE(of, msm_mdss_dsi_dt_match);
+
+static struct platform_driver mdss_dsi_driver = {
+ .probe = mdss_dsi_probe,
+ .remove = __devexit_p(mdss_dsi_remove),
+ .shutdown = NULL,
+ .driver = {
+ .name = "mdss_dsi",
+ .of_match_table = msm_mdss_dsi_dt_match,
+ },
+};
+
+static int mdss_dsi_register_driver(void)
+{
+ return platform_driver_register(&mdss_dsi_driver);
+}
+
+static int __init mdss_dsi_driver_init(void)
+{
+ int ret;
+
+ mdss_dsi_init();
+
+ ret = mdss_dsi_register_driver();
+ if (ret) {
+ pr_err("mdss_dsi_register_driver() failed!\n");
+ return ret;
+ }
+
+ return ret;
+}
+module_init(mdss_dsi_driver_init);
+
+static void __exit mdss_dsi_driver_cleanup(void)
+{
+ iounmap(mdss_dsi_base);
+ platform_driver_unregister(&mdss_dsi_driver);
+}
+module_exit(mdss_dsi_driver_cleanup);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("DSI controller driver");
+MODULE_AUTHOR("Chandan Uddaraju <chandanu@codeaurora.org>");
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
new file mode 100644
index 0000000..57fce1a
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -0,0 +1,294 @@
+/* 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 MDSS_DSI_H
+#define MDSS_DSI_H
+
+#include <linux/list.h>
+#include <mach/scm-io.h>
+
+#include "mdss_panel.h"
+
+#define MMSS_MDSS_CC_BASE_PHY 0xFD8C2300 /* mmss clcok control */
+#define MMSS_SERDES_BASE_PHY 0x04f01000 /* mmss (De)Serializer CFG */
+
+#define MIPI_OUTP(addr, data) writel_relaxed((data), (addr))
+#define MIPI_INP(addr) readl_relaxed(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_relaxed((data), (addr))
+#define MIPI_INP_SECURE(addr) readl_relaxed(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_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 mdss_dsi_clk_on;
+extern u32 dsi_irq;
+
+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 analog_posDiv;
+ u32 digital_posDiv;
+};
+
+extern struct dsiphy_pll_divider_config pll_divider_config;
+
+struct dsi_clk_mnd_table {
+ u8 lanes;
+ u8 bpp;
+ u8 pll_digital_posDiv;
+ u8 pclk_m;
+ u8 pclk_n;
+ u8 pclk_d;
+};
+
+static const struct dsi_clk_mnd_table mnd_table[] = {
+ { 1, 2, 8, 1, 1, 0},
+ { 1, 3, 12, 1, 1, 0},
+ { 2, 2, 4, 1, 1, 0},
+ { 2, 3, 6, 1, 1, 0},
+ { 3, 2, 1, 3, 8, 4},
+ { 3, 3, 4, 1, 1, 0},
+ { 4, 2, 2, 1, 1, 0},
+ { 4, 3, 3, 1, 1, 0},
+};
+
+struct dsi_clk_desc {
+ u32 src;
+ u32 m;
+ u32 n;
+ u32 d;
+ u32 mnd_mode;
+ u32 pre_div_func;
+};
+
+#define DSI_HOST_HDR_SIZE 4
+#define DSI_HDR_LAST BIT(31)
+#define DSI_HDR_LONG_PKT BIT(30)
+#define DSI_HDR_BTA BIT(29)
+#define DSI_HDR_VC(vc) (((vc) & 0x03) << 22)
+#define DSI_HDR_DTYPE(dtype) (((dtype) & 0x03f) << 16)
+#define DSI_HDR_DATA2(data) (((data) & 0x0ff) << 8)
+#define DSI_HDR_DATA1(data) ((data) & 0x0ff)
+#define DSI_HDR_WC(wc) ((wc) & 0x0ffff)
+
+#define DSI_BUF_SIZE 1024
+#define MDSS_DSI_MRPS 0x04 /* Maximum Return Packet Size */
+
+#define MDSS_DSI_LEN 8 /* 4 x 4 - 6 - 2, bytes dcs header+crc-align */
+
+struct dsi_buf {
+ u32 *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;
+};
+
+struct dsi_kickoff_action {
+ struct list_head act_entry;
+ void (*action) (void *);
+ void *data;
+};
+
+struct mdss_panel_common_pdata {
+ struct mdss_panel_info panel_info;
+ int (*on) (struct mdss_panel_data *pdata);
+ int (*off) (struct mdss_panel_data *pdata);
+};
+
+int dsi_panel_device_register(struct platform_device *pdev,
+ struct mdss_panel_common_pdata *panel_data);
+
+char *mdss_dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen);
+char *mdss_dsi_buf_init(struct dsi_buf *dp);
+void mdss_dsi_init(void);
+int mdss_dsi_buf_alloc(struct dsi_buf *, int size);
+int mdss_dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm);
+int mdss_dsi_cmds_tx(struct mdss_panel_data *pdata,
+ struct dsi_buf *dp, struct dsi_cmd_desc *cmds, int cnt);
+
+int mdss_dsi_cmd_dma_tx(struct dsi_buf *dp,
+ struct mdss_panel_data *pdata);
+int mdss_dsi_cmd_reg_tx(u32 data,
+ struct mdss_panel_data *pdata);
+int mdss_dsi_cmds_rx(struct mdss_panel_data *pdata,
+ struct dsi_buf *tp, struct dsi_buf *rp,
+ struct dsi_cmd_desc *cmds, int len);
+int mdss_dsi_cmd_dma_rx(struct dsi_buf *tp, int rlen,
+ struct mdss_panel_data *pdata);
+void mdss_dsi_host_init(struct mipi_panel_info *pinfo,
+ struct mdss_panel_data *pdata);
+void mdss_dsi_op_mode_config(int mode,
+ struct mdss_panel_data *pdata);
+void mdss_dsi_cmd_mode_ctrl(int enable);
+void mdp4_dsi_cmd_trigger(void);
+void mdss_dsi_cmd_mdp_start(void);
+void mdss_dsi_cmd_bta_sw_trigger(struct mdss_panel_data *pdata);
+void mdss_dsi_ack_err_status(unsigned char *dsi_base);
+void mdss_dsi_clk_enable(void);
+void mdss_dsi_clk_disable(void);
+void mdss_dsi_controller_cfg(int enable,
+ struct mdss_panel_data *pdata);
+void mdss_dsi_sw_reset(struct mdss_panel_data *pdata);
+
+irqreturn_t mdss_dsi_isr(int irq, void *ptr);
+
+void mipi_set_tx_power_mode(int mode, struct mdss_panel_data *pdata);
+int mdss_dsi_clk_div_config(u8 bpp, u8 lanes,
+ u32 *expected_dsi_pclk);
+int mdss_dsi_clk_init(struct platform_device *pdev);
+void mdss_dsi_clk_deinit(struct device *dev);
+void mdss_dsi_prepare_clocks(void);
+void mdss_dsi_unprepare_clocks(void);
+void cont_splash_clk_ctrl(int enable);
+unsigned char *mdss_dsi_get_base_adr(void);
+
+#endif /* MDSS_DSI_H */
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
new file mode 100644
index 0000000..7bc0105
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -0,0 +1,1259 @@
+
+/* 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 <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/iopoll.h>
+
+#include "mdss.h"
+#include "mdss_dsi.h"
+
+static struct completion dsi_dma_comp;
+static int dsi_irq_enabled;
+static spinlock_t dsi_irq_lock;
+static spinlock_t dsi_mdp_lock;
+static int dsi_mdp_busy;
+
+spinlock_t dsi_clk_lock;
+
+struct mdss_hw mdss_dsi_hw = {
+ .hw_ndx = MDSS_HW_DSI0,
+ .irq_handler = mdss_dsi_isr,
+};
+
+void mdss_dsi_init(void)
+{
+ init_completion(&dsi_dma_comp);
+ spin_lock_init(&dsi_irq_lock);
+ spin_lock_init(&dsi_mdp_lock);
+ spin_lock_init(&dsi_clk_lock);
+}
+
+void mdss_dsi_enable_irq(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dsi_irq_lock, flags);
+ if (dsi_irq_enabled) {
+ pr_debug("%s: IRQ aleady enabled\n", __func__);
+ spin_unlock_irqrestore(&dsi_irq_lock, flags);
+ return;
+ }
+ mdss_enable_irq(&mdss_dsi_hw);
+ dsi_irq_enabled = 1;
+ /* TO DO: Check whether MDSS IRQ is enabled */
+ spin_unlock_irqrestore(&dsi_irq_lock, flags);
+}
+
+void mdss_dsi_disable_irq(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dsi_irq_lock, flags);
+ if (dsi_irq_enabled == 0) {
+ pr_debug("%s: IRQ already disabled\n", __func__);
+ spin_unlock_irqrestore(&dsi_irq_lock, flags);
+ return;
+ }
+ mdss_disable_irq(&mdss_dsi_hw);
+ dsi_irq_enabled = 0;
+ /* TO DO: Check whether MDSS IRQ is Disabled */
+ spin_unlock_irqrestore(&dsi_irq_lock, flags);
+}
+
+/*
+ * mdss_dsi_disale_irq_nosync() should be called
+ * from interrupt context
+ */
+void mdss_dsi_disable_irq_nosync(void)
+{
+ spin_lock(&dsi_irq_lock);
+ if (dsi_irq_enabled == 0) {
+ pr_debug("%s: IRQ cannot be disabled\n", __func__);
+ spin_unlock(&dsi_irq_lock);
+ return;
+ }
+
+ dsi_irq_enabled = 0;
+ spin_unlock(&dsi_irq_lock);
+}
+
+/*
+ * mipi dsi buf mechanism
+ */
+char *mdss_dsi_buf_reserve(struct dsi_buf *dp, int len)
+{
+ dp->data += len;
+ return dp->data;
+}
+
+char *mdss_dsi_buf_unreserve(struct dsi_buf *dp, int len)
+{
+ dp->data -= len;
+ return dp->data;
+}
+
+char *mdss_dsi_buf_push(struct dsi_buf *dp, int len)
+{
+ dp->data -= len;
+ dp->len += len;
+ return dp->data;
+}
+
+char *mdss_dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen)
+{
+ dp->hdr = (u32 *)dp->data;
+ return mdss_dsi_buf_reserve(dp, hlen);
+}
+
+char *mdss_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 mdss_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 generic long write
+ */
+static int mdss_dsi_generic_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ char *bp;
+ u32 *hp;
+ int i, len;
+
+ bp = mdss_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;
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len;
+}
+
+/*
+ * mipi dsi generic short write with 0, 1 2 parameters
+ */
+static int mdss_dsi_generic_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+ int len;
+
+ if (cm->dlen && cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return 0;
+ }
+
+ mdss_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);
+ }
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+/*
+ * mipi dsi gerneric read with 0, 1 2 parameters
+ */
+static int mdss_dsi_generic_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+ int len;
+
+ if (cm->dlen && cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return 0;
+ }
+
+ mdss_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);
+ }
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+ return dp->len; /* 4 bytes */
+}
+
+/*
+ * mipi dsi dcs long write
+ */
+static int mdss_dsi_dcs_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ char *bp;
+ u32 *hp;
+ int i, len;
+
+ bp = mdss_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;
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len;
+}
+
+/*
+ * mipi dsi dcs short write with 0 parameters
+ */
+static int mdss_dsi_dcs_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+ int len;
+
+ if (cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return -EINVAL;
+ }
+
+ mdss_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);
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+ return dp->len;
+}
+
+/*
+ * mipi dsi dcs short write with 1 parameters
+ */
+static int mdss_dsi_dcs_swrite1(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+
+ if (cm->dlen < 2 || cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return -EINVAL;
+ }
+
+ mdss_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 */
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len;
+}
+/*
+ * mipi dsi dcs read with 0 parameters
+ */
+
+static int mdss_dsi_dcs_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+
+ if (cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return -EINVAL;
+ }
+
+ mdss_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);
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+static int mdss_dsi_cm_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+
+ mdss_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;
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+static int mdss_dsi_cm_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+
+ mdss_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;
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+static int mdss_dsi_peripheral_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+
+ mdss_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;
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+static int mdss_dsi_peripheral_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+
+ mdss_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;
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+static int mdss_dsi_set_max_pktsize(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+
+ if (cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return 0;
+ }
+
+ mdss_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]);
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+static int mdss_dsi_null_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+
+ mdss_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;
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+static int mdss_dsi_blank_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+
+ mdss_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;
+
+ mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+/*
+ * prepare cmd buffer to be txed
+ */
+int mdss_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 = mdss_dsi_generic_swrite(dp, cm);
+ break;
+ case DTYPE_GEN_LWRITE:
+ len = mdss_dsi_generic_lwrite(dp, cm);
+ break;
+ case DTYPE_GEN_READ:
+ case DTYPE_GEN_READ1:
+ case DTYPE_GEN_READ2:
+ len = mdss_dsi_generic_read(dp, cm);
+ break;
+ case DTYPE_DCS_LWRITE:
+ len = mdss_dsi_dcs_lwrite(dp, cm);
+ break;
+ case DTYPE_DCS_WRITE:
+ len = mdss_dsi_dcs_swrite(dp, cm);
+ break;
+ case DTYPE_DCS_WRITE1:
+ len = mdss_dsi_dcs_swrite1(dp, cm);
+ break;
+ case DTYPE_DCS_READ:
+ len = mdss_dsi_dcs_read(dp, cm);
+ break;
+ case DTYPE_MAX_PKTSIZE:
+ len = mdss_dsi_set_max_pktsize(dp, cm);
+ break;
+ case DTYPE_NULL_PKT:
+ len = mdss_dsi_null_pkt(dp, cm);
+ break;
+ case DTYPE_BLANK_PKT:
+ len = mdss_dsi_blank_pkt(dp, cm);
+ break;
+ case DTYPE_CM_ON:
+ len = mdss_dsi_cm_on(dp, cm);
+ break;
+ case DTYPE_CM_OFF:
+ len = mdss_dsi_cm_off(dp, cm);
+ break;
+ case DTYPE_PERIPHERAL_ON:
+ len = mdss_dsi_peripheral_on(dp, cm);
+ break;
+ case DTYPE_PERIPHERAL_OFF:
+ len = mdss_dsi_peripheral_off(dp, cm);
+ break;
+ default:
+ pr_debug("%s: dtype=%x NOT supported\n",
+ __func__, cm->dtype);
+ break;
+
+ }
+
+ return len;
+}
+
+/*
+ * mdss_dsi_short_read1_resp: 1 parameter
+ */
+static int mdss_dsi_short_read1_resp(struct dsi_buf *rp)
+{
+ /* strip out dcs type */
+ rp->data++;
+ rp->len = 1;
+ return rp->len;
+}
+
+/*
+ * mdss_dsi_short_read2_resp: 2 parameter
+ */
+static int mdss_dsi_short_read2_resp(struct dsi_buf *rp)
+{
+ /* strip out dcs type */
+ rp->data++;
+ rp->len = 2;
+ return rp->len;
+}
+
+static int mdss_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 mdss_dsi_host_init(struct mipi_panel_info *pinfo,
+ struct mdss_panel_data *pdata)
+{
+ u32 dsi_ctrl, intr_ctrl;
+ u32 data;
+
+ pinfo->rgb_swap = DSI_RGB_SWAP_RGB;
+
+ 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((pdata->dsi_base) + 0x0010, 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((pdata->dsi_base) + 0x0020, 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((pdata->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((pdata->dsi_base) + 0x0044, 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((pdata->dsi_base) + 0x3C, 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((pdata->dsi_base) + 0x0084, data); /* DSI_TRIG_CTRL */
+
+ /* DSI_LAN_SWAP_CTRL */
+ MIPI_OUTP((pdata->dsi_base) + 0x00b0, pinfo->dlane_swap);
+
+ /* clock out ctrl */
+ data = pinfo->t_clk_post & 0x3f; /* 6 bits */
+ data <<= 8;
+ data |= pinfo->t_clk_pre & 0x3f; /* 6 bits */
+ /* DSI_CLKOUT_TIMING_CTRL */
+ MIPI_OUTP((pdata->dsi_base) + 0xc4, data);
+
+ data = 0;
+ if (pinfo->rx_eot_ignore)
+ data |= BIT(4);
+ if (pinfo->tx_eot_append)
+ data |= BIT(0);
+ MIPI_OUTP((pdata->dsi_base) + 0x00cc, data); /* DSI_EOT_PACKET_CTRL */
+
+
+ /* allow only ack-err-status to generate interrupt */
+ /* DSI_ERR_INT_MASK0 */
+ MIPI_OUTP((pdata->dsi_base) + 0x010c, 0x13ff3fe0);
+
+ intr_ctrl |= DSI_INTR_ERROR_MASK;
+ MIPI_OUTP((pdata->dsi_base) + 0x0110, intr_ctrl); /* DSI_INTL_CTRL */
+
+ /* turn esc, byte, dsi, pclk, sclk, hclk on */
+ MIPI_OUTP((pdata->dsi_base) + 0x11c, 0x23f); /* DSI_CLK_CTRL */
+
+ dsi_ctrl |= BIT(0); /* enable dsi */
+ MIPI_OUTP((pdata->dsi_base) + 0x0004, dsi_ctrl);
+
+ wmb();
+}
+
+void mipi_set_tx_power_mode(int mode, struct mdss_panel_data *pdata)
+{
+ u32 data = MIPI_INP((pdata->dsi_base) + 0x3c);
+
+ if (mode == 0)
+ data &= ~BIT(26);
+ else
+ data |= BIT(26);
+
+ MIPI_OUTP((pdata->dsi_base) + 0x3c, data);
+}
+
+void mdss_dsi_sw_reset(struct mdss_panel_data *pdata)
+{
+ MIPI_OUTP((pdata->dsi_base) + 0x118, 0x01);
+ wmb();
+ MIPI_OUTP((pdata->dsi_base) + 0x118, 0x00);
+ wmb();
+}
+
+void mdss_dsi_controller_cfg(int enable,
+ struct mdss_panel_data *pdata)
+{
+
+ u32 dsi_ctrl;
+ u32 status;
+ u32 sleep_us = 1000;
+ u32 timeout_us = 16000;
+
+ /* Check for CMD_MODE_DMA_BUSY */
+ if (readl_poll_timeout(((pdata->dsi_base) + 0x0008),
+ status,
+ ((status & 0x02) == 0),
+ sleep_us, timeout_us))
+ pr_info("%s: DSI status=%x failed\n", __func__, status);
+
+ /* Check for x_HS_FIFO_EMPTY */
+ if (readl_poll_timeout(((pdata->dsi_base) + 0x000c),
+ status,
+ ((status & 0x11111000) == 0x11111000),
+ sleep_us, timeout_us))
+ pr_info("%s: FIFO status=%x failed\n", __func__, status);
+
+ dsi_ctrl = MIPI_INP((pdata->dsi_base) + 0x0004);
+ if (enable)
+ dsi_ctrl |= 0x01;
+ else
+ dsi_ctrl &= ~0x01;
+
+ MIPI_OUTP((pdata->dsi_base) + 0x0004, dsi_ctrl);
+ wmb();
+}
+
+void mdss_dsi_op_mode_config(int mode,
+ struct mdss_panel_data *pdata)
+{
+
+ u32 dsi_ctrl, intr_ctrl;
+
+ dsi_ctrl = MIPI_INP((pdata->dsi_base) + 0x0004);
+ 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((pdata->dsi_base) + 0x0110, intr_ctrl); /* DSI_INTL_CTRL */
+ MIPI_OUTP((pdata->dsi_base) + 0x0004, dsi_ctrl);
+ wmb();
+}
+
+void mdss_dsi_cmd_mdp_start(void)
+{
+ unsigned long flag;
+
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ mdss_dsi_enable_irq();
+ dsi_mdp_busy = true;
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+}
+
+
+void mdss_dsi_cmd_bta_sw_trigger(struct mdss_panel_data *pdata)
+{
+ u32 status;
+ int timeout_us = 10000;
+
+ MIPI_OUTP((pdata->dsi_base) + 0x098, 0x01); /* trigger */
+ wmb();
+
+ /* Check for CMD_MODE_DMA_BUSY */
+ if (readl_poll_timeout(((pdata->dsi_base) + 0x0008),
+ status, ((status & 0x0010) == 0),
+ 0, timeout_us))
+ pr_info("%s: DSI status=%x failed\n", __func__, status);
+
+ mdss_dsi_ack_err_status((pdata->dsi_base));
+
+ pr_debug("%s: BTA done, status = %d\n", __func__, status);
+}
+
+int mdss_dsi_cmd_reg_tx(u32 data,
+ struct mdss_panel_data *pdata)
+{
+ int i;
+ char *bp;
+
+ bp = (char *)&data;
+ pr_debug("%s: ", __func__);
+ for (i = 0; i < 4; i++)
+ pr_debug("%x ", *bp++);
+
+ pr_debug("\n");
+
+ MIPI_OUTP((pdata->dsi_base) + 0x0084, 0x04);/* sw trigger */
+ MIPI_OUTP((pdata->dsi_base) + 0x0004, 0x135);
+
+ wmb();
+
+ MIPI_OUTP((pdata->dsi_base) + 0x03c, data);
+ wmb();
+ MIPI_OUTP((pdata->dsi_base) + 0x090, 0x01); /* trigger */
+ wmb();
+
+ udelay(300);
+
+ return 4;
+}
+
+/*
+ * mdss_dsi_cmds_tx:
+ * ov_mutex need to be acquired before call this function.
+ */
+int mdss_dsi_cmds_tx(struct mdss_panel_data *pdata,
+ struct dsi_buf *tp, struct dsi_cmd_desc *cmds, int cnt)
+{
+ struct dsi_cmd_desc *cm;
+ u32 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((pdata->dsi_base) + 0x0004);
+ video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
+ if (video_mode) {
+ ctrl = dsi_ctrl | 0x04; /* CMD_MODE_EN */
+ MIPI_OUTP((pdata->dsi_base) + 0x0004, ctrl);
+ }
+
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ mdss_dsi_enable_irq();
+ dsi_mdp_busy = true;
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+
+ cm = cmds;
+ mdss_dsi_buf_init(tp);
+ for (i = 0; i < cnt; i++) {
+ mdss_dsi_buf_init(tp);
+ mdss_dsi_cmd_dma_add(tp, cm);
+ mdss_dsi_cmd_dma_tx(tp, pdata);
+ if (cm->wait)
+ msleep(cm->wait);
+ cm++;
+ }
+
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ dsi_mdp_busy = false;
+ mdss_dsi_disable_irq();
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+
+ if (video_mode)
+ MIPI_OUTP((pdata->dsi_base) + 0x0004, dsi_ctrl); /* restore */
+
+ return cnt;
+}
+
+/* MDSS_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
+ * mdss_dsi_controller only have 4x32 bits register ( 16 bytes) to
+ * hold data per transaction.
+ * MDSS_DSI_LEN equal to 8
+ * len should be either 4 or 8
+ * any return data more than MDSS_DSI_LEN need to be break down
+ * to multiple transactions.
+ *
+ * ov_mutex need to be acquired before call this function.
+ */
+int mdss_dsi_cmds_rx(struct mdss_panel_data *pdata,
+ struct dsi_buf *tp, struct dsi_buf *rp,
+ struct dsi_cmd_desc *cmds, int rlen)
+{
+ int cnt, len, diff, pkt_size;
+ unsigned long flag;
+ char cmd;
+
+ if (pdata->panel_info.mipi.no_max_pkt_size)
+ rlen = ALIGN(rlen, 4); /* Only support rlen = 4*n */
+
+ len = rlen;
+ diff = 0;
+
+ if (len <= 2)
+ cnt = 4; /* short read */
+ else {
+ if (len > MDSS_DSI_LEN)
+ len = MDSS_DSI_LEN; /* 8 bytes at most */
+
+ len = ALIGN(len, 4); /* 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);
+ mdss_dsi_enable_irq();
+ dsi_mdp_busy = true;
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+
+ if (!pdata->panel_info.mipi.no_max_pkt_size) {
+ /* packet size need to be set at every read */
+ pkt_size = len;
+ max_pktsize[0] = pkt_size;
+ mdss_dsi_buf_init(tp);
+ mdss_dsi_cmd_dma_add(tp, pkt_size_cmd);
+ mdss_dsi_cmd_dma_tx(tp, pdata);
+ }
+
+ mdss_dsi_buf_init(tp);
+ mdss_dsi_cmd_dma_add(tp, cmds);
+
+ /* transmit read comamnd to client */
+ mdss_dsi_cmd_dma_tx(tp, pdata);
+ /*
+ * once cmd_dma_done interrupt received,
+ * return data from client is ready and stored
+ * at RDBK_DATA register already
+ */
+ mdss_dsi_buf_init(rp);
+ if (pdata->panel_info.mipi.no_max_pkt_size) {
+ /*
+ * expect rlen = n * 4
+ * short alignement for start addr
+ */
+ rp->data += 2;
+ }
+
+ mdss_dsi_cmd_dma_rx(rp, cnt, pdata);
+
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ dsi_mdp_busy = false;
+ mdss_dsi_disable_irq();
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+
+ if (pdata->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:
+ mdss_dsi_short_read1_resp(rp);
+ break;
+ case DTYPE_GEN_READ2_RESP:
+ case DTYPE_DCS_READ2_RESP:
+ mdss_dsi_short_read2_resp(rp);
+ break;
+ case DTYPE_GEN_LREAD_RESP:
+ case DTYPE_DCS_LREAD_RESP:
+ mdss_dsi_long_read_resp(rp);
+ rp->len -= 2; /* extra 2 bytes added */
+ rp->len -= diff; /* align bytes */
+ break;
+ default:
+ break;
+ }
+
+ return rp->len;
+}
+
+int mdss_dsi_cmd_dma_tx(struct dsi_buf *tp,
+ struct mdss_panel_data *pdata)
+{
+ int len;
+ 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");
+
+ len = tp->len;
+ len += 3;
+ len &= ~0x03; /* multipled by 4 */
+
+ tp->dmap = dma_map_single(&dsi_dev, tp->data, len, DMA_TO_DEVICE);
+ if (dma_mapping_error(&dsi_dev, tp->dmap))
+ pr_err("%s: dmap mapp failed\n", __func__);
+
+ INIT_COMPLETION(dsi_dma_comp);
+
+ MIPI_OUTP((pdata->dsi_base) + 0x048, tp->dmap);
+ MIPI_OUTP((pdata->dsi_base) + 0x04c, len);
+ wmb();
+
+ MIPI_OUTP((pdata->dsi_base) + 0x090, 0x01); /* trigger */
+ wmb();
+
+ wait_for_completion(&dsi_dma_comp);
+
+ dma_unmap_single(&dsi_dev, tp->dmap, len, DMA_TO_DEVICE);
+ tp->dmap = 0;
+ return tp->len;
+}
+
+int mdss_dsi_cmd_dma_rx(struct dsi_buf *rp, int rlen,
+ struct mdss_panel_data *pdata)
+{
+ u32 *lp, data;
+ int i, off, cnt;
+
+ lp = (u32 *)rp->data;
+ cnt = rlen;
+ cnt += 3;
+ cnt >>= 2;
+
+ if (cnt > 4)
+ cnt = 4; /* 4 x 32 bits registers only */
+
+ off = 0x06c; /* DSI_RDBK_DATA0 */
+ off += ((cnt - 1) * 4);
+
+
+ for (i = 0; i < cnt; i++) {
+ data = (u32)MIPI_INP((pdata->dsi_base) + off);
+ *lp++ = ntohl(data); /* to network byte order */
+ off -= 4;
+ rp->len += sizeof(*lp);
+ }
+
+ return rlen;
+}
+
+void mdss_dsi_ack_err_status(unsigned char *dsi_base)
+{
+ u32 status;
+
+ status = MIPI_INP(dsi_base + 0x0068);/* DSI_ACK_ERR_STATUS */
+
+ if (status) {
+ MIPI_OUTP(dsi_base + 0x0068, status);
+ pr_debug("%s: status=%x\n", __func__, status);
+ }
+}
+
+void mdss_dsi_timeout_status(unsigned char *dsi_base)
+{
+ u32 status;
+
+ status = MIPI_INP(dsi_base + 0x00c0);/* DSI_TIMEOUT_STATUS */
+ if (status & 0x0111) {
+ MIPI_OUTP(dsi_base + 0x00c0, status);
+ pr_debug("%s: status=%x\n", __func__, status);
+ }
+}
+
+void mdss_dsi_dln0_phy_err(unsigned char *dsi_base)
+{
+ u32 status;
+
+ status = MIPI_INP(dsi_base + 0x00b4);/* DSI_DLN0_PHY_ERR */
+
+ if (status & 0x011111) {
+ MIPI_OUTP(dsi_base + 0x00b4, status);
+ pr_debug("%s: status=%x\n", __func__, status);
+ }
+}
+
+void mdss_dsi_fifo_status(unsigned char *dsi_base)
+{
+ u32 status;
+
+ status = MIPI_INP(dsi_base + 0x000c);/* DSI_FIFO_STATUS */
+
+ if (status & 0x44444489) {
+ MIPI_OUTP(dsi_base + 0x000c, status);
+ pr_debug("%s: status=%x\n", __func__, status);
+ }
+}
+
+void mdss_dsi_status(unsigned char *dsi_base)
+{
+ u32 status;
+
+ status = MIPI_INP(dsi_base + 0x0008);/* DSI_STATUS */
+
+ if (status & 0x80000000) {
+ MIPI_OUTP(dsi_base + 0x0008, status);
+ pr_debug("%s: status=%x\n", __func__, status);
+ }
+}
+
+void mdss_dsi_error(unsigned char *dsi_base)
+{
+ /* DSI_ERR_INT_MASK0 */
+ mdss_dsi_ack_err_status(dsi_base); /* mask0, 0x01f */
+ mdss_dsi_timeout_status(dsi_base); /* mask0, 0x0e0 */
+ mdss_dsi_fifo_status(dsi_base); /* mask0, 0x133d00 */
+ mdss_dsi_status(dsi_base); /* mask0, 0xc0100 */
+ mdss_dsi_dln0_phy_err(dsi_base); /* mask0, 0x3e00000 */
+}
+
+
+irqreturn_t mdss_dsi_isr(int irq, void *ptr)
+{
+ u32 isr;
+ unsigned char *dsi_base;
+
+ dsi_base = mdss_dsi_get_base_adr();
+ if (!dsi_base)
+ pr_err("%s:%d DSI base adr no Initialized",
+ __func__, __LINE__);
+
+ isr = MIPI_INP(dsi_base + 0x0110);/* DSI_INTR_CTRL */
+ MIPI_OUTP(dsi_base + 0x0110, isr);
+
+ if (isr & DSI_INTR_ERROR)
+ mdss_dsi_error(dsi_base);
+
+ if (isr & DSI_INTR_VIDEO_DONE) {
+ /*
+ * do something here
+ */
+ }
+
+ if (isr & DSI_INTR_CMD_DMA_DONE)
+ complete(&dsi_dma_comp);
+
+ if (isr & DSI_INTR_CMD_MDP_DONE) {
+ spin_lock(&dsi_mdp_lock);
+ dsi_mdp_busy = false;
+ mdss_dsi_disable_irq_nosync();
+ spin_unlock(&dsi_mdp_lock);
+ }
+
+ return IRQ_HANDLED;
+}
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
new file mode 100644
index 0000000..bfb7fae
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -0,0 +1,358 @@
+/* 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 <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+#include "mdss_dsi.h"
+
+#define DT_CMD_HDR 6
+
+static struct dsi_buf dsi_panel_tx_buf;
+static struct dsi_buf dsi_panel_rx_buf;
+
+static struct dsi_cmd_desc *dsi_panel_on_cmds;
+static struct dsi_cmd_desc *dsi_panel_off_cmds;
+static int num_of_on_cmds;
+static int num_of_off_cmds;
+static char *on_cmds, *off_cmds;
+
+static int mdss_dsi_panel_on(struct mdss_panel_data *pdata)
+{
+ struct mipi_panel_info *mipi;
+
+ mipi = &pdata->panel_info.mipi;
+
+ pr_debug("%s:%d, debug info (mode) : %d\n", __func__, __LINE__,
+ mipi->mode);
+
+ if (mipi->mode == DSI_VIDEO_MODE) {
+ mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf, dsi_panel_on_cmds,
+ num_of_on_cmds);
+ } else {
+ pr_err("%s:%d, CMD MODE NOT SUPPORTED", __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int mdss_dsi_panel_off(struct mdss_panel_data *pdata)
+{
+ struct mipi_panel_info *mipi;
+
+ mipi = &pdata->panel_info.mipi;
+
+ pr_debug("%s:%d, debug info\n", __func__, __LINE__);
+
+ if (mipi->mode == DSI_VIDEO_MODE) {
+ mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf, dsi_panel_off_cmds,
+ num_of_off_cmds);
+ } else {
+ pr_debug("%s:%d, CMD mode not supported", __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int mdss_panel_parse_dt(struct platform_device *pdev,
+ struct mdss_panel_common_pdata *panel_data)
+{
+ struct device_node *np = pdev->dev.of_node;
+ u32 res[6], tmp;
+ int rc, i, len;
+ int cmd_plen, data_offset;
+ const char *data;
+
+ rc = of_property_read_u32_array(np, "qcom,mdss-pan-res", res, 2);
+ if (rc) {
+ pr_err("%s:%d, panel resolution not specified\n",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+ panel_data->panel_info.xres = (!rc ? res[0] : 640);
+ panel_data->panel_info.yres = (!rc ? res[1] : 480);
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-bpp", &tmp);
+ if (rc) {
+ pr_err("%s:%d, panel bpp not specified\n",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+ panel_data->panel_info.bpp = (!rc ? tmp : 24);
+
+ rc = of_property_read_u32_array(np,
+ "qcom,mdss-pan-porch-values", res, 6);
+ panel_data->panel_info.lcdc.h_back_porch = (!rc ? res[0] : 6);
+ panel_data->panel_info.lcdc.h_pulse_width = (!rc ? res[1] : 2);
+ panel_data->panel_info.lcdc.h_front_porch = (!rc ? res[2] : 6);
+ panel_data->panel_info.lcdc.v_back_porch = (!rc ? res[3] : 6);
+ panel_data->panel_info.lcdc.v_pulse_width = (!rc ? res[4] : 2);
+ panel_data->panel_info.lcdc.v_front_porch = (!rc ? res[5] : 6);
+
+ rc = of_property_read_u32(np,
+ "qcom,mdss-pan-underflow-clr", &tmp);
+ panel_data->panel_info.lcdc.underflow_clr = (!rc ? tmp : 0xff);
+
+ rc = of_property_read_u32_array(np,
+ "qcom,mdss-pan-bl-levels", res, 2);
+ panel_data->panel_info.bl_min = (!rc ? res[0] : 0);
+ panel_data->panel_info.bl_max = (!rc ? res[1] : 255);
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mode", &tmp);
+ panel_data->panel_info.mipi.mode = (!rc ? tmp : DSI_VIDEO_MODE);
+
+ rc = of_property_read_u32(np,
+ "qcom,mdss-pan-dsi-h-pulse-mode", &tmp);
+ panel_data->panel_info.mipi.pulse_mode_hsa_he = (!rc ? tmp : false);
+
+ rc = of_property_read_u32_array(np,
+ "qcom,mdss-pan-dsi-h-power-stop", res, 3);
+ panel_data->panel_info.mipi.hbp_power_stop = (!rc ? res[0] : false);
+ panel_data->panel_info.mipi.hsa_power_stop = (!rc ? res[1] : false);
+ panel_data->panel_info.mipi.hfp_power_stop = (!rc ? res[2] : false);
+
+ rc = of_property_read_u32_array(np,
+ "qcom,mdss-pan-dsi-bllp-power-stop", res, 2);
+ panel_data->panel_info.mipi.bllp_power_stop =
+ (!rc ? res[0] : false);
+ panel_data->panel_info.mipi.eof_bllp_power_stop =
+ (!rc ? res[1] : false);
+
+ rc = of_property_read_u32(np,
+ "qcom,mdss-pan-dsi-traffic-mode", &tmp);
+ panel_data->panel_info.mipi.traffic_mode =
+ (!rc ? tmp : DSI_NON_BURST_SYNCH_PULSE);
+
+ rc = of_property_read_u32(np,
+ "qcom,mdss-pan-dsi-dst-format", &tmp);
+ panel_data->panel_info.mipi.dst_format =
+ (!rc ? tmp : DSI_VIDEO_DST_FORMAT_RGB888);
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-vc", &tmp);
+ panel_data->panel_info.mipi.vc = (!rc ? tmp : 0);
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-rgb-swap", &tmp);
+ panel_data->panel_info.mipi.rgb_swap = (!rc ? tmp : DSI_RGB_SWAP_RGB);
+
+ rc = of_property_read_u32_array(np,
+ "qcom,mdss-pan-dsi-data-lanes", res, 4);
+ panel_data->panel_info.mipi.data_lane0 = (!rc ? res[0] : true);
+ panel_data->panel_info.mipi.data_lane1 = (!rc ? res[1] : false);
+ panel_data->panel_info.mipi.data_lane2 = (!rc ? res[2] : false);
+ panel_data->panel_info.mipi.data_lane3 = (!rc ? res[3] : false);
+
+ rc = of_property_read_u32_array(np, "qcom,mdss-pan-dsi-t-clk", res, 2);
+ panel_data->panel_info.mipi.t_clk_pre = (!rc ? res[0] : 0x24);
+ panel_data->panel_info.mipi.t_clk_post = (!rc ? res[1] : 0x03);
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-stream", &tmp);
+ panel_data->panel_info.mipi.stream = (!rc ? tmp : 0);
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mdp-tr", &tmp);
+ panel_data->panel_info.mipi.mdp_trigger =
+ (!rc ? tmp : DSI_CMD_TRIGGER_SW);
+ if (panel_data->panel_info.mipi.mdp_trigger > 6) {
+ pr_err("%s:%d, Invalid mdp trigger. Forcing to sw trigger",
+ __func__, __LINE__);
+ panel_data->panel_info.mipi.mdp_trigger =
+ DSI_CMD_TRIGGER_SW;
+ }
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-dma-tr", &tmp);
+ panel_data->panel_info.mipi.dma_trigger =
+ (!rc ? tmp : DSI_CMD_TRIGGER_SW);
+ if (panel_data->panel_info.mipi.dma_trigger > 6) {
+ pr_err("%s:%d, Invalid dma trigger. Forcing to sw trigger",
+ __func__, __LINE__);
+ panel_data->panel_info.mipi.dma_trigger =
+ DSI_CMD_TRIGGER_SW;
+ }
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-frame-rate", &tmp);
+ panel_data->panel_info.mipi.frame_rate = (!rc ? tmp : 60);
+
+ data = of_get_property(np, "qcom,panel-on-cmds", &len);
+ if (!data) {
+ pr_err("%s:%d, Unable to read ON cmds", __func__, __LINE__);
+ goto error;
+ }
+
+ on_cmds = kzalloc(sizeof(char) * len, GFP_KERNEL);
+ if (!on_cmds)
+ return -ENOMEM;
+
+ memcpy(on_cmds, data, len);
+
+ data_offset = 0;
+ cmd_plen = 0;
+ while ((len - data_offset) >= DT_CMD_HDR) {
+ data_offset += (DT_CMD_HDR - 1);
+ cmd_plen = on_cmds[data_offset++];
+ data_offset += cmd_plen;
+ num_of_on_cmds++;
+ }
+ if (!num_of_on_cmds) {
+ pr_err("%s:%d, No ON cmds specified", __func__, __LINE__);
+ goto error;
+ }
+
+ dsi_panel_on_cmds =
+ kzalloc((num_of_on_cmds * sizeof(struct dsi_cmd_desc)),
+ GFP_KERNEL);
+ if (!dsi_panel_on_cmds)
+ return -ENOMEM;
+
+ data_offset = 0;
+ for (i = 0; i < num_of_on_cmds; i++) {
+ dsi_panel_on_cmds[i].dtype = on_cmds[data_offset++];
+ dsi_panel_on_cmds[i].last = on_cmds[data_offset++];
+ dsi_panel_on_cmds[i].vc = on_cmds[data_offset++];
+ dsi_panel_on_cmds[i].ack = on_cmds[data_offset++];
+ dsi_panel_on_cmds[i].wait = on_cmds[data_offset++];
+ dsi_panel_on_cmds[i].dlen = on_cmds[data_offset++];
+ dsi_panel_on_cmds[i].payload = &on_cmds[data_offset];
+ data_offset += (dsi_panel_on_cmds[i].dlen);
+ }
+
+ if (data_offset != len) {
+ pr_err("%s:%d, Incorrect ON command entries",
+ __func__, __LINE__);
+ goto error;
+ }
+
+ data = of_get_property(np, "qcom,panel-off-cmds", &len);
+ if (!data) {
+ pr_err("%s:%d, Unable to read OFF cmds", __func__, __LINE__);
+ goto error;
+ }
+
+ off_cmds = kzalloc(sizeof(char) * len, GFP_KERNEL);
+ if (!off_cmds)
+ return -ENOMEM;
+
+ memcpy(off_cmds, data, len);
+
+ data_offset = 0;
+ cmd_plen = 0;
+ while ((len - data_offset) >= DT_CMD_HDR) {
+ data_offset += (DT_CMD_HDR - 1);
+ cmd_plen = off_cmds[data_offset++];
+ data_offset += cmd_plen;
+ num_of_off_cmds++;
+ }
+ if (!num_of_off_cmds) {
+ pr_err("%s:%d, No OFF cmds specified", __func__, __LINE__);
+ goto error;
+ }
+
+ dsi_panel_off_cmds = kzalloc(num_of_off_cmds
+ * sizeof(struct dsi_cmd_desc),
+ GFP_KERNEL);
+ if (!dsi_panel_off_cmds)
+ return -ENOMEM;
+
+ data_offset = 0;
+ for (i = 0; i < num_of_off_cmds; i++) {
+ dsi_panel_off_cmds[i].dtype = off_cmds[data_offset++];
+ dsi_panel_off_cmds[i].last = off_cmds[data_offset++];
+ dsi_panel_off_cmds[i].vc = off_cmds[data_offset++];
+ dsi_panel_off_cmds[i].ack = off_cmds[data_offset++];
+ dsi_panel_off_cmds[i].wait = off_cmds[data_offset++];
+ dsi_panel_off_cmds[i].dlen = off_cmds[data_offset++];
+ dsi_panel_off_cmds[i].payload = &off_cmds[data_offset];
+ data_offset += (dsi_panel_off_cmds[i].dlen);
+ }
+
+ if (data_offset != len) {
+ pr_err("%s:%d, Incorrect OFF command entries",
+ __func__, __LINE__);
+ goto error;
+ }
+
+ return 0;
+error:
+ kfree(dsi_panel_on_cmds);
+ kfree(dsi_panel_off_cmds);
+ kfree(on_cmds);
+ kfree(off_cmds);
+
+ return -EINVAL;
+}
+
+static int __devinit mdss_dsi_panel_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+ struct mdss_panel_common_pdata *vendor_pdata = NULL;
+ static const char *panel_name;
+
+ if (pdev->dev.parent == NULL) {
+ pr_err("%s: parent device missing\n", __func__);
+ return -ENODEV;
+ }
+
+ pr_debug("%s:%d, debug info id=%d", __func__, __LINE__, pdev->id);
+ if (!pdev->dev.of_node)
+ return -ENODEV;
+
+ panel_name = of_get_property(pdev->dev.of_node, "label", NULL);
+ if (!panel_name)
+ pr_info("%s:%d, panel name not specified\n",
+ __func__, __LINE__);
+ else
+ pr_info("%s: Panel Name = %s\n", __func__, panel_name);
+
+ vendor_pdata = devm_kzalloc(&pdev->dev,
+ sizeof(*vendor_pdata), GFP_KERNEL);
+ if (!vendor_pdata)
+ return -ENOMEM;
+
+ rc = mdss_panel_parse_dt(pdev, vendor_pdata);
+ if (rc) {
+ devm_kfree(&pdev->dev, vendor_pdata);
+ vendor_pdata = NULL;
+ return rc;
+ }
+ vendor_pdata->on = mdss_dsi_panel_on;
+ vendor_pdata->off = mdss_dsi_panel_off;
+
+ rc = dsi_panel_device_register(pdev, vendor_pdata);
+ if (rc)
+ return rc;
+
+ return 0;
+}
+
+static const struct of_device_id mdss_dsi_panel_match[] = {
+ {.compatible = "qcom,mdss-dsi-panel"},
+ {}
+};
+
+static struct platform_driver this_driver = {
+ .probe = mdss_dsi_panel_probe,
+ .driver = {
+ .name = "dsi_panel",
+ .of_match_table = mdss_dsi_panel_match,
+ },
+};
+
+static int __init mdss_dsi_panel_init(void)
+{
+ mdss_dsi_buf_alloc(&dsi_panel_tx_buf, DSI_BUF_SIZE);
+ mdss_dsi_buf_alloc(&dsi_panel_rx_buf, DSI_BUF_SIZE);
+
+ return platform_driver_register(&this_driver);
+}
+module_init(mdss_dsi_panel_init);
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index 4ca1dce..8825cc6 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -375,6 +375,7 @@
#define MDSS_MDP_REG_INTF_FRAME_LINE_COUNT_EN 0x0A8
#define MDSS_MDP_REG_INTF_FRAME_COUNT 0x0AC
#define MDSS_MDP_REG_INTF_LINE_COUNT 0x0B0
+#define MDSS_MDP_PANEL_FORMAT_RGB888 0x213F
enum mdss_mdp_pingpong_index {
MDSS_MDP_PINGPONG0,
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index 21ef290..2f0a1f5 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -135,6 +135,8 @@
p->hsync_skew);
MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_POLARITY_CTL,
polarity_ctl);
+ MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_PANEL_FORMAT,
+ MDSS_MDP_PANEL_FORMAT_RGB888);
return 0;
}
@@ -297,14 +299,14 @@
itp.underflow_clr = pinfo->lcdc.underflow_clr;
itp.hsync_skew = pinfo->lcdc.hsync_skew;
- itp.xres = fbi->var.xres;
- itp.yres = fbi->var.yres;
- itp.h_back_porch = fbi->var.left_margin;
- itp.h_front_porch = fbi->var.right_margin;
- itp.v_back_porch = fbi->var.upper_margin;
- itp.v_front_porch = fbi->var.lower_margin;
- itp.hsync_pulse_width = fbi->var.hsync_len;
- itp.vsync_pulse_width = fbi->var.vsync_len;
+ itp.xres = pinfo->xres;
+ itp.yres = pinfo->yres;
+ itp.h_back_porch = pinfo->lcdc.h_back_porch;
+ itp.h_front_porch = pinfo->lcdc.h_front_porch;
+ itp.v_back_porch = pinfo->lcdc.v_back_porch;
+ itp.v_front_porch = pinfo->lcdc.h_front_porch;
+ itp.hsync_pulse_width = pinfo->lcdc.h_pulse_width;
+ itp.vsync_pulse_width = pinfo->lcdc.v_pulse_width;
if (mdss_mdp_video_timegen_setup(ctl, &itp)) {
pr_err("unable to get timing parameters\n");
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index 0411d8e..3ec3a5d 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -167,6 +167,7 @@
struct mdss_panel_data {
struct mdss_panel_info panel_info;
void (*set_backlight) (u32 bl_level);
+ unsigned char *dsi_base;
/* function entry chain */
int (*on) (struct mdss_panel_data *pdata);
diff --git a/drivers/video/msm/mdss/msm_mdss_io_8974.c b/drivers/video/msm/mdss/msm_mdss_io_8974.c
new file mode 100644
index 0000000..c766ec7
--- /dev/null
+++ b/drivers/video/msm/mdss/msm_mdss_io_8974.c
@@ -0,0 +1,199 @@
+/* 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 <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <mach/clk.h>
+#include <mach/msm_iomap.h>
+
+#include "mdss_dsi.h"
+
+#define SW_RESET BIT(2)
+#define SW_RESET_PLL BIT(0)
+#define PWRDN_B BIT(7)
+
+static struct dsi_clk_desc dsi_pclk;
+
+static struct clk *dsi_byte_div_clk;
+static struct clk *dsi_esc_clk;
+
+int mdss_dsi_clk_on;
+
+int mdss_dsi_clk_init(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+
+ 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 mdss_dsi_clk_err;
+ }
+
+ dsi_esc_clk = clk_get(dev, "core_clk");
+ if (IS_ERR(dsi_esc_clk)) {
+ printk(KERN_ERR "can't find dsi_esc_clk\n");
+ dsi_esc_clk = NULL;
+ goto mdss_dsi_clk_err;
+ }
+
+ return 0;
+
+mdss_dsi_clk_err:
+ mdss_dsi_clk_deinit(dev);
+ return -EPERM;
+}
+
+void mdss_dsi_clk_deinit(struct device *dev)
+{
+ if (dsi_byte_div_clk)
+ clk_put(dsi_byte_div_clk);
+ if (dsi_esc_clk)
+ clk_put(dsi_esc_clk);
+}
+
+#define PREF_DIV_RATIO 27
+struct dsiphy_pll_divider_config pll_divider_config;
+
+int mdss_dsi_clk_div_config(u8 bpp, u8 lanes,
+ u32 *expected_dsi_pclk)
+{
+ u32 fb_divider, rate, vco;
+ u32 div_ratio = 0;
+ u32 pll_analog_posDiv = 1;
+ 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 / 2)
+ / 1000000; /* Half Bit Clock In Mhz */
+
+ if (rate < 43) {
+ vco = rate * 16;
+ div_ratio = 16;
+ pll_analog_posDiv = 8;
+ } else if (rate < 85) {
+ vco = rate * 8;
+ div_ratio = 8;
+ pll_analog_posDiv = 4;
+ } else if (rate < 170) {
+ vco = rate * 4;
+ div_ratio = 4;
+ pll_analog_posDiv = 2;
+ } else if (rate < 340) {
+ vco = rate * 2;
+ div_ratio = 2;
+ pll_analog_posDiv = 1;
+ } else {
+ /* DSI PLL Direct path configuration */
+ vco = rate * 1;
+ div_ratio = 1;
+ pll_analog_posDiv = 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.analog_posDiv = pll_analog_posDiv;
+ pll_divider_config.digital_posDiv =
+ (mnd_entry->pll_digital_posDiv) * div_ratio;
+
+ 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);
+ } 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 = (((pll_divider_config.clk_rate) * lanes)
+ / (8 * bpp));
+
+ return 0;
+}
+
+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 mdss_dsi_prepare_clocks(void)
+{
+ clk_prepare(dsi_byte_div_clk);
+ clk_prepare(dsi_esc_clk);
+}
+
+void mdss_dsi_unprepare_clocks(void)
+{
+ clk_unprepare(dsi_esc_clk);
+ clk_unprepare(dsi_byte_div_clk);
+}
+
+void mdss_dsi_clk_enable(void)
+{
+ if (mdss_dsi_clk_on) {
+ pr_info("%s: mdss_dsi_clks already ON\n", __func__);
+ return;
+ }
+
+ if (clk_set_rate(dsi_byte_div_clk, 1) < 0) /* divided by 1 */
+ pr_err("%s: dsi_byte_div_clk - clk_set_rate failed\n",
+ __func__);
+ if (clk_set_rate(dsi_esc_clk, 2) < 0) /* divided by 2 */
+ pr_err("%s: dsi_esc_clk - clk_set_rate failed\n",
+ __func__);
+ clk_enable(dsi_byte_div_clk);
+ clk_enable(dsi_esc_clk);
+ mdss_dsi_clk_on = 1;
+}
+
+void mdss_dsi_clk_disable(void)
+{
+ if (mdss_dsi_clk_on == 0) {
+ pr_info("%s: mdss_dsi_clks already OFF\n", __func__);
+ return;
+ }
+ clk_disable(dsi_esc_clk);
+ clk_disable(dsi_byte_div_clk);
+ mdss_dsi_clk_on = 0;
+}
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index b6f4874..a984637 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -1438,10 +1438,22 @@
/* cursor memory allocation */
if (mfd->cursor_update) {
+ unsigned long cursor_buf_iommu = 0;
mfd->cursor_buf = dma_alloc_coherent(NULL,
MDP_CURSOR_SIZE,
(dma_addr_t *) &mfd->cursor_buf_phys,
GFP_KERNEL);
+
+ msm_iommu_map_contig_buffer((unsigned long)mfd->cursor_buf_phys,
+ DISPLAY_READ_DOMAIN,
+ GEN_POOL,
+ MDP_CURSOR_SIZE,
+ SZ_4K,
+ 0,
+ &cursor_buf_iommu);
+ if (cursor_buf_iommu)
+ mfd->cursor_buf_phys = (void *)cursor_buf_iommu;
+
if (!mfd->cursor_buf)
mfd->cursor_update = 0;
}
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index fbffdd2..7769950 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -24,6 +24,7 @@
#define MEMORY_DEVICE_MODE 2
#define NO_LOGGING_MODE 3
#define UART_MODE 4
+#define SOCKET_MODE 5
/* different values that go in for diag_data_type */
#define DATA_TYPE_EVENT 0
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 32d8ec2..cb56293 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -210,6 +210,7 @@
int use_for_apm;
};
+#if defined(CONFIG_POWER_SUPPLY) || defined(CONFIG_POWER_SUPPLY_MODULE)
extern struct power_supply *power_supply_get_by_name(char *name);
extern void power_supply_changed(struct power_supply *psy);
extern int power_supply_am_i_supplied(struct power_supply *psy);
@@ -218,10 +219,31 @@
extern int power_supply_set_online(struct power_supply *psy, bool enable);
extern int power_supply_set_scope(struct power_supply *psy, int scope);
extern int power_supply_set_charge_type(struct power_supply *psy, int type);
-
-#if defined(CONFIG_POWER_SUPPLY) || defined(CONFIG_POWER_SUPPLY_MODULE)
+extern int power_supply_set_supply_type(struct power_supply *psy,
+ enum power_supply_type supply_type);
extern int power_supply_is_system_supplied(void);
#else
+static inline struct power_supply *power_supply_get_by_name(char *name)
+ { return -ENOSYS; }
+static inline int power_supply_am_i_supplied(struct power_supply *psy)
+ { return -ENOSYS; }
+static inline int power_supply_set_battery_charged(struct power_supply *psy)
+ { return -ENOSYS; }
+static inline int power_supply_set_current_limit(struct power_supply *psy,
+ int limit)
+ { return -ENOSYS; }
+static inline int power_supply_set_online(struct power_supply *psy,
+ bool enable)
+ { return -ENOSYS; }
+static inline int power_supply_set_scope(struct power_supply *psy,
+ int scope)
+ { return -ENOSYS; }
+static inline int power_supply_set_charge_type(struct power_supply *psy,
+ int type)
+ { return -ENOSYS; }
+static inline int power_supply_set_supply_type(struct power_supply *psy,
+ enum power_supply_type supply_type);
+ { return -ENOSYS; }
static inline int power_supply_is_system_supplied(void) { return -ENOSYS; }
#endif
diff --git a/include/trace/events/irq.h b/include/trace/events/irq.h
index 1c09820..0296174 100644
--- a/include/trace/events/irq.h
+++ b/include/trace/events/irq.h
@@ -43,14 +43,17 @@
TP_STRUCT__entry(
__field( int, irq )
__string( name, action->name )
+ __field(void*, handler)
),
TP_fast_assign(
__entry->irq = irq;
__assign_str(name, action->name);
+ __entry->handler = action->handler;
),
- TP_printk("irq=%d name=%s", __entry->irq, __get_str(name))
+ TP_printk("irq=%d name=%s handler=%pf",
+ __entry->irq, __get_str(name), __entry->handler)
);
/**
diff --git a/include/trace/events/timer.h b/include/trace/events/timer.h
index 425bcfe..dd53c79 100644
--- a/include/trace/events/timer.h
+++ b/include/trace/events/timer.h
@@ -43,15 +43,17 @@
*/
TRACE_EVENT(timer_start,
- TP_PROTO(struct timer_list *timer, unsigned long expires),
+ TP_PROTO(struct timer_list *timer,
+ unsigned long expires, char deferrable),
- TP_ARGS(timer, expires),
+ TP_ARGS(timer, expires, deferrable),
TP_STRUCT__entry(
__field( void *, timer )
__field( void *, function )
__field( unsigned long, expires )
__field( unsigned long, now )
+ __field(char, deferrable)
),
TP_fast_assign(
@@ -59,11 +61,12 @@
__entry->function = timer->function;
__entry->expires = expires;
__entry->now = jiffies;
+ __entry->deferrable = deferrable;
),
- TP_printk("timer=%p function=%pf expires=%lu [timeout=%ld]",
+ TP_printk("timer=%p function=%pf expires=%lu [timeout=%ld] defer=%c",
__entry->timer, __entry->function, __entry->expires,
- (long)__entry->expires - __entry->now)
+ (long)__entry->expires - __entry->now, __entry->deferrable)
);
/**
diff --git a/kernel/timer.c b/kernel/timer.c
index a297ffc..24c5d20 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -584,7 +584,8 @@
debug_activate(struct timer_list *timer, unsigned long expires)
{
debug_timer_activate(timer);
- trace_timer_start(timer, expires);
+ trace_timer_start(timer, expires,
+ tbase_get_deferrable(timer->base) > 0 ? 'y' : 'n');
}
static inline void debug_deactivate(struct timer_list *timer)
diff --git a/sound/soc/msm/msm-pcm-afe.c b/sound/soc/msm/msm-pcm-afe.c
index 5f3cada..b7b4d51 100644
--- a/sound/soc/msm/msm-pcm-afe.c
+++ b/sound/soc/msm/msm-pcm-afe.c
@@ -140,9 +140,6 @@
runtime->channels * 2)));
pr_debug("prtd->poll_time: %d",
prtd->poll_time);
- hrtimer_start(&prtd->hrt,
- ns_to_ktime(0),
- HRTIMER_MODE_REL);
break;
}
case AFE_EVENT_RTPORT_STOP:
@@ -206,9 +203,6 @@
snd_pcm_lib_period_bytes(prtd->substream)
* 1000 * 1000)/(runtime->rate
* runtime->channels * 2)));
- hrtimer_start(&prtd->hrt,
- ns_to_ktime(0),
- HRTIMER_MODE_REL);
pr_debug("prtd->poll_time : %d", prtd->poll_time);
break;
}
@@ -465,6 +459,8 @@
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
pr_debug("%s: SNDRV_PCM_TRIGGER_START\n", __func__);
prtd->start = 1;
+ hrtimer_start(&prtd->hrt, ns_to_ktime(0),
+ HRTIMER_MODE_REL);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index 4c0ac9e..a4f4b60 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.c
@@ -448,7 +448,7 @@
if ((port_id == RT_PROXY_DAI_001_RX) ||
(port_id == RT_PROXY_DAI_002_TX))
- return -EINVAL;
+ return 0;
if ((port_id == RT_PROXY_DAI_002_RX) ||
(port_id == RT_PROXY_DAI_001_TX))
port_id = VIRTUAL_ID_TO_PORTID(port_id);
@@ -608,7 +608,7 @@
if ((port_id == RT_PROXY_DAI_001_RX) ||
(port_id == RT_PROXY_DAI_002_TX))
- return -EINVAL;
+ return 0;
if ((port_id == RT_PROXY_DAI_002_RX) ||
(port_id == RT_PROXY_DAI_001_TX))
port_id = VIRTUAL_ID_TO_PORTID(port_id);
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index 99fd1d3..485569b 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -40,7 +40,11 @@
union afe_port_config port_config;
};
-static struct clk *pcm_clk;
+static struct clk *pcm_src_clk;
+static struct clk *pcm_branch_clk;
+static struct clk *pcm_oe_src_clk;
+static struct clk *pcm_oe_branch_clk;
+
static DEFINE_MUTEX(aux_pcm_mutex);
static int aux_pcm_count;
@@ -120,6 +124,9 @@
if (IS_ERR_VALUE(rc))
dev_err(dai->dev, "fail to close AUX PCM TX port\n");
+ clk_disable_unprepare(pcm_branch_clk);
+ clk_disable_unprepare(pcm_oe_branch_clk);
+
mutex_unlock(&aux_pcm_mutex);
}
@@ -127,8 +134,11 @@
struct snd_soc_dai *dai)
{
struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
+ struct msm_dai_auxpcm_pdata *auxpcm_pdata = NULL;
int rc = 0;
+ auxpcm_pdata = dai->dev->platform_data;
+
mutex_lock(&aux_pcm_mutex);
if (aux_pcm_count == 2) {
@@ -170,12 +180,37 @@
* assert/deasset and afe_open sequence is not followed.
*/
+ rc = clk_set_rate(pcm_src_clk, auxpcm_pdata->pcm_clk_rate);
+ if (rc < 0) {
+ pr_err("%s: clk_set_rate failed\n", __func__);
+ goto fail;
+ }
+
+ rc = clk_prepare_enable(pcm_branch_clk);
+ if (rc) {
+ pr_err("%s: clk enable failed\n", __func__);
+ goto fail;
+ }
+
+ rc = clk_set_rate(pcm_oe_src_clk, 24576000>>1);
+ if (rc < 0) {
+ pr_err("%s: clk_set_rate on pcm oe failed\n", __func__);
+ goto fail;
+ }
+
+ rc = clk_prepare_enable(pcm_oe_branch_clk);
+ if (rc) {
+ pr_err("%s: clk enable pcm_oe_branch_clk failed\n", __func__);
+ goto fail;
+ }
+
afe_open(PCM_RX, &dai_data->port_config, dai_data->rate);
afe_open(PCM_TX, &dai_data->port_config, dai_data->rate);
mutex_unlock(&aux_pcm_mutex);
+fail:
return rc;
}
@@ -217,6 +252,7 @@
auxpcm_pdata = (struct msm_dai_auxpcm_pdata *)
dev_get_drvdata(dai->dev);
dai->dev->platform_data = auxpcm_pdata;
+ dai->id = dai->dev->id;
mutex_lock(&aux_pcm_mutex);
@@ -225,9 +261,41 @@
* data to the cpu driver, since cpu drive is unaware of any
* boarc specific configuration.
*/
- if (!pcm_clk)
- pcm_clk = clk_get(dai->dev, auxpcm_pdata->clk);
+ if ((!pcm_src_clk) || (!pcm_branch_clk)) {
+ pcm_src_clk = clk_get(dai->dev, auxpcm_pdata->clk);
+ if (IS_ERR(pcm_src_clk)) {
+ pr_err("%s: could not get pcm_src_clk\n", __func__);
+ pcm_src_clk = NULL;
+ return -ENODEV;
+ }
+
+ pcm_branch_clk = clk_get(dai->dev, "ibit_clk");
+
+ if (IS_ERR(pcm_branch_clk)) {
+ pr_err("%s: could not get pcm_branch_clk\n", __func__);
+ pcm_branch_clk = NULL;
+ return -ENODEV;
+ }
+ }
+
+ if ((!pcm_oe_src_clk) || (!pcm_oe_branch_clk)) {
+
+ pcm_oe_src_clk = clk_get(dai->dev, "core_oe_src_clk");
+
+ if (IS_ERR(pcm_oe_src_clk)) {
+ pr_err("%s: could not get pcm_oe_src_clk\n", __func__);
+ pcm_oe_src_clk = NULL;
+ return -ENODEV;
+ }
+
+ pcm_oe_branch_clk = clk_get(dai->dev, "core_oe_clk");
+ if (IS_ERR(pcm_oe_branch_clk)) {
+ pr_err("%s: could not get pcm_oe_clk\n", __func__);
+ pcm_oe_branch_clk = NULL;
+ return -ENODEV;
+ }
+ }
mutex_unlock(&aux_pcm_mutex);
dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data), GFP_KERNEL);
@@ -813,7 +881,7 @@
.remove = msm_dai_q6_dai_remove,
};
-static int msm_auxpcm_dev_probe(struct platform_device *pdev)
+static int __devinit msm_auxpcm_dev_probe(struct platform_device *pdev)
{
int id;
void *plat_data;
@@ -837,6 +905,7 @@
dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
dev_set_drvdata(&pdev->dev, plat_data);
+ pdev->dev.id = id;
switch (id) {
case AFE_PORT_ID_PRIMARY_PCM_RX:
@@ -855,7 +924,7 @@
return rc;
}
-static int msm_auxpcm_resource_probe(
+static int __devinit msm_auxpcm_resource_probe(
struct platform_device *pdev)
{
int rc = 0;
@@ -950,13 +1019,13 @@
return rc;
}
-static int msm_auxpcm_dev_remove(struct platform_device *pdev)
+static int __devexit msm_auxpcm_dev_remove(struct platform_device *pdev)
{
snd_soc_unregister_dai(&pdev->dev);
return 0;
}
-static int msm_auxpcm_resource_remove(
+static int __devexit msm_auxpcm_resource_remove(
struct platform_device *pdev)
{
void *auxpcm_pdata;
@@ -967,22 +1036,20 @@
return 0;
}
-static const struct of_device_id msm_auxpcm_resource_dt_match[] = {
+static struct of_device_id msm_auxpcm_resource_dt_match[] = {
{ .compatible = "qcom,msm-auxpcm-resource", },
{}
};
-MODULE_DEVICE_TABLE(of, msm_auxpcm_resource_dt_match);
-static const struct of_device_id msm_auxpcm_dev_dt_match[] = {
+static struct of_device_id msm_auxpcm_dev_dt_match[] = {
{ .compatible = "qcom,msm-auxpcm-dev", },
{}
};
-MODULE_DEVICE_TABLE(of, msm_auxpcm_dev_dt_match);
-static struct platform_driver msm_auxpcm_dev = {
+static struct platform_driver msm_auxpcm_dev_driver = {
.probe = msm_auxpcm_dev_probe,
- .remove = msm_auxpcm_dev_remove,
+ .remove = __devexit_p(msm_auxpcm_dev_remove),
.driver = {
.name = "msm-auxpcm-dev",
.owner = THIS_MODULE,
@@ -990,9 +1057,9 @@
},
};
-static struct platform_driver msm_auxpcm_resource = {
+static struct platform_driver msm_auxpcm_resource_driver = {
.probe = msm_auxpcm_resource_probe,
- .remove = msm_auxpcm_resource_remove,
+ .remove = __devexit_p(msm_auxpcm_resource_remove),
.driver = {
.name = "msm-auxpcm-resource",
.owner = THIS_MODULE,
@@ -1134,22 +1201,23 @@
{
int rc;
- rc = platform_driver_register(&msm_auxpcm_dev);
+ rc = platform_driver_register(&msm_auxpcm_dev_driver);
if (rc)
goto fail;
- rc = platform_driver_register(&msm_auxpcm_resource);
+ rc = platform_driver_register(&msm_auxpcm_resource_driver);
+
if (rc) {
pr_err("%s: fail to register cpu dai driver\n", __func__);
- platform_driver_unregister(&msm_auxpcm_dev);
+ platform_driver_unregister(&msm_auxpcm_dev_driver);
goto fail;
}
rc = platform_driver_register(&msm_dai_q6);
if (rc) {
pr_err("%s: fail to register dai q6 driver", __func__);
- platform_driver_unregister(&msm_auxpcm_dev);
- platform_driver_unregister(&msm_auxpcm_resource);
+ platform_driver_unregister(&msm_auxpcm_dev_driver);
+ platform_driver_unregister(&msm_auxpcm_resource_driver);
goto fail;
}
@@ -1157,8 +1225,8 @@
if (rc) {
pr_err("%s: fail to register dai q6 dev driver", __func__);
platform_driver_unregister(&msm_dai_q6);
- platform_driver_unregister(&msm_auxpcm_dev);
- platform_driver_unregister(&msm_auxpcm_resource);
+ platform_driver_unregister(&msm_auxpcm_dev_driver);
+ platform_driver_unregister(&msm_auxpcm_resource_driver);
goto fail;
}
fail:
@@ -1170,8 +1238,8 @@
{
platform_driver_unregister(&msm_dai_q6_dev);
platform_driver_unregister(&msm_dai_q6);
- platform_driver_unregister(&msm_auxpcm_dev);
- platform_driver_unregister(&msm_auxpcm_resource);
+ platform_driver_unregister(&msm_auxpcm_dev_driver);
+ platform_driver_unregister(&msm_auxpcm_resource_driver);
}
module_exit(msm_dai_q6_exit);