summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChandan Uddaraju <chandanu@codeaurora.org>2013-01-25 11:30:25 -0800
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:14:25 -0700
commit1f567fcce93e81707484cc7681748555475c5a24 (patch)
tree5259f7364c9d1acf70da6e55d3569aac4353ba41
parent9704b38c1eff266ad4f471bfb0e078d94e619a28 (diff)
msm: mdss: Add driver changes to support multiple DSI controllers
Add support for second controller interrupts. Remove panel commands as global varibles. Add reference to framebuffer that the interface will use. Add support to send commands in broadcast mode. Add support to check for controller state when panel ON/OFF commands are sent. Use panel destination variable to select the DSI interface for the panel. Change-Id: If1a353b0d3d5e329ec9e41333db16a055bde96a7 Signed-off-by: Chandan Uddaraju <chandanu@codeaurora.org>
-rw-r--r--Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt7
-rw-r--r--Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt18
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.c82
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.h18
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_host.c202
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_panel.c144
-rw-r--r--drivers/video/fbdev/msm/msm_mdss_io_8974.c13
7 files changed, 388 insertions, 96 deletions
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
index 0f758f1c3204..7d19c03b005f 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
@@ -12,9 +12,14 @@ Required properties:
- vreg-supply: Phandle for vreg regulator device node.
- qcom,mdss-fb-map: pHandle that specifies the framebuffer to which the
interface is mapped.
+
+Optional properties:
+- label: A string used to describe the controller used.
+
Example:
- mdss_dsi: qcom,mdss_dsi@fd922800 {
+ mdss_dsi0: qcom,mdss_dsi@fd922800 {
compatible = "qcom,mdss-dsi-ctrl";
+ label = "MDSS DSI CTRL->0";
cell-index = <0>;
reg = <0xfd922800 0x600>;
vdd-supply = <&pm8941_l22>;
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index f12127158450..94746b8dea12 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -55,6 +55,7 @@ Optional properties:
- label: A string used as a descriptive name of the panel
- qcom,enable-gpio: Specifies the panel lcd/display enable gpio.
- qcom,rst-gpio: Specifies the panel reset gpio.
+- qcom,mdss-pan-broadcast-mode: Boolean used to enable broadcast mode.
- 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.
@@ -103,6 +104,15 @@ Optional properties:
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-dlane-swap: Specifies the data lane swap configuration.
+ 0 = <0 1 2 3> (default value)
+ 1 = <3 0 1 2>
+ 2 = <2 3 0 1>
+ 3 = <1 2 3 0>
+ 4 = <0 3 2 1>
+ 5 = <1 0 3 2>
+ 6 = <2 1 0 3>
+ 7 = <3 2 1 0>
- 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.
@@ -121,6 +131,10 @@ Optional properties:
6 = Software trigger and TE
- qcom,mdss-pan-dsi-frame-rate: Specifies the frame rate for the panel.
60 = 60 frames per second (default)
+- qcom,on-cmds-dsi-state: A string that Specifies the ctrl state for sending ON commands.
+ Supported modes are "DSI_LP_MODE" and "DSI_HS_MODE".
+- qcom,off-cmds-dsi-state: A string that Specifies the ctrl state for sending ON commands.
+ Supported modes are "DSI_LP_MODE" and "DSI_HS_MODE".
Note, if a given optional qcom,* binding is not present, then the driver will configure
the default values specified.
@@ -131,7 +145,7 @@ Example:
compatible = "qcom,mdss-dsi-panel";
label = "simulator video mode dsi panel";
status = "disable";
- qcom,dsi-ctrl-phandle = <&mdss_dsi>;
+ qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
qcom,mdss-pan-res = <640 480>;
qcom,mdss-pan-bpp = <24>;
qcom,mdss-pan-dest = "display_1";
@@ -153,6 +167,8 @@ Example:
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,on-cmds-dsi-state = "DSI_LP_MODE";
qcom,panel-off-cmds = [22 01 00 00 00 00 00];
+ qcom,off-cmds-dsi-state = "DSI LP MODE";
};
};
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c
index 4f806463f70c..5bd70947fa97 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -356,32 +356,84 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
int event, void *arg)
{
int rc = 0;
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
- pr_debug("%s: event=%d\n", __func__, event);
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return -EINVAL;
+ }
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
switch (event) {
case MDSS_EVENT_UNBLANK:
- rc = mdss_dsi_on(pdata);
+ if (ctrl_pdata->on_cmds->ctrl_state == DSI_LP_MODE) {
+ rc = mdss_dsi_on(pdata);
+ } else {
+ pr_debug("%s:event=%d, Dsi On not called: ctrl_state: %d\n",
+ __func__, event,
+ ctrl_pdata->on_cmds->ctrl_state);
+ rc = -EINVAL;
+ }
break;
case MDSS_EVENT_BLANK:
- rc = mdss_dsi_ctrl_unprepare(pdata);
+ if (ctrl_pdata->off_cmds->ctrl_state == DSI_HS_MODE) {
+ rc = mdss_dsi_ctrl_unprepare(pdata);
+ } else {
+ pr_debug("%s:event=%d,Unprepare not called.Ctrl_state: %d\n",
+ __func__, event,
+ ctrl_pdata->on_cmds->ctrl_state);
+ rc = -EINVAL;
+ }
break;
case MDSS_EVENT_TIMEGEN_OFF:
+ if (ctrl_pdata->off_cmds->ctrl_state == DSI_LP_MODE) {
+ pr_debug("%s:event=%d, calling unprepare: ctrl_state: %d\n",
+ __func__, event,
+ ctrl_pdata->on_cmds->ctrl_state);
+ rc = mdss_dsi_ctrl_unprepare(pdata);
+ }
rc = mdss_dsi_off(pdata);
break;
+ default:
+ pr_debug("%s: unhandled event=%d\n", __func__, event);
+ break;
}
return rc;
}
-static int mdss_dsi_resource_initialized;
-
static int mdss_dsi_ctrl_probe(struct platform_device *pdev)
{
int rc = 0;
+ u32 index;
+
pr_debug("%s\n", __func__);
- if (pdev->dev.of_node && !mdss_dsi_resource_initialized) {
+ if (pdev->dev.of_node) {
struct resource *mdss_dsi_mres;
- pdev->id = 1;
+ const char *ctrl_name;
+
+ ctrl_name = of_get_property(pdev->dev.of_node, "label", NULL);
+ if (!ctrl_name)
+ pr_info("%s:%d, DSI Ctrl name not specified\n",
+ __func__, __LINE__);
+ else
+ pr_info("%s: DSI Ctrl name = %s\n",
+ __func__, ctrl_name);
+
+ rc = of_property_read_u32(pdev->dev.of_node,
+ "cell-index", &index);
+ if (rc) {
+ dev_err(&pdev->dev,
+ "%s: Cell-index not specified, rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ if (index == 0)
+ pdev->id = 1;
+ else
+ pdev->id = 2;
+
mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mdss_dsi_mres) {
pr_err("%s:%d unable to get the MDSS resources",
@@ -398,8 +450,6 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev)
}
}
-
-
rc = of_platform_populate(pdev->dev.of_node,
NULL, NULL, &pdev->dev);
if (rc) {
@@ -410,12 +460,9 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev)
return rc;
}
- mdss_dsi_resource_initialized = 1;
+ pr_debug("%s: Dsi Ctrl->%d initialized\n", __func__, index);
}
- if (!mdss_dsi_resource_initialized)
- return -EPERM;
-
return 0;
}
@@ -494,6 +541,7 @@ int dsi_panel_device_register(struct platform_device *pdev,
struct device_node *dsi_ctrl_np = NULL;
struct platform_device *ctrl_pdev = NULL;
unsigned char *ctrl_addr;
+ bool broadcast;
h_period = ((panel_data->panel_info.lcdc.h_pulse_width)
+ (panel_data->panel_info.lcdc.h_back_porch)
@@ -583,6 +631,11 @@ int dsi_panel_device_register(struct platform_device *pdev,
return rc;
}
+ broadcast = of_property_read_bool(pdev->dev.of_node,
+ "qcom,mdss-pan-broadcast-mode");
+ if (broadcast)
+ ctrl_pdata->shared_pdata.broadcast_enable = 1;
+
ctrl_pdata->disp_en_gpio = of_get_named_gpio(pdev->dev.of_node,
"qcom,enable-gpio", 0);
if (!gpio_is_valid(ctrl_pdata->disp_en_gpio)) {
@@ -638,6 +691,9 @@ int dsi_panel_device_register(struct platform_device *pdev,
pr_debug("%s: ctrl base address: 0x%x\n", __func__, (int)ctrl_addr);
ctrl_pdata->panel_data.event_handler = mdss_dsi_event_handler;
+ ctrl_pdata->on_cmds = panel_data->dsi_panel_on_cmds;
+ ctrl_pdata->off_cmds = panel_data->dsi_panel_off_cmds;
+
memcpy(&((ctrl_pdata->panel_data).panel_info),
&(panel_data->panel_info),
sizeof(struct mdss_panel_info));
diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h
index 60a9506fd1b9..06c2952686c1 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.h
+++ b/drivers/video/fbdev/msm/mdss_dsi.h
@@ -83,6 +83,11 @@ enum dsi_panel_bl_ctrl {
UNKNOWN_CTRL,
};
+enum dsi_ctrl_state {
+ DSI_LP_MODE,
+ DSI_HS_MODE,
+};
+
#define DSI_NON_BURST_SYNCH_PULSE 0
#define DSI_NON_BURST_SYNCH_EVENT 1
#define DSI_BURST_MODE 2
@@ -244,17 +249,26 @@ struct dsi_kickoff_action {
void *data;
};
+struct dsi_panel_cmds_list {
+ struct dsi_cmd_desc *buf;
+ char size;
+ char ctrl_state;
+};
+
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);
void (*bl_fnc) (struct mdss_panel_data *pdata, u32 bl_level);
+ struct dsi_panel_cmds_list *dsi_panel_on_cmds;
+ struct dsi_panel_cmds_list *dsi_panel_off_cmds;
};
struct dsi_drv_cm_data {
struct regulator *vdd_vreg;
struct regulator *vdd_io_vreg;
struct regulator *dsi_vreg;
+ int broadcast_enable;
};
struct mdss_dsi_ctrl_pdata {
@@ -269,6 +283,8 @@ struct mdss_dsi_ctrl_pdata {
int mdss_dsi_clk_on;
int rst_gpio;
int disp_en_gpio;
+ struct dsi_panel_cmds_list *on_cmds;
+ struct dsi_panel_cmds_list *off_cmds;
struct dsi_drv_cm_data shared_pdata;
};
@@ -299,7 +315,7 @@ 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_mdp_start(struct mdss_panel_data *pdata);
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(struct mdss_panel_data *pdata);
diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c
index a8fcffe5163b..6f7023c745df 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_host.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_host.c
@@ -1,5 +1,4 @@
-
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -31,13 +30,20 @@ static int dsi_irq_enabled;
static spinlock_t dsi_irq_lock;
static spinlock_t dsi_mdp_lock;
static int dsi_mdp_busy;
+static struct mdss_dsi_ctrl_pdata *left_ctrl_pdata;
-struct mdss_hw mdss_dsi_hw = {
+struct mdss_hw mdss_dsi0_hw = {
.hw_ndx = MDSS_HW_DSI0,
.ptr = NULL,
.irq_handler = mdss_dsi_isr,
};
+struct mdss_hw mdss_dsi1_hw = {
+ .hw_ndx = MDSS_HW_DSI1,
+ .ptr = NULL,
+ .irq_handler = mdss_dsi_isr,
+};
+
void mdss_dsi_init(void)
{
init_completion(&dsi_dma_comp);
@@ -47,12 +53,24 @@ void mdss_dsi_init(void)
void mdss_dsi_irq_handler_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
- mdss_dsi_hw.ptr = (void *)(ctrl_pdata);
+ if (ctrl_pdata->panel_data.panel_info.pdest == DISPLAY_1)
+ mdss_dsi0_hw.ptr = (void *)(ctrl_pdata);
+ else
+ mdss_dsi1_hw.ptr = (void *)(ctrl_pdata);
}
-void mdss_dsi_enable_irq(void)
+void mdss_dsi_enable_irq(struct mdss_panel_data *pdata)
{
unsigned long flags;
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return;
+ }
+
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
spin_lock_irqsave(&dsi_irq_lock, flags);
if (dsi_irq_enabled) {
@@ -61,15 +79,28 @@ void mdss_dsi_enable_irq(void)
return;
}
- mdss_enable_irq(&mdss_dsi_hw);
+ if ((ctrl_pdata->panel_data).panel_info.pdest == DISPLAY_1)
+ mdss_enable_irq(&mdss_dsi0_hw);
+ else
+ mdss_enable_irq(&mdss_dsi1_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)
+void mdss_dsi_disable_irq(struct mdss_panel_data *pdata)
{
unsigned long flags;
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return;
+ }
+
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
spin_lock_irqsave(&dsi_irq_lock, flags);
if (dsi_irq_enabled == 0) {
@@ -77,7 +108,11 @@ void mdss_dsi_disable_irq(void)
spin_unlock_irqrestore(&dsi_irq_lock, flags);
return;
}
- mdss_disable_irq(&mdss_dsi_hw);
+ if (ctrl_pdata->panel_data.panel_info.pdest == DISPLAY_1)
+ mdss_disable_irq(&mdss_dsi0_hw);
+ else
+ mdss_disable_irq(&mdss_dsi1_hw);
+
dsi_irq_enabled = 0;
/* TO DO: Check whether MDSS IRQ is Disabled */
spin_unlock_irqrestore(&dsi_irq_lock, flags);
@@ -661,13 +696,14 @@ void mdss_dsi_host_init(struct mipi_panel_info *pinfo,
u32 data;
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
- ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
- panel_data);
- if (!ctrl_pdata) {
+ if (pdata == NULL) {
pr_err("%s: Invalid input data\n", __func__);
return;
}
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
+
pinfo->rgb_swap = DSI_RGB_SWAP_RGB;
if (pinfo->mode == DSI_VIDEO_MODE) {
@@ -740,7 +776,17 @@ void mdss_dsi_host_init(struct mipi_panel_info *pinfo,
/* from frame buffer, low power mode */
/* DSI_COMMAND_MODE_DMA_CTRL */
- MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x3C, 0x14000000);
+ if (ctrl_pdata->shared_pdata.broadcast_enable)
+ MIPI_OUTP(ctrl_pdata->ctrl_base + 0x3C, 0x94000000);
+ else
+ MIPI_OUTP(ctrl_pdata->ctrl_base + 0x3C, 0x14000000);
+
+ if (ctrl_pdata->shared_pdata.broadcast_enable)
+ if (pdata->panel_info.pdest == DISPLAY_1) {
+ pr_debug("%s: Broadcast mode enabled.\n",
+ __func__);
+ left_ctrl_pdata = ctrl_pdata;
+ }
data = 0;
if (pinfo->te_sel)
@@ -793,13 +839,14 @@ void mipi_set_tx_power_mode(int mode, struct mdss_panel_data *pdata)
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
u32 data;
- ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
- panel_data);
- if (!ctrl_pdata) {
+ if (pdata == NULL) {
pr_err("%s: Invalid input data\n", __func__);
return;
}
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
+
data = MIPI_INP((ctrl_pdata->ctrl_base) + 0x3c);
if (mode == 0)
@@ -815,13 +862,13 @@ void mdss_dsi_sw_reset(struct mdss_panel_data *pdata)
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
u32 dsi_ctrl;
- ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
- panel_data);
- if (!ctrl_pdata) {
+ if (pdata == NULL) {
pr_err("%s: Invalid input data\n", __func__);
return;
}
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0004);
dsi_ctrl &= ~0x01;
MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl);
@@ -848,13 +895,14 @@ void mdss_dsi_controller_cfg(int enable,
u32 timeout_us = 16000;
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
- ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
- panel_data);
- if (!ctrl_pdata) {
+ if (pdata == NULL) {
pr_err("%s: Invalid input data\n", __func__);
return;
}
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
+
/* Check for CMD_MODE_DMA_BUSY */
if (readl_poll_timeout(((ctrl_pdata->ctrl_base) + 0x0008),
status,
@@ -895,13 +943,21 @@ void mdss_dsi_op_mode_config(int mode,
u32 dsi_ctrl, intr_ctrl;
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
- ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
- panel_data);
- if (!ctrl_pdata) {
+ if (pdata == NULL) {
pr_err("%s: Invalid input data\n", __func__);
return;
}
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
+
+ if (ctrl_pdata->shared_pdata.broadcast_enable)
+ if (pdata->panel_info.pdest == DISPLAY_1) {
+ pr_debug("%s: Broadcast mode. 1st ctrl\n",
+ __func__);
+ return;
+ }
+
dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0004);
/*If Video enabled, Keep Video and Cmd mode ON */
if (dsi_ctrl & 0x02)
@@ -923,18 +979,27 @@ void mdss_dsi_op_mode_config(int mode,
pr_debug("%s: dsi_ctrl=%x intr=%x\n", __func__, dsi_ctrl, intr_ctrl);
+ if (ctrl_pdata->shared_pdata.broadcast_enable)
+ if ((pdata->panel_info.pdest == DISPLAY_2)
+ && (left_ctrl_pdata != NULL)) {
+ MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0110,
+ intr_ctrl); /* DSI_INTL_CTRL */
+ MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
+ dsi_ctrl);
+ }
+
MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0110,
intr_ctrl); /* DSI_INTL_CTRL */
MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl);
wmb();
}
-void mdss_dsi_cmd_mdp_start(void)
+void mdss_dsi_cmd_mdp_start(struct mdss_panel_data *pdata)
{
unsigned long flag;
spin_lock_irqsave(&dsi_mdp_lock, flag);
- mdss_dsi_enable_irq();
+ mdss_dsi_enable_irq(pdata);
dsi_mdp_busy = true;
spin_unlock_irqrestore(&dsi_mdp_lock, flag);
}
@@ -946,13 +1011,14 @@ void mdss_dsi_cmd_bta_sw_trigger(struct mdss_panel_data *pdata)
int timeout_us = 10000;
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
- ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
- panel_data);
- if (!ctrl_pdata) {
+ if (pdata == NULL) {
pr_err("%s: Invalid input data\n", __func__);
return;
}
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
+
MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x098, 0x01); /* trigger */
wmb();
@@ -1008,18 +1074,40 @@ int mdss_dsi_cmds_tx(struct mdss_panel_data *pdata,
unsigned long flag;
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
- ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
- panel_data);
- if (!ctrl_pdata) {
+ if (pdata == NULL) {
pr_err("%s: Invalid input data\n", __func__);
return -EINVAL;
}
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
+
+ if (ctrl_pdata->shared_pdata.broadcast_enable)
+ if (pdata->panel_info.pdest == DISPLAY_1) {
+ pr_debug("%s: Broadcast mode. 1st ctrl\n",
+ __func__);
+ return 0;
+ }
+
/* turn on cmd mode
* for video mode, do not send cmds more than
* one pixel line, since it only transmit it
* during BLLP.
*/
+
+ if (ctrl_pdata->shared_pdata.broadcast_enable)
+ if ((pdata->panel_info.pdest == DISPLAY_2)
+ && (left_ctrl_pdata != NULL)) {
+ dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base
+ + 0x0004);
+ video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
+ if (video_mode) {
+ ctrl = dsi_ctrl | 0x04; /* CMD_MODE_EN */
+ MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
+ ctrl);
+ }
+ }
+
dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0004);
video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
if (video_mode) {
@@ -1028,7 +1116,8 @@ int mdss_dsi_cmds_tx(struct mdss_panel_data *pdata,
}
spin_lock_irqsave(&dsi_mdp_lock, flag);
- mdss_dsi_enable_irq();
+ mdss_dsi_enable_irq(pdata);
+
dsi_mdp_busy = true;
spin_unlock_irqrestore(&dsi_mdp_lock, flag);
@@ -1045,7 +1134,7 @@ int mdss_dsi_cmds_tx(struct mdss_panel_data *pdata,
spin_lock_irqsave(&dsi_mdp_lock, flag);
dsi_mdp_busy = false;
- mdss_dsi_disable_irq();
+ mdss_dsi_disable_irq(pdata);
spin_unlock_irqrestore(&dsi_mdp_lock, flag);
if (video_mode)
@@ -1083,13 +1172,14 @@ int mdss_dsi_cmds_rx(struct mdss_panel_data *pdata,
char cmd;
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
- ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
- panel_data);
- if (!ctrl_pdata) {
+ if (pdata == NULL) {
pr_err("%s: Invalid input data\n", __func__);
return -EINVAL;
}
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
+
if (pdata->panel_info.mipi.no_max_pkt_size)
rlen = ALIGN(rlen, 4); /* Only support rlen = 4*n */
@@ -1116,7 +1206,7 @@ int mdss_dsi_cmds_rx(struct mdss_panel_data *pdata,
}
spin_lock_irqsave(&dsi_mdp_lock, flag);
- mdss_dsi_enable_irq();
+ mdss_dsi_enable_irq(pdata);
dsi_mdp_busy = true;
spin_unlock_irqrestore(&dsi_mdp_lock, flag);
@@ -1153,7 +1243,7 @@ int mdss_dsi_cmds_rx(struct mdss_panel_data *pdata,
spin_lock_irqsave(&dsi_mdp_lock, flag);
dsi_mdp_busy = false;
- mdss_dsi_disable_irq();
+ mdss_dsi_disable_irq(pdata);
spin_unlock_irqrestore(&dsi_mdp_lock, flag);
if (pdata->panel_info.mipi.no_max_pkt_size) {
@@ -1204,13 +1294,13 @@ int mdss_dsi_cmd_dma_tx(struct dsi_buf *tp,
unsigned long size, addr;
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
- ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
- panel_data);
- if (!ctrl_pdata) {
+ if (pdata == NULL) {
pr_err("%s: Invalid input data\n", __func__);
return -EINVAL;
}
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
bp = tp->data;
pr_debug("%s: ", __func__);
@@ -1242,10 +1332,23 @@ int mdss_dsi_cmd_dma_tx(struct dsi_buf *tp,
INIT_COMPLETION(dsi_dma_comp);
+ if (ctrl_pdata->shared_pdata.broadcast_enable)
+ if ((pdata->panel_info.pdest == DISPLAY_2)
+ && (left_ctrl_pdata != NULL)) {
+ MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x048, addr);
+ MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x04c, len);
+ }
+
MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x048, addr);
MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x04c, len);
wmb();
+ if (ctrl_pdata->shared_pdata.broadcast_enable)
+ if ((pdata->panel_info.pdest == DISPLAY_2)
+ && (left_ctrl_pdata != NULL)) {
+ MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x090, 0x01);
+ }
+
MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x090, 0x01); /* trigger */
wmb();
@@ -1267,13 +1370,13 @@ int mdss_dsi_cmd_dma_rx(struct dsi_buf *rp, int rlen,
int i, off, cnt;
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
- ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
- panel_data);
- if (!ctrl_pdata) {
+ if (pdata == NULL) {
pr_err("%s: Invalid input data\n", __func__);
return -EINVAL;
}
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
lp = (u32 *)rp->data;
cnt = rlen;
cnt += 3;
@@ -1383,6 +1486,15 @@ irqreturn_t mdss_dsi_isr(int irq, void *ptr)
isr = MIPI_INP(dsi_base + 0x0110);/* DSI_INTR_CTRL */
MIPI_OUTP(dsi_base + 0x0110, isr);
+ if (ctrl_pdata->shared_pdata.broadcast_enable)
+ if ((ctrl_pdata->panel_data.panel_info.pdest == DISPLAY_2)
+ && (left_ctrl_pdata != NULL)) {
+ u32 isr0;
+ isr0 = MIPI_INP(left_ctrl_pdata->ctrl_base
+ + 0x0110);/* DSI_INTR_CTRL */
+ MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0110, isr0);
+ }
+
if (isr & DSI_INTR_ERROR)
mdss_dsi_error(dsi_base);
diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c
index 50652a50f7d5..77a8e944cbbf 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c
@@ -26,12 +26,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;
-
DEFINE_LED_TRIGGER(bl_led_trigger);
static struct mdss_dsi_phy_ctrl phy_params;
@@ -111,15 +105,24 @@ static void mdss_dsi_panel_bl_ctrl(struct mdss_panel_data *pdata,
static int mdss_dsi_panel_on(struct mdss_panel_data *pdata)
{
struct mipi_panel_info *mipi;
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return -EINVAL;
+ }
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
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);
+ mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf,
+ ctrl_pdata->on_cmds->buf,
+ ctrl_pdata->on_cmds->size);
} else {
pr_err("%s:%d, CMD MODE NOT SUPPORTED", __func__, __LINE__);
return -EINVAL;
@@ -131,14 +134,23 @@ static int mdss_dsi_panel_on(struct mdss_panel_data *pdata)
static int mdss_dsi_panel_off(struct mdss_panel_data *pdata)
{
struct mipi_panel_info *mipi;
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return -EINVAL;
+ }
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
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);
+ mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf,
+ ctrl_pdata->off_cmds->buf,
+ ctrl_pdata->off_cmds->size);
} else {
pr_debug("%s:%d, CMD mode not supported", __func__, __LINE__);
return -EINVAL;
@@ -157,6 +169,9 @@ static int mdss_panel_parse_dt(struct platform_device *pdev,
int cmd_plen, data_offset;
const char *data;
static const char *bl_ctrl_type, *pdest;
+ static const char *on_cmds_state, *off_cmds_state;
+ char *on_cmds = NULL, *off_cmds = NULL;
+ int num_of_on_cmds = 0, num_of_off_cmds = 0;
rc = of_property_read_u32_array(np, "qcom,mdss-pan-res", res, 2);
if (rc) {
@@ -214,7 +229,7 @@ static int mdss_panel_parse_dt(struct platform_device *pdev,
bl_ctrl_type = of_get_property(pdev->dev.of_node,
"qcom,mdss-pan-bl-ctrl", NULL);
- if (!strncmp(bl_ctrl_type, "bl_ctrl_wled", 12)) {
+ if ((bl_ctrl_type) && (!strncmp(bl_ctrl_type, "bl_ctrl_wled", 12))) {
led_trigger_register_simple("bkl-trigger", &bl_led_trigger);
pr_debug("%s: SUCCESS-> WLED TRIGGER register\n", __func__);
*bl_ctrl = BL_WLED;
@@ -268,6 +283,9 @@ static int mdss_panel_parse_dt(struct platform_device *pdev,
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(np, "qcom,mdss-pan-dsi-dlane-swap", &tmp);
+ panel_data->panel_info.mipi.dlane_swap = (!rc ? tmp : 0);
+
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);
@@ -370,22 +388,34 @@ static int mdss_panel_parse_dt(struct platform_device *pdev,
goto error;
}
- dsi_panel_on_cmds =
+ panel_data->dsi_panel_on_cmds =
+ kzalloc(sizeof(struct dsi_panel_cmds_list), GFP_KERNEL);
+ if (!panel_data->dsi_panel_on_cmds)
+ return -ENOMEM;
+
+ (panel_data->dsi_panel_on_cmds)->buf =
kzalloc((num_of_on_cmds * sizeof(struct dsi_cmd_desc)),
GFP_KERNEL);
- if (!dsi_panel_on_cmds)
+ if (!(panel_data->dsi_panel_on_cmds)->buf)
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);
+ panel_data->dsi_panel_on_cmds->buf[i].dtype =
+ on_cmds[data_offset++];
+ panel_data->dsi_panel_on_cmds->buf[i].last =
+ on_cmds[data_offset++];
+ panel_data->dsi_panel_on_cmds->buf[i].vc =
+ on_cmds[data_offset++];
+ panel_data->dsi_panel_on_cmds->buf[i].ack =
+ on_cmds[data_offset++];
+ panel_data->dsi_panel_on_cmds->buf[i].wait =
+ on_cmds[data_offset++];
+ panel_data->dsi_panel_on_cmds->buf[i].dlen =
+ on_cmds[data_offset++];
+ panel_data->dsi_panel_on_cmds->buf[i].payload =
+ &on_cmds[data_offset];
+ data_offset += (panel_data->dsi_panel_on_cmds->buf[i].dlen);
}
if (data_offset != len) {
@@ -394,6 +424,23 @@ static int mdss_panel_parse_dt(struct platform_device *pdev,
goto error;
}
+ (panel_data->dsi_panel_on_cmds)->size = num_of_on_cmds;
+
+ on_cmds_state = of_get_property(pdev->dev.of_node,
+ "qcom,on-cmds-dsi-state", NULL);
+ if (!strncmp(on_cmds_state, "DSI_LP_MODE", 11)) {
+ (panel_data->dsi_panel_on_cmds)->ctrl_state =
+ DSI_LP_MODE;
+ } else if (!strncmp(on_cmds_state, "DSI_HS_MODE", 11)) {
+ (panel_data->dsi_panel_on_cmds)->ctrl_state =
+ DSI_HS_MODE;
+ } else {
+ pr_debug("%s: ON cmds state not specified. Set Default\n",
+ __func__);
+ (panel_data->dsi_panel_on_cmds)->ctrl_state =
+ DSI_LP_MODE;
+ }
+
data = of_get_property(np, "qcom,panel-off-cmds", &len);
if (!data) {
pr_err("%s:%d, Unable to read OFF cmds", __func__, __LINE__);
@@ -419,22 +466,34 @@ static int mdss_panel_parse_dt(struct platform_device *pdev,
goto error;
}
- dsi_panel_off_cmds = kzalloc(num_of_off_cmds
+ panel_data->dsi_panel_off_cmds =
+ kzalloc(sizeof(struct dsi_panel_cmds_list), GFP_KERNEL);
+ if (!panel_data->dsi_panel_off_cmds)
+ return -ENOMEM;
+
+ (panel_data->dsi_panel_off_cmds)->buf = kzalloc(num_of_off_cmds
* sizeof(struct dsi_cmd_desc),
GFP_KERNEL);
- if (!dsi_panel_off_cmds)
+ if (!(panel_data->dsi_panel_off_cmds)->buf)
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);
+ panel_data->dsi_panel_off_cmds->buf[i].dtype =
+ off_cmds[data_offset++];
+ panel_data->dsi_panel_off_cmds->buf[i].last =
+ off_cmds[data_offset++];
+ panel_data->dsi_panel_off_cmds->buf[i].vc =
+ off_cmds[data_offset++];
+ panel_data->dsi_panel_off_cmds->buf[i].ack =
+ off_cmds[data_offset++];
+ panel_data->dsi_panel_off_cmds->buf[i].wait =
+ off_cmds[data_offset++];
+ panel_data->dsi_panel_off_cmds->buf[i].dlen =
+ off_cmds[data_offset++];
+ panel_data->dsi_panel_off_cmds->buf[i].payload =
+ &off_cmds[data_offset];
+ data_offset += (panel_data->dsi_panel_off_cmds->buf[i].dlen);
}
if (data_offset != len) {
@@ -443,10 +502,29 @@ static int mdss_panel_parse_dt(struct platform_device *pdev,
goto error;
}
+ (panel_data->dsi_panel_off_cmds)->size = num_of_off_cmds;
+
+ off_cmds_state = of_get_property(pdev->dev.of_node,
+ "qcom,off-cmds-dsi-state", NULL);
+ if (!strncmp(off_cmds_state, "DSI_LP_MODE", 11)) {
+ (panel_data->dsi_panel_off_cmds)->ctrl_state =
+ DSI_LP_MODE;
+ } else if (!strncmp(off_cmds_state, "DSI_HS_MODE", 11)) {
+ (panel_data->dsi_panel_off_cmds)->ctrl_state =
+ DSI_HS_MODE;
+ } else {
+ pr_debug("%s: ON cmds state not specified. Set Default\n",
+ __func__);
+ (panel_data->dsi_panel_off_cmds)->ctrl_state =
+ DSI_LP_MODE;
+ }
+
return 0;
error:
- kfree(dsi_panel_on_cmds);
- kfree(dsi_panel_off_cmds);
+ kfree((panel_data->dsi_panel_on_cmds)->buf);
+ kfree((panel_data->dsi_panel_off_cmds)->buf);
+ kfree(panel_data->dsi_panel_on_cmds);
+ kfree(panel_data->dsi_panel_off_cmds);
kfree(on_cmds);
kfree(off_cmds);
diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
index 0f2b1b115402..83e89c505d79 100644
--- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c
+++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
@@ -299,7 +299,13 @@ void mdss_dsi_phy_init(struct mdss_panel_data *pdata)
MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0484, 0x07);
MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0484, pd->strength[0]);
- off = 0x0580; /* phy regulator ctrl settings */
+ /* phy regulator ctrl settings. Both the DSI controller
+ have one regulator */
+ if ((ctrl_pdata->panel_data).panel_info.pdest == DISPLAY_1)
+ off = 0x0580;
+ else
+ off = 0x0580 - 0x600;
+
/* Regulator ctrl - CAL_PWD_CFG */
MIPI_OUTP((ctrl_pdata->ctrl_base) + off + (4 * 6), pd->regulator[6]);
/* Regulator ctrl - TEST */
@@ -350,7 +356,10 @@ void mdss_dsi_phy_init(struct mdss_panel_data *pdata)
wmb();
/* DSI_0_PHY_DSIPHY_GLBL_TEST_CTRL */
- MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x04d4, 0x01);
+ if ((ctrl_pdata->panel_data).panel_info.pdest == DISPLAY_1)
+ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x04d4, 0x01);
+ else
+ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x04d4, 0x00);
wmb();
off = 0x04b4; /* phy BIST ctrl 0 - 5 */