[PATCH] drm/msm/dsi: Updata LNn_CFG4 register settings for 28nm PHY

2015-09-11 Thread Hai Li
The current settings for 28nm PHY data lane CFG4 registers do
not work with certain panels. This change is to modify them to
hw recommended values.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c 
b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
index f1a7c7b..edf7411 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
@@ -99,16 +99,14 @@ static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy, int 
src_pll_id,
dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_1(i), 0);
dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_2(i), 0);
dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_3(i), 0);
+   dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_4(i), 0);
dsi_phy_write(base + REG_DSI_28nm_PHY_LN_TEST_DATAPATH(i), 0);
dsi_phy_write(base + REG_DSI_28nm_PHY_LN_DEBUG_SEL(i), 0);
dsi_phy_write(base + REG_DSI_28nm_PHY_LN_TEST_STR_0(i), 0x1);
dsi_phy_write(base + REG_DSI_28nm_PHY_LN_TEST_STR_1(i), 0x97);
}
-   dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_4(0), 0);
-   dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_4(1), 0x5);
-   dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_4(2), 0xa);
-   dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_4(3), 0xf);

+   dsi_phy_write(base + REG_DSI_28nm_PHY_LNCK_CFG_4, 0);
dsi_phy_write(base + REG_DSI_28nm_PHY_LNCK_CFG_1, 0xc0);
dsi_phy_write(base + REG_DSI_28nm_PHY_LNCK_TEST_STR0, 0x1);
dsi_phy_write(base + REG_DSI_28nm_PHY_LNCK_TEST_STR1, 0xbb);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH] drm/msm/dsi: Parse lane swap information from DT

2015-09-03 Thread Hai Li
Lane swap configuration is based on the board design.
This change allows the DSI host to get this information
from device tree, instead of hardcoding in driver.

Signed-off-by: Hai Li 
---
 Documentation/devicetree/bindings/drm/msm/dsi.txt | 13 ++
 drivers/gpu/drm/msm/dsi/dsi_host.c| 49 +--
 2 files changed, 49 insertions(+), 13 deletions(-)

diff --git a/Documentation/devicetree/bindings/drm/msm/dsi.txt 
b/Documentation/devicetree/bindings/drm/msm/dsi.txt
index d56923c..febcc51 100644
--- a/Documentation/devicetree/bindings/drm/msm/dsi.txt
+++ b/Documentation/devicetree/bindings/drm/msm/dsi.txt
@@ -44,6 +44,17 @@ Optional properties:
 - port: DSI controller output port. This contains one endpoint subnode, with 
its
   remote-endpoint set to the phandle of the connected panel's endpoint.
   See Documentation/devicetree/bindings/graph.txt for device graph info.
+- qcom,dsi-logical-lane-swap: Character string to swap logical lane to physical
+  lane mapping. Supported lane mappings:
+  "0123": Logic 0->Phys 0; Logic 1->Phys 1; Logic 2->Phys 2; Logic 3->Phys 3;
+  "3012": Logic 3->Phys 0; Logic 0->Phys 1; Logic 1->Phys 2; Logic 2->Phys 3;
+  "2301": Logic 2->Phys 0; Logic 3->Phys 1; Logic 0->Phys 2; Logic 1->Phys 3;
+  "1230": Logic 1->Phys 0; Logic 2->Phys 1; Logic 3->Phys 2; Logic 0->Phys 3;
+  "0321": Logic 0->Phys 0; Logic 3->Phys 1; Logic 2->Phys 2; Logic 1->Phys 3;
+  "1032": Logic 1->Phys 0; Logic 0->Phys 1; Logic 3->Phys 2; Logic 2->Phys 3;
+  "2103": Logic 2->Phys 0; Logic 1->Phys 1; Logic 0->Phys 2; Logic 3->Phys 3;
+  "3210": Logic 3->Phys 0; Logic 2->Phys 1; Logic 1->Phys 2; Logic 0->Phys 3;
+  Default value is "0123", which means no lane swap.

 DSI PHY:
 Required properties:
@@ -129,6 +140,8 @@ Example:
remote-endpoint = <_in>;
};
};
+
+   qcom,dsi-logical-lane-swap = "0123";
};

mdss_dsi_phy0: qcom,mdss_dsi_phy at fd922a00 {
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 8d82973f..eaba417 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -131,6 +131,7 @@ struct msm_dsi_host {
enum mipi_dsi_pixel_format format;
unsigned long mode_flags;

+   u32 dlane_swap;
u32 dma_cmd_ctrl_restore;

bool registered;
@@ -684,19 +685,9 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, 
bool enable,
data = DSI_CTRL_CLK_EN;

DBG("lane number=%d", msm_host->lanes);
-   if (msm_host->lanes == 2) {
-   data |= DSI_CTRL_LANE1 | DSI_CTRL_LANE2;
-   /* swap lanes for 2-lane panel for better performance */
-   dsi_write(msm_host, REG_DSI_LANE_SWAP_CTRL,
-   DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL(LANE_SWAP_1230));
-   } else {
-   /* Take 4 lanes as default */
-   data |= DSI_CTRL_LANE0 | DSI_CTRL_LANE1 | DSI_CTRL_LANE2 |
-   DSI_CTRL_LANE3;
-   /* Do not swap lanes for 4-lane panel */
-   dsi_write(msm_host, REG_DSI_LANE_SWAP_CTRL,
-   DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL(LANE_SWAP_0123));
-   }
+   data |= ((DSI_CTRL_LANE0 << msm_host->lanes) - DSI_CTRL_LANE0);
+   dsi_write(msm_host, REG_DSI_LANE_SWAP_CTRL,
+   DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL(msm_host->dlane_swap));

if (!(flags & MIPI_DSI_CLOCK_NON_CONTINUOUS))
dsi_write(msm_host, REG_DSI_LANE_CTRL,
@@ -1289,6 +1280,9 @@ static int dsi_host_attach(struct mipi_dsi_host *host,
struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
int ret;

+   if (dsi->lanes > 4 || dsi->channel > 3)
+   return -EINVAL;
+
msm_host->channel = dsi->channel;
msm_host->lanes = dsi->lanes;
msm_host->format = dsi->format;
@@ -1344,6 +1338,33 @@ static struct mipi_dsi_host_ops dsi_host_ops = {
.transfer = dsi_host_transfer,
 };

+static void dsi_parse_dlane_swap(struct msm_dsi_host *msm_host,
+   struct device_node *np)
+{
+   const char *lane_swap;
+
+   lane_swap = of_get_property(np, "qcom,dsi-logical-lane-swap", NULL);
+
+   if (!lane_swap)
+   msm_host->dlane_swap = LANE_SWAP_0123;
+   else if (!strncmp(lane_swap, "3012", 5))
+   msm_host->dlane_swap = LANE_SWAP_3012;
+   else if (!strncmp(lane_swap, "2301", 5))
+   msm_host->dlane_swap = LANE_SWAP_2301;
+   else if (!strncmp(lane_swap, "1230", 5))
+   msm_host->dlane_swap = LANE_SWAP_

drm/msm/dsi: hs_zero timing

2015-09-01 Thread Hai Li
Hi Werner,



Based on the discussion with our hw team, changing the LNn_CFG4 to all 0 is the 
solution for this issue.

I will prepare a change to this.



Thanks,

Hai



From: dri-devel [mailto:dri-devel-boun...@lists.freedesktop.org] On Behalf Of 
Werner Johansson
Sent: Friday, August 28, 2015 2:10 AM
To: Archit Taneja
Cc: dri-devel at lists.freedesktop.org
Subject: Re: drm/msm/dsi: hs_zero timing




On Aug 27, 2015 10:56 PM, "Archit Taneja" mailto:architt at codeaurora.org> > wrote:
>
> There are certain modes (generally for HDMI/DVI) where the refresh rate
> isn't an integer. It can be something like 59.94 Hz, or 60.04Hz. The
> above calculation may not work well with such modes.
>
[...] 
> We have platforms where the DSI output is connected to HDMI bridge
> chips. So the issue I mentioned holds true for msm/dsi too.

That makes sense, the non-integer vrefresh rates completely slipped my mind.

Thanks!

/wj

-- next part --
An HTML attachment was scrubbed...
URL: 



drm/msm/dsi: hs_zero timing

2015-08-26 Thread Hai Li
Thanks Werner to test it out. I will focus on the dphy timing calculation then.



It’s better to avoid discussing the excel formula publicly. :)





Thanks,

Hai



From: Werner Johansson [mailto:werner.johans...@gmail.com] 
Sent: Wednesday, August 26, 2015 1:39 PM
To: Hai Li
Cc: Rob Clark; werner.johansson at sonymobile.com; dri-devel at 
lists.freedesktop.org
Subject: RE: drm/msm/dsi: hs_zero timing




On Aug 26, 2015 08:34, "Hai Li" mailto:hali at 
codeaurora.org> > wrote:
>
> Hi Werner,
>
> Thanks for sharing this. The DPHY timings in downstream dtsi are exactly the 
> same as the excel calculation, but slightly different from the output of drm 
> code as you posted. (e.g hs_zero is 116 vs 118)
> I think it is caused by some precision loss during driver calculation, but I 
> need to double check.
>
> Could you help to try configuring the same DPHY timings as downstream, but 
> leave the values in  DSIPHY_LNx_CFG4 as is, to see if it works?

116 to hs_zero works fine without any other changes (only 118 and every eighth 
number up and down from there fails with this panel timing), so if we can do 
something to make sure we hit a working value for hs_zero without touching 
anything else that would be great! 

Thanks for checking the timings and let me know if you want me to test anything 
else. Is the excel formula considered public so we can discuss it here? 

/wj

-- next part --
An HTML attachment was scrubbed...
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20150826/91186538/attachment.html>


drm/msm/dsi: hs_zero timing

2015-08-26 Thread Hai Li
Hi Werner,

Thanks for sharing this. The DPHY timings in downstream dtsi are exactly the 
same as the excel calculation, but slightly different from the output of drm 
code as you posted. (e.g hs_zero is 116 vs 118)
I think it is caused by some precision loss during driver calculation, but I 
need to double check.

Could you help to try configuring the same DPHY timings as downstream, but 
leave the values in  DSIPHY_LNx_CFG4 as is, to see if it works?

This could help us to narrow down the issue.


Thanks,
Hai

-Original Message-
From: Werner Johansson [mailto:werner.johans...@gmail.com] 
Sent: Monday, August 24, 2015 9:24 PM
To: Hai Li
Cc: Rob Clark; Johansson, Werner; dri-devel at lists.freedesktop.org
Subject: Re: drm/msm/dsi: hs_zero timing

On Mon, Aug 24, 2015 at 7:32 AM, Hai Li  wrote:
> Hi Werner,
>
> Yes, the register is to adjust hs_zero.
> Could you share the panel's video timing and dphy timings (or the panel DT), 
> used by downstream driver?
>
> The dphy timing calculations in the phy driver are from the excel sheet as 
> well, I can check if there is any issue inside the calculation code making 
> the difference.
>
>
> Thanks,
> Hai

Hi Hai,

Yes definitely, our downstream DT definitions for the Panasonic panel looks 
like this: (taken from our kernel available here:
https://github.com/sonyxperiadev/kernel-copyleft/blob/23.1.A.1.xxx/arch/arm/boot/dts/dsi-panel-castor.dtsi#L78-L145)

dsi_novatek_panasonic_wuxga_vid: somc,novatek_panasonic_wuxga_panel { 
qcom,mdss-dsi-panel-name = "panasonic novatek wuxga video"; 
qcom,mdss-dsi-panel-controller = <_dsi0>; qcom,mdss-dsi-panel-type = 
"dsi_video_mode"; qcom,mdss-dsi-panel-destination = "display_1"; 
qcom,mdss-dsi-panel-framerate = <60>; qcom,mdss-dsi-virtual-channel-id = <0>; 
qcom,mdss-dsi-stream = <0>; qcom,mdss-dsi-panel-width = <1920>; 
qcom,mdss-dsi-panel-height = <1200>; qcom,mdss-dsi-h-front-porch = <152>; 
qcom,mdss-dsi-h-back-porch = <20>; qcom,mdss-dsi-h-pulse-width = <52>; 
qcom,mdss-dsi-h-sync-skew = <0>; qcom,mdss-dsi-v-back-porch = <48>; 
qcom,mdss-dsi-v-front-porch = <24>; qcom,mdss-dsi-v-pulse-width = <6>; 
qcom,mdss-dsi-h-left-border = <0>; qcom,mdss-dsi-h-right-border = <0>; 
qcom,mdss-dsi-v-top-border = <0>; qcom,mdss-dsi-v-bottom-border = <0>; 
qcom,mdss-dsi-bpp = <24>; qcom,mdss-dsi-underflow-color = <0x0>; 
qcom,mdss-dsi-border-color = <0>; qcom,mdss-dsi-on-command = [32 01 00 00 00 00 
02 00 00]; qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; 
qcom,mdss-dsi-h-sync-pulse = <1>; qcom,mdss-dsi-traffic-mode = 
"non_burst_sync_event"; qcom,mdss-dsi-bllp-eof-power-mode;
qcom,mdss-dsi-bllp-power-mode;
qcom,mdss-dsi-lane-0-state;
qcom,mdss-dsi-lane-1-state;
qcom,mdss-dsi-lane-2-state;
qcom,mdss-dsi-lane-3-state;
qcom,mdss-dsi-panel-timings = [FB 3E 2A 00 70 74 2E 42 33 03 04 00]; 
qcom,mdss-dsi-t-clk-post = <0x02>; qcom,mdss-dsi-t-clk-pre = <0x2E>; 
qcom,mdss-dsi-bl-min-level = <1>; qcom,mdss-dsi-bl-max-level = <255>; 
qcom,mdss-brightness-max-level = <255>; qcom,mdss-dsi-dma-trigger = 
"trigger_sw"; qcom,mdss-dsi-mdp-trigger = "none"; 
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; 
qcom,mdss-dsi-pan-enable-dynamic-fps;
qcom,mdss-dsi-pan-fps-update = "dfps_suspend_resume_mode"; 
qcom,cont-splash-enabled; qcom,mdss-dsi-tx-eot-append; somc,driver-ic = <3>; 
somc,dric-gpio = < 26 0>; somc,mul-channel-scaling = <3>; 
somc,mdss-phy-size-mm = <217 135>; somc,mdss-dsi-lane-config = [00 c2 ef 00 00 
00 00 01 ff
00 c2 ef 00 00 00 00 01 ff
00 c2 ef 00 00 00 00 01 ff
00 c2 ef 00 00 00 00 01 ff
00 02 00 00 00 00 00 01 97];
somc,lcd-id = <1>;
somc,lcd-id-adc = <801000 917000>;
somc,disp-en-on-post = <251>;
somc,disp-en-off-pre = <86>;
somc,pw-down-period = <500>;
somc,mdss-dsi-uv-param-type = <0>;
somc,mdss-dsi-pcc-table-size = <1>;
somc,mdss-dsi-pcc-table = <
0x00 0x01 0x1C 0x1F 0x1C 0x1F 0x8000 0x8000 0x7D80>; };

/wj



drm/msm/dsi: hs_zero timing

2015-08-24 Thread Hai Li
Hi Werner,

Yes, the register is to adjust hs_zero.
Could you share the panel's video timing and dphy timings (or the panel DT), 
used by downstream driver?

The dphy timing calculations in the phy driver are from the excel sheet as 
well, I can check if there is any issue inside the calculation code making the 
difference.


Thanks,
Hai

-Original Message-
From: Rob Clark [mailto:robdcl...@gmail.com] 
Sent: Saturday, August 22, 2015 9:25 AM
To: Johansson, Werner
Cc: Hai Li; dri-devel at lists.freedesktop.org
Subject: Re: drm/msm/dsi: hs_zero timing

On Fri, Aug 21, 2015 at 4:38 PM, Johansson, Werner  wrote:
>> From: Hai Li [mailto:hali at codeaurora.org]
>> Sent: den 21 augusti 2015 12:56
>>
>> When I made DSI changes, I tried to limit the information in DT (like 
>> our downstream driver), until there is a case driver really cannot 
>> figure it out by the existing information.
>> I think this is the requirement of upstream kernel.
>>
>> If we see a panel requires different value in PHY_LN_CFG_4(x) ga
>> register and cannot derive it from any other timings, we could think 
>> about adding it into DT.
>
> Not sure how these skew values can be determined from the rest of the timing? 
> Am I correct in my understanding that these registers would compensate for 
> differences in physical length of the dsi lanes, or are they designed for a 
> different purpose? The documentation is very vague on this point. Adjusting 
> the values down to the default zero still works fine on the other panels (and 
> enabled the Panasonic panel to work properly too).
>

fwiw, if the values are related to the physical cabling/wiring, rather than the 
panel timing, we should probably get them from DT..

if a combination of the timing and the wiring, that gets a bit more complicated

(I am not actually sure myself about these)

BR,
-R

>> Also, I am wondering if this Panasonic WUXGA panel works with 
>> downstream driver, since I see the same hardcoded values set for all 
>> the panels.
>
> We have the Panasonic WUXGA panel working with the downstream driver (it's 
> shipping in our Xperia Z2 tablets). The problem with our shipping kernel is 
> that the timing values are derived from the Qualcomm Excel sheet and then 
> hardcoded (in DT), the timing is not calculated on the fly as is the case 
> here. It's very easy to just modify hs_zero value up or down one notch 
> manually when having the timing hardcoded, but such a solution is certainly 
> not generic.
>
> Thanks!
> /wj
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel



drm/msm/dsi Lane-swapping for 2-lane panels non-functional for msm8x74?

2015-08-21 Thread Hai Li
Hi Werner,

I will prepare a change to make the lane swap configurable.

Thanks,
Hai

-Original Message-
From: dri-devel [mailto:dri-devel-boun...@lists.freedesktop.org] On Behalf Of 
Johansson, Werner
Sent: Thursday, August 20, 2015 8:54 PM
To: dri-devel at lists.freedesktop.org
Subject: drm/msm/dsi Lane-swapping for 2-lane panels non-functional for msm8x74?

Hi,

I'm having issues with non-functional DSI output driving a 2-lane panel 
connected to DSI0 on MSM8x74 MDP5 v1.2 hardware. The code in 
drivers/gpu/drm/msm/dsi/dsi_host.c around line 703 enables lane 1 and 2 instead 
of lane 0 and 1 for performance reasons (and then enables lane swapping in the 
DSI PHY (LANE_SWAP_1230)). I cannot get this to work on the MSM8x74, no data 
observed on physical lane 0 (can't access lane1 easily unfortunately). 
Disabling this swap and enabling lane0 and 1 instead results in a fully 
functional panel.

Would it make sense to make this performance optimization a compile-time option 
that defaults to off (for certain problematic hardware or in general)?

/wj
___
dri-devel mailing list
dri-devel at lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel



drm/msm/dsi: hs_zero timing

2015-08-21 Thread Hai Li
Hi Werner,

When I made DSI changes, I tried to limit the information in DT (like our 
downstream driver), until there is a case driver really cannot figure it out by 
the existing information.
I think this is the requirement of upstream kernel.

If we see a panel requires different value in PHY_LN_CFG_4(x) register and 
cannot derive it from any other timings, we could think about adding it into DT.

Also, I am wondering if this Panasonic WUXGA panel works with downstream 
driver, since I see the same hardcoded values set for all the panels.


Thanks,
Hai

-Original Message-
From: dri-devel [mailto:dri-devel-boun...@lists.freedesktop.org] On Behalf Of 
Johansson, Werner
Sent: Friday, August 21, 2015 2:27 PM
To: dri-devel at lists.freedesktop.org
Subject: drm/msm/dsi: hs_zero timing

Hi,

In drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c there are a few "magic number" 
writes to the PHY_LN_CFG_4(x) registers around line 108 (adjusting the hs_zero 
period per lane). This causes some problems with certain panel timings when 
timing->hs_zero plus an "unknown integer" becomes evenly divisible by 8 - this 
will cause the DSI output to misbehave (typically leading to black screen). On 
the three panels I've tested I have different "unknown integers" which I can't 
immediately derive from the rest of the PHY timings:

(PHY timing debug output in this order: clk_pre, clk_post, clk_zero, clk_trail, 
clk_prepare, hs_exit, hs_zero, hs_prepare, hs_trail, hs_rqst)

Panasonic VVX panel (WUXGA): PHY timings: 47, 2, 259, 62, 42, 112, 118, 46, 66, 
51 hs_zero calculated value of 118 does not work (neither does anything <74, 
78, 86, 94, 102, 110, 126, 134, 142, 150, 158, 166, 174, 182, 190, 198, 206, 
214, 222, 230, 238, 246, 254)

Sharp (1080p) on Xperia Z3: PHY timings: 44, 2, 238, 56, 38, 104, 110, 42, 60, 
44 hs_zero calculated value of 110 works fine here but 104, 112, 120 and the 
remaining multiples of 8 does not.

Sharp (qHD) on Dragonboard 800: PHY timings: 28, 4, 139, 30, 20, 68, 72, 24, 
34, 25 hs_zero calculated value of 72 works fine but 62, 70, 78, 86 and the 
remaining multiples of 8 does not.

hs_trail looked promising at first: a bad hs_zero value + hs_trail would be 
evenly divisible by 8 for Panasonic and the 1080p Sharp panel but not for the 
Sharp qHD display, and adjusting hs_trail did not solve the issue.

However, setting all the lane adjust values for hs_zero to 0 solves the problem 
for the troublesome WUXGA panel timing and does not create any apparent 
downsides for the other two.

Does anyone know of a reason this skew is implemented? If it is indeed needed 
in some cases would a move to DT instead of leaving it hard-coded make sense?

Thanks for any input!

/wj

___
dri-devel mailing list
dri-devel at lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel



[PATCH] drm/msm/dsi: Introduce DSI configuration module

2015-08-13 Thread Hai Li
With more platforms supported, the DSI host
configuration array keeps expanding. This change
moves those to a separate dsi_cfg module.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/Makefile   |   1 +
 drivers/gpu/drm/msm/dsi/dsi_cfg.c  |  92 ++
 drivers/gpu/drm/msm/dsi/dsi_cfg.h  |  44 +
 drivers/gpu/drm/msm/dsi/dsi_host.c | 186 -
 4 files changed, 177 insertions(+), 146 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi_cfg.c
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi_cfg.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 89debc7..0a543eb 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -54,6 +54,7 @@ msm-$(CONFIG_DRM_MSM_FBDEV) += msm_fbdev.o
 msm-$(CONFIG_COMMON_CLK) += mdp/mdp4/mdp4_lvds_pll.o

 msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \
+   dsi/dsi_cfg.o \
dsi/dsi_host.o \
dsi/dsi_manager.o \
dsi/phy/dsi_phy.o \
diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c 
b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
new file mode 100644
index 000..5872d5e
--- /dev/null
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 "dsi_cfg.h"
+
+/* DSI v2 has not been supported by now */
+static const struct msm_dsi_config dsi_v2_cfg = {
+   .io_offset = 0,
+};
+
+static const struct msm_dsi_config msm8974_apq8084_dsi_cfg = {
+   .io_offset = DSI_6G_REG_SHIFT,
+   .reg_cfg = {
+   .num = 4,
+   .regs = {
+   {"gdsc", -1, -1, -1, -1},
+   {"vdd", 300, 300, 15, 100},
+   {"vdda", 120, 120, 10, 100},
+   {"vddio", 180, 180, 10, 100},
+   },
+   },
+};
+
+static const struct msm_dsi_config msm8916_dsi_cfg = {
+   .io_offset = DSI_6G_REG_SHIFT,
+   .reg_cfg = {
+   .num = 4,
+   .regs = {
+   {"gdsc", -1, -1, -1, -1},
+   {"vdd", 285, 285, 10, 100},
+   {"vdda", 120, 120, 10, 100},
+   {"vddio", 180, 180, 10, 100},
+   },
+   },
+};
+
+static const struct msm_dsi_config msm8994_dsi_cfg = {
+   .io_offset = DSI_6G_REG_SHIFT,
+   .reg_cfg = {
+   .num = 7,
+   .regs = {
+   {"gdsc", -1, -1, -1, -1},
+   {"vdda", 125, 125, 10, 100},
+   {"vddio", 180, 180, 10, 100},
+   {"vcca", 100, 100, 1, 100},
+   {"vdd", 180, 180, 10, 100},
+   {"lab_reg", -1, -1, -1, -1},
+   {"ibb_reg", -1, -1, -1, -1},
+   },
+   }
+};
+
+static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] = {
+   {MSM_DSI_VER_MAJOR_V2, U32_MAX, _v2_cfg},
+   {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_0,
+   _apq8084_dsi_cfg},
+   {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_1,
+   _apq8084_dsi_cfg},
+   {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_1_1,
+   _apq8084_dsi_cfg},
+   {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_2,
+   _apq8084_dsi_cfg},
+   {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_3, _dsi_cfg},
+   {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_3_1, _dsi_cfg},
+};
+
+const struct msm_dsi_cfg_handler *msm_dsi_cfg_get(u32 major, u32 minor)
+{
+   const struct msm_dsi_cfg_handler *cfg_hnd = NULL;
+   int i;
+
+   for (i = ARRAY_SIZE(dsi_cfg_handlers) - 1; i >= 0; i--) {
+   if ((dsi_cfg_handlers[i].major == major) &&
+   (dsi_cfg_handlers[i].minor == minor)) {
+   cfg_hnd = _cfg_handlers[i];
+   break;
+   }
+   }
+
+   return cfg_hnd;
+}
+
diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.h 
b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
new file mode

[PATCH 5/5] drm/msm/dsi: Make each PHY type compilation independent

2015-08-13 Thread Hai Li
On a certain platform, only one type of DSI PHY is used.
This change allows the user to only compile the PHY type
which is being used.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/Kconfig   | 14 ++
 drivers/gpu/drm/msm/Makefile  | 11 +++
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c |  4 
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.h |  8 
 4 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 331b291..8e6c7c6 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -54,3 +54,17 @@ config DRM_MSM_DSI_PLL
help
  Choose this option to enable DSI PLL driver which provides DSI
  source clocks under common clock framework.
+
+config DRM_MSM_DSI_28NM_PHY
+   bool "Enable DSI 28nm PHY driver in MSM DRM"
+   depends on DRM_MSM_DSI
+   default y
+   help
+ Choose this option if the 28nm DSI PHY is used on the platform.
+
+config DRM_MSM_DSI_20NM_PHY
+   bool "Enable DSI 20nm PHY driver in MSM DRM"
+   depends on DRM_MSM_DSI
+   default y
+   help
+ Choose this option if the 20nm DSI PHY is used on the platform.
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 30f998a..89debc7 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -57,11 +57,14 @@ msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \
dsi/dsi_host.o \
dsi/dsi_manager.o \
dsi/phy/dsi_phy.o \
-   dsi/phy/dsi_phy_20nm.o \
-   dsi/phy/dsi_phy_28nm.o \
mdp/mdp5/mdp5_cmd_encoder.o

-msm-$(CONFIG_DRM_MSM_DSI_PLL) += dsi/pll/dsi_pll.o \
-   dsi/pll/dsi_pll_28nm.o
+msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/phy/dsi_phy_28nm.o
+msm-$(CONFIG_DRM_MSM_DSI_20NM_PHY) += dsi/phy/dsi_phy_20nm.o
+
+ifeq ($(CONFIG_DRM_MSM_DSI_PLL),y)
+msm-y += dsi/pll/dsi_pll.o
+msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/pll/dsi_pll_28nm.o
+endif

 obj-$(CONFIG_DRM_MSM)  += msm.o
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c 
b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index 828a94c..401ff58 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -267,12 +267,16 @@ static void dsi_phy_disable_resource(struct msm_dsi_phy 
*phy)
 }

 static const struct of_device_id dsi_phy_dt_match[] = {
+#ifdef CONFIG_DRM_MSM_DSI_28NM_PHY
{ .compatible = "qcom,dsi-phy-28nm-hpm",
  .data = _phy_28nm_hpm_cfgs },
{ .compatible = "qcom,dsi-phy-28nm-lp",
  .data = _phy_28nm_lp_cfgs },
+#endif
+#ifdef CONFIG_DRM_MSM_DSI_20NM_PHY
{ .compatible = "qcom,dsi-phy-20nm",
  .data = _phy_20nm_cfgs },
+#endif
{}
 };

diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h 
b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h
index b69df19..063caa2 100644
--- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h
+++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h
@@ -83,8 +83,16 @@ void msm_dsi_pll_helper_unregister_clks(struct 
platform_device *pdev,
 /*
  * Initialization for Each PLL Type
  */
+#ifdef CONFIG_DRM_MSM_DSI_28NM_PHY
 struct msm_dsi_pll *msm_dsi_pll_28nm_init(struct platform_device *pdev,
enum msm_dsi_phy_type type, int id);
+#else
+static inline struct msm_dsi_pll *msm_dsi_pll_28nm_init(
+   struct platform_device *pdev, enum msm_dsi_phy_type type, int id)
+{
+   return ERR_PTR(-ENODEV);
+}
+#endif

 #endif /* __DSI_PLL_H__ */

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH 4/5] drm/msm/dsi: Split PHY drivers to separate files

2015-08-13 Thread Hai Li
This change moves each PHY type specific code into
separate files.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/Makefile   |   6 +-
 drivers/gpu/drm/msm/dsi/dsi_phy.c  | 756 -
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c  | 448 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.h  |  89 
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c | 150 ++
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c | 166 +++
 6 files changed, 857 insertions(+), 758 deletions(-)
 delete mode 100644 drivers/gpu/drm/msm/dsi/dsi_phy.c
 create mode 100644 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
 create mode 100644 drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
 create mode 100644 drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c
 create mode 100644 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 14d167e..30f998a 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -1,5 +1,5 @@
 ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/msm
-ccflags-$(CONFIG_DRM_MSM_DSI_PLL) += -Idrivers/gpu/drm/msm/dsi
+ccflags-$(CONFIG_DRM_MSM_DSI) += -Idrivers/gpu/drm/msm/dsi

 msm-y := \
adreno/adreno_device.o \
@@ -56,7 +56,9 @@ msm-$(CONFIG_COMMON_CLK) += mdp/mdp4/mdp4_lvds_pll.o
 msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \
dsi/dsi_host.o \
dsi/dsi_manager.o \
-   dsi/dsi_phy.o \
+   dsi/phy/dsi_phy.o \
+   dsi/phy/dsi_phy_20nm.o \
+   dsi/phy/dsi_phy_28nm.o \
mdp/mdp5/mdp5_cmd_encoder.o

 msm-$(CONFIG_DRM_MSM_DSI_PLL) += dsi/pll/dsi_pll.o \
diff --git a/drivers/gpu/drm/msm/dsi/dsi_phy.c 
b/drivers/gpu/drm/msm/dsi/dsi_phy.c
deleted file mode 100644
index 77f1efe..000
--- a/drivers/gpu/drm/msm/dsi/dsi_phy.c
+++ /dev/null
@@ -1,756 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT 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 
-#include 
-
-#include "dsi.h"
-#include "dsi.xml.h"
-
-#define dsi_phy_read(offset) msm_readl((offset))
-#define dsi_phy_write(offset, data) msm_writel((data), (offset))
-
-struct dsi_phy_ops {
-   int (*enable)(struct msm_dsi_phy *phy, int src_pll_id,
-   const unsigned long bit_rate, const unsigned long esc_rate);
-   void (*disable)(struct msm_dsi_phy *phy);
-};
-
-struct dsi_phy_cfg {
-   enum msm_dsi_phy_type type;
-   struct dsi_reg_config reg_cfg;
-   struct dsi_phy_ops ops;
-
-   /* Each cell {phy_id, pll_id} of the truth table indicates
-* if the source PLL is on the right side of the PHY.
-* Fill default H/W values in illegal cells, eg. cell {0, 1}.
-*/
-   bool src_pll_truthtable[DSI_MAX][DSI_MAX];
-};
-
-struct dsi_dphy_timing {
-   u32 clk_pre;
-   u32 clk_post;
-   u32 clk_zero;
-   u32 clk_trail;
-   u32 clk_prepare;
-   u32 hs_exit;
-   u32 hs_zero;
-   u32 hs_prepare;
-   u32 hs_trail;
-   u32 hs_rqst;
-   u32 ta_go;
-   u32 ta_sure;
-   u32 ta_get;
-};
-
-struct msm_dsi_phy {
-   struct platform_device *pdev;
-   void __iomem *base;
-   void __iomem *reg_base;
-   int id;
-
-   struct clk *ahb_clk;
-   struct regulator_bulk_data supplies[DSI_DEV_REGULATOR_MAX];
-
-   struct dsi_dphy_timing timing;
-   const struct dsi_phy_cfg *cfg;
-
-   bool regulator_ldo_mode;
-
-   struct msm_dsi_pll *pll;
-};
-
-static int dsi_phy_regulator_init(struct msm_dsi_phy *phy)
-{
-   struct regulator_bulk_data *s = phy->supplies;
-   const struct dsi_reg_entry *regs = phy->cfg->reg_cfg.regs;
-   struct device *dev = >pdev->dev;
-   int num = phy->cfg->reg_cfg.num;
-   int i, ret;
-
-   for (i = 0; i < num; i++)
-   s[i].supply = regs[i].name;
-
-   ret = devm_regulator_bulk_get(>pdev->dev, num, s);
-   if (ret < 0) {
-   dev_err(dev, "%s: failed to init regulator, ret=%d\n",
-   __func__, ret);
-   return ret;
-   }
-
-   for (i = 0; i < num; i++) {
-   if ((regs[i].min_voltage >= 0) && (regs[i].max_voltage >= 0)) {
-   ret = regulator_set_voltage(s[i].consumer,
-   regs[i].min_voltage, regs[i].max_voltage);
-   if (ret < 0) {
-  

[PATCH 3/5] drm/msm/dsi: Return void from msm_dsi_phy_disable()

2015-08-13 Thread Hai Li
We are not checking the return value from msm_dsi_phy_disable().
Change the return type to void.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/dsi/dsi.h |  2 +-
 drivers/gpu/drm/msm/dsi/dsi_phy.c | 16 +---
 2 files changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 09492bf..5f5a373 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -168,7 +168,7 @@ void msm_dsi_phy_driver_register(void);
 void msm_dsi_phy_driver_unregister(void);
 int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
const unsigned long bit_rate, const unsigned long esc_rate);
-int msm_dsi_phy_disable(struct msm_dsi_phy *phy);
+void msm_dsi_phy_disable(struct msm_dsi_phy *phy);
 void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy,
u32 *clk_pre, u32 *clk_post);
 struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_phy.c 
b/drivers/gpu/drm/msm/dsi/dsi_phy.c
index 799201e..77f1efe 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_phy.c
@@ -23,7 +23,7 @@
 struct dsi_phy_ops {
int (*enable)(struct msm_dsi_phy *phy, int src_pll_id,
const unsigned long bit_rate, const unsigned long esc_rate);
-   int (*disable)(struct msm_dsi_phy *phy);
+   void (*disable)(struct msm_dsi_phy *phy);
 };

 struct dsi_phy_cfg {
@@ -399,7 +399,7 @@ static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy, int 
src_pll_id,
return 0;
 }

-static int dsi_28nm_phy_disable(struct msm_dsi_phy *phy)
+static void dsi_28nm_phy_disable(struct msm_dsi_phy *phy)
 {
dsi_phy_write(phy->base + REG_DSI_28nm_PHY_CTRL_0, 0);
dsi_28nm_phy_regulator_ctrl(phy, false);
@@ -409,8 +409,6 @@ static int dsi_28nm_phy_disable(struct msm_dsi_phy *phy)
 * ensure that the phy is completely disabled
 */
wmb();
-
-   return 0;
 }

 static void dsi_20nm_phy_regulator_ctrl(struct msm_dsi_phy *phy, bool enable)
@@ -515,12 +513,10 @@ static int dsi_20nm_phy_enable(struct msm_dsi_phy *phy, 
int src_pll_id,
return 0;
 }

-static int dsi_20nm_phy_disable(struct msm_dsi_phy *phy)
+static void dsi_20nm_phy_disable(struct msm_dsi_phy *phy)
 {
dsi_phy_write(phy->base + REG_DSI_20nm_PHY_CTRL_0, 0);
dsi_20nm_phy_regulator_ctrl(phy, false);
-
-   return 0;
 }

 static int dsi_phy_enable_resource(struct msm_dsi_phy *phy)
@@ -730,15 +726,13 @@ int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int 
src_pll_id,
return phy->cfg->ops.enable(phy, src_pll_id, bit_rate, esc_rate);
 }

-int msm_dsi_phy_disable(struct msm_dsi_phy *phy)
+void msm_dsi_phy_disable(struct msm_dsi_phy *phy)
 {
if (!phy || !phy->cfg->ops.disable)
-   return -EINVAL;
+   return;

phy->cfg->ops.disable(phy);
dsi_phy_regulator_disable(phy);
-
-   return 0;
 }

 void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy,
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH 2/5] drm/msm/dsi: Specify bitmask to set source PLL

2015-08-13 Thread Hai Li
The bit position to configure source PLL will change
on new types of PHYs. The caller should pass down
this information.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/dsi/dsi_phy.c | 16 +++-
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_phy.c 
b/drivers/gpu/drm/msm/dsi/dsi_phy.c
index bd37e61..799201e 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_phy.c
@@ -157,17 +157,21 @@ fail:
return ret;
 }

-static void dsi_phy_set_src_pll(struct msm_dsi_phy *phy, int pll_id, u32 reg)
+static void dsi_phy_set_src_pll(struct msm_dsi_phy *phy, int pll_id, u32 reg,
+   u32 bit_mask)
 {
int phy_id = phy->id;
+   u32 val;

if ((phy_id >= DSI_MAX) || (pll_id >= DSI_MAX))
return;

+   val = dsi_phy_read(phy->base + reg);
+
if (phy->cfg->src_pll_truthtable[phy_id][pll_id])
-   dsi_phy_write(phy->base + reg, 0x01);
+   dsi_phy_write(phy->base + reg, val | bit_mask);
else
-   dsi_phy_write(phy->base + reg, 0x00);
+   dsi_phy_write(phy->base + reg, val & (~bit_mask));
 }

 #define S_DIV_ROUND_UP(n, d)   \
@@ -389,7 +393,8 @@ static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy, int 
src_pll_id,

dsi_phy_write(base + REG_DSI_28nm_PHY_CTRL_0, 0x5f);

-   dsi_phy_set_src_pll(phy, src_pll_id, REG_DSI_28nm_PHY_GLBL_TEST_CTRL);
+   dsi_phy_set_src_pll(phy, src_pll_id, REG_DSI_28nm_PHY_GLBL_TEST_CTRL,
+   DSI_28nm_PHY_GLBL_TEST_CTRL_BITCLK_HS_SEL);

return 0;
 }
@@ -451,7 +456,8 @@ static int dsi_20nm_phy_enable(struct msm_dsi_phy *phy, int 
src_pll_id,

dsi_phy_write(base + REG_DSI_20nm_PHY_STRENGTH_0, 0xff);

-   dsi_phy_set_src_pll(phy, src_pll_id, REG_DSI_20nm_PHY_GLBL_TEST_CTRL);
+   dsi_phy_set_src_pll(phy, src_pll_id, REG_DSI_20nm_PHY_GLBL_TEST_CTRL,
+   DSI_20nm_PHY_GLBL_TEST_CTRL_BITCLK_HS_SEL);

for (i = 0; i < 4; i++) {
dsi_phy_write(base + REG_DSI_20nm_PHY_LN_CFG_3(i),
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH 1/5] drm/msm/dsi: Update generated header file for DSI PHY

2015-08-13 Thread Hai Li
This change is to update DSI register definition changes
introduced by the following change:

rnndb/dsi: Add more bits for DSI PHY

More registers and bit fields are added for PHY timings
and bitclk source selection.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/dsi/dsi.xml.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h 
b/drivers/gpu/drm/msm/dsi/dsi.xml.h
index 0af0981..41c6376 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
@@ -440,6 +440,9 @@ static inline uint32_t DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL(enum 
dsi_lane_swap val)
 #define REG_DSI_PHY_RESET  0x0128
 #define DSI_PHY_RESET_RESET0x0001

+#define REG_DSI_T_CLK_PRE_EXTEND   0x017c
+#define DSI_T_CLK_PRE_EXTEND_INC_BY_2_BYTECLK  0x0001
+
 #define REG_DSI_RDBK_DATA_CTRL 0x01d0
 #define DSI_RDBK_DATA_CTRL_COUNT__MASK 0x00ff
 #define DSI_RDBK_DATA_CTRL_COUNT__SHIFT16
@@ -835,6 +838,7 @@ static inline uint32_t 
DSI_28nm_PHY_TIMING_CTRL_11_TRIG3_CMD(uint32_t val)
 #define REG_DSI_28nm_PHY_BIST_CTRL_5   0x01c8

 #define REG_DSI_28nm_PHY_GLBL_TEST_CTRL
0x01d4
+#define DSI_28nm_PHY_GLBL_TEST_CTRL_BITCLK_HS_SEL  0x0001

 #define REG_DSI_28nm_PHY_LDO_CNTRL 0x01dc

@@ -1161,6 +1165,7 @@ static inline uint32_t 
DSI_20nm_PHY_TIMING_CTRL_11_TRIG3_CMD(uint32_t val)
 #define REG_DSI_20nm_PHY_BIST_CTRL_5   0x01c8

 #define REG_DSI_20nm_PHY_GLBL_TEST_CTRL
0x01d4
+#define DSI_20nm_PHY_GLBL_TEST_CTRL_BITCLK_HS_SEL  0x0001

 #define REG_DSI_20nm_PHY_LDO_CNTRL 0x01dc

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH 0/5] drm/msm/dsi: Split different types of PHY drivers

2015-08-13 Thread Hai Li
The DSI PHY driver currently includes the implementation of all PHY types.
To support more types in the future, this patch series is moving each PHY
code into a separate file and making them compile independent. Some clean
up patches for DSI PHY are also included.

Hai Li (5):
  drm/msm/dsi: Update generated header file for DSI PHY
  drm/msm/dsi: Specify bitmask to set source PLL
  drm/msm/dsi: Return void from msm_dsi_phy_disable()
  drm/msm/dsi: Split PHY drivers to separate files
  drm/msm/dsi: Make each PHY type compilation independent

 drivers/gpu/drm/msm/Kconfig|  14 +
 drivers/gpu/drm/msm/Makefile   |  13 +-
 drivers/gpu/drm/msm/dsi/dsi.h  |   2 +-
 drivers/gpu/drm/msm/dsi/dsi.xml.h  |   5 +
 drivers/gpu/drm/msm/dsi/dsi_phy.c  | 756 -
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c  | 452 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.h  |  89 
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c | 150 ++
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c | 166 +++
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.h  |   8 +
 10 files changed, 894 insertions(+), 761 deletions(-)
 delete mode 100644 drivers/gpu/drm/msm/dsi/dsi_phy.c
 create mode 100644 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
 create mode 100644 drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
 create mode 100644 drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c
 create mode 100644 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH] rnndb/dsi: Add more bits for DSI PHY

2015-08-13 Thread Hai Li
More registers and bit fields are added for PHY timings
and bitclk source selection.

Signed-off-by: Hai Li 
---
 rnndb/dsi/dsi.xml | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/rnndb/dsi/dsi.xml b/rnndb/dsi/dsi.xml
index 02cfa3b..956f3ff 100644
--- a/rnndb/dsi/dsi.xml
+++ b/rnndb/dsi/dsi.xml
@@ -217,6 +217,9 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



+   
+   
+   



@@ -437,7 +440,9 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



-   
+   
+   
+   

 

@@ -608,7 +613,9 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



-   
+   
+   
+   

 

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH v2] drm/msm: Enable clocks during enable/disable_vblank() callbacks

2015-07-27 Thread Hai Li
AHB clock should be enabled before accessing registers during
enable/disable_vblank(). Since these 2 callbacks are called in
atomic context while clk_prepare may cause thread sleep, a work
is scheduled to control vblanks.

v2: fixup spinlock initialization

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c |  9 
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c |  9 
 drivers/gpu/drm/msm/msm_drv.c   | 74 -
 drivers/gpu/drm/msm/msm_drv.h   |  8 
 4 files changed, 98 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c 
b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
index 7369ee7f..64d24fc 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
@@ -86,13 +86,22 @@ irqreturn_t mdp4_irq(struct msm_kms *kms)

 int mdp4_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
 {
+   struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
+
+   mdp4_enable(mdp4_kms);
mdp_update_vblank_mask(to_mdp_kms(kms),
mdp4_crtc_vblank(crtc), true);
+   mdp4_disable(mdp4_kms);
+
return 0;
 }

 void mdp4_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
 {
+   struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
+
+   mdp4_enable(mdp4_kms);
mdp_update_vblank_mask(to_mdp_kms(kms),
mdp4_crtc_vblank(crtc), false);
+   mdp4_disable(mdp4_kms);
 }
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
index 33bd4c6..2a578f2 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
@@ -112,15 +112,24 @@ irqreturn_t mdp5_irq(struct msm_kms *kms)

 int mdp5_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
 {
+   struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+
+   mdp5_enable(mdp5_kms);
mdp_update_vblank_mask(to_mdp_kms(kms),
mdp5_crtc_vblank(crtc), true);
+   mdp5_disable(mdp5_kms);
+
return 0;
 }

 void mdp5_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
 {
+   struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+
+   mdp5_enable(mdp5_kms);
mdp_update_vblank_mask(to_mdp_kms(kms),
mdp5_crtc_vblank(crtc), false);
+   mdp5_disable(mdp5_kms);
 }

 /*
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index b7ef56e..0c47c2d 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -116,6 +116,65 @@ u32 msm_readl(const void __iomem *addr)
return val;
 }

+struct vblank_event {
+   struct list_head node;
+   int crtc_id;
+   bool enable;
+};
+
+static void vblank_ctrl_worker(struct work_struct *work)
+{
+   struct msm_vblank_ctrl *vbl_ctrl = container_of(work,
+   struct msm_vblank_ctrl, work);
+   struct msm_drm_private *priv = container_of(vbl_ctrl,
+   struct msm_drm_private, vblank_ctrl);
+   struct msm_kms *kms = priv->kms;
+   struct vblank_event *vbl_ev, *tmp;
+   unsigned long flags;
+
+   spin_lock_irqsave(_ctrl->lock, flags);
+   list_for_each_entry_safe(vbl_ev, tmp, _ctrl->event_list, node) {
+   list_del(_ev->node);
+   spin_unlock_irqrestore(_ctrl->lock, flags);
+
+   if (vbl_ev->enable)
+   kms->funcs->enable_vblank(kms,
+   priv->crtcs[vbl_ev->crtc_id]);
+   else
+   kms->funcs->disable_vblank(kms,
+   priv->crtcs[vbl_ev->crtc_id]);
+
+   kfree(vbl_ev);
+
+   spin_lock_irqsave(_ctrl->lock, flags);
+   }
+
+   spin_unlock_irqrestore(_ctrl->lock, flags);
+}
+
+static int vblank_ctrl_queue_work(struct msm_drm_private *priv,
+   int crtc_id, bool enable)
+{
+   struct msm_vblank_ctrl *vbl_ctrl = >vblank_ctrl;
+   struct vblank_event *vbl_ev;
+   unsigned long flags;
+
+   vbl_ev = kzalloc(sizeof(*vbl_ev), GFP_ATOMIC);
+   if (!vbl_ev)
+   return -ENOMEM;
+
+   vbl_ev->crtc_id = crtc_id;
+   vbl_ev->enable = enable;
+
+   spin_lock_irqsave(_ctrl->lock, flags);
+   list_add_tail(_ev->node, _ctrl->event_list);
+   spin_unlock_irqrestore(_ctrl->lock, flags);
+
+   queue_work(priv->wq, _ctrl->work);
+
+   return 0;
+}
+
 /*
  * DRM operations:
  */
@@ -125,6 +184,14 @@ static int msm_unload(struct drm_device *dev)
struct msm_drm_private *priv = dev->dev_private;
struct msm_kms *kms = priv->kms;
struct msm_gpu *gpu = priv->gpu;
+   struct msm_vblank_ctrl *vbl_ctrl = >vblank_

[PATCH] drm/msm: Enable clocks during enable/disable_vblank() callbacks

2015-07-10 Thread Hai Li
AHB clock should be enabled before accessing registers during
enable/disable_vblank(). Since these 2 callbacks are called in
atomic context while clk_prepare may cause thread sleep, a work
is scheduled to control vblanks.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c |  9 
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c |  9 
 drivers/gpu/drm/msm/msm_drv.c   | 73 -
 drivers/gpu/drm/msm/msm_drv.h   |  8 
 4 files changed, 97 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c 
b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
index 7369ee7f..64d24fc 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
@@ -86,13 +86,22 @@ irqreturn_t mdp4_irq(struct msm_kms *kms)

 int mdp4_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
 {
+   struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
+
+   mdp4_enable(mdp4_kms);
mdp_update_vblank_mask(to_mdp_kms(kms),
mdp4_crtc_vblank(crtc), true);
+   mdp4_disable(mdp4_kms);
+
return 0;
 }

 void mdp4_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
 {
+   struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
+
+   mdp4_enable(mdp4_kms);
mdp_update_vblank_mask(to_mdp_kms(kms),
mdp4_crtc_vblank(crtc), false);
+   mdp4_disable(mdp4_kms);
 }
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
index 33bd4c6..2a578f2 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
@@ -112,15 +112,24 @@ irqreturn_t mdp5_irq(struct msm_kms *kms)

 int mdp5_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
 {
+   struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+
+   mdp5_enable(mdp5_kms);
mdp_update_vblank_mask(to_mdp_kms(kms),
mdp5_crtc_vblank(crtc), true);
+   mdp5_disable(mdp5_kms);
+
return 0;
 }

 void mdp5_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
 {
+   struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+
+   mdp5_enable(mdp5_kms);
mdp_update_vblank_mask(to_mdp_kms(kms),
mdp5_crtc_vblank(crtc), false);
+   mdp5_disable(mdp5_kms);
 }

 /*
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index b7ef56e..5265933 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -116,6 +116,65 @@ u32 msm_readl(const void __iomem *addr)
return val;
 }

+struct vblank_event {
+   struct list_head node;
+   int crtc_id;
+   bool enable;
+};
+
+static void vblank_ctrl_worker(struct work_struct *work)
+{
+   struct msm_vblank_ctrl *vbl_ctrl = container_of(work,
+   struct msm_vblank_ctrl, work);
+   struct msm_drm_private *priv = container_of(vbl_ctrl,
+   struct msm_drm_private, vblank_ctrl);
+   struct msm_kms *kms = priv->kms;
+   struct vblank_event *vbl_ev, *tmp;
+   unsigned long flags;
+
+   spin_lock_irqsave(_ctrl->lock, flags);
+   list_for_each_entry_safe(vbl_ev, tmp, _ctrl->event_list, node) {
+   list_del(_ev->node);
+   spin_unlock_irqrestore(_ctrl->lock, flags);
+
+   if (vbl_ev->enable)
+   kms->funcs->enable_vblank(kms,
+   priv->crtcs[vbl_ev->crtc_id]);
+   else
+   kms->funcs->disable_vblank(kms,
+   priv->crtcs[vbl_ev->crtc_id]);
+
+   kfree(vbl_ev);
+
+   spin_lock_irqsave(_ctrl->lock, flags);
+   }
+
+   spin_unlock_irqrestore(_ctrl->lock, flags);
+}
+
+static int vblank_ctrl_queue_work(struct msm_drm_private *priv,
+   int crtc_id, bool enable)
+{
+   struct msm_vblank_ctrl *vbl_ctrl = >vblank_ctrl;
+   struct vblank_event *vbl_ev;
+   unsigned long flags;
+
+   vbl_ev = kzalloc(sizeof(*vbl_ev), GFP_ATOMIC);
+   if (!vbl_ev)
+   return -ENOMEM;
+
+   vbl_ev->crtc_id = crtc_id;
+   vbl_ev->enable = enable;
+
+   spin_lock_irqsave(_ctrl->lock, flags);
+   list_add_tail(_ev->node, _ctrl->event_list);
+   spin_unlock_irqrestore(_ctrl->lock, flags);
+
+   queue_work(priv->wq, _ctrl->work);
+
+   return 0;
+}
+
 /*
  * DRM operations:
  */
@@ -125,6 +184,14 @@ static int msm_unload(struct drm_device *dev)
struct msm_drm_private *priv = dev->dev_private;
struct msm_kms *kms = priv->kms;
struct msm_gpu *gpu = priv->gpu;
+   struct msm_vblank_ctrl *vbl_ctrl = >vblank_ctrl;
+   struct vblank_event *vbl_ev, *tmp;
+
+  

[PATCH] drm/msm/dsi: Save/Restore PLL status across PHY reset

2015-07-03 Thread Hai Li
Reset DSI PHY silently changes its PLL registers to reset status,
which will make cached status in clock driver invalid and result
in wrong output rate of link clocks. The current restore mechanism
in DSI PLL does not cover all the cases. This change is to recover
PLL status after PHY reset to match HW status with cached status
in clock driver.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/dsi/dsi.h  |  9 +++
 drivers/gpu/drm/msm/dsi/dsi_manager.c  | 21 +++
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.c  | 42 +-
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.h  |  1 +
 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c | 31 +-
 5 files changed, 68 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index e18872a..912057d 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -95,6 +95,8 @@ struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device 
*pdev,
 void msm_dsi_pll_destroy(struct msm_dsi_pll *pll);
 int msm_dsi_pll_get_clk_provider(struct msm_dsi_pll *pll,
struct clk **byte_clk_provider, struct clk **pixel_clk_provider);
+void msm_dsi_pll_save_state(struct msm_dsi_pll *pll);
+int msm_dsi_pll_restore_state(struct msm_dsi_pll *pll);
 #else
 static inline struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device 
*pdev,
 enum msm_dsi_phy_type type, int id) {
@@ -108,6 +110,13 @@ static inline int msm_dsi_pll_get_clk_provider(struct 
msm_dsi_pll *pll,
 {
return -ENODEV;
 }
+static inline void msm_dsi_pll_save_state(struct msm_dsi_pll *pll)
+{
+}
+static inline int msm_dsi_pll_restore_state(struct msm_dsi_pll *pll)
+{
+   return 0;
+}
 #endif

 /* dsi host */
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c 
b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index bd247b7..ca4ff4a 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -611,12 +611,28 @@ int msm_dsi_manager_phy_enable(int id,
struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
struct msm_dsi_phy *phy = msm_dsi->phy;
int src_pll_id = IS_DUAL_DSI() ? DSI_CLOCK_MASTER : id;
+   struct msm_dsi_pll *pll = msm_dsi_phy_get_pll(msm_dsi->phy);
int ret;

ret = msm_dsi_phy_enable(phy, src_pll_id, bit_rate, esc_rate);
if (ret)
return ret;

+   /*
+* Reset DSI PHY silently changes its PLL registers to reset status,
+* which will confuse clock driver and result in wrong output rate of
+* link clocks. Restore PLL status if its PLL is being used as clock
+* source.
+*/
+   if (!IS_DUAL_DSI() || (id == DSI_CLOCK_MASTER)) {
+   ret = msm_dsi_pll_restore_state(pll);
+   if (ret) {
+   pr_err("%s: failed to restore pll state\n", __func__);
+   msm_dsi_phy_disable(phy);
+   return ret;
+   }
+   }
+
msm_dsi->phy_enabled = true;
msm_dsi_phy_get_clk_pre_post(phy, clk_pre, clk_post);

@@ -629,6 +645,11 @@ void msm_dsi_manager_phy_disable(int id)
struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
struct msm_dsi_phy *phy = msm_dsi->phy;
+   struct msm_dsi_pll *pll = msm_dsi_phy_get_pll(msm_dsi->phy);
+
+   /* Save PLL status if it is a clock source */
+   if (!IS_DUAL_DSI() || (id == DSI_CLOCK_MASTER))
+   msm_dsi_pll_save_state(pll);

/* disable DSI phy
 * In dual-dsi configuration, the phy should be disabled for the
diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c 
b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c
index 509376f..5104fc9 100644
--- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c
+++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c
@@ -72,31 +72,14 @@ long msm_dsi_pll_helper_clk_round_rate(struct clk_hw *hw,
 int msm_dsi_pll_helper_clk_prepare(struct clk_hw *hw)
 {
struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
-   int ret;
-
-   /*
-* Certain PLLs need to update the same VCO rate and registers
-* after resume in suspend/resume scenario.
-*/
-   if (pll->restore_state) {
-   ret = pll->restore_state(pll);
-   if (ret)
-   goto error;
-   }

-   ret = dsi_pll_enable(pll);
-
-error:
-   return ret;
+   return dsi_pll_enable(pll);
 }

 void msm_dsi_pll_helper_clk_unprepare(struct clk_hw *hw)
 {
struct msm_dsi_pll *pll = hw_clk_to_pll(hw);

-   if (pll->save_state)
-   pll->save_state(pll);
-
dsi_pll_disable(pll);
 }

@@ -134,6 +117,29 @@ void msm_dsi_pll_destroy(struct msm_dsi_pll *pll)
pll->destroy(pll);
 }

+void msm_dsi_pll_save_state(struct msm_dsi_pll *pll)
+{
+   if (pll->save_state) {
+ 

[PATCH 2/2] drm/msm/mdp5: Allocate CTL0/1 for dual DSI single FLUSH

2015-06-26 Thread Hai Li
This change takes advantage of a HW feature that synchronize
flush operation on CTL1 to CTL0, to keep dual DSI pipes in
sync.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c | 140 
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h |   4 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c |   6 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c |   2 +-
 4 files changed, 129 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
index c968ec5..62dac5c 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
@@ -17,7 +17,7 @@
 /*
  * CTL - MDP Control Pool Manager
  *
- * Controls are shared between all CRTCs.
+ * Controls are shared between all display interfaces.
  *
  * They are intended to be used for data path configuration.
  * The top level register programming describes the complete data path for
@@ -27,12 +27,11 @@
  *
  * In certain use cases (high-resolution dual pipe), one single CTL can be
  * shared across multiple CRTCs.
- *
- * Because the number of CTLs can be less than the number of CRTCs,
- * CTLs are dynamically allocated from a pool of CTLs, only once a CRTC is
- * requested by the client (in mdp5_crtc_mode_set()).
  */

+#define CTL_STAT_BUSY  0x1
+#define CTL_STAT_BOOKED0x2
+
 struct op_mode {
struct mdp5_interface intf;

@@ -46,8 +45,8 @@ struct mdp5_ctl {
u32 id;
int lm;

-   /* whether this CTL has been allocated or not: */
-   bool busy;
+   /* CTL status bitmask */
+   u32 status;

/* Operation Mode Configuration for the Pipeline */
struct op_mode pipeline;
@@ -60,6 +59,11 @@ struct mdp5_ctl {
u32 pending_ctl_trigger;

bool cursor_on;
+
+   /* True if the current CTL has FLUSH bits pending for single FLUSH. */
+   bool flush_pending;
+
+   struct mdp5_ctl *pair; /* Paired CTL to be flushed together */
 };

 struct mdp5_ctl_manager {
@@ -72,6 +76,10 @@ struct mdp5_ctl_manager {
/* to filter out non-present bits in the current hardware config */
u32 flush_hw_mask;

+   /* status for single FLUSH */
+   bool single_flush_supported;
+   u32 single_flush_pending_mask;
+
/* pool of CTLs + lock to protect resource allocation (ctls[i].busy) */
spinlock_t pool_lock;
struct mdp5_ctl ctls[MAX_CTL];
@@ -387,6 +395,31 @@ static u32 fix_sw_flush(struct mdp5_ctl *ctl, u32 
flush_mask)
return sw_mask;
 }

+static void fix_for_single_flush(struct mdp5_ctl *ctl, u32 *flush_mask,
+   u32 *flush_id)
+{
+   struct mdp5_ctl_manager *ctl_mgr = ctl->ctlm;
+
+   if (ctl->pair) {
+   DBG("CTL %d FLUSH pending mask %x", ctl->id, *flush_mask);
+   ctl->flush_pending = true;
+   ctl_mgr->single_flush_pending_mask |= (*flush_mask);
+   *flush_mask = 0;
+
+   if (ctl->pair->flush_pending) {
+   *flush_id = min_t(u32, ctl->id, ctl->pair->id);
+   *flush_mask = ctl_mgr->single_flush_pending_mask;
+
+   ctl->flush_pending = false;
+   ctl->pair->flush_pending = false;
+   ctl_mgr->single_flush_pending_mask = 0;
+
+   DBG("Single FLUSH mask %x,ID %d", *flush_mask,
+   *flush_id);
+   }
+   }
+}
+
 /**
  * mdp5_ctl_commit() - Register Flush
  *
@@ -408,6 +441,8 @@ u32 mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask)
struct mdp5_ctl_manager *ctl_mgr = ctl->ctlm;
struct op_mode *pipeline = >pipeline;
unsigned long flags;
+   u32 flush_id = ctl->id;
+   u32 curr_ctl_flush_mask;

pipeline->start_mask &= ~flush_mask;

@@ -423,9 +458,13 @@ u32 mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask)

flush_mask &= ctl_mgr->flush_hw_mask;

+   curr_ctl_flush_mask = flush_mask;
+
+   fix_for_single_flush(ctl, _mask, _id);
+
if (flush_mask) {
spin_lock_irqsave(>hw_lock, flags);
-   ctl_write(ctl, REG_MDP5_CTL_FLUSH(ctl->id), flush_mask);
+   ctl_write(ctl, REG_MDP5_CTL_FLUSH(flush_id), flush_mask);
spin_unlock_irqrestore(>hw_lock, flags);
}

@@ -434,7 +473,7 @@ u32 mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask)
refill_start_mask(ctl);
}

-   return flush_mask;
+   return curr_ctl_flush_mask;
 }

 u32 mdp5_ctl_get_commit_status(struct mdp5_ctl *ctl)
@@ -448,32 +487,79 @@ int mdp5_ctl_get_ctl_id(struct mdp5_ctl *ctl)
 }

 /*
+ * mdp5_ctl_pair() - Associate 2 booked CTLs for single FLUSH
+ */
+int mdp5_ctl_pair(struct mdp5_ctl *ctlx, struct mdp5_ctl *ctly, bool enable)
+{
+   struct mdp5_ctl_manager *ctl_mgr = c

[PATCH 1/2] drm/msm/mdp5: Allocate CTL for each display interface

2015-06-26 Thread Hai Li
In MDP5, CTL contains information of the whole pipeline whose
output goes down to a display interface. In various cases, one
interface may require 2 CRTCs, but only one CTL. Some interfaces
also require to use certain CTLs.

Instead of allocating CTL for each active CRTC, this change is to
associate a CTL with each interface.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c | 12 --
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c| 26 +++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c | 49 +
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h |  9 ++---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c | 12 --
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 36 ++
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h |  8 ++--
 7 files changed, 76 insertions(+), 76 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
index ee31b16..8e6c9b5 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
@@ -21,6 +21,8 @@ struct mdp5_cmd_encoder {
struct mdp5_interface intf;
bool enabled;
uint32_t bsc;
+
+   struct mdp5_ctl *ctl;
 };
 #define to_mdp5_cmd_encoder(x) container_of(x, struct mdp5_cmd_encoder, base)

@@ -210,13 +212,14 @@ static void mdp5_cmd_encoder_mode_set(struct drm_encoder 
*encoder,
mode->vsync_end, mode->vtotal,
mode->type, mode->flags);
pingpong_tearcheck_setup(encoder, mode);
-   mdp5_crtc_set_intf(encoder->crtc, _cmd_enc->intf);
+   mdp5_crtc_set_pipeline(encoder->crtc, _cmd_enc->intf,
+   mdp5_cmd_enc->ctl);
 }

 static void mdp5_cmd_encoder_disable(struct drm_encoder *encoder)
 {
struct mdp5_cmd_encoder *mdp5_cmd_enc = to_mdp5_cmd_encoder(encoder);
-   struct mdp5_ctl *ctl = mdp5_crtc_get_ctl(encoder->crtc);
+   struct mdp5_ctl *ctl = mdp5_cmd_enc->ctl;
struct mdp5_interface *intf = _cmd_enc->intf;

if (WARN_ON(!mdp5_cmd_enc->enabled))
@@ -235,7 +238,7 @@ static void mdp5_cmd_encoder_disable(struct drm_encoder 
*encoder)
 static void mdp5_cmd_encoder_enable(struct drm_encoder *encoder)
 {
struct mdp5_cmd_encoder *mdp5_cmd_enc = to_mdp5_cmd_encoder(encoder);
-   struct mdp5_ctl *ctl = mdp5_crtc_get_ctl(encoder->crtc);
+   struct mdp5_ctl *ctl = mdp5_cmd_enc->ctl;
struct mdp5_interface *intf = _cmd_enc->intf;

if (WARN_ON(mdp5_cmd_enc->enabled))
@@ -300,7 +303,7 @@ int mdp5_cmd_encoder_set_split_display(struct drm_encoder 
*encoder,

 /* initialize command mode encoder */
 struct drm_encoder *mdp5_cmd_encoder_init(struct drm_device *dev,
-   struct mdp5_interface *intf)
+   struct mdp5_interface *intf, struct mdp5_ctl *ctl)
 {
struct drm_encoder *encoder = NULL;
struct mdp5_cmd_encoder *mdp5_cmd_enc;
@@ -320,6 +323,7 @@ struct drm_encoder *mdp5_cmd_encoder_init(struct drm_device 
*dev,

memcpy(_cmd_enc->intf, intf, sizeof(mdp5_cmd_enc->intf));
encoder = _cmd_enc->base;
+   mdp5_cmd_enc->ctl = ctl;

drm_encoder_init(dev, encoder, _cmd_encoder_funcs,
DRM_MODE_ENCODER_DSI);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index dea3d2e..ca3d40b 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -160,8 +160,7 @@ static void complete_flip(struct drm_crtc *crtc, struct 
drm_file *file)

if (mdp5_crtc->ctl && !crtc->state->enable) {
/* set STAGE_UNUSED for all layers */
-   mdp5_ctl_blend(mdp5_crtc->ctl, mdp5_crtc->lm, 0x);
-   mdp5_ctl_release(mdp5_crtc->ctl);
+   mdp5_ctl_blend(mdp5_crtc->ctl, 0x);
mdp5_crtc->ctl = NULL;
}
 }
@@ -248,7 +247,7 @@ static void blend_setup(struct drm_crtc *crtc)
}

DBG("%s: lm%d: blend config = 0x%08x", mdp5_crtc->name, lm, blend_cfg);
-   mdp5_ctl_blend(mdp5_crtc->ctl, lm, blend_cfg);
+   mdp5_ctl_blend(mdp5_crtc->ctl, blend_cfg);

 out:
spin_unlock_irqrestore(_crtc->lm_lock, flags);
@@ -336,7 +335,6 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
struct drm_crtc_state *state)
 {
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
-   struct mdp5_kms *mdp5_kms = get_kms(crtc);
struct drm_plane *plane;
struct drm_device *dev = crtc->dev;
struct plane_state pstates[STAGE3 + 1];
@@ -344,13 +342,6 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,

DBG("%s: check", mdp5_crtc->name);

-   /* request a free CTL, if none is 

[PATCH 0/2] drm/msm/mdp5: Refactor CTL code

2015-06-26 Thread Hai Li
Instead of allocating CTL for each CRTC, we start to associate CTL
to each display interface, which reflects real HW requirement.
It also helps in making use of HW single FLUSH feature to sync
between dual DSI pipes.

Hai Li (2):
  drm/msm/mdp5: Allocate CTL for each display interface
  drm/msm/mdp5: Allocate CTL0/1 for dual DSI single FLUSH

 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c |  12 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c|  26 +---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c | 179 ++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h |  13 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c |  18 ++-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c |  38 +++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h |   8 +-
 7 files changed, 200 insertions(+), 94 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH] drm/msm: Set different display size limitation on each target

2015-06-24 Thread Hai Li
The maximum output width of one pipeline depends on the LayerMixer's
capability. It may be different on each target. Also, MDP5 doesn't
have vertical limitation in one frame, as long as the pixel clock
can be supported.

This change obtains the maximum LM resolution from configuration
table and treat it as the whole pipe's limitation for MDP5. The size
limit on MDP4 is not changed.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c | 5 +
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c | 8 
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h | 2 ++
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 5 +
 drivers/gpu/drm/msm/msm_drv.c   | 4 
 5 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c 
b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
index f0b6c4b..b3f5415 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
@@ -525,6 +525,11 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
goto fail;
}

+   dev->mode_config.min_width = 0;
+   dev->mode_config.min_height = 0;
+   dev->mode_config.max_width = 2048;
+   dev->mode_config.max_height = 2048;
+
return kms;

 fail:
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
index 9430a29..fc67926 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
@@ -58,6 +58,8 @@ const struct mdp5_cfg_hw msm8x74_config = {
.count = 5,
.base = { 0x03200, 0x03600, 0x03a00, 0x03e00, 0x04200 },
.nb_stages = 5,
+   .max_width = 2048,
+   .max_height = 0x,
},
.dspp = {
.count = 3,
@@ -126,6 +128,8 @@ const struct mdp5_cfg_hw apq8084_config = {
.count = 6,
.base = { 0x03a00, 0x03e00, 0x04200, 0x04600, 0x04a00, 0x04e00 
},
.nb_stages = 5,
+   .max_width = 2048,
+   .max_height = 0x,
},
.dspp = {
.count = 4,
@@ -187,6 +191,8 @@ const struct mdp5_cfg_hw msm8x16_config = {
.count = 2, /* LM0 and LM3 */
.base = { 0x45000, 0x48000 },
.nb_stages = 5,
+   .max_width = 2048,
+   .max_height = 0x,
},
.dspp = {
.count = 1,
@@ -248,6 +254,8 @@ const struct mdp5_cfg_hw msm8994_config = {
.count = 6,
.base = { 0x45000, 0x46000, 0x47000, 0x48000, 0x49000, 0x4a000 
},
.nb_stages = 5,
+   .max_width = 2048,
+   .max_height = 0x,
},
.dspp = {
.count = 4,
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
index 69349ab..8a19d27 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
@@ -42,6 +42,8 @@ struct mdp5_sub_block {
 struct mdp5_lm_block {
MDP5_SUB_BLOCK_DEFINITION;
uint32_t nb_stages; /* number of stages per blender */
+   uint32_t max_width; /* Maximum output resolution */
+   uint32_t max_height;
 };

 struct mdp5_ctl_block {
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index 7cc5153..4c8d3d0 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -576,6 +576,11 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
goto fail;
}

+   dev->mode_config.min_width = 0;
+   dev->mode_config.min_height = 0;
+   dev->mode_config.max_width = config->hw->lm.max_width;
+   dev->mode_config.max_height = config->hw->lm.max_height;
+
return kms;

 fail:
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 5af5d8c..41b412b 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -331,10 +331,6 @@ static int msm_load(struct drm_device *dev, unsigned long 
flags)
}
}

-   dev->mode_config.min_width = 0;
-   dev->mode_config.min_height = 0;
-   dev->mode_config.max_width = 2048;
-   dev->mode_config.max_height = 2048;
dev->mode_config.funcs = _config_funcs;

ret = drm_vblank_init(dev, priv->num_crtcs);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH 2/2] drm/msm/dsi: Add support for msm8x94

2015-06-18 Thread Hai Li
DSI controller on msm8x94 is version 1.3, which requires different
power supplies and works with 20nm DSI PHY. This change is to add
the basic support for this version.

Signed-off-by: Hai Li 
---
 Documentation/devicetree/bindings/drm/msm/dsi.txt |   7 ++
 drivers/gpu/drm/msm/dsi/dsi.h |   1 +
 drivers/gpu/drm/msm/dsi/dsi_host.c|  18 +++
 drivers/gpu/drm/msm/dsi/dsi_phy.c | 131 ++
 4 files changed, 157 insertions(+)

diff --git a/Documentation/devicetree/bindings/drm/msm/dsi.txt 
b/Documentation/devicetree/bindings/drm/msm/dsi.txt
index 4edd6fa..4309f0f 100644
--- a/Documentation/devicetree/bindings/drm/msm/dsi.txt
+++ b/Documentation/devicetree/bindings/drm/msm/dsi.txt
@@ -47,6 +47,7 @@ Required properties:
 - compatible: Could be the following
   * "qcom,dsi-phy-28nm-hpm"
   * "qcom,dsi-phy-28nm-lp"
+  * "qcom,dsi-phy-20nm"
 - reg: Physical base address and length of the registers of PLL, PHY and PHY
   regulator
 - reg-names: The names of register regions. The following regions are required:
@@ -62,6 +63,10 @@ Required properties:
   * "iface_clk"
 - vddio-supply: phandle to vdd-io regulator device node

+Optional properties:
+- qcom,dsi-phy-regulator-ldo-mode: Boolean value indicating if the LDO mode PHY
+  regulator is wanted.
+
 Example:
mdss_dsi0: qcom,mdss_dsi at fd922800 {
compatible = "qcom,mdss-dsi-ctrl";
@@ -124,4 +129,6 @@ Example:
clock-names = "iface_clk";
clocks = < MDSS_AHB_CLK>;
vddio-supply = <_l12>;
+
+   qcom,dsi-phy-regulator-ldo-mode;
};
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 5e29aad..e18872a 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -30,6 +30,7 @@
 enum msm_dsi_phy_type {
MSM_DSI_PHY_28NM_HPM,
MSM_DSI_PHY_28NM_LP,
+   MSM_DSI_PHY_20NM,
MSM_DSI_PHY_MAX
 };

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 69c1397..2d8f194 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -34,6 +34,7 @@
 #define MSM_DSI_6G_VER_MINOR_V1_1  0x1001
 #define MSM_DSI_6G_VER_MINOR_V1_1_10x10010001
 #define MSM_DSI_6G_VER_MINOR_V1_2  0x1002
+#define MSM_DSI_6G_VER_MINOR_V1_3  0x1003
 #define MSM_DSI_6G_VER_MINOR_V1_3_10x10030001

 #define DSI_6G_REG_SHIFT   4
@@ -117,6 +118,23 @@ static const struct dsi_config dsi_cfgs[] = {
},
},
},
+   { /* 8x94 */
+   .major = MSM_DSI_VER_MAJOR_6G,
+   .minor = MSM_DSI_6G_VER_MINOR_V1_3,
+   .io_offset = DSI_6G_REG_SHIFT,
+   .reg_cfg = {
+   .num = 7,
+   .regs = {
+   {"gdsc", -1, -1, -1, -1},
+   {"vdda", 125, 125, 10, 100},
+   {"vddio", 180, 180, 10, 100},
+   {"vcca", 100, 100, 1, 100},
+   {"vdd", 180, 180, 10, 100},
+   {"lab_reg", -1, -1, -1, -1},
+   {"ibb_reg", -1, -1, -1, -1},
+   },
+   }
+   },
 };

 static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)
diff --git a/drivers/gpu/drm/msm/dsi/dsi_phy.c 
b/drivers/gpu/drm/msm/dsi/dsi_phy.c
index 52b463e..bd37e61 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_phy.c
@@ -66,6 +66,8 @@ struct msm_dsi_phy {
struct dsi_dphy_timing timing;
const struct dsi_phy_cfg *cfg;

+   bool regulator_ldo_mode;
+
struct msm_dsi_pll *pll;
 };

@@ -406,6 +408,115 @@ static int dsi_28nm_phy_disable(struct msm_dsi_phy *phy)
return 0;
 }

+static void dsi_20nm_phy_regulator_ctrl(struct msm_dsi_phy *phy, bool enable)
+{
+   void __iomem *base = phy->reg_base;
+
+   if (!enable) {
+   dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CAL_PWR_CFG, 0);
+   return;
+   }
+
+   if (phy->regulator_ldo_mode) {
+   dsi_phy_write(phy->base + REG_DSI_20nm_PHY_LDO_CNTRL, 0x1d);
+   return;
+   }
+
+   /* non LDO mode */
+   dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_1, 0x03);
+   dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_2, 0x03);
+   dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_3, 0x00);
+   dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_4, 0x20);
+   dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CAL_PWR_CFG, 0x01);
+   dsi_phy_write(phy->base + REG_DSI_20nm_PHY_LDO_CNTRL, 

[PATCH 1/2] drm/msm/dsi: Update generated headers with 20nm PHY support

2015-06-18 Thread Hai Li
Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/dsi/dsi.xml.h | 192 +++---
 1 file changed, 181 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h 
b/drivers/gpu/drm/msm/dsi/dsi.xml.h
index 9791ea0..9bb63a9 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
@@ -8,17 +8,8 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git

 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/msm.xml (
676 bytes, from 2014-12-05 15:34:49)
-- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   
1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml(  
20915 bytes, from 2015-03-24 22:05:22)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml  (   
2352 bytes, from 2015-04-12 15:02:42)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml(  
35083 bytes, from 2015-04-12 15:04:03)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml (  
22094 bytes, from 2015-05-12 12:45:23)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml(
344 bytes, from 2013-08-11 19:26:32)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml (   
1686 bytes, from 2014-10-31 16:48:57)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml (
600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml   (  
29012 bytes, from 2015-05-12 12:45:23)
-- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml (  
10416 bytes, from 2015-05-12 12:45:23)
+- /usr2/hali/local/envytools/envytools/rnndb/dsi/dsi.xml (  25475 
bytes, from 2015-05-08 22:31:43)
+- /usr2/hali/local/envytools/envytools/rnndb/freedreno_copyright.xml (   1453 
bytes, from 2015-01-28 21:43:22)

 Copyright (C) 2013-2015 by the following authors:
 - Rob Clark  (robclark)
@@ -994,5 +985,184 @@ static inline uint32_t 
DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8(uint32_t val)

 #define REG_DSI_28nm_PHY_PLL_CTRL_54   0x00d4

+static inline uint32_t REG_DSI_20nm_PHY_LN(uint32_t i0) { return 0x + 
0x40*i0; }
+
+static inline uint32_t REG_DSI_20nm_PHY_LN_CFG_0(uint32_t i0) { return 
0x + 0x40*i0; }
+
+static inline uint32_t REG_DSI_20nm_PHY_LN_CFG_1(uint32_t i0) { return 
0x0004 + 0x40*i0; }
+
+static inline uint32_t REG_DSI_20nm_PHY_LN_CFG_2(uint32_t i0) { return 
0x0008 + 0x40*i0; }
+
+static inline uint32_t REG_DSI_20nm_PHY_LN_CFG_3(uint32_t i0) { return 
0x000c + 0x40*i0; }
+
+static inline uint32_t REG_DSI_20nm_PHY_LN_CFG_4(uint32_t i0) { return 
0x0010 + 0x40*i0; }
+
+static inline uint32_t REG_DSI_20nm_PHY_LN_TEST_DATAPATH(uint32_t i0) { return 
0x0014 + 0x40*i0; }
+
+static inline uint32_t REG_DSI_20nm_PHY_LN_DEBUG_SEL(uint32_t i0) { return 
0x0018 + 0x40*i0; }
+
+static inline uint32_t REG_DSI_20nm_PHY_LN_TEST_STR_0(uint32_t i0) { return 
0x001c + 0x40*i0; }
+
+static inline uint32_t REG_DSI_20nm_PHY_LN_TEST_STR_1(uint32_t i0) { return 
0x0020 + 0x40*i0; }
+
+#define REG_DSI_20nm_PHY_LNCK_CFG_00x0100
+
+#define REG_DSI_20nm_PHY_LNCK_CFG_10x0104
+
+#define REG_DSI_20nm_PHY_LNCK_CFG_20x0108
+
+#define REG_DSI_20nm_PHY_LNCK_CFG_30x010c
+
+#define REG_DSI_20nm_PHY_LNCK_CFG_40x0110
+
+#define REG_DSI_20nm_PHY_LNCK_TEST_DATAPATH0x0114
+
+#define REG_DSI_20nm_PHY_LNCK_DEBUG_SEL
0x0118
+
+#define REG_DSI_20nm_PHY_LNCK_TEST_STR0
0x011c
+
+#define REG_DSI_20nm_PHY_LNCK_TEST_STR1
0x0120
+
+#define REG_DSI_20nm_PHY_TIMING_CTRL_0 0x0140
+#define DSI_20nm_PHY_TIMING_CTRL_0_CLK_ZERO__MASK  0x00ff
+#define DSI_20nm_PHY_TIMING_CTRL_0_CLK_ZERO__SHIFT 0
+static inline uint32_t DSI_20nm_PHY_TIMING_CTRL_0_CLK_ZERO(uint32_t val)
+{
+   return ((val) << DSI_20nm_PHY_TIMING_CTRL_0_CLK_ZERO__SHIFT) & 
DSI_20nm_PHY_TIMING_CTRL_0_CLK_ZERO__MASK;
+}
+
+#define REG_DSI_20nm_PHY_TIMING_CTRL_1 0x0144
+#define DSI_20nm_PHY_TIMING_CTRL_1_CLK_TRAIL__MASK 0x00ff
+#define DSI_20nm_PHY_TIMING_CTRL_1_CLK_TRAIL__SHIFT0
+static inline uint32_t DSI_20nm_PHY_TIMING_CTRL_1_CLK_TRAIL(uint32_t val)
+{
+   return ((val) << DSI_20nm_PHY_TIMING_CTRL_1_CLK_TRAIL__SHIFT) & 
DSI_20nm_PHY_TIMING_CTRL_1_CLK_TRAIL__MASK;
+}
+
+#define REG_DSI_20nm_PHY_TIMING_CTRL_2 0x0148
+#define DSI_20nm_PHY_TIMING_CTRL_2_CLK_PREPARE__MASK  

[PATCH 0/2] drm/msm/dsi: msm8x94 configuration and support

2015-06-18 Thread Hai Li

Hai Li (2):
  drm/msm/dsi: Update generated headers with 20nm PHY support
  drm/msm/dsi: Add support for msm8x94

 Documentation/devicetree/bindings/drm/msm/dsi.txt |   7 +
 drivers/gpu/drm/msm/dsi/dsi.h |   1 +
 drivers/gpu/drm/msm/dsi/dsi.xml.h | 192 --
 drivers/gpu/drm/msm/dsi/dsi_host.c|  18 ++
 drivers/gpu/drm/msm/dsi/dsi_phy.c | 131 +++
 5 files changed, 338 insertions(+), 11 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH] rnndb/dsi: Add register descriptions for 20nm PHY

2015-06-18 Thread Hai Li
This change introduces new domains of PHY and PHY_REGULATOR
for 20nm DSI PHY registers.

Signed-off-by: Hai Li 
---
 rnndb/dsi/dsi.xml | 91 +++
 1 file changed, 91 insertions(+)

diff --git a/rnndb/dsi/dsi.xml b/rnndb/dsi/dsi.xml
index d19bea9..0f3d4ff 100644
--- a/rnndb/dsi/dsi.xml
+++ b/rnndb/dsi/dsi.xml
@@ -525,4 +525,95 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">

 

+
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+
+   
+   
+   
+   
+   
+   
+   
+   
+   
+
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+
+   
+   
+   
+   
+   
+
+   
+   
+
+   
+   
+   
+   
+   
+   
+
+   
+   
+
+
+
+   
+   
+   
+   
+   
+   
+   
+
+
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH] drm/msm/dsi: Use pinctrl in DSI driver

2015-06-11 Thread Hai Li
Some targets use pinctrl framework to configure some
pins. This change allows DSI driver to set default and
sleep pinctrl status.

Signed-off-by: Hai Li 
---
 Documentation/devicetree/bindings/drm/msm/dsi.txt |  7 +++
 drivers/gpu/drm/msm/dsi/dsi_host.c| 12 
 2 files changed, 19 insertions(+)

diff --git a/Documentation/devicetree/bindings/drm/msm/dsi.txt 
b/Documentation/devicetree/bindings/drm/msm/dsi.txt
index 6ccd860..4edd6fa 100644
--- a/Documentation/devicetree/bindings/drm/msm/dsi.txt
+++ b/Documentation/devicetree/bindings/drm/msm/dsi.txt
@@ -38,6 +38,9 @@ Optional properties:
   driving a 2-DSI panel whose 2 links need receive command simultaneously.
 - interrupt-parent: phandle to the MDP block if the interrupt signal is routed
   through MDP block
+- pinctrl-names: the pin control state names; should contain "default"
+- pinctrl-0: the default pinctrl state (active)
+- pinctrl-n: the "sleep" pinctrl state

 DSI PHY:
 Required properties:
@@ -94,6 +97,10 @@ Example:
qcom,master-dsi;
qcom,sync-dual-dsi;

+   pinctrl-names = "default", "sleep";
+   pinctrl-0 = <_dsi_active>;
+   pinctrl-1 = <_dsi_suspend>;
+
panel: panel at 0 {
compatible = "sharp,lq101r1sx01";
reg = <0>;
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index de04009..69c1397 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1919,6 +1920,13 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host)
goto fail_disable_reg;
}

+   ret = pinctrl_pm_select_default_state(_host->pdev->dev);
+   if (ret) {
+   pr_err("%s: failed to set pinctrl default state, %d\n",
+   __func__, ret);
+   goto fail_disable_clk;
+   }
+
dsi_timing_setup(msm_host);
dsi_sw_reset(msm_host);
dsi_ctrl_config(msm_host, true, clk_pre, clk_post);
@@ -1931,6 +1939,8 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host)

return 0;

+fail_disable_clk:
+   dsi_clk_ctrl(msm_host, 0);
 fail_disable_reg:
dsi_host_regulator_disable(msm_host);
 unlock_ret:
@@ -1953,6 +1963,8 @@ int msm_dsi_host_power_off(struct mipi_dsi_host *host)
if (msm_host->disp_en_gpio)
gpiod_set_value(msm_host->disp_en_gpio, 0);

+   pinctrl_pm_select_sleep_state(_host->pdev->dev);
+
msm_dsi_manager_phy_disable(msm_host->id);

dsi_clk_ctrl(msm_host, 0);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH 2/2] drm/msm/dsi: Rename *dual panel* to *dual DSI*

2015-06-10 Thread Hai Li
The current term of *dual panel* in DSI driver code causes confusion.
It is supposed to indicate the panel using two DSI links. Rename it
to *dual DSI*.

Signed-off-by: Hai Li 
---
 Documentation/devicetree/bindings/drm/msm/dsi.txt | 12 ++--
 drivers/gpu/drm/msm/dsi/dsi_manager.c | 84 +++
 2 files changed, 48 insertions(+), 48 deletions(-)

diff --git a/Documentation/devicetree/bindings/drm/msm/dsi.txt 
b/Documentation/devicetree/bindings/drm/msm/dsi.txt
index cd8fe6c..6ccd860 100644
--- a/Documentation/devicetree/bindings/drm/msm/dsi.txt
+++ b/Documentation/devicetree/bindings/drm/msm/dsi.txt
@@ -30,11 +30,11 @@ Optional properties:
 - panel at 0: Node of panel connected to this DSI controller.
   See files in Documentation/devicetree/bindings/panel/ for each supported
   panel.
-- qcom,dual-panel-mode: Boolean value indicating if the DSI controller is
+- qcom,dual-dsi-mode: Boolean value indicating if the DSI controller is
   driving a panel which needs 2 DSI links.
-- qcom,master-panel: Boolean value indicating if the DSI controller is driving
+- qcom,master-dsi: Boolean value indicating if the DSI controller is driving
   the master link of the 2-DSI panel.
-- qcom,sync-dual-panel: Boolean value indicating if the DSI controller is
+- qcom,sync-dual-dsi: Boolean value indicating if the DSI controller is
   driving a 2-DSI panel whose 2 links need receive command simultaneously.
 - interrupt-parent: phandle to the MDP block if the interrupt signal is routed
   through MDP block
@@ -90,9 +90,9 @@ Example:

qcom,dsi-phy = <_dsi_phy0>;

-   qcom,dual-panel-mode;
-   qcom,master-panel;
-   qcom,sync-dual-panel;
+   qcom,dual-dsi-mode;
+   qcom,master-dsi;
+   qcom,sync-dual-dsi;

panel: panel at 0 {
compatible = "sharp,lq101r1sx01";
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c 
b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index cfa632f..bd247b7 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -29,16 +29,16 @@
 struct msm_dsi_manager {
struct msm_dsi *dsi[DSI_MAX];

-   bool is_dual_panel;
+   bool is_dual_dsi;
bool is_sync_needed;
-   int master_panel_id;
+   int master_dsi_link_id;
 };

 static struct msm_dsi_manager msm_dsim_glb;

-#define IS_DUAL_PANEL()(msm_dsim_glb.is_dual_panel)
+#define IS_DUAL_DSI()  (msm_dsim_glb.is_dual_dsi)
 #define IS_SYNC_NEEDED()   (msm_dsim_glb.is_sync_needed)
-#define IS_MASTER_PANEL(id)(msm_dsim_glb.master_panel_id == id)
+#define IS_MASTER_DSI_LINK(id) (msm_dsim_glb.master_dsi_link_id == id)

 static inline struct msm_dsi *dsi_mgr_get_dsi(int id)
 {
@@ -50,23 +50,23 @@ static inline struct msm_dsi *dsi_mgr_get_other_dsi(int id)
return msm_dsim_glb.dsi[(id + 1) % DSI_MAX];
 }

-static int dsi_mgr_parse_dual_panel(struct device_node *np, int id)
+static int dsi_mgr_parse_dual_dsi(struct device_node *np, int id)
 {
struct msm_dsi_manager *msm_dsim = _dsim_glb;

-   /* We assume 2 dsi nodes have the same information of dual-panel and
+   /* We assume 2 dsi nodes have the same information of dual-dsi and
 * sync-mode, and only one node specifies master in case of dual mode.
 */
-   if (!msm_dsim->is_dual_panel)
-   msm_dsim->is_dual_panel = of_property_read_bool(
-   np, "qcom,dual-panel-mode");
+   if (!msm_dsim->is_dual_dsi)
+   msm_dsim->is_dual_dsi = of_property_read_bool(
+   np, "qcom,dual-dsi-mode");

-   if (msm_dsim->is_dual_panel) {
-   if (of_property_read_bool(np, "qcom,master-panel"))
-   msm_dsim->master_panel_id = id;
+   if (msm_dsim->is_dual_dsi) {
+   if (of_property_read_bool(np, "qcom,master-dsi"))
+   msm_dsim->master_dsi_link_id = id;
if (!msm_dsim->is_sync_needed)
msm_dsim->is_sync_needed = of_property_read_bool(
-   np, "qcom,sync-dual-panel");
+   np, "qcom,sync-dual-dsi");
}

return 0;
@@ -80,7 +80,7 @@ static int dsi_mgr_host_register(int id)
struct msm_dsi_pll *src_pll;
int ret;

-   if (!IS_DUAL_PANEL()) {
+   if (!IS_DUAL_DSI()) {
ret = msm_dsi_host_register(msm_dsi->host, true);
if (ret)
return ret;
@@ -90,9 +90,9 @@ static int dsi_mgr_host_register(int id)
} else if (!other_dsi) {
ret = 0;
} else {
-   struct msm_dsi *mdsi = IS_MASTER_PANEL(id) ?
+   struct msm_dsi *mdsi = IS_MAST

[PATCH 1/2] drm/msm/dsi: Update source PLL selection in DSI PHY

2015-06-10 Thread Hai Li
The source PLL to be used by each DSI PHY should be decided by
DSI manager based on dual DSI information, while the register
programming to select PLL is different from one type of PHY to
another. This change adds the H/W difference to PHY configuration
and updates the interface between DSI manager and PHY.

With this change, PLL selection can be supported on different
targets.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/dsi/dsi.h | 14 +-
 drivers/gpu/drm/msm/dsi/dsi_manager.c | 15 ++-
 drivers/gpu/drm/msm/dsi/dsi_phy.c | 34 ++
 3 files changed, 41 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 92d697d..5e29aad 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -27,18 +27,6 @@
 #define DSI_1  1
 #define DSI_MAX2

-#define DSI_CLOCK_MASTER   DSI_0
-#define DSI_CLOCK_SLAVEDSI_1
-
-#define DSI_LEFT   DSI_0
-#define DSI_RIGHT  DSI_1
-
-/* According to the current drm framework sequence, take the encoder of
- * DSI_1 as master encoder
- */
-#define DSI_ENCODER_MASTER DSI_1
-#define DSI_ENCODER_SLAVE  DSI_0
-
 enum msm_dsi_phy_type {
MSM_DSI_PHY_28NM_HPM,
MSM_DSI_PHY_28NM_LP,
@@ -153,7 +141,7 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi);
 struct msm_dsi_phy;
 void msm_dsi_phy_driver_register(void);
 void msm_dsi_phy_driver_unregister(void);
-int msm_dsi_phy_enable(struct msm_dsi_phy *phy, bool is_dual_panel,
+int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
const unsigned long bit_rate, const unsigned long esc_rate);
 int msm_dsi_phy_disable(struct msm_dsi_phy *phy);
 void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy,
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c 
b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 87ac661..cfa632f 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -14,6 +14,18 @@
 #include "msm_kms.h"
 #include "dsi.h"

+#define DSI_CLOCK_MASTER   DSI_0
+#define DSI_CLOCK_SLAVEDSI_1
+
+#define DSI_LEFT   DSI_0
+#define DSI_RIGHT  DSI_1
+
+/* According to the current drm framework sequence, take the encoder of
+ * DSI_1 as master encoder
+ */
+#define DSI_ENCODER_MASTER DSI_1
+#define DSI_ENCODER_SLAVE  DSI_0
+
 struct msm_dsi_manager {
struct msm_dsi *dsi[DSI_MAX];

@@ -598,9 +610,10 @@ int msm_dsi_manager_phy_enable(int id,
 {
struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
struct msm_dsi_phy *phy = msm_dsi->phy;
+   int src_pll_id = IS_DUAL_PANEL() ? DSI_CLOCK_MASTER : id;
int ret;

-   ret = msm_dsi_phy_enable(phy, IS_DUAL_PANEL(), bit_rate, esc_rate);
+   ret = msm_dsi_phy_enable(phy, src_pll_id, bit_rate, esc_rate);
if (ret)
return ret;

diff --git a/drivers/gpu/drm/msm/dsi/dsi_phy.c 
b/drivers/gpu/drm/msm/dsi/dsi_phy.c
index 2d3b33c..52b463e 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_phy.c
@@ -21,7 +21,7 @@
 #define dsi_phy_write(offset, data) msm_writel((data), (offset))

 struct dsi_phy_ops {
-   int (*enable)(struct msm_dsi_phy *phy, bool is_dual_panel,
+   int (*enable)(struct msm_dsi_phy *phy, int src_pll_id,
const unsigned long bit_rate, const unsigned long esc_rate);
int (*disable)(struct msm_dsi_phy *phy);
 };
@@ -30,6 +30,12 @@ struct dsi_phy_cfg {
enum msm_dsi_phy_type type;
struct dsi_reg_config reg_cfg;
struct dsi_phy_ops ops;
+
+   /* Each cell {phy_id, pll_id} of the truth table indicates
+* if the source PLL is on the right side of the PHY.
+* Fill default H/W values in illegal cells, eg. cell {0, 1}.
+*/
+   bool src_pll_truthtable[DSI_MAX][DSI_MAX];
 };

 struct dsi_dphy_timing {
@@ -149,6 +155,19 @@ fail:
return ret;
 }

+static void dsi_phy_set_src_pll(struct msm_dsi_phy *phy, int pll_id, u32 reg)
+{
+   int phy_id = phy->id;
+
+   if ((phy_id >= DSI_MAX) || (pll_id >= DSI_MAX))
+   return;
+
+   if (phy->cfg->src_pll_truthtable[phy_id][pll_id])
+   dsi_phy_write(phy->base + reg, 0x01);
+   else
+   dsi_phy_write(phy->base + reg, 0x00);
+}
+
 #define S_DIV_ROUND_UP(n, d)   \
(((n) >= 0) ? (((n) + (d) - 1) / (d)) : (((n) - (d) + 1) / (d)))

@@ -295,7 +314,7 @@ static void dsi_28nm_phy_regulator_ctrl(struct msm_dsi_phy 
*phy, bool enable)
dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CTRL_4, 0x20);
 }

-static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy, bool is_dual_panel,
+static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
const unsigned long bit_rate, const unsigned long esc_rate)
 {
struct dsi_dphy_timing *timing = >timing;
@

[PATCH 0/2] drm/msm/dsi: Miscellaneous patches

2015-06-10 Thread Hai Li
These changes are for code cleanup and better support new targets in the future.

Hai Li (2):
  drm/msm/dsi: Update source PLL selection in DSI PHY
  drm/msm/dsi: Rename *dual panel* to *dual DSI*

 Documentation/devicetree/bindings/drm/msm/dsi.txt | 12 +--
 drivers/gpu/drm/msm/dsi/dsi.h | 14 +---
 drivers/gpu/drm/msm/dsi/dsi_manager.c | 97 +--
 drivers/gpu/drm/msm/dsi/dsi_phy.c | 34 ++--
 4 files changed, 88 insertions(+), 69 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH] drm/msm/mdp5: Always generate active-high sync signals for DSI

2015-05-22 Thread Hai Li
DSI video mode engine can only take active-high sync signals. This
change prevents MDP5 sending active-low sync signals to DSI in any
case.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
index 53bb1f7..2e98ce0 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
@@ -144,10 +144,14 @@ static void mdp5_encoder_mode_set(struct drm_encoder 
*encoder,
mode->type, mode->flags);

ctrl_pol = 0;
-   if (mode->flags & DRM_MODE_FLAG_NHSYNC)
-   ctrl_pol |= MDP5_INTF_POLARITY_CTL_HSYNC_LOW;
-   if (mode->flags & DRM_MODE_FLAG_NVSYNC)
-   ctrl_pol |= MDP5_INTF_POLARITY_CTL_VSYNC_LOW;
+
+   /* DSI controller cannot handle active-low sync signals. */
+   if (mdp5_encoder->intf.type != INTF_DSI) {
+   if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+   ctrl_pol |= MDP5_INTF_POLARITY_CTL_HSYNC_LOW;
+   if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+   ctrl_pol |= MDP5_INTF_POLARITY_CTL_VSYNC_LOW;
+   }
/* probably need to get DATA_EN polarity from panel.. */

dtv_hsync_skew = 0;  /* get this from panel? */
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH 3/3] drm/msm/dsi: Separate PHY to another platform device

2015-05-15 Thread Hai Li
There are different types of PHY from one chipset to another, while
the DSI host controller is relatively consistent across platforms.
Also, the PLL inside PHY is providing the source of DSI byte and
pixel clocks, which are used by DSI host controller. Separated devices
for clock provider and clock consumer make DSI driver better fit into
common clock framework.

Signed-off-by: Hai Li 
---
 Documentation/devicetree/bindings/drm/msm/dsi.txt |  59 +++--
 drivers/gpu/drm/msm/dsi/dsi.c |  45 +++-
 drivers/gpu/drm/msm/dsi/dsi.h |  25 +-
 drivers/gpu/drm/msm/dsi/dsi_host.c|  25 +-
 drivers/gpu/drm/msm/dsi/dsi_phy.c | 266 ++
 5 files changed, 325 insertions(+), 95 deletions(-)

diff --git a/Documentation/devicetree/bindings/drm/msm/dsi.txt 
b/Documentation/devicetree/bindings/drm/msm/dsi.txt
index b3cf325..2b17281 100644
--- a/Documentation/devicetree/bindings/drm/msm/dsi.txt
+++ b/Documentation/devicetree/bindings/drm/msm/dsi.txt
@@ -1,15 +1,12 @@
 Qualcomm Technologies Inc. adreno/snapdragon DSI output

+DSI Controller:
 Required properties:
 - compatible:
   * "qcom,mdss-dsi-ctrl"
-- reg: Physical base address and length of the registers of controller, PLL,
-  PHY and PHY regulator
+- reg: Physical base address and length of the registers of controller
 - reg-names: The names of register regions. The following regions are required:
   * "dsi_ctrl"
-  * "dsi_pll"
-  * "dsi_phy"
-  * "dsi_phy_regulator"
 - qcom,dsi-host-index: The ID of DSI controller hardware instance. This should
   be 0 or 1, since we have 2 DSI controllers at most for now.
 - interrupts: The interrupt signal from the DSI block.
@@ -24,10 +21,10 @@ Required properties:
   * "iface_clk"
   * "mdp_core_clk"
   * "pixel_clk"
-- #clock-cells: The value should be 1.
 - vdd-supply: phandle to vdd regulator device node
 - vddio-supply: phandle to vdd-io regulator device node
 - vdda-supply: phandle to vdda regulator device node
+- qcom,dsi-phy: phandle to DSI PHY device node

 Optional properties:
 - panel at 0: Node of panel connected to this DSI controller.
@@ -42,22 +39,34 @@ Optional properties:
 - interrupt-parent: phandle to the MDP block if the interrupt signal is routed
   through MDP block

+DSI PHY:
+Required properties:
+- compatible: Could be the following
+  * "qcom,dsi-phy-28nm-hpm"
+  * "qcom,dsi-phy-28nm-lp"
+- reg: Physical base address and length of the registers of PLL, PHY and PHY
+  regulator
+- reg-names: The names of register regions. The following regions are required:
+  * "dsi_pll"
+  * "dsi_phy"
+  * "dsi_phy_regulator"
+- qcom,dsi-phy-index: The ID of DSI PHY hardware instance. This should
+  be 0 or 1, since we have 2 DSI PHYs at most for now.
+- power-domains: Should be < MDSS_GDSC>.
+- clocks: device clocks
+  See Documentation/devicetree/bindings/clocks/clock-bindings.txt for details.
+- clock-names: the following clocks are required:
+  * "iface_clk"
+- vddio-supply: phandle to vdd-io regulator device node
+
 Example:
mdss_dsi0: qcom,mdss_dsi at fd922800 {
compatible = "qcom,mdss-dsi-ctrl";
qcom,dsi-host-index = <0>;
interrupt-parent = <_mdp>;
interrupts = <4 0>;
-   reg-names =
-   "dsi_ctrl",
-   "dsi_pll",
-   "dsi_phy",
-   "dsi_phy_regulator",
-   reg =   <0xfd922800 0x200>,
-   <0xfd922a00 0xd4>,
-   <0xfd922b00 0x2b0>,
-   <0xfd922d80 0x7b>,
-   <0xfd828000 0x108>;
+   reg-names = "dsi_ctrl";
+   reg = <0xfd922800 0x200>;
power-domains = < MDSS_GDSC>;
clock-names =
"bus_clk",
@@ -75,11 +84,12 @@ Example:
< MDSS_AHB_CLK>,
< MDSS_MDP_CLK>,
< MDSS_PCLK0_CLK>;
-   #clock-cells = <1>;
vdda-supply = <_l2>;
vdd-supply = <_l22>;
vddio-supply = <_l12>;

+   qcom,dsi-phy = <_dsi_phy0>;
+
qcom,dual-panel-mode;
qcom,master-panel;
qcom,sync-dual-panel;
@@ -94,4 +104,17 @@ Example:
};
};

-
+   mdss_dsi_phy0: qcom,mdss_dsi_phy at fd922a00 {
+   compatible = "qcom,dsi-phy-28nm-hpm";
+   qcom,dsi-phy-index = <0>;
+   reg-names =
+   "dsi_pll",
+   "dsi_phy",
+

[PATCH 2/3] drm/msm/dsi: Enable PLL driver in MSM DSI

2015-05-15 Thread Hai Li
This change activates PLL driver for DSI to work with
common clock framework.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/dsi/dsi.c | 14 +++
 drivers/gpu/drm/msm/dsi/dsi.h | 43 ---
 drivers/gpu/drm/msm/dsi/dsi_host.c| 60 ++
 drivers/gpu/drm/msm/dsi/dsi_manager.c | 79 +--
 drivers/gpu/drm/msm/dsi/dsi_phy.c | 68 ++
 5 files changed, 229 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index ad50b80..beb26df 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -29,6 +29,12 @@ static void dsi_destroy(struct msm_dsi *msm_dsi)
return;

msm_dsi_manager_unregister(msm_dsi);
+
+   if (msm_dsi->phy) {
+   msm_dsi_phy_destroy(msm_dsi->phy);
+   msm_dsi->phy = NULL;
+   }
+
if (msm_dsi->host) {
msm_dsi_host_destroy(msm_dsi->host);
msm_dsi->host = NULL;
@@ -63,6 +69,14 @@ static struct msm_dsi *dsi_init(struct platform_device *pdev)
if (ret)
goto fail;

+   /* Init dsi PHY */
+   msm_dsi->phy = msm_dsi_phy_init(pdev, msm_dsi->phy_type, msm_dsi->id);
+   if (!msm_dsi->phy) {
+   ret = -ENXIO;
+   pr_err("%s: phy init failed\n", __func__);
+   goto fail;
+   }
+
/* Register to dsi manager */
ret = msm_dsi_manager_register(msm_dsi);
if (ret)
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 321964a..8022814 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -38,6 +38,13 @@
 #define DSI_ENCODER_MASTER DSI_1
 #define DSI_ENCODER_SLAVE  DSI_0

+enum msm_dsi_phy_type {
+   MSM_DSI_PHY_UNKNOWN,
+   MSM_DSI_PHY_28NM_HPM,
+   MSM_DSI_PHY_28NM_LP,
+   MSM_DSI_PHY_MAX
+};
+
 struct msm_dsi {
struct drm_device *dev;
struct platform_device *pdev;
@@ -49,6 +56,8 @@ struct msm_dsi {
struct msm_dsi_phy *phy;
struct drm_panel *panel;
unsigned long panel_flags;
+
+   enum msm_dsi_phy_type phy_type;
bool phy_enabled;

/* the encoders we are hooked to (outside of dsi block) */
@@ -73,6 +82,29 @@ void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi);
 /* msm dsi */
 struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi);

+/* dsi pll */
+struct msm_dsi_pll;
+#ifdef CONFIG_DRM_MSM_DSI_PLL
+struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev,
+   enum msm_dsi_phy_type type, int dsi_id);
+void msm_dsi_pll_destroy(struct msm_dsi_pll *pll);
+int msm_dsi_pll_get_clk_provider(struct msm_dsi_pll *pll,
+   struct clk **byte_clk_provider, struct clk **pixel_clk_provider);
+#else
+static inline struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device 
*pdev,
+enum msm_dsi_phy_type type, int id) {
+   return ERR_PTR(-ENODEV);
+}
+static inline void msm_dsi_pll_destroy(struct msm_dsi_pll *pll)
+{
+}
+static inline int msm_dsi_pll_get_clk_provider(struct msm_dsi_pll *pll,
+   struct clk **byte_clk_provider, struct clk **pixel_clk_provider)
+{
+   return -ENODEV;
+}
+#endif
+
 /* dsi host */
 int msm_dsi_host_xfer_prepare(struct mipi_dsi_host *host,
const struct mipi_dsi_msg *msg);
@@ -94,6 +126,8 @@ struct drm_panel *msm_dsi_host_get_panel(struct 
mipi_dsi_host *host,
unsigned long *panel_flags);
 int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer);
 void msm_dsi_host_unregister(struct mipi_dsi_host *host);
+int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host,
+   struct msm_dsi_pll *src_pll);
 void msm_dsi_host_destroy(struct mipi_dsi_host *host);
 int msm_dsi_host_modeset_init(struct mipi_dsi_host *host,
struct drm_device *dev);
@@ -101,18 +135,15 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi);

 /* dsi phy */
 struct msm_dsi_phy;
-enum msm_dsi_phy_type {
-   MSM_DSI_PHY_UNKNOWN,
-   MSM_DSI_PHY_28NM_HPM,
-   MSM_DSI_PHY_28NM_LP,
-   MSM_DSI_PHY_MAX
-};
 struct msm_dsi_phy *msm_dsi_phy_init(struct platform_device *pdev,
enum msm_dsi_phy_type type, int id);
+void msm_dsi_phy_destroy(struct msm_dsi_phy *phy);
 int msm_dsi_phy_enable(struct msm_dsi_phy *phy, bool is_dual_panel,
const unsigned long bit_rate, const unsigned long esc_rate);
 int msm_dsi_phy_disable(struct msm_dsi_phy *phy);
 void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy,
u32 *clk_pre, u32 *clk_post);
+struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy);
+
 #endif /* __DSI_CONNECTOR_H__ */

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host

[PATCH 1/3] drm/msm/dsi: Add DSI PLL clock driver support

2015-05-15 Thread Hai Li
DSI byte clock and pixel clocks are sourced from DSI PLL.
This change adds the DSI PLL source clock driver under
common clock framework.

This change handles DSI 28nm PLL only.

Signed-off-by: Hai Li 
Signed-off-by: Archit Taneja 
Signed-off-by: Stephane Viau 
Signed-off-by: Wentao Xu 
---
 drivers/gpu/drm/msm/Kconfig|   7 +
 drivers/gpu/drm/msm/Makefile   |   5 +
 drivers/gpu/drm/msm/dsi/dsi.h  |   3 +-
 drivers/gpu/drm/msm/dsi/dsi_host.c |  10 +-
 drivers/gpu/drm/msm/dsi/dsi_phy.c  |   3 +-
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.c  | 164 
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.h  |  89 
 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c | 652 +
 8 files changed, 926 insertions(+), 7 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll.c
 create mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll.h
 create mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c

diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 0a6f676..08ba8d0 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -46,3 +46,10 @@ config DRM_MSM_DSI
  Choose this option if you have a need for MIPI DSI connector
  support.

+config DRM_MSM_DSI_PLL
+   bool "Enable DSI PLL driver in MSM DRM"
+   depends on DRM_MSM_DSI && COMMON_CLK
+   default y
+   help
+ Choose this option to enable DSI PLL driver which provides DSI
+ source clocks under common clock framework.
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index ab20867..16a81b9 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -1,4 +1,5 @@
 ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/msm
+ccflags-$(CONFIG_DRM_MSM_DSI_PLL) += -Idrivers/gpu/drm/msm/dsi

 msm-y := \
adreno/adreno_device.o \
@@ -50,10 +51,14 @@ msm-y := \

 msm-$(CONFIG_DRM_MSM_FBDEV) += msm_fbdev.o
 msm-$(CONFIG_COMMON_CLK) += mdp/mdp4/mdp4_lvds_pll.o
+
 msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \
dsi/dsi_host.o \
dsi/dsi_manager.o \
dsi/dsi_phy.o \
mdp/mdp5/mdp5_cmd_encoder.o

+msm-$(CONFIG_DRM_MSM_DSI_PLL) += dsi/pll/dsi_pll.o \
+   dsi/pll/dsi_pll_28nm.o
+
 obj-$(CONFIG_DRM_MSM)  += msm.o
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 10f54d4..321964a 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -103,7 +103,8 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi);
 struct msm_dsi_phy;
 enum msm_dsi_phy_type {
MSM_DSI_PHY_UNKNOWN,
-   MSM_DSI_PHY_28NM,
+   MSM_DSI_PHY_28NM_HPM,
+   MSM_DSI_PHY_28NM_LP,
MSM_DSI_PHY_MAX
 };
 struct msm_dsi_phy *msm_dsi_phy_init(struct platform_device *pdev,
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 360b765..f7ba890 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -64,7 +64,7 @@ static const struct dsi_config dsi_cfgs[] = {
.major = MSM_DSI_VER_MAJOR_6G,
.minor = MSM_DSI_6G_VER_MINOR_V1_0,
.io_offset = DSI_6G_REG_SHIFT,
-   .phy_type = MSM_DSI_PHY_28NM,
+   .phy_type = MSM_DSI_PHY_28NM_HPM,
.reg_cfg = {
.num = 4,
.regs = {
@@ -79,7 +79,7 @@ static const struct dsi_config dsi_cfgs[] = {
.major = MSM_DSI_VER_MAJOR_6G,
.minor = MSM_DSI_6G_VER_MINOR_V1_1,
.io_offset = DSI_6G_REG_SHIFT,
-   .phy_type = MSM_DSI_PHY_28NM,
+   .phy_type = MSM_DSI_PHY_28NM_HPM,
.reg_cfg = {
.num = 4,
.regs = {
@@ -94,7 +94,7 @@ static const struct dsi_config dsi_cfgs[] = {
.major = MSM_DSI_VER_MAJOR_6G,
.minor = MSM_DSI_6G_VER_MINOR_V1_1_1,
.io_offset = DSI_6G_REG_SHIFT,
-   .phy_type = MSM_DSI_PHY_28NM,
+   .phy_type = MSM_DSI_PHY_28NM_HPM,
.reg_cfg = {
.num = 4,
.regs = {
@@ -109,7 +109,7 @@ static const struct dsi_config dsi_cfgs[] = {
.major = MSM_DSI_VER_MAJOR_6G,
.minor = MSM_DSI_6G_VER_MINOR_V1_2,
.io_offset = DSI_6G_REG_SHIFT,
-   .phy_type = MSM_DSI_PHY_28NM,
+   .phy_type = MSM_DSI_PHY_28NM_HPM,
.reg_cfg = {
.num = 4,
.regs = {
@@ -124,7 +124,7 @@ static const struct dsi_config dsi_cfgs[] = {
.major = MSM_DSI_VER_MAJOR_6G,
.minor = MSM_DSI_6G_VER_MINOR_V1_3_1,
.io_offset = DSI_6G_REG_SHIFT,
-   .phy_type = MSM_DSI_PHY_28NM,
+  

[PATCH 0/3] drm/msm/dsi: Add DSI PLL driver under common clock framework

2015-05-15 Thread Hai Li
DSI PLL driver can work with common clock framework and provide source of DSI
byte clock and pixel clock, as a clock provider.

Hai Li (3):
  drm/msm/dsi: Add DSI PLL clock driver support
  drm/msm/dsi: Enable PLL driver in MSM DSI
  drm/msm/dsi: Separate PHY to another platform device

 Documentation/devicetree/bindings/drm/msm/dsi.txt |  59 +-
 drivers/gpu/drm/msm/Kconfig   |   7 +
 drivers/gpu/drm/msm/Makefile  |   5 +
 drivers/gpu/drm/msm/dsi/dsi.c |  43 +-
 drivers/gpu/drm/msm/dsi/dsi.h |  61 +-
 drivers/gpu/drm/msm/dsi/dsi_host.c|  83 ++-
 drivers/gpu/drm/msm/dsi/dsi_manager.c |  79 ++-
 drivers/gpu/drm/msm/dsi/dsi_phy.c | 311 ++-
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.c | 164 ++
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.h |  89 +++
 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c| 652 ++
 11 files changed, 1448 insertions(+), 105 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll.c
 create mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll.h
 create mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH] rnndb: Add 28nm PLL register description

2015-05-11 Thread Hai Li
From: Stephane Viau <sv...@codeaurora.org>

Each interface (DSI/eDP/HDMI) has to control its own PLL.
This change only add the register description for each one of them.

Let's not make the register description common as some registers
may not be implemented the same way for each interface PHY.

v2:
- Add description for more bit fields
- Rebase on change "rnndb: dsi: Add DSI_LANE_CTRL info"

Signed-off-by: Stephane Viau 
Signed-off-by: Hai Li 
---
 rnndb/dsi/dsi.xml   | 80 +
 rnndb/edp/edp.xml   | 51 ++
 rnndb/hdmi/hdmi.xml | 51 ++
 3 files changed, 182 insertions(+)

diff --git a/rnndb/dsi/dsi.xml b/rnndb/dsi/dsi.xml
index e645c45..d19bea9 100644
--- a/rnndb/dsi/dsi.xml
+++ b/rnndb/dsi/dsi.xml
@@ -445,4 +445,84 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">

 

+
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+
+
 
diff --git a/rnndb/edp/edp.xml b/rnndb/edp/edp.xml
index ea2a74b..00fc611 100644
--- a/rnndb/edp/edp.xml
+++ b/rnndb/edp/edp.xml
@@ -185,4 +185,55 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">

 

+
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+
+
 
diff --git a/rnndb/hdmi/hdmi.xml b/rnndb/hdmi/hdmi.xml
index 64393b4..ddab016 100644
--- a/rnndb/hdmi/hdmi.xml
+++ b/rnndb/hdmi/hdmi.xml
@@ -569,4 +569,55 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">

 

+
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+
+
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH] drm/msm: Update generated headers (PLL registers)

2015-05-11 Thread Hai Li
This change includes the generated file of the following:

rnndb: Add 28nm PLL register description

Each interface (DSI/eDP/HDMI) has to control its own PLL.
This change only add the register description for each one of them.

Let's not make the register description common as some registers
may not be implemented the same way for each interface PHY.

v2:
- Add description for more bit fields
- Rebase on change "rnndb: dsi: Add DSI_LANE_CTRL info"

Signed-off-by: Stephane Viau 
Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/dsi/dsi.xml.h   | 149 +++-
 drivers/gpu/drm/msm/edp/edp.xml.h   | 104 +
 drivers/gpu/drm/msm/hdmi/hdmi.xml.h | 102 +---
 3 files changed, 330 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h 
b/drivers/gpu/drm/msm/dsi/dsi.xml.h
index 06c1441..4e4a700 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
@@ -8,7 +8,7 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git

 The rules-ng-ng source files this header was generated from are:
-- /usr2/hali/local/envytools/envytools/rnndb/dsi/dsi.xml (  18802 
bytes, from 2015-05-06 21:35:51)
+- /usr2/hali/local/envytools/envytools/rnndb/dsi/dsi.xml (  22094 
bytes, from 2015-05-06 21:40:40)
 - /usr2/hali/local/envytools/envytools/rnndb/freedreno_copyright.xml (   1453 
bytes, from 2015-01-28 21:43:22)

 Copyright (C) 2013-2015 by the following authors:
@@ -838,5 +838,152 @@ static inline uint32_t 
DSI_28nm_PHY_TIMING_CTRL_11_TRIG3_CMD(uint32_t val)

 #define REG_DSI_28nm_PHY_REGULATOR_CAL_PWR_CFG 0x0018

+#define REG_DSI_28nm_PHY_PLL_REFCLK_CFG
0x
+#define DSI_28nm_PHY_PLL_REFCLK_CFG_DBLR   0x0001
+
+#define REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG  0x0004
+
+#define REG_DSI_28nm_PHY_PLL_CHGPUMP_CFG   0x0008
+
+#define REG_DSI_28nm_PHY_PLL_VCOLPF_CFG
0x000c
+
+#define REG_DSI_28nm_PHY_PLL_VREG_CFG  0x0010
+#define DSI_28nm_PHY_PLL_VREG_CFG_POSTDIV1_BYPASS_B0x0002
+
+#define REG_DSI_28nm_PHY_PLL_PWRGEN_CFG
0x0014
+
+#define REG_DSI_28nm_PHY_PLL_DMUX_CFG  0x0018
+
+#define REG_DSI_28nm_PHY_PLL_AMUX_CFG  0x001c
+
+#define REG_DSI_28nm_PHY_PLL_GLB_CFG   0x0020
+#define DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B   0x0001
+#define DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B   0x0002
+#define DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B0x0004
+#define DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE0x0008
+
+#define REG_DSI_28nm_PHY_PLL_POSTDIV2_CFG  0x0024
+
+#define REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG  0x0028
+
+#define REG_DSI_28nm_PHY_PLL_LPFR_CFG  0x002c
+
+#define REG_DSI_28nm_PHY_PLL_LPFC1_CFG 0x0030
+
+#define REG_DSI_28nm_PHY_PLL_LPFC2_CFG 0x0034
+
+#define REG_DSI_28nm_PHY_PLL_SDM_CFG0  0x0038
+#define DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV__MASK
0x003f
+#define DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV__SHIFT   0
+static inline uint32_t DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV(uint32_t val)
+{
+   return ((val) << DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV__SHIFT) & 
DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV__MASK;
+}
+#define DSI_28nm_PHY_PLL_SDM_CFG0_BYP  0x0040
+
+#define REG_DSI_28nm_PHY_PLL_SDM_CFG1  0x003c
+#define DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__MASK  0x003f
+#define DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__SHIFT 0
+static inline uint32_t DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET(uint32_t val)
+{
+   return ((val) << DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__SHIFT) & 
DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__MASK;
+}
+#define DSI_28nm_PHY_PLL_SDM_CFG1_DITHER_EN__MASK  0x0040
+#define DSI_28nm_PHY_PLL_SDM_CFG1_DITHER_EN__SHIFT 6
+static inline uint32_t DSI_28nm_PHY_PLL_SDM_CFG1_DITHER_EN(uint32_t val)
+{
+   return ((val) << DSI_28nm_PHY_PLL_SDM_CFG1_DITHER_EN__SHIFT) & 
DSI_28nm_PHY_PLL_SDM_CFG1_DITHER_EN__MASK;
+}
+
+#define REG_DSI_28nm_PHY_PLL_SDM_CFG2  0x0040
+#define DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0__MASK  0x00ff
+#define DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0__SHIFT 0
+static inline uint32_t DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0(uint32_t val)
+{
+   return ((val) << DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0__SHIFT) & 
DSI_28nm_P

linux-4.1-rc1/drivers/gpu/drm/msm/dsi/dsi_host.c:1799: possible missing break ?

2015-04-29 Thread Hai Li
Yes, this is a bug in DSI driver. I have sent a patch to fix it.
http://lists.freedesktop.org/archives/dri-devel/2015-April/081893.html

Sorry for any inconvenience it caused.

Hai


-Original Message-
From: dri-devel [mailto:dri-devel-boun...@lists.freedesktop.org] On Behalf Of 
David Binderman
Sent: Monday, April 27, 2015 1:59 AM
To: airlied at linux.ie; dri-devel at lists.freedesktop.org
Subject: linux-4.1-rc1/drivers/gpu/drm/msm/dsi/dsi_host.c:1799: possible 
missing break ?

Hello there,

[linux-4.1-rc1/drivers/gpu/drm/msm/dsi/dsi_host.c:1799] -> 
[linux-4.1-rc1/drivers/gpu/drm/msm/dsi/dsi_host.c:1802]: (warning) Variable 
'ret' is reassigned a value before the old one has been used. 'break;' missing?

switch (cmd) {
case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
pr_err("%s: rx ACK_ERR_PACLAGE\n", __func__);
ret = 0;
case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
ret = dsi_short_read1_resp(buf, msg);
break;

Regards

David Binderman


___
dri-devel mailing list
dri-devel at lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel



[PATCH 2/2] drm/msm/dsi: Simplify the code to get the number of read byte

2015-04-29 Thread Hai Li
During cmd rx, only new versions of H/W provide register to read back
the real number of byte returned by panel. For the old versions, reading
this register will not get the right number. In fact, we only need to
assume the returned data is the same size as we expected, because later
we will check the data type to detect error.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 14 --
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 473d417..72d4d5f 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1093,7 +1093,6 @@ static int dsi_cmd_dma_rx(struct msm_dsi_host *msm_host,
 {
u32 *lp, *temp, data;
int i, j = 0, cnt;
-   bool ack_error = false;
u32 read_cnt;
u8 reg[16];
int repeated_bytes = 0;
@@ -1105,15 +1104,10 @@ static int dsi_cmd_dma_rx(struct msm_dsi_host *msm_host,
if (cnt > 4)
cnt = 4; /* 4 x 32 bits registers only */

-   /* Calculate real read data count */
-   read_cnt = dsi_read(msm_host, 0x1d4) >> 16;
-
-   ack_error = (rx_byte == 4) ?
-   (read_cnt == 8) : /* short pkt + 4-byte error pkt */
-   (read_cnt == (pkt_size + 6 + 4)); /* long pkt+4-byte error pkt*/
-
-   if (ack_error)
-   read_cnt -= 4; /* Remove 4 byte error pkt */
+   if (rx_byte == 4)
+   read_cnt = 4;
+   else
+   read_cnt = pkt_size + 6;

/*
 * In case of multiple reads from the panel, after the first read, there
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH 1/2] drm/msm/dsi: Fixup missing *break* statement during cmd rx

2015-04-29 Thread Hai Li
Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index fdc54e3..473d417 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1797,6 +1797,7 @@ int msm_dsi_host_cmd_rx(struct mipi_dsi_host *host,
case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
pr_err("%s: rx ACK_ERR_PACLAGE\n", __func__);
ret = 0;
+   break;
case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
ret = dsi_short_read1_resp(buf, msg);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH 0/2] drm/msm/dsi: Fix issues during cmd rx

2015-04-29 Thread Hai Li
These 2 patches are to fix the issues during DSI command rx.

Hai Li (2):
  drm/msm/dsi: Fixup missing *break* statement during cmd rx
  drm/msm/dsi: Simplify the code to get the number of read byte

 drivers/gpu/drm/msm/dsi/dsi_host.c | 15 +--
 1 file changed, 5 insertions(+), 10 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH v2 2/2] drm/msm/mdp5: Wait for PP_DONE irq for command mode CRTC atomic commit

2015-04-28 Thread Hai Li
CRTCs in DSI command mode data path should wait for pingpong done,
instead of vblank, to finish atomic commit.

This change is to enable PP_DONE irq on command mode CRTCs and wait for
this irq happens before atomic commit completion.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c |  4 --
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c| 82 -
 2 files changed, 66 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
index e4e8956..5f87357 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
@@ -216,16 +216,12 @@ static void mdp5_cmd_encoder_mode_set(struct drm_encoder 
*encoder,
 static void mdp5_cmd_encoder_disable(struct drm_encoder *encoder)
 {
struct mdp5_cmd_encoder *mdp5_cmd_enc = to_mdp5_cmd_encoder(encoder);
-   struct mdp5_kms *mdp5_kms = get_kms(encoder);
struct mdp5_ctl *ctl = mdp5_crtc_get_ctl(encoder->crtc);
struct mdp5_interface *intf = _cmd_enc->intf;
-   int lm = mdp5_crtc_get_lm(encoder->crtc);

if (WARN_ON(!mdp5_cmd_enc->enabled))
return;

-   /* Wait for the last frame done */
-   mdp_irq_wait(_kms->base, lm2ppdone(lm));
pingpong_tearcheck_disable(encoder);

mdp5_ctl_set_encoder_state(ctl, false);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index aa0b0c5..8d9d67a 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark 
  *
@@ -60,6 +60,11 @@ struct mdp5_crtc {

struct mdp_irq vblank;
struct mdp_irq err;
+   struct mdp_irq pp_done;
+
+   struct completion pp_completion;
+
+   bool cmd_mode;

struct {
/* protect REG_MDP5_LM_CURSOR* registers and cursor scanout_bo*/
@@ -87,6 +92,12 @@ static void request_pending(struct drm_crtc *crtc, uint32_t 
pending)
mdp_irq_register(_kms(crtc)->base, _crtc->vblank);
 }

+static void request_pp_done_pending(struct drm_crtc *crtc)
+{
+   struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+   reinit_completion(_crtc->pp_completion);
+}
+
 static u32 crtc_flush(struct drm_crtc *crtc, u32 flush_mask)
 {
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
@@ -282,6 +293,9 @@ static void mdp5_crtc_disable(struct drm_crtc *crtc)
/* set STAGE_UNUSED for all layers */
mdp5_ctl_blend(mdp5_crtc->ctl, mdp5_crtc->lm, 0x);

+   if (mdp5_crtc->cmd_mode)
+   mdp_irq_unregister(_kms->base, _crtc->pp_done);
+
mdp_irq_unregister(_kms->base, _crtc->err);
mdp5_disable(mdp5_kms);

@@ -301,6 +315,9 @@ static void mdp5_crtc_enable(struct drm_crtc *crtc)
mdp5_enable(mdp5_kms);
mdp_irq_register(_kms->base, _crtc->err);

+   if (mdp5_crtc->cmd_mode)
+   mdp_irq_register(_kms->base, _crtc->pp_done);
+
mdp5_crtc->enabled = true;
 }

@@ -402,6 +419,15 @@ static void mdp5_crtc_atomic_flush(struct drm_crtc *crtc)

blend_setup(crtc);

+   /* PP_DONE irq is only used by command mode for now.
+* It is better to request pending before FLUSH and START trigger
+* to make sure no pp_done irq missed.
+* This is safe because no pp_done will happen before SW trigger
+* in command mode.
+*/
+   if (mdp5_crtc->cmd_mode)
+   request_pp_done_pending(crtc);
+
mdp5_crtc->flushed_mask = crtc_flush_all(crtc);

request_pending(crtc, PENDING_FLIP);
@@ -612,6 +638,26 @@ static void mdp5_crtc_err_irq(struct mdp_irq *irq, 
uint32_t irqstatus)
DBG("%s: error: %08x", mdp5_crtc->name, irqstatus);
 }

+static void mdp5_crtc_pp_done_irq(struct mdp_irq *irq, uint32_t irqstatus)
+{
+   struct mdp5_crtc *mdp5_crtc = container_of(irq, struct mdp5_crtc,
+   pp_done);
+
+   complete(_crtc->pp_completion);
+}
+
+static void mdp5_crtc_wait_for_pp_done(struct drm_crtc *crtc)
+{
+   struct drm_device *dev = crtc->dev;
+   struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+   int ret;
+
+   ret = wait_for_completion_timeout(_crtc->pp_completion,
+   msecs_to_jiffies(50));
+   if (ret == 0)
+   dev_warn(dev->dev, "pp done time out, lm=%d\n", mdp5_crtc->lm);
+}
+
 static void mdp5_crtc_wait_for_flush_done(struct drm_crtc *crtc)
 {
struct drm_device *dev = crtc->dev;
@@ -659,16 +705,18 @@ void mdp5_crtc_set_intf(struct drm_c

[PATCH v2 1/2] drm/msm: Use customized function to wait for atomic commit done

2015-04-28 Thread Hai Li
MDP FLUSH registers could indicate if the previous flush updates
has taken effect at vsync boundary. Making use of this H/W feature
can catch the vsync that happened between CRTC atomic_flush and
*_wait_for_vblanks, to avoid unnecessary wait.

This change allows kms CRTCs to use their own *_wait_for_commit_done
functions to wait for FLUSH register cleared at vsync, before commit
completion.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 39 ++
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c  |  7 
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h  |  1 +
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 55 
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c  | 11 +--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h  |  3 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c  |  7 
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h  |  1 +
 drivers/gpu/drm/msm/msm_atomic.c | 30 +++--
 drivers/gpu/drm/msm/msm_kms.h|  3 ++
 10 files changed, 146 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c 
b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
index 73afa21..c4bb9d9 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
@@ -51,6 +51,11 @@ struct mdp4_crtc {
/* if there is a pending flip, these will be non-null: */
struct drm_pending_vblank_event *event;

+   /* Bits have been flushed at the last commit,
+* used to decide if a vsync has happened since last commit.
+*/
+   u32 flushed_mask;
+
 #define PENDING_CURSOR 0x1
 #define PENDING_FLIP   0x2
atomic_t pending;
@@ -93,6 +98,8 @@ static void crtc_flush(struct drm_crtc *crtc)

DBG("%s: flush=%08x", mdp4_crtc->name, flush);

+   mdp4_crtc->flushed_mask = flush;
+
mdp4_write(mdp4_kms, REG_MDP4_OVERLAY_FLUSH, flush);
 }

@@ -537,6 +544,29 @@ static void mdp4_crtc_err_irq(struct mdp_irq *irq, 
uint32_t irqstatus)
crtc_flush(crtc);
 }

+static void mdp4_crtc_wait_for_flush_done(struct drm_crtc *crtc)
+{
+   struct drm_device *dev = crtc->dev;
+   struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+   struct mdp4_kms *mdp4_kms = get_kms(crtc);
+   int ret;
+
+   ret = drm_crtc_vblank_get(crtc);
+   if (ret)
+   return;
+
+   ret = wait_event_timeout(dev->vblank[drm_crtc_index(crtc)].queue,
+   !(mdp4_read(mdp4_kms, REG_MDP4_OVERLAY_FLUSH) &
+   mdp4_crtc->flushed_mask),
+   msecs_to_jiffies(50));
+   if (ret <= 0)
+   dev_warn(dev->dev, "vblank time out, crtc=%d\n", mdp4_crtc->id);
+
+   mdp4_crtc->flushed_mask = 0;
+
+   drm_crtc_vblank_put(crtc);
+}
+
 uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc)
 {
struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
@@ -600,6 +630,15 @@ void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum 
mdp4_intf intf, int mixer)
mdp4_write(mdp4_kms, REG_MDP4_DISP_INTF_SEL, intf_sel);
 }

+void mdp4_crtc_wait_for_commit_done(struct drm_crtc *crtc)
+{
+   /* wait_for_flush_done is the only case for now.
+* Later we will have command mode CRTC to wait for
+* other event.
+*/
+   mdp4_crtc_wait_for_flush_done(crtc);
+}
+
 static const char *dma_names[] = {
"DMA_P", "DMA_S", "DMA_E",
 };
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c 
b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
index d81e19d..f0b6c4b 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
@@ -157,6 +157,12 @@ static void mdp4_complete_commit(struct msm_kms *kms, 
struct drm_atomic_state *s
mdp4_disable(mdp4_kms);
 }

+static void mdp4_wait_for_crtc_commit_done(struct msm_kms *kms,
+   struct drm_crtc *crtc)
+{
+   mdp4_crtc_wait_for_commit_done(crtc);
+}
+
 static long mdp4_round_pixclk(struct msm_kms *kms, unsigned long rate,
struct drm_encoder *encoder)
 {
@@ -195,6 +201,7 @@ static const struct mdp_kms_funcs kms_funcs = {
.disable_vblank  = mdp4_disable_vblank,
.prepare_commit  = mdp4_prepare_commit,
.complete_commit = mdp4_complete_commit,
+   .wait_for_crtc_commit_done = mdp4_wait_for_crtc_commit_done,
.get_format  = mdp_get_format,
.round_pixclk= mdp4_round_pixclk,
.preclose= mdp4_preclose,
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h 
b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
index 0a5c58b..5b1a412 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
@@ -206,6 +206,7 @@ uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc);
 void mdp4_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file 
*file);
 void mdp4_crtc_se

[PATCH v2 0/2] drm/msm: Customize wait for atomic commit done function

2015-04-28 Thread Hai Li
The current way to wait for atomic commit done may cause unnecessary wait for
another vsync for video mode path. Also, for command mode path, we need to wait
for PP_DONE event other than vsync before finish. This patch series is to fix
these issues.

v2: Replace function pointer with a cmd mode flag to differentiate cmd mode wait
function from video mode. (From Rob Clark)

Hai Li (2):
  drm/msm: Use customized function to wait for atomic commit done
  drm/msm/mdp5: Wait for PP_DONE irq for command mode CRTC atomic commit

 drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c|  39 
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c |   7 ++
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h |   1 +
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c |   4 -
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c| 125 +---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c |  11 ++-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h |   3 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c |   7 ++
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h |   1 +
 drivers/gpu/drm/msm/msm_atomic.c|  30 +-
 drivers/gpu/drm/msm/msm_kms.h   |   3 +
 11 files changed, 206 insertions(+), 25 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH 2/2] drm/msm/mdp5: Wait for PP_DONE irq for command mode CRTC atomic commit

2015-04-24 Thread Hai Li
CRTCs in DSI command mode data path should wait for pingpong done,
instead of vblank, to finish atomic commit.

This change is to enable PP_DONE irq on command mode CRTCs and wait for
this irq happens before atomic commit completion.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c |  4 --
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c| 71 -
 2 files changed, 58 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
index e4e8956..5f87357 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
@@ -216,16 +216,12 @@ static void mdp5_cmd_encoder_mode_set(struct drm_encoder 
*encoder,
 static void mdp5_cmd_encoder_disable(struct drm_encoder *encoder)
 {
struct mdp5_cmd_encoder *mdp5_cmd_enc = to_mdp5_cmd_encoder(encoder);
-   struct mdp5_kms *mdp5_kms = get_kms(encoder);
struct mdp5_ctl *ctl = mdp5_crtc_get_ctl(encoder->crtc);
struct mdp5_interface *intf = _cmd_enc->intf;
-   int lm = mdp5_crtc_get_lm(encoder->crtc);

if (WARN_ON(!mdp5_cmd_enc->enabled))
return;

-   /* Wait for the last frame done */
-   mdp_irq_wait(_kms->base, lm2ppdone(lm));
pingpong_tearcheck_disable(encoder);

mdp5_ctl_set_encoder_state(ctl, false);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index 034b1b9..a38c27b 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark 
  *
@@ -60,6 +60,9 @@ struct mdp5_crtc {

struct mdp_irq vblank;
struct mdp_irq err;
+   struct mdp_irq pp_done;
+
+   struct completion pp_completion;

void (*wait_for_commit_done)(struct drm_crtc *crtc);

@@ -89,6 +92,12 @@ static void request_pending(struct drm_crtc *crtc, uint32_t 
pending)
mdp_irq_register(_kms(crtc)->base, _crtc->vblank);
 }

+static void request_pp_done_pending(struct drm_crtc *crtc)
+{
+   struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+   reinit_completion(_crtc->pp_completion);
+}
+
 static u32 crtc_flush(struct drm_crtc *crtc, u32 flush_mask)
 {
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
@@ -284,6 +293,9 @@ static void mdp5_crtc_disable(struct drm_crtc *crtc)
/* set STAGE_UNUSED for all layers */
mdp5_ctl_blend(mdp5_crtc->ctl, mdp5_crtc->lm, 0x);

+   if (mdp5_crtc->pp_done.irq)
+   mdp_irq_unregister(_kms->base, _crtc->pp_done);
+
mdp_irq_unregister(_kms->base, _crtc->err);
mdp5_disable(mdp5_kms);

@@ -303,6 +315,9 @@ static void mdp5_crtc_enable(struct drm_crtc *crtc)
mdp5_enable(mdp5_kms);
mdp_irq_register(_kms->base, _crtc->err);

+   if (mdp5_crtc->pp_done.irq)
+   mdp_irq_register(_kms->base, _crtc->pp_done);
+
mdp5_crtc->enabled = true;
 }

@@ -404,6 +419,15 @@ static void mdp5_crtc_atomic_flush(struct drm_crtc *crtc)

blend_setup(crtc);

+   /* PP_DONE irq is only used by command mode for now.
+* It is better to request pending before FLUSH and START trigger
+* to make sure no pp_done irq missed.
+* This is safe because no pp_done will happen before SW trigger
+* in command mode.
+*/
+   if (mdp5_crtc->pp_done.irq)
+   request_pp_done_pending(crtc);
+
mdp5_crtc->flushed_mask = crtc_flush_all(crtc);

request_pending(crtc, PENDING_FLIP);
@@ -614,6 +638,26 @@ static void mdp5_crtc_err_irq(struct mdp_irq *irq, 
uint32_t irqstatus)
DBG("%s: error: %08x", mdp5_crtc->name, irqstatus);
 }

+static void mdp5_crtc_pp_done_irq(struct mdp_irq *irq, uint32_t irqstatus)
+{
+   struct mdp5_crtc *mdp5_crtc = container_of(irq, struct mdp5_crtc,
+   pp_done);
+
+   complete(_crtc->pp_completion);
+}
+
+static void mdp5_crtc_wait_for_pp_done(struct drm_crtc *crtc)
+{
+   struct drm_device *dev = crtc->dev;
+   struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+   int ret;
+
+   ret = wait_for_completion_timeout(_crtc->pp_completion,
+   msecs_to_jiffies(50));
+   if (ret == 0)
+   dev_warn(dev->dev, "pp done time out, lm=%d\n", mdp5_crtc->lm);
+}
+
 static void mdp5_crtc_wait_for_flush_done(struct drm_crtc *crtc)
 {
struct drm_device *dev = crtc->dev;
@@ -661,18 +705,18 @@ void mdp5_crtc_set_intf(struct drm_crtc *crtc, struct 
mdp5_interface *intf)

/* now t

[PATCH 1/2] drm/msm: Use customized function to wait for atomic commit done

2015-04-24 Thread Hai Li
MDP FLUSH registers could indicate if the previous flush updates
has taken effect at vsync boundary. Making use of this H/W feature
can catch the vsync that happened between CRTC atomic_flush and
*_wait_for_vblanks, to avoid unnecessary wait.

This change allows kms CRTCs to use their own *_wait_for_commit_done
functions to wait for FLUSH register cleared at vsync, before commit
completion.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 46 
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c  |  7 
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h  |  1 +
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 62 
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c  | 11 --
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h  |  3 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c  |  7 
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h  |  1 +
 drivers/gpu/drm/msm/msm_atomic.c | 30 ++--
 drivers/gpu/drm/msm/msm_kms.h|  3 ++
 10 files changed, 160 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c 
b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
index 73afa21..99cb126 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
@@ -51,6 +51,11 @@ struct mdp4_crtc {
/* if there is a pending flip, these will be non-null: */
struct drm_pending_vblank_event *event;

+   /* Bits have been flushed at the last commit,
+* used to decide if a vsync has happened since last commit.
+*/
+   u32 flushed_mask;
+
 #define PENDING_CURSOR 0x1
 #define PENDING_FLIP   0x2
atomic_t pending;
@@ -60,6 +65,8 @@ struct mdp4_crtc {

struct mdp_irq vblank;
struct mdp_irq err;
+
+   void (*wait_for_commit_done)(struct drm_crtc *crtc);
 };
 #define to_mdp4_crtc(x) container_of(x, struct mdp4_crtc, base)

@@ -93,6 +100,8 @@ static void crtc_flush(struct drm_crtc *crtc)

DBG("%s: flush=%08x", mdp4_crtc->name, flush);

+   mdp4_crtc->flushed_mask = flush;
+
mdp4_write(mdp4_kms, REG_MDP4_OVERLAY_FLUSH, flush);
 }

@@ -537,6 +546,29 @@ static void mdp4_crtc_err_irq(struct mdp_irq *irq, 
uint32_t irqstatus)
crtc_flush(crtc);
 }

+static void mdp4_crtc_wait_for_flush_done(struct drm_crtc *crtc)
+{
+   struct drm_device *dev = crtc->dev;
+   struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+   struct mdp4_kms *mdp4_kms = get_kms(crtc);
+   int ret;
+
+   ret = drm_crtc_vblank_get(crtc);
+   if (ret)
+   return;
+
+   ret = wait_event_timeout(dev->vblank[drm_crtc_index(crtc)].queue,
+   !(mdp4_read(mdp4_kms, REG_MDP4_OVERLAY_FLUSH) &
+   mdp4_crtc->flushed_mask),
+   msecs_to_jiffies(50));
+   if (ret <= 0)
+   dev_warn(dev->dev, "vblank time out, crtc=%d\n", mdp4_crtc->id);
+
+   mdp4_crtc->flushed_mask = 0;
+
+   drm_crtc_vblank_put(crtc);
+}
+
 uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc)
 {
struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
@@ -566,6 +598,8 @@ void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum 
mdp4_intf intf, int mixer)
struct mdp4_kms *mdp4_kms = get_kms(crtc);
uint32_t intf_sel;

+   mdp4_crtc->wait_for_commit_done = mdp4_crtc_wait_for_flush_done;
+
intf_sel = mdp4_read(mdp4_kms, REG_MDP4_DISP_INTF_SEL);

switch (mdp4_crtc->dma) {
@@ -600,6 +634,18 @@ void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum 
mdp4_intf intf, int mixer)
mdp4_write(mdp4_kms, REG_MDP4_DISP_INTF_SEL, intf_sel);
 }

+void mdp4_crtc_wait_for_commit_done(struct drm_crtc *crtc)
+{
+   struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+   struct drm_device *dev = crtc->dev;
+
+   if (mdp4_crtc->wait_for_commit_done)
+   mdp4_crtc->wait_for_commit_done(crtc);
+   else
+   dev_warn(dev->dev, "no wait_for_commit_done func, crtc=%d\n",
+   mdp4_crtc->id);
+}
+
 static const char *dma_names[] = {
"DMA_P", "DMA_S", "DMA_E",
 };
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c 
b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
index d81e19d..f0b6c4b 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
@@ -157,6 +157,12 @@ static void mdp4_complete_commit(struct msm_kms *kms, 
struct drm_atomic_state *s
mdp4_disable(mdp4_kms);
 }

+static void mdp4_wait_for_crtc_commit_done(struct msm_kms *kms,
+   struct drm_crtc *crtc)
+{
+   mdp4_crtc_wait_for_commit_done(crtc);
+}
+
 static long mdp4_round_pixclk(struct msm_kms *kms, unsigned long rate,
struct drm_encoder *encoder)
 {
@@ -195,6 +201,7 @@ static const struct mdp_kms_funcs kms_funcs = {
.disable_vblank 

[PATCH 0/2] drm/msm: Customize wait for atomic commit done function

2015-04-24 Thread Hai Li
The current way to wait for atomic commit done may cause unnecessary wait for
another vsync for video mode path. Also, for command mode path, we need to wait
for PP_DONE event other than vsync before finish. This patch series is to fix
these issues.

Hai Li (2):
  drm/msm: Use customized function to wait for atomic commit done
  drm/msm/mdp5: Wait for PP_DONE irq for command mode CRTC atomic commit

 drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c|  46 +
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c |   7 ++
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h |   1 +
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c |   4 -
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c| 127 +---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c |  11 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h |   3 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c |   7 ++
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h |   1 +
 drivers/gpu/drm/msm/msm_atomic.c|  30 +-
 drivers/gpu/drm/msm/msm_kms.h   |   3 +
 11 files changed, 215 insertions(+), 25 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH] drm/msm: Attach assigned encoder to eDP and DSI connectors

2015-04-23 Thread Hai Li
drm_mode_connector_attach_encoder() function call is missing
during eDP and DSI connector initialization. As a result,
no encoder is returned by DRM_IOCTL_MODE_GETCONNECTOR system
call. This change is to fix this issue.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/dsi/dsi.c   | 10 +-
 drivers/gpu/drm/msm/dsi/dsi_manager.c   |  6 +-
 drivers/gpu/drm/msm/edp/edp_connector.c |  2 ++
 3 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index 28d1f95..ad50b80 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -177,6 +177,11 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct 
drm_device *dev,
goto fail;
}

+   for (i = 0; i < MSM_DSI_ENCODER_NUM; i++) {
+   encoders[i]->bridge = msm_dsi->bridge;
+   msm_dsi->encoders[i] = encoders[i];
+   }
+
msm_dsi->connector = msm_dsi_manager_connector_init(msm_dsi->id);
if (IS_ERR(msm_dsi->connector)) {
ret = PTR_ERR(msm_dsi->connector);
@@ -185,11 +190,6 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct 
drm_device *dev,
goto fail;
}

-   for (i = 0; i < MSM_DSI_ENCODER_NUM; i++) {
-   encoders[i]->bridge = msm_dsi->bridge;
-   msm_dsi->encoders[i] = encoders[i];
-   }
-
priv->bridges[priv->num_bridges++]   = msm_dsi->bridge;
priv->connectors[priv->num_connectors++] = msm_dsi->connector;

diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c 
b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index ee3ebca..0a40f3c 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -462,7 +462,7 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id)
struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
struct drm_connector *connector = NULL;
struct dsi_connector *dsi_connector;
-   int ret;
+   int ret, i;

dsi_connector = devm_kzalloc(msm_dsi->dev->dev,
sizeof(*dsi_connector), GFP_KERNEL);
@@ -495,6 +495,10 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id)
if (ret)
goto fail;

+   for (i = 0; i < MSM_DSI_ENCODER_NUM; i++)
+   drm_mode_connector_attach_encoder(connector,
+   msm_dsi->encoders[i]);
+
return connector;

 fail:
diff --git a/drivers/gpu/drm/msm/edp/edp_connector.c 
b/drivers/gpu/drm/msm/edp/edp_connector.c
index d8812e8..b4d1b46 100644
--- a/drivers/gpu/drm/msm/edp/edp_connector.c
+++ b/drivers/gpu/drm/msm/edp/edp_connector.c
@@ -151,6 +151,8 @@ struct drm_connector *msm_edp_connector_init(struct msm_edp 
*edp)
if (ret)
goto fail;

+   drm_mode_connector_attach_encoder(connector, edp->encoder);
+
return connector;

 fail:
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH 2/2] dt-bindings: Add MSM eDP controller documentation

2015-04-15 Thread Hai Li
Signed-off-by: Hai Li 
---
 Documentation/devicetree/bindings/drm/msm/edp.txt | 61 +++
 1 file changed, 61 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/drm/msm/edp.txt

diff --git a/Documentation/devicetree/bindings/drm/msm/edp.txt 
b/Documentation/devicetree/bindings/drm/msm/edp.txt
new file mode 100644
index 000..6e633aa
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/msm/edp.txt
@@ -0,0 +1,61 @@
+Qualcomm Technologies Inc. adreno/snapdragon eDP output
+
+Required properties:
+- compatible:
+  * "qcom,mdss-edp"
+- reg: Physical base address and length of the registers of controller and PLL
+- reg-names: The names of register regions. The following regions are required:
+  * "edp"
+  * "pll_base"
+- interrupts: The interrupt signal from the eDP block.
+- power-domains: Should be < MDSS_GDSC>.
+- clocks: device clocks
+  See Documentation/devicetree/bindings/clocks/clock-bindings.txt for details.
+- clock-names: the following clocks are required:
+  * "core_clk"
+  * "iface_clk"
+  * "mdp_core_clk"
+  * "pixel_clk"
+  * "link_clk"
+- #clock-cells: The value should be 1.
+- vdda-supply: phandle to vdda regulator device node
+- lvl-vdd-supply: phandle to regulator device node which is used to supply 
power
+  to HPD receiving chip
+- panel-en-gpios: GPIO pin to supply power to panel.
+- panel-hpd-gpios: GPIO pin used for eDP hpd.
+
+
+Optional properties:
+- interrupt-parent: phandle to the MDP block if the interrupt signal is routed
+  through MDP block
+
+Example:
+   mdss_edp: qcom,mdss_edp at fd923400 {
+   compatible = "qcom,mdss-edp";
+   reg-names =
+   "edp",
+   "pll_base";
+   reg =   <0xfd923400 0x700>,
+   <0xfd923a00 0xd4>;
+   interrupt-parent = <_mdp>;
+   interrupts = <12 0>;
+   power-domains = < MDSS_GDSC>;
+   clock-names =
+   "core_clk",
+   "pixel_clk",
+   "iface_clk",
+   "link_clk",
+   "mdp_core_clk";
+   clocks =
+   < MDSS_EDPAUX_CLK>,
+   < MDSS_EDPPIXEL_CLK>,
+   < MDSS_AHB_CLK>,
+   < MDSS_EDPLINK_CLK>,
+   < MDSS_MDP_CLK>;
+   #clock-cells = <1>;
+   vdda-supply = <_l12>;
+   lvl-vdd-supply = <_vreg>;
+   panel-en-gpios = < 137 0>;
+   panel-hpd-gpios = < 103 0>;
+   };
+
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH 1/2] dt-bindings: Add MSM DSI controller documentation

2015-04-15 Thread Hai Li
Signed-off-by: Hai Li 
---
 Documentation/devicetree/bindings/drm/msm/dsi.txt | 97 +++
 1 file changed, 97 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/drm/msm/dsi.txt

diff --git a/Documentation/devicetree/bindings/drm/msm/dsi.txt 
b/Documentation/devicetree/bindings/drm/msm/dsi.txt
new file mode 100644
index 000..b3cf325
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/msm/dsi.txt
@@ -0,0 +1,97 @@
+Qualcomm Technologies Inc. adreno/snapdragon DSI output
+
+Required properties:
+- compatible:
+  * "qcom,mdss-dsi-ctrl"
+- reg: Physical base address and length of the registers of controller, PLL,
+  PHY and PHY regulator
+- reg-names: The names of register regions. The following regions are required:
+  * "dsi_ctrl"
+  * "dsi_pll"
+  * "dsi_phy"
+  * "dsi_phy_regulator"
+- qcom,dsi-host-index: The ID of DSI controller hardware instance. This should
+  be 0 or 1, since we have 2 DSI controllers at most for now.
+- interrupts: The interrupt signal from the DSI block.
+- power-domains: Should be < MDSS_GDSC>.
+- clocks: device clocks
+  See Documentation/devicetree/bindings/clocks/clock-bindings.txt for details.
+- clock-names: the following clocks are required:
+  * "bus_clk"
+  * "byte_clk"
+  * "core_clk"
+  * "core_mmss_clk"
+  * "iface_clk"
+  * "mdp_core_clk"
+  * "pixel_clk"
+- #clock-cells: The value should be 1.
+- vdd-supply: phandle to vdd regulator device node
+- vddio-supply: phandle to vdd-io regulator device node
+- vdda-supply: phandle to vdda regulator device node
+
+Optional properties:
+- panel at 0: Node of panel connected to this DSI controller.
+  See files in Documentation/devicetree/bindings/panel/ for each supported
+  panel.
+- qcom,dual-panel-mode: Boolean value indicating if the DSI controller is
+  driving a panel which needs 2 DSI links.
+- qcom,master-panel: Boolean value indicating if the DSI controller is driving
+  the master link of the 2-DSI panel.
+- qcom,sync-dual-panel: Boolean value indicating if the DSI controller is
+  driving a 2-DSI panel whose 2 links need receive command simultaneously.
+- interrupt-parent: phandle to the MDP block if the interrupt signal is routed
+  through MDP block
+
+Example:
+   mdss_dsi0: qcom,mdss_dsi at fd922800 {
+   compatible = "qcom,mdss-dsi-ctrl";
+   qcom,dsi-host-index = <0>;
+   interrupt-parent = <_mdp>;
+   interrupts = <4 0>;
+   reg-names =
+   "dsi_ctrl",
+   "dsi_pll",
+   "dsi_phy",
+   "dsi_phy_regulator",
+   reg =   <0xfd922800 0x200>,
+   <0xfd922a00 0xd4>,
+   <0xfd922b00 0x2b0>,
+   <0xfd922d80 0x7b>,
+   <0xfd828000 0x108>;
+   power-domains = < MDSS_GDSC>;
+   clock-names =
+   "bus_clk",
+   "byte_clk",
+   "core_clk",
+   "core_mmss_clk",
+   "iface_clk",
+   "mdp_core_clk",
+   "pixel_clk";
+   clocks =
+   < MDSS_AXI_CLK>,
+   < MDSS_BYTE0_CLK>,
+   < MDSS_ESC0_CLK>,
+   < MMSS_MISC_AHB_CLK>,
+   < MDSS_AHB_CLK>,
+   < MDSS_MDP_CLK>,
+   < MDSS_PCLK0_CLK>;
+   #clock-cells = <1>;
+   vdda-supply = <_l2>;
+   vdd-supply = <_l22>;
+   vddio-supply = <_l12>;
+
+   qcom,dual-panel-mode;
+   qcom,master-panel;
+   qcom,sync-dual-panel;
+
+   panel: panel at 0 {
+   compatible = "sharp,lq101r1sx01";
+   reg = <0>;
+   link2 = <>;
+
+   power-supply = <...>;
+   backlight = <...>;
+   };
+   };
+
+
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH v3] drm/msm: Initial add DSI connector support

2015-03-31 Thread Hai Li
This change adds the DSI connector support in msm drm driver.

v1: Initial change
v2:
- Address comments from Archit + minor clean-ups
- Rebase to not depend on msm_drm_sub_dev change [Rob's comment]
v3: Fix issues when initialization is failed

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/Kconfig   |   11 +
 drivers/gpu/drm/msm/Makefile  |4 +
 drivers/gpu/drm/msm/dsi/dsi.c |  212 
 drivers/gpu/drm/msm/dsi/dsi.h |  117 ++
 drivers/gpu/drm/msm/dsi/dsi_host.c| 1993 +
 drivers/gpu/drm/msm/dsi/dsi_manager.c |  705 
 drivers/gpu/drm/msm/dsi/dsi_phy.c |  352 ++
 drivers/gpu/drm/msm/msm_drv.h |   29 +
 8 files changed, 3423 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi.c
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi.h
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi_host.c
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi_manager.c
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi_phy.c

diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 1e6a907..5ba5631 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -35,3 +35,14 @@ config DRM_MSM_REGISTER_LOGGING
  Compile in support for logging register reads/writes in a format
  that can be parsed by envytools demsm tool.  If enabled, register
  logging can be switched on via msm.reglog=y module param.
+
+config DRM_MSM_DSI
+   bool "Enable DSI support in MSM DRM driver"
+   depends on DRM_MSM
+   select DRM_PANEL
+   select DRM_MIPI_DSI
+   default y
+   help
+ Choose this option if you have a need for MIPI DSI connector
+ support.
+
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 674a132..5c144cc 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -50,5 +50,9 @@ msm-y := \

 msm-$(CONFIG_DRM_MSM_FBDEV) += msm_fbdev.o
 msm-$(CONFIG_COMMON_CLK) += mdp/mdp4/mdp4_lvds_pll.o
+msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \
+   dsi/dsi_host.o \
+   dsi/dsi_manager.o \
+   dsi/dsi_phy.o

 obj-$(CONFIG_DRM_MSM)  += msm.o
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
new file mode 100644
index 000..28d1f95
--- /dev/null
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 "dsi.h"
+
+struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi)
+{
+   if (!msm_dsi || !msm_dsi->panel)
+   return NULL;
+
+   return (msm_dsi->panel_flags & MIPI_DSI_MODE_VIDEO) ?
+   msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID] :
+   msm_dsi->encoders[MSM_DSI_CMD_ENCODER_ID];
+}
+
+static void dsi_destroy(struct msm_dsi *msm_dsi)
+{
+   if (!msm_dsi)
+   return;
+
+   msm_dsi_manager_unregister(msm_dsi);
+   if (msm_dsi->host) {
+   msm_dsi_host_destroy(msm_dsi->host);
+   msm_dsi->host = NULL;
+   }
+
+   platform_set_drvdata(msm_dsi->pdev, NULL);
+}
+
+static struct msm_dsi *dsi_init(struct platform_device *pdev)
+{
+   struct msm_dsi *msm_dsi = NULL;
+   int ret;
+
+   if (!pdev) {
+   dev_err(>dev, "no dsi device\n");
+   ret = -ENXIO;
+   goto fail;
+   }
+
+   msm_dsi = devm_kzalloc(>dev, sizeof(*msm_dsi), GFP_KERNEL);
+   if (!msm_dsi) {
+   ret = -ENOMEM;
+   goto fail;
+   }
+   DBG("dsi probed=%p", msm_dsi);
+
+   msm_dsi->pdev = pdev;
+   platform_set_drvdata(pdev, msm_dsi);
+
+   /* Init dsi host */
+   ret = msm_dsi_host_init(msm_dsi);
+   if (ret)
+   goto fail;
+
+   /* Register to dsi manager */
+   ret = msm_dsi_manager_register(msm_dsi);
+   if (ret)
+   goto fail;
+
+   return msm_dsi;
+
+fail:
+   if (msm_dsi)
+   dsi_destroy(msm_dsi);
+
+   return ERR_PTR(ret);
+}
+
+static int dsi_bind(struct device *dev, struct device *master, void *data)
+{
+   struct drm_device *drm = dev_get_drvdata(master);
+   struct msm_drm_private *priv = drm->dev_private;
+   struct platform_device *pdev = to_platform_device(dev);
+   struct msm_dsi *msm_dsi;
+
+   DBG("");
+   msm_dsi = dsi_init(pdev);

[PATCH v2 4/4] drm/msm/mdp5: Enable DSI connector in msm drm driver

2015-03-26 Thread Hai Li
This change adds the support in mdp5 kms driver for single
and dual DSI. Dual DSI case depends on the framework API
and sequence change to support dual data path.

v1: Initial change
v2: Address Rob Clark's comment
- Separate command mode encoder to a new file mdp5_cmd_encoder.c
- Rebase to not depend on msm_drm_sub_dev change

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/Makefile|   3 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c |   4 +
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c | 343 
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c|  11 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c |  43 ++-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c |  70 -
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h |  28 +-
 drivers/gpu/drm/msm/msm_drv.c   |   2 +
 8 files changed, 497 insertions(+), 7 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 5c144cc..ab20867 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -53,6 +53,7 @@ msm-$(CONFIG_COMMON_CLK) += mdp/mdp4/mdp4_lvds_pll.o
 msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \
dsi/dsi_host.o \
dsi/dsi_manager.o \
-   dsi/dsi_phy.o
+   dsi/dsi_phy.o \
+   mdp/mdp5/mdp5_cmd_encoder.o

 obj-$(CONFIG_DRM_MSM)  += msm.o
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
index 6c467fb..2c9a9dc 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
@@ -68,6 +68,8 @@ const struct mdp5_cfg_hw msm8x74_config = {
},
.intfs = {
[0] = INTF_eDP,
+   [1] = INTF_DSI,
+   [2] = INTF_DSI,
[3] = INTF_HDMI,
},
.max_clk = 2,
@@ -125,6 +127,8 @@ const struct mdp5_cfg_hw apq8084_config = {
},
.intfs = {
[0] = INTF_eDP,
+   [1] = INTF_DSI,
+   [2] = INTF_DSI,
[3] = INTF_HDMI,
},
.max_clk = 32000,
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
new file mode 100644
index 000..e4e8956
--- /dev/null
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 "mdp5_kms.h"
+
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+
+struct mdp5_cmd_encoder {
+   struct drm_encoder base;
+   struct mdp5_interface intf;
+   bool enabled;
+   uint32_t bsc;
+};
+#define to_mdp5_cmd_encoder(x) container_of(x, struct mdp5_cmd_encoder, base)
+
+static struct mdp5_kms *get_kms(struct drm_encoder *encoder)
+{
+   struct msm_drm_private *priv = encoder->dev->dev_private;
+   return to_mdp5_kms(to_mdp_kms(priv->kms));
+}
+
+#ifdef CONFIG_MSM_BUS_SCALING
+#include 
+#include 
+#include 
+#define MDP_BUS_VECTOR_ENTRY(ab_val, ib_val)   \
+   {   \
+   .src = MSM_BUS_MASTER_MDP_PORT0,\
+   .dst = MSM_BUS_SLAVE_EBI_CH0,   \
+   .ab = (ab_val), \
+   .ib = (ib_val), \
+   }
+
+static struct msm_bus_vectors mdp_bus_vectors[] = {
+   MDP_BUS_VECTOR_ENTRY(0, 0),
+   MDP_BUS_VECTOR_ENTRY(20, 20),
+};
+static struct msm_bus_paths mdp_bus_usecases[] = { {
+   .num_paths = 1,
+   .vectors = _bus_vectors[0],
+}, {
+   .num_paths = 1,
+   .vectors = _bus_vectors[1],
+} };
+static struct msm_bus_scale_pdata mdp_bus_scale_table = {
+   .usecase = mdp_bus_usecases,
+   .num_usecases = ARRAY_SIZE(mdp_bus_usecases),
+   .name = "mdss_mdp",
+};
+
+static void bs_init(struct mdp5_cmd_encoder *mdp5_cmd_enc)
+{
+   mdp5_cmd_enc->bsc = msm_bus_scale_register_client(
+   _bus_scale_table);
+   DBG("bus scale client: %08x", mdp5_cmd_enc->bsc);
+}
+
+static void bs_fini(struct mdp5_cmd_encoder *mdp5_cmd_enc)
+{
+   if (mdp5_cmd_enc->bsc) {
+   msm_bus_scale_unregister_client(mdp5_cmd_enc->bsc);
+   mdp5_cmd_e

[PATCH v2 3/4] drm/msm: Initial add DSI connector support

2015-03-26 Thread Hai Li
This change adds the DSI connector support in msm drm driver.

v1: Initial change
v2:
- Address comments from Archit + minor clean-ups
- Rebase to not depend on msm_drm_sub_dev change [Rob's comment]

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/Kconfig   |   11 +
 drivers/gpu/drm/msm/Makefile  |4 +
 drivers/gpu/drm/msm/dsi/dsi.c |  212 
 drivers/gpu/drm/msm/dsi/dsi.h |  117 ++
 drivers/gpu/drm/msm/dsi/dsi_host.c| 1992 +
 drivers/gpu/drm/msm/dsi/dsi_manager.c |  699 
 drivers/gpu/drm/msm/dsi/dsi_phy.c |  352 ++
 drivers/gpu/drm/msm/msm_drv.h |   29 +
 8 files changed, 3416 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi.c
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi.h
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi_host.c
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi_manager.c
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi_phy.c

diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 1e6a907..5ba5631 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -35,3 +35,14 @@ config DRM_MSM_REGISTER_LOGGING
  Compile in support for logging register reads/writes in a format
  that can be parsed by envytools demsm tool.  If enabled, register
  logging can be switched on via msm.reglog=y module param.
+
+config DRM_MSM_DSI
+   bool "Enable DSI support in MSM DRM driver"
+   depends on DRM_MSM
+   select DRM_PANEL
+   select DRM_MIPI_DSI
+   default y
+   help
+ Choose this option if you have a need for MIPI DSI connector
+ support.
+
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 674a132..5c144cc 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -50,5 +50,9 @@ msm-y := \

 msm-$(CONFIG_DRM_MSM_FBDEV) += msm_fbdev.o
 msm-$(CONFIG_COMMON_CLK) += mdp/mdp4/mdp4_lvds_pll.o
+msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \
+   dsi/dsi_host.o \
+   dsi/dsi_manager.o \
+   dsi/dsi_phy.o

 obj-$(CONFIG_DRM_MSM)  += msm.o
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
new file mode 100644
index 000..28d1f95
--- /dev/null
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 "dsi.h"
+
+struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi)
+{
+   if (!msm_dsi || !msm_dsi->panel)
+   return NULL;
+
+   return (msm_dsi->panel_flags & MIPI_DSI_MODE_VIDEO) ?
+   msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID] :
+   msm_dsi->encoders[MSM_DSI_CMD_ENCODER_ID];
+}
+
+static void dsi_destroy(struct msm_dsi *msm_dsi)
+{
+   if (!msm_dsi)
+   return;
+
+   msm_dsi_manager_unregister(msm_dsi);
+   if (msm_dsi->host) {
+   msm_dsi_host_destroy(msm_dsi->host);
+   msm_dsi->host = NULL;
+   }
+
+   platform_set_drvdata(msm_dsi->pdev, NULL);
+}
+
+static struct msm_dsi *dsi_init(struct platform_device *pdev)
+{
+   struct msm_dsi *msm_dsi = NULL;
+   int ret;
+
+   if (!pdev) {
+   dev_err(>dev, "no dsi device\n");
+   ret = -ENXIO;
+   goto fail;
+   }
+
+   msm_dsi = devm_kzalloc(>dev, sizeof(*msm_dsi), GFP_KERNEL);
+   if (!msm_dsi) {
+   ret = -ENOMEM;
+   goto fail;
+   }
+   DBG("dsi probed=%p", msm_dsi);
+
+   msm_dsi->pdev = pdev;
+   platform_set_drvdata(pdev, msm_dsi);
+
+   /* Init dsi host */
+   ret = msm_dsi_host_init(msm_dsi);
+   if (ret)
+   goto fail;
+
+   /* Register to dsi manager */
+   ret = msm_dsi_manager_register(msm_dsi);
+   if (ret)
+   goto fail;
+
+   return msm_dsi;
+
+fail:
+   if (msm_dsi)
+   dsi_destroy(msm_dsi);
+
+   return ERR_PTR(ret);
+}
+
+static int dsi_bind(struct device *dev, struct device *master, void *data)
+{
+   struct drm_device *drm = dev_get_drvdata(master);
+   struct msm_drm_private *priv = drm->dev_private;
+   struct platform_device *pdev = to_platform_device(dev);
+   struct msm_dsi *msm_dsi;
+
+   DBG("");
+   msm_dsi = dsi_init(pdev);
+   if (IS_ERR(msm_dsi))
+

[PATCH v2 2/4] drm/msm: Add split display interface

2015-03-26 Thread Hai Li
This change is to add an interface to MDP for connector devices
setting split display information.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/msm_kms.h | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index 3a78cb4..a9f17bd 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -47,6 +47,10 @@ struct msm_kms_funcs {
const struct msm_format *(*get_format)(struct msm_kms *kms, uint32_t 
format);
long (*round_pixclk)(struct msm_kms *kms, unsigned long rate,
struct drm_encoder *encoder);
+   int (*set_split_display)(struct msm_kms *kms,
+   struct drm_encoder *encoder,
+   struct drm_encoder *slave_encoder,
+   bool is_cmd_mode);
/* cleanup: */
void (*preclose)(struct msm_kms *kms, struct drm_file *file);
void (*destroy)(struct msm_kms *kms);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH v2 1/4] drm/msm/mdp5: Move *_modeset_init out of construct_encoder function

2015-03-26 Thread Hai Li
This change is to make the content in construct_encoder reflect its
name.
Also, DSI connector may be connected to video mode or command mode
encoder, so that 2 different encoders need to be constructed for DSI.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 89 -
 1 file changed, 54 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index f882019..6d967a8 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -163,8 +163,9 @@ int mdp5_enable(struct mdp5_kms *mdp5_kms)
return 0;
 }

-static int construct_encoder(struct mdp5_kms *mdp5_kms,
-   enum mdp5_intf_type intf_type, int intf_num)
+static struct drm_encoder *construct_encoder(struct mdp5_kms *mdp5_kms,
+   enum mdp5_intf_type intf_type, int intf_num,
+   enum mdp5_intf_mode intf_mode)
 {
struct drm_device *dev = mdp5_kms->dev;
struct msm_drm_private *priv = dev->dev_private;
@@ -172,30 +173,64 @@ static int construct_encoder(struct mdp5_kms *mdp5_kms,
struct mdp5_interface intf = {
.num= intf_num,
.type   = intf_type,
-   .mode   = MDP5_INTF_MODE_NONE,
+   .mode   = intf_mode,
};
-   int ret = 0;

encoder = mdp5_encoder_init(dev, );
if (IS_ERR(encoder)) {
-   ret = PTR_ERR(encoder);
-   dev_err(dev->dev, "failed to construct encoder: %d\n", ret);
-   return ret;
+   dev_err(dev->dev, "failed to construct encoder\n");
+   return encoder;
}

encoder->possible_crtcs = (1 << priv->num_crtcs) - 1;
priv->encoders[priv->num_encoders++] = encoder;

-   if (intf_type == INTF_HDMI) {
-   ret = hdmi_modeset_init(priv->hdmi, dev, encoder);
-   if (ret)
-   dev_err(dev->dev, "failed to init HDMI: %d\n", ret);
+   return encoder;
+}
+
+static int modeset_init_intf(struct mdp5_kms *mdp5_kms, int intf_num)
+{
+   struct drm_device *dev = mdp5_kms->dev;
+   struct msm_drm_private *priv = dev->dev_private;
+   const struct mdp5_cfg_hw *hw_cfg =
+   mdp5_cfg_get_hw_config(mdp5_kms->cfg);
+   enum mdp5_intf_type intf_type = hw_cfg->intfs[intf_num];
+   struct drm_encoder *encoder;
+   int ret = 0;
+
+   switch (intf_type) {
+   case INTF_DISABLED:
+   break;
+   case INTF_eDP:
+   if (!priv->edp)
+   break;
+
+   encoder = construct_encoder(mdp5_kms, INTF_eDP, intf_num,
+   MDP5_INTF_MODE_NONE);
+   if (IS_ERR(encoder)) {
+   ret = PTR_ERR(encoder);
+   break;
+   }

-   } else if (intf_type == INTF_eDP) {
-   /* Construct bridge/connector for eDP: */
ret = msm_edp_modeset_init(priv->edp, dev, encoder);
-   if (ret)
-   dev_err(dev->dev, "failed to init eDP: %d\n", ret);
+   break;
+   case INTF_HDMI:
+   if (!priv->hdmi)
+   break;
+
+   encoder = construct_encoder(mdp5_kms, INTF_HDMI, intf_num,
+   MDP5_INTF_MODE_NONE);
+   if (IS_ERR(encoder)) {
+   ret = PTR_ERR(encoder);
+   break;
+   }
+
+   ret = hdmi_modeset_init(priv->hdmi, dev, encoder);
+   break;
+   default:
+   dev_err(dev->dev, "unknown intf: %d\n", intf_type);
+   ret = -EINVAL;
+   break;
}

return ret;
@@ -261,27 +296,11 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
}
}

-   /* Construct external display interfaces' encoders: */
+   /* Construct encoders and modeset initialize connector devices
+* for each external display interface.
+*/
for (i = 0; i < ARRAY_SIZE(hw_cfg->intfs); i++) {
-   enum mdp5_intf_type intf_type = hw_cfg->intfs[i];
-
-   switch (intf_type) {
-   case INTF_DISABLED:
-   break;
-   case INTF_eDP:
-   if (priv->edp)
-   ret = construct_encoder(mdp5_kms, INTF_eDP, i);
-   break;
-   case INTF_HDMI:
-   if (priv->hdmi)
-   ret = construct_encoder(mdp5_kms, INTF_HDMI, i);
-   break;
-   default:
-   dev_err(dev->dev, "unk

[PATCH v2 0/4] drm/msm: Initial add DSI support

2015-03-26 Thread Hai Li
Resending initial MSM DSI patches
DSI is supported by both mdp4 and mdp5. This patch series adds the common DSI
controller driver and also enable it in mdp5.

Hai Li (4):
  drm/msm/mdp5: Move *_modeset_init out of construct_encoder function
  drm/msm: Add split display interface
  drm/msm: Initial add DSI connector support
  drm/msm/mdp5: Enable DSI connector in msm drm driver

 drivers/gpu/drm/msm/Kconfig |   11 +
 drivers/gpu/drm/msm/Makefile|5 +
 drivers/gpu/drm/msm/dsi/dsi.c   |  212 +++
 drivers/gpu/drm/msm/dsi/dsi.h   |  117 ++
 drivers/gpu/drm/msm/dsi/dsi_host.c  | 1992 +++
 drivers/gpu/drm/msm/dsi/dsi_manager.c   |  699 
 drivers/gpu/drm/msm/dsi/dsi_phy.c   |  352 
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c |4 +
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c |  343 
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c|   11 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c |   43 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c |  159 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h |   28 +-
 drivers/gpu/drm/msm/msm_drv.c   |2 +
 drivers/gpu/drm/msm/msm_drv.h   |   29 +
 drivers/gpu/drm/msm/msm_kms.h   |4 +
 16 files changed, 3970 insertions(+), 41 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi.c
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi.h
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi_host.c
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi_manager.c
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi_phy.c
 create mode 100644 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH] drm/msm: Initial add DSI connector support (v2)

2015-03-24 Thread Hai Li
This change adds the DSI connector support in msm drm driver.

v1: Initial change
v2: Address comments from Archit + minor clean-ups

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/Kconfig   |   11 +
 drivers/gpu/drm/msm/Makefile  |4 +
 drivers/gpu/drm/msm/dsi/dsi.c |  214 
 drivers/gpu/drm/msm/dsi/dsi.h |  118 ++
 drivers/gpu/drm/msm/dsi/dsi_host.c| 1992 +
 drivers/gpu/drm/msm/dsi/dsi_manager.c |  699 
 drivers/gpu/drm/msm/dsi/dsi_phy.c |  352 ++
 drivers/gpu/drm/msm/msm_drv.h |   20 +
 8 files changed, 3410 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi.c
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi.h
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi_host.c
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi_manager.c
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi_phy.c

diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 1e6a907..5ba5631 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -35,3 +35,14 @@ config DRM_MSM_REGISTER_LOGGING
  Compile in support for logging register reads/writes in a format
  that can be parsed by envytools demsm tool.  If enabled, register
  logging can be switched on via msm.reglog=y module param.
+
+config DRM_MSM_DSI
+   bool "Enable DSI support in MSM DRM driver"
+   depends on DRM_MSM
+   select DRM_PANEL
+   select DRM_MIPI_DSI
+   default y
+   help
+ Choose this option if you have a need for MIPI DSI connector
+ support.
+
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 674a132..5c144cc 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -50,5 +50,9 @@ msm-y := \

 msm-$(CONFIG_DRM_MSM_FBDEV) += msm_fbdev.o
 msm-$(CONFIG_COMMON_CLK) += mdp/mdp4/mdp4_lvds_pll.o
+msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \
+   dsi/dsi_host.o \
+   dsi/dsi_manager.o \
+   dsi/dsi_phy.o

 obj-$(CONFIG_DRM_MSM)  += msm.o
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
new file mode 100644
index 000..1125264
--- /dev/null
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 "dsi.h"
+
+struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi)
+{
+   if (!msm_dsi || !msm_dsi->panel)
+   return NULL;
+
+   return (msm_dsi->panel_flags & MIPI_DSI_MODE_VIDEO) ?
+   msm_dsi->base.encoders[MSM_DSI_VIDEO_ENCODER_ID] :
+   msm_dsi->base.encoders[MSM_DSI_CMD_ENCODER_ID];
+}
+
+static int dsi_modeset_init(struct msm_drm_sub_dev *base,
+   struct drm_device *dev)
+{
+   struct msm_dsi *msm_dsi = container_of(base, struct msm_dsi, base);
+   struct msm_drm_private *priv = dev->dev_private;
+   int ret, i;
+
+   if (WARN_ON((base->num_encoders != MSM_DSI_ENCODER_NUM) ||
+   !base->encoders[MSM_DSI_VIDEO_ENCODER_ID] ||
+   !base->encoders[MSM_DSI_CMD_ENCODER_ID]))
+   return -EINVAL;
+
+   msm_dsi->dev = dev;
+
+   ret = msm_dsi_host_modeset_init(msm_dsi->host, dev);
+   if (ret) {
+   dev_err(dev->dev, "failed to modeset init host: %d\n", ret);
+   goto fail;
+   }
+
+   msm_dsi->bridge = msm_dsi_manager_bridge_init(msm_dsi->id);
+   if (IS_ERR(msm_dsi->bridge)) {
+   ret = PTR_ERR(msm_dsi->bridge);
+   dev_err(dev->dev, "failed to create dsi bridge: %d\n", ret);
+   msm_dsi->bridge = NULL;
+   goto fail;
+   }
+
+   msm_dsi->connector = msm_dsi_manager_connector_init(msm_dsi->id);
+   if (IS_ERR(msm_dsi->connector)) {
+   ret = PTR_ERR(msm_dsi->connector);
+   dev_err(dev->dev, "failed to create dsi connector: %d\n", ret);
+   msm_dsi->connector = NULL;
+   goto fail;
+   }
+
+   for (i = 0; i < base->num_encoders; i++)
+   base->encoders[i]->bridge = msm_dsi->bridge;
+
+   priv->bridges[priv->num_bridges++]   = msm_dsi->bridge;
+   priv->connectors[priv->num_connectors++] = msm_dsi->connector;

[PATCH 4/4] drm/msm/mdp5: Enable DSI connector in msm drm driver

2015-03-13 Thread Hai Li
This change adds the support in mdp5 kms driver for single
and dual DSI. Dual DSI case depends on the framework API
and sequence change to support dual data path.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c |   4 +
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c|  11 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c | 268 +++-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c |  69 ++-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h |  12 +-
 drivers/gpu/drm/msm/msm_drv.c   |   2 +
 6 files changed, 353 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
index 6c467fb..2c9a9dc 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
@@ -68,6 +68,8 @@ const struct mdp5_cfg_hw msm8x74_config = {
},
.intfs = {
[0] = INTF_eDP,
+   [1] = INTF_DSI,
+   [2] = INTF_DSI,
[3] = INTF_HDMI,
},
.max_clk = 2,
@@ -125,6 +127,8 @@ const struct mdp5_cfg_hw apq8084_config = {
},
.intfs = {
[0] = INTF_eDP,
+   [1] = INTF_DSI,
+   [2] = INTF_DSI,
[3] = INTF_HDMI,
},
.max_clk = 32000,
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index 9b38cde..f877e1d 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -626,7 +626,16 @@ void mdp5_crtc_set_intf(struct drm_crtc *crtc, struct 
mdp5_interface *intf)

/* now that we know what irq's we want: */
mdp5_crtc->err.irqmask = intf2err(intf->num);
-   mdp5_crtc->vblank.irqmask = intf2vblank(lm, intf);
+
+   /* Register command mode Pingpong done as vblank for now,
+* so that atomic commit should wait for it to finish.
+* Ideally, in the future, we should take rd_ptr done as vblank,
+* and let atomic commit wait for pingpong done for commond mode.
+*/
+   if (intf->mode == MDP5_INTF_DSI_MODE_COMMAND)
+   mdp5_crtc->vblank.irqmask = lm2ppdone(lm);
+   else
+   mdp5_crtc->vblank.irqmask = intf2vblank(lm, intf);
mdp_irq_update(_kms->base);

mdp5_ctl_set_intf(mdp5_crtc->ctl, intf);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
index a17eb9c..efe7aaf 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
@@ -98,6 +98,221 @@ static void bs_fini(struct mdp5_encoder *mdp5_encoder) {}
 static void bs_set(struct mdp5_encoder *mdp5_encoder, int idx) {}
 #endif

+/*
+ * Command mode encoder, used by DSI command mode path.
+ * Should move to a separate file, once global bandwidth
+ * functions are available.
+ */
+#define VSYNC_CLK_RATE 1920
+static int pingpong_tearcheck_setup(struct drm_encoder *encoder,
+   struct drm_display_mode *mode)
+{
+   struct mdp5_kms *mdp5_kms = get_kms(encoder);
+   struct device *dev = encoder->dev->dev;
+   u32 total_lines_x100, vclks_line, cfg;
+   long vsync_clk_speed;
+   int pp_id = GET_PING_PONG_ID(mdp5_crtc_get_lm(encoder->crtc));
+
+   if (IS_ERR_OR_NULL(mdp5_kms->vsync_clk)) {
+   dev_err(dev, "vsync_clk is not initialized\n");
+   return -EINVAL;
+   }
+
+   total_lines_x100 = mode->vtotal * mode->vrefresh;
+   if (!total_lines_x100) {
+   dev_err(dev, "%s: vtotal(%d) or vrefresh(%d) is 0\n",
+   __func__, mode->vtotal, mode->vrefresh);
+   return -EINVAL;
+   }
+
+   vsync_clk_speed = clk_round_rate(mdp5_kms->vsync_clk, VSYNC_CLK_RATE);
+   if (vsync_clk_speed <= 0) {
+   dev_err(dev, "vsync_clk round rate failed %ld\n",
+   vsync_clk_speed);
+   return -EINVAL;
+   }
+   vclks_line = vsync_clk_speed * 100 / total_lines_x100;
+
+   cfg = MDP5_PP_SYNC_CONFIG_VSYNC_COUNTER_EN
+   | MDP5_PP_SYNC_CONFIG_VSYNC_IN_EN;
+   cfg |= MDP5_PP_SYNC_CONFIG_VSYNC_COUNT(vclks_line);
+
+   mdp5_write(mdp5_kms, REG_MDP5_PP_SYNC_CONFIG_VSYNC(pp_id), cfg);
+   mdp5_write(mdp5_kms,
+   REG_MDP5_PP_SYNC_CONFIG_HEIGHT(pp_id), 0xfff0);
+   mdp5_write(mdp5_kms,
+   REG_MDP5_PP_VSYNC_INIT_VAL(pp_id), mode->vdisplay);
+   mdp5_write(mdp5_kms, REG_MDP5_PP_RD_PTR_IRQ(pp_id), mode->vdisplay + 1);
+   mdp5_write(mdp5_kms, REG_MDP5_PP_START_POS(pp_id), mode->vdisplay);
+   mdp5_write(mdp5_kms, REG_MDP5_PP_SYNC_THRESH(pp_id),
+   MDP5_PP_SYNC_THRESH_START(4) |
+   MDP5_PP_SY

[PATCH 3/4] drm/msm: Initial add DSI connector support

2015-03-13 Thread Hai Li
This change adds the DSI connector support in msm drm driver.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/Kconfig   |   11 +
 drivers/gpu/drm/msm/Makefile  |4 +
 drivers/gpu/drm/msm/dsi/dsi.c |  203 
 drivers/gpu/drm/msm/dsi/dsi.h |  115 ++
 drivers/gpu/drm/msm/dsi/dsi_host.c| 1997 +
 drivers/gpu/drm/msm/dsi/dsi_manager.c |  706 
 drivers/gpu/drm/msm/dsi/dsi_phy.c |  352 ++
 drivers/gpu/drm/msm/msm_drv.h |   20 +
 8 files changed, 3408 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi.c
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi.h
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi_host.c
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi_manager.c
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi_phy.c

diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 1e6a907..5ba5631 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -35,3 +35,14 @@ config DRM_MSM_REGISTER_LOGGING
  Compile in support for logging register reads/writes in a format
  that can be parsed by envytools demsm tool.  If enabled, register
  logging can be switched on via msm.reglog=y module param.
+
+config DRM_MSM_DSI
+   bool "Enable DSI support in MSM DRM driver"
+   depends on DRM_MSM
+   select DRM_PANEL
+   select DRM_MIPI_DSI
+   default y
+   help
+ Choose this option if you have a need for MIPI DSI connector
+ support.
+
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 674a132..5c144cc 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -50,5 +50,9 @@ msm-y := \

 msm-$(CONFIG_DRM_MSM_FBDEV) += msm_fbdev.o
 msm-$(CONFIG_COMMON_CLK) += mdp/mdp4/mdp4_lvds_pll.o
+msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \
+   dsi/dsi_host.o \
+   dsi/dsi_manager.o \
+   dsi/dsi_phy.o

 obj-$(CONFIG_DRM_MSM)  += msm.o
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
new file mode 100644
index 000..de77260
--- /dev/null
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 "dsi.h"
+
+int msm_dsi_modeset_init(struct msm_drm_sub_dev *base, struct drm_device *dev)
+{
+   struct msm_dsi *msm_dsi = container_of(base, struct msm_dsi, base);
+   struct msm_drm_private *priv = dev->dev_private;
+   int ret, i;
+
+   if (WARN_ON((base->num_encoders != MSM_DSI_ENCODER_NUM) ||
+   !base->encoders[MSM_DSI_VIDEO_ENCODER_ID] ||
+   !base->encoders[MSM_DSI_CMD_ENCODER_ID]))
+   return -EINVAL;
+
+   msm_dsi->dev = dev;
+
+   ret = msm_dsi_host_modeset_init(msm_dsi->host, dev);
+   if (ret) {
+   dev_err(dev->dev, "failed to modeset init host: %d\n", ret);
+   goto fail;
+   }
+
+   msm_dsi->bridge = msm_dsi_manager_bridge_init(msm_dsi->id);
+   if (IS_ERR(msm_dsi->bridge)) {
+   ret = PTR_ERR(msm_dsi->bridge);
+   dev_err(dev->dev, "failed to create dsi bridge: %d\n", ret);
+   msm_dsi->bridge = NULL;
+   goto fail;
+   }
+
+   msm_dsi->connector = msm_dsi_manager_connector_init(msm_dsi->id);
+   if (IS_ERR(msm_dsi->connector)) {
+   ret = PTR_ERR(msm_dsi->connector);
+   dev_err(dev->dev, "failed to create dsi connector: %d\n", ret);
+   msm_dsi->connector = NULL;
+   goto fail;
+   }
+
+   for (i = 0; i < base->num_encoders; i++)
+   base->encoders[i]->bridge = msm_dsi->bridge;
+
+   priv->bridges[priv->num_bridges++]   = msm_dsi->bridge;
+   priv->connectors[priv->num_connectors++] = msm_dsi->connector;
+
+   return 0;
+fail:
+   if (msm_dsi) {
+   /* bridge/connector are normally destroyed by drm: */
+   if (msm_dsi->bridge) {
+   msm_dsi_manager_bridge_destroy(msm_dsi->bridge);
+   msm_dsi->bridge = NULL;
+   }
+   if (msm_dsi->connector) {
+   msm_dsi->connector->funcs->destroy(msm_dsi->connector);
+   msm_dsi->con

[PATCH 2/4] drm/msm: Add split display interface

2015-03-13 Thread Hai Li
This change is to add an interface to MDP for connector devices
setting split display information.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/msm_kms.h | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index 3a78cb4..a9f17bd 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -47,6 +47,10 @@ struct msm_kms_funcs {
const struct msm_format *(*get_format)(struct msm_kms *kms, uint32_t 
format);
long (*round_pixclk)(struct msm_kms *kms, unsigned long rate,
struct drm_encoder *encoder);
+   int (*set_split_display)(struct msm_kms *kms,
+   struct drm_encoder *encoder,
+   struct drm_encoder *slave_encoder,
+   bool is_cmd_mode);
/* cleanup: */
void (*preclose)(struct msm_kms *kms, struct drm_file *file);
void (*destroy)(struct msm_kms *kms);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH 1/4] drm/msm/dsi: Update generated DSI header file

2015-03-13 Thread Hai Li
Prepare for initial DSI implementation

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/dsi/dsi.xml.h | 418 ++
 1 file changed, 376 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h 
b/drivers/gpu/drm/msm/dsi/dsi.xml.h
index abf1bba..1dcfae2 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
@@ -8,19 +8,10 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git

 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/msm.xml (
676 bytes, from 2014-12-05 15:34:49)
-- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   
1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml(  
20908 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml  (   
2357 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml(  
27208 bytes, from 2015-01-13 23:56:11)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml (  
11712 bytes, from 2013-08-17 17:13:43)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml(
344 bytes, from 2013-08-11 19:26:32)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml (   
1686 bytes, from 2014-10-31 16:48:57)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml (
600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml   (  
26848 bytes, from 2015-01-13 23:55:57)
-- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml (   
8253 bytes, from 2014-12-08 16:13:00)
-
-Copyright (C) 2013 by the following authors:
+- /usr2/hali/local/envytools/envytools/rnndb/dsi/dsi.xml (  18681 
bytes, from 2015-03-04 23:08:31)
+- /usr2/hali/local/envytools/envytools/rnndb/freedreno_copyright.xml (   1453 
bytes, from 2015-01-28 21:43:22)
+
+Copyright (C) 2013-2015 by the following authors:
 - Rob Clark  (robclark)

 Permission is hereby granted, free of charge, to any person obtaining
@@ -51,11 +42,11 @@ enum dsi_traffic_mode {
BURST_MODE = 2,
 };

-enum dsi_dst_format {
-   DST_FORMAT_RGB565 = 0,
-   DST_FORMAT_RGB666 = 1,
-   DST_FORMAT_RGB666_LOOSE = 2,
-   DST_FORMAT_RGB888 = 3,
+enum dsi_vid_dst_format {
+   VID_DST_FORMAT_RGB565 = 0,
+   VID_DST_FORMAT_RGB666 = 1,
+   VID_DST_FORMAT_RGB666_LOOSE = 2,
+   VID_DST_FORMAT_RGB888 = 3,
 };

 enum dsi_rgb_swap {
@@ -69,20 +60,63 @@ enum dsi_rgb_swap {

 enum dsi_cmd_trigger {
TRIGGER_NONE = 0,
+   TRIGGER_SEOF = 1,
TRIGGER_TE = 2,
TRIGGER_SW = 4,
TRIGGER_SW_SEOF = 5,
TRIGGER_SW_TE = 6,
 };

+enum dsi_cmd_dst_format {
+   CMD_DST_FORMAT_RGB111 = 0,
+   CMD_DST_FORMAT_RGB332 = 3,
+   CMD_DST_FORMAT_RGB444 = 4,
+   CMD_DST_FORMAT_RGB565 = 6,
+   CMD_DST_FORMAT_RGB666 = 7,
+   CMD_DST_FORMAT_RGB888 = 8,
+};
+
+enum dsi_lane_swap {
+   LANE_SWAP_0123 = 0,
+   LANE_SWAP_3012 = 1,
+   LANE_SWAP_2301 = 2,
+   LANE_SWAP_1230 = 3,
+   LANE_SWAP_0321 = 4,
+   LANE_SWAP_1032 = 5,
+   LANE_SWAP_2103 = 6,
+   LANE_SWAP_3210 = 7,
+};
+
 #define DSI_IRQ_CMD_DMA_DONE   0x0001
 #define DSI_IRQ_MASK_CMD_DMA_DONE  0x0002
 #define DSI_IRQ_CMD_MDP_DONE   0x0100
 #define DSI_IRQ_MASK_CMD_MDP_DONE  0x0200
 #define DSI_IRQ_VIDEO_DONE 0x0001
 #define DSI_IRQ_MASK_VIDEO_DONE
0x0002
+#define DSI_IRQ_BTA_DONE   0x0010
+#define DSI_IRQ_MASK_BTA_DONE  0x0020
 #define DSI_IRQ_ERROR  0x0100
 #define DSI_IRQ_MASK_ERROR 0x0200
+#define REG_DSI_6G_HW_VERSION  0x
+#define DSI_6G_HW_VERSION_MAJOR__MASK  0xf000
+#define DSI_6G_HW_VERSION_MAJOR__SHIFT 28
+static inline uint32_t DSI_6G_HW_VERSION_MAJOR(uint32_t val)
+{
+   return ((val) << DSI_6G_HW_VERSION_MAJOR__SHIFT) & 
DSI_6G_HW_VERSION_MAJOR__MASK;
+}
+#define DSI_6G_HW_VERSION_MINOR__MASK  0x0fff
+#define DSI_6G_HW_VERSION_MINOR__SHIFT 16
+static inline uint32_t DSI_6G_HW_VERSION_MINOR(uint32_t val)
+{
+   return ((val) << DSI_6G_HW_VERSION_MINOR__SHIFT) & 
DSI_6G_HW_VERSION_MINOR__MASK;
+}
+#define DSI_6G_HW_VERSION_STEP__MASK   0x
+#define DSI_6G_HW_VERSION_STEP__SHIFT  

[PATCH 0/4] drm/msm: Initial add DSI support

2015-03-13 Thread Hai Li
DSI is supported by both mdp4 and mdp5. This patch series adds the common DSI
controller driver and also enable it in mdp5.

Hai Li (4):
  drm/msm/dsi: Update generated DSI header file
  drm/msm: Add split display interface
  drm/msm: Initial add DSI connector support
  drm/msm/mdp5: Enable DSI connector in msm drm driver

 drivers/gpu/drm/msm/Kconfig |   11 +
 drivers/gpu/drm/msm/Makefile|4 +
 drivers/gpu/drm/msm/dsi/dsi.c   |  203 +++
 drivers/gpu/drm/msm/dsi/dsi.h   |  115 ++
 drivers/gpu/drm/msm/dsi/dsi.xml.h   |  418 +-
 drivers/gpu/drm/msm/dsi/dsi_host.c  | 1997 +++
 drivers/gpu/drm/msm/dsi/dsi_manager.c   |  706 ++
 drivers/gpu/drm/msm/dsi/dsi_phy.c   |  352 +
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c |4 +
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c|   11 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c |  268 +++-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c |   69 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h |   12 +-
 drivers/gpu/drm/msm/msm_drv.c   |2 +
 drivers/gpu/drm/msm/msm_drv.h   |   20 +
 drivers/gpu/drm/msm/msm_kms.h   |4 +
 16 files changed, 4141 insertions(+), 55 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi.c
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi.h
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi_host.c
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi_manager.c
 create mode 100644 drivers/gpu/drm/msm/dsi/dsi_phy.c

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH] rnndb: Update DSI core and PHY registers for 8084

2015-03-13 Thread Hai Li
DSI core registers in DSI6G are compatible with the old versions.
The offsets are 4-byte shift down because of the addition of a
HW_VERSION register. This difference will be handled in source code.

DSI PHY registers are incompatible. This change adds a new domain
for 28nm PHY and PHY regulator, which are used in 8084 and some other
chips.

Signed-off-by: Hai Li 
---
 rnndb/dsi/dsi.xml | 212 --
 1 file changed, 191 insertions(+), 21 deletions(-)

diff --git a/rnndb/dsi/dsi.xml b/rnndb/dsi/dsi.xml
index 19898e1..480ec46 100644
--- a/rnndb/dsi/dsi.xml
+++ b/rnndb/dsi/dsi.xml
@@ -10,11 +10,11 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



-   
-   
-   
-   
-   
+   
+   
+   
+   
+   



@@ -26,11 +26,30 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



+   





+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   



@@ -38,10 +57,18 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



+   
+   




+   
+   
+   
+   
+   
+



@@ -56,15 +83,20 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



+   

+   

  
+   


-   
+   
+   
+   

  

-   
+   



@@ -74,11 +106,10 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



-   
-   
-   
-   
-   
+   
+   
+   
+   



@@ -96,27 +127,53 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



-   
+   
+   
+   
+   
+   





+   



-   
-   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   


+   
+   
+   
+   
+   
+   
+   
+   
+   





-   
-   
-   
+   
+   
+   
+   



@@ -130,12 +187,34 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



-   
+   
+   
+   



-   
-   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   



@@ -272,4 +351,95 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">

 

+
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+
+   
+   
+   
+   
+   
+   
+   
+   
+   
+
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+
+   
+   
+   
+   
+   
+
+   
+   
+
+   
+   
+   
+   
+   
+   
+
+   
+   
+
+
+
+   
+   
+   
+ 

[PATCH 4/4] drm/msm: Fix default fb var width and height

2015-03-05 Thread Hai Li
The framebuffer var width and height should reflect the size of
framebuffer memory allocated, which is the entire surface size.

In case of dual DSI connectors with TILE properties, this change
makes the whole image show on the dual DSI panel, instead of
duplicated images on both sides.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/msm_fbdev.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c
index df60f65..d3e8b14 100644
--- a/drivers/gpu/drm/msm/msm_fbdev.c
+++ b/drivers/gpu/drm/msm/msm_fbdev.c
@@ -169,7 +169,8 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
}

drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
-   drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
+   drm_fb_helper_fill_var(fbi, helper,
+   sizes->surface_width, sizes->surface_height);

dev->mode_config.fb_base = paddr;

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH 3/4] drm/msm/mdp5: Fix PIPE source image size settings

2015-03-05 Thread Hai Li
The width and height in SSPP_SRC_IMG_SIZE register should be the
size of the entire source framebuffer, not the fetch size.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 05cf9ab..37fef77 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -505,8 +505,8 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
spin_lock_irqsave(_plane->pipe_lock, flags);

mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_IMG_SIZE(pipe),
-   MDP5_PIPE_SRC_IMG_SIZE_WIDTH(src_w) |
-   MDP5_PIPE_SRC_IMG_SIZE_HEIGHT(src_h));
+   MDP5_PIPE_SRC_IMG_SIZE_WIDTH(fb->width) |
+   MDP5_PIPE_SRC_IMG_SIZE_HEIGHT(fb->height));

mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_SIZE(pipe),
MDP5_PIPE_SRC_SIZE_WIDTH(src_w) |
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH 2/4] drm/msm/mdp5: Update generated mdp5 header file with DSI support

2015-03-05 Thread Hai Li
This change adds the registers in mdp5 ping pong blocks
and split display control registers.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h | 105 
 1 file changed, 105 insertions(+)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
index d8360a5..e86bcf0 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
@@ -235,6 +235,9 @@ static inline uint32_t MDP5_DISP_INTF_SEL_INTF3(enum 
mdp5_intf_type val)

 #define REG_MDP5_HIST_INTR_CLEAR   0x0124

+#define REG_MDP5_SPARE_0   0x0128
+#define MDP5_SPARE_0_SPLIT_DPL_SINGLE_FLUSH_EN 0x0001
+
 static inline uint32_t REG_MDP5_SMP_ALLOC_W(uint32_t i0) { return 0x0180 + 
0x4*i0; }

 static inline uint32_t REG_MDP5_SMP_ALLOC_W_REG(uint32_t i0) { return 
0x0180 + 0x4*i0; }
@@ -305,6 +308,20 @@ static inline uint32_t MDP5_IGC_LUT_REG_VAL(uint32_t val)
 #define MDP5_IGC_LUT_REG_DISABLE_PIPE_1
0x2000
 #define MDP5_IGC_LUT_REG_DISABLE_PIPE_2
0x4000

+#define REG_MDP5_SPLIT_DPL_EN  0x03f4
+
+#define REG_MDP5_SPLIT_DPL_UPPER   0x03f8
+#define MDP5_SPLIT_DPL_UPPER_SMART_PANEL   0x0002
+#define MDP5_SPLIT_DPL_UPPER_SMART_PANEL_FREE_RUN  0x0004
+#define MDP5_SPLIT_DPL_UPPER_INTF1_SW_TRG_MUX  0x0010
+#define MDP5_SPLIT_DPL_UPPER_INTF2_SW_TRG_MUX  0x0100
+
+#define REG_MDP5_SPLIT_DPL_LOWER   0x04f0
+#define MDP5_SPLIT_DPL_LOWER_SMART_PANEL   0x0002
+#define MDP5_SPLIT_DPL_LOWER_SMART_PANEL_FREE_RUN  0x0004
+#define MDP5_SPLIT_DPL_LOWER_INTF1_TG_SYNC 0x0010
+#define MDP5_SPLIT_DPL_LOWER_INTF2_TG_SYNC 0x0100
+
 static inline uint32_t __offset_CTL(uint32_t idx)
 {
switch (idx) {
@@ -1114,6 +1131,94 @@ static inline uint32_t REG_MDP5_DSPP_GAMUT_BASE(uint32_t 
i0) { return 0x02dc

 static inline uint32_t REG_MDP5_DSPP_GC_BASE(uint32_t i0) { return 0x02b0 
+ __offset_DSPP(i0); }

+static inline uint32_t __offset_PP(uint32_t idx)
+{
+   switch (idx) {
+   case 0: return (mdp5_cfg->pp.base[0]);
+   case 1: return (mdp5_cfg->pp.base[1]);
+   case 2: return (mdp5_cfg->pp.base[2]);
+   case 3: return (mdp5_cfg->pp.base[3]);
+   default: return INVALID_IDX(idx);
+   }
+}
+static inline uint32_t REG_MDP5_PP(uint32_t i0) { return 0x + 
__offset_PP(i0); }
+
+static inline uint32_t REG_MDP5_PP_TEAR_CHECK_EN(uint32_t i0) { return 
0x + __offset_PP(i0); }
+
+static inline uint32_t REG_MDP5_PP_SYNC_CONFIG_VSYNC(uint32_t i0) { return 
0x0004 + __offset_PP(i0); }
+#define MDP5_PP_SYNC_CONFIG_VSYNC_COUNT__MASK  0x0007
+#define MDP5_PP_SYNC_CONFIG_VSYNC_COUNT__SHIFT 0
+static inline uint32_t MDP5_PP_SYNC_CONFIG_VSYNC_COUNT(uint32_t val)
+{
+   return ((val) << MDP5_PP_SYNC_CONFIG_VSYNC_COUNT__SHIFT) & 
MDP5_PP_SYNC_CONFIG_VSYNC_COUNT__MASK;
+}
+#define MDP5_PP_SYNC_CONFIG_VSYNC_COUNTER_EN   0x0008
+#define MDP5_PP_SYNC_CONFIG_VSYNC_IN_EN
0x0010
+
+static inline uint32_t REG_MDP5_PP_SYNC_CONFIG_HEIGHT(uint32_t i0) { return 
0x0008 + __offset_PP(i0); }
+
+static inline uint32_t REG_MDP5_PP_SYNC_WRCOUNT(uint32_t i0) { return 
0x000c + __offset_PP(i0); }
+#define MDP5_PP_SYNC_WRCOUNT_LINE_COUNT__MASK  0x
+#define MDP5_PP_SYNC_WRCOUNT_LINE_COUNT__SHIFT 0
+static inline uint32_t MDP5_PP_SYNC_WRCOUNT_LINE_COUNT(uint32_t val)
+{
+   return ((val) << MDP5_PP_SYNC_WRCOUNT_LINE_COUNT__SHIFT) & 
MDP5_PP_SYNC_WRCOUNT_LINE_COUNT__MASK;
+}
+#define MDP5_PP_SYNC_WRCOUNT_FRAME_COUNT__MASK 0x
+#define MDP5_PP_SYNC_WRCOUNT_FRAME_COUNT__SHIFT16
+static inline uint32_t MDP5_PP_SYNC_WRCOUNT_FRAME_COUNT(uint32_t val)
+{
+   return ((val) << MDP5_PP_SYNC_WRCOUNT_FRAME_COUNT__SHIFT) & 
MDP5_PP_SYNC_WRCOUNT_FRAME_COUNT__MASK;
+}
+
+static inline uint32_t REG_MDP5_PP_VSYNC_INIT_VAL(uint32_t i0) { return 
0x0010 + __offset_PP(i0); }
+
+static inline uint32_t REG_MDP5_PP_INT_COUNT_VAL(uint32_t i0) { return 
0x0014 + __offset_PP(i0); }
+#define MDP5_PP_INT_COUNT_VAL_LINE_COUNT__MASK 0x
+#define MDP5_PP_INT_COUNT_VAL_LINE_COUNT__SHIFT0
+static inline uint32_t MDP5_PP_INT_COUNT_VAL_LINE_COUNT(uint32_t val)
+{
+   return ((val) << MDP5_PP_INT_COUNT_VAL_LINE_COUNT__SHIFT) & 
MDP5_PP_INT_COUNT_VAL_LINE_COUNT__MASK;
+}
+#define MDP5_PP_INT_COUNT_VAL_

[PATCH 1/4] drm/msm/mdp5: Add pingpong entry to mdp5 config table

2015-03-05 Thread Hai Li
Pingpong register base addresses are different across platforms.
This change adds this information to config table and initialize
the values for 8x74 and 8084.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c | 8 
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h | 1 +
 2 files changed, 9 insertions(+)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
index 8bee023..6c467fb 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
@@ -58,6 +58,10 @@ const struct mdp5_cfg_hw msm8x74_config = {
.count = 2,
.base = { 0x13100, 0x13300 }, /* NOTE: no ad in v1.0 */
},
+   .pp = {
+   .count = 3,
+   .base = { 0x12d00, 0x12e00, 0x12f00 },
+   },
.intf = {
.count = 4,
.base = { 0x12500, 0x12700, 0x12900, 0x12b00 },
@@ -111,6 +115,10 @@ const struct mdp5_cfg_hw apq8084_config = {
.count = 3,
.base = { 0x13500, 0x13700, 0x13900 },
},
+   .pp = {
+   .count = 4,
+   .base = { 0x12f00, 0x13000, 0x13100, 0x13200 },
+   },
.intf = {
.count = 5,
.base = { 0x12500, 0x12700, 0x12900, 0x12b00, 0x12d00 },
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
index 4e91f14..c2d4498 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
@@ -71,6 +71,7 @@ struct mdp5_cfg_hw {
struct mdp5_lm_block  lm;
struct mdp5_sub_block dspp;
struct mdp5_sub_block ad;
+   struct mdp5_sub_block pp;
struct mdp5_sub_block intf;

u32 intfs[MDP5_INTF_NUM_MAX]; /* array of enum mdp5_intf_type */
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH] rnndb: Add registers needed by DSI in mdp5

2015-03-05 Thread Hai Li
Pingpong registers are needed by dsi command mode operation
for tearing check.
Split display registers are needed by dual dsi broadcast mode
for synchronization.

Signed-off-by: Hai Li 
---
 rnndb/mdp/mdp5.xml | 48 
 1 file changed, 48 insertions(+)

diff --git a/rnndb/mdp/mdp5.xml b/rnndb/mdp/mdp5.xml
index 2e61e05..b4c90c7 100644
--- a/rnndb/mdp/mdp5.xml
+++ b/rnndb/mdp/mdp5.xml
@@ -172,6 +172,9 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



+   
+   
+   



@@ -204,6 +207,19 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
 
 

@@ -412,6 +428,38 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ 
rules-ng.xsd">



+
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+
 


-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH] drm/msm: Initial add eDP support in msm drm driver (V4)

2015-01-07 Thread Hai Li
This change adds a new eDP connector in msm drm driver. With this
change, eDP panel can work with msm platform under drm framework.

V1: Initial change

V2: Address Rob's comments
Use generated header file for register definitions
Change to devm_* APIs

V3: Address Thierry's comments and rebase on top of atomic changes
Remove edp_bridge_mode_fixup
Remove backlight control code and rely on pwm-backlight
Remove continuous splash screen support for now
Change to gpiod_* APIs

V4: Fix kbuild test issue

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/Makefile|6 +
 drivers/gpu/drm/msm/edp/edp.c   |  208 +
 drivers/gpu/drm/msm/edp/edp.h   |   84 ++
 drivers/gpu/drm/msm/edp/edp_aux.c   |  268 ++
 drivers/gpu/drm/msm/edp/edp_bridge.c|  124 +++
 drivers/gpu/drm/msm/edp/edp_connector.c |  161 
 drivers/gpu/drm/msm/edp/edp_ctrl.c  | 1390 +++
 drivers/gpu/drm/msm/edp/edp_phy.c   |  106 +++
 drivers/gpu/drm/msm/msm_drv.h   |6 +
 9 files changed, 2353 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/edp/edp.c
 create mode 100644 drivers/gpu/drm/msm/edp/edp.h
 create mode 100644 drivers/gpu/drm/msm/edp/edp_aux.c
 create mode 100644 drivers/gpu/drm/msm/edp/edp_bridge.c
 create mode 100644 drivers/gpu/drm/msm/edp/edp_connector.c
 create mode 100644 drivers/gpu/drm/msm/edp/edp_ctrl.c
 create mode 100644 drivers/gpu/drm/msm/edp/edp_phy.c

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 143d988..e5464a0 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -16,6 +16,12 @@ msm-y := \
hdmi/hdmi_phy_8960.o \
hdmi/hdmi_phy_8x60.o \
hdmi/hdmi_phy_8x74.o \
+   edp/edp.o \
+   edp/edp_aux.o \
+   edp/edp_bridge.o \
+   edp/edp_connector.o \
+   edp/edp_ctrl.o \
+   edp/edp_phy.o \
mdp/mdp_format.o \
mdp/mdp_kms.o \
mdp/mdp4/mdp4_crtc.o \
diff --git a/drivers/gpu/drm/msm/edp/edp.c b/drivers/gpu/drm/msm/edp/edp.c
new file mode 100644
index 000..5ca2d46
--- /dev/null
+++ b/drivers/gpu/drm/msm/edp/edp.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2014-2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 
+#include "edp.h"
+
+static irqreturn_t edp_irq(int irq, void *dev_id)
+{
+   struct msm_edp *edp = dev_id;
+
+   /* Process eDP irq */
+   return msm_edp_ctrl_irq(edp->ctrl);
+}
+
+static void edp_destroy(struct platform_device *pdev)
+{
+   struct msm_edp *edp = platform_get_drvdata(pdev);
+
+   if (!edp)
+   return;
+
+   if (edp->ctrl) {
+   msm_edp_ctrl_destroy(edp->ctrl);
+   edp->ctrl = NULL;
+   }
+
+   platform_set_drvdata(pdev, NULL);
+}
+
+/* construct eDP at bind/probe time, grab all the resources. */
+static struct msm_edp *edp_init(struct platform_device *pdev)
+{
+   struct msm_edp *edp = NULL;
+   int ret;
+
+   if (!pdev) {
+   pr_err("no eDP device\n");
+   ret = -ENXIO;
+   goto fail;
+   }
+
+   edp = devm_kzalloc(>dev, sizeof(*edp), GFP_KERNEL);
+   if (!edp) {
+   ret = -ENOMEM;
+   goto fail;
+   }
+   DBG("eDP probed=%p", edp);
+
+   edp->pdev = pdev;
+   platform_set_drvdata(pdev, edp);
+
+   ret = msm_edp_ctrl_init(edp);
+   if (ret)
+   goto fail;
+
+   return edp;
+
+fail:
+   if (edp)
+   edp_destroy(pdev);
+
+   return ERR_PTR(ret);
+}
+
+static int edp_bind(struct device *dev, struct device *master, void *data)
+{
+   struct drm_device *drm = dev_get_drvdata(master);
+   struct msm_drm_private *priv = drm->dev_private;
+   struct msm_edp *edp;
+
+   DBG("");
+   edp = edp_init(to_platform_device(dev));
+   if (IS_ERR(edp))
+   return PTR_ERR(edp);
+   priv->edp = edp;
+
+   return 0;
+}
+
+static void edp_unbind(struct device *dev, struct device *master, void *data)
+{
+   struct drm_device *drm = dev_get_drvdata(master);
+   struct msm_drm_private *priv = drm->dev_private;
+
+   DBG("");
+   if (priv->edp) {
+   edp_destroy(to_platform_device(dev));
+   priv->edp = NULL;
+   }
+}
+
+static const struct component_ops edp_ops = {
+   .bind   = edp_bind,
+   .unbind = edp_u

[PATCH 2/2] drm/msm: Add the eDP connector in msm drm driver (V2)

2014-12-12 Thread Hai Li
Modified the hard-coded hdmi connector/encoder implementations in msm drm
driver to support both edp and hdmi.

V1: Initial change

V2: Address Thierry's change

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c | 38 +++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 43 -
 drivers/gpu/drm/msm/msm_drv.c   |  2 ++
 drivers/gpu/drm/msm/msm_drv.h   |  6 
 4 files changed, 74 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
index 3ce82be..dd2e5fa 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark 
  *
@@ -162,11 +163,13 @@ static void mdp5_encoder_mode_set(struct drm_encoder 
*encoder,
 {
struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
struct mdp5_kms *mdp5_kms = get_kms(encoder);
+   struct drm_device *dev = encoder->dev;
+   struct drm_connector *connector;
int intf = mdp5_encoder->intf;
uint32_t dtv_hsync_skew, vsync_period, vsync_len, ctrl_pol;
uint32_t display_v_start, display_v_end;
uint32_t hsync_start_x, hsync_end_x;
-   uint32_t format;
+   uint32_t format = 0x2100;
unsigned long flags;

mode = adjusted_mode;
@@ -188,7 +191,28 @@ static void mdp5_encoder_mode_set(struct drm_encoder 
*encoder,
/* probably need to get DATA_EN polarity from panel.. */

dtv_hsync_skew = 0;  /* get this from panel? */
-   format = 0x213f; /* get this from panel? */
+
+   /* Get color format from panel, default is 8bpc */
+   list_for_each_entry(connector, >mode_config.connector_list, head) {
+   if (connector->encoder == encoder) {
+   switch (connector->display_info.bpc) {
+   case 4:
+   format |= 0;
+   break;
+   case 5:
+   format |= 0x15;
+   break;
+   case 6:
+   format |= 0x2A;
+   break;
+   case 8:
+   default:
+   format |= 0x3F;
+   break;
+   }
+   break;
+   }
+   }

hsync_start_x = (mode->htotal - mode->hsync_start);
hsync_end_x = mode->htotal - (mode->hsync_start - mode->hdisplay) - 1;
@@ -198,6 +222,16 @@ static void mdp5_encoder_mode_set(struct drm_encoder 
*encoder,
display_v_start = (mode->vtotal - mode->vsync_start) * mode->htotal + 
dtv_hsync_skew;
display_v_end = vsync_period - ((mode->vsync_start - mode->vdisplay) * 
mode->htotal) + dtv_hsync_skew - 1;

+   /*
+* For edp only:
+* DISPLAY_V_START = (VBP * HCYCLE) + HBP
+* DISPLAY_V_END = (VBP + VACTIVE) * HCYCLE - 1 - HFP
+*/
+   if (mdp5_encoder->intf_id == INTF_eDP) {
+   display_v_start += mode->htotal - mode->hsync_start;
+   display_v_end -= mode->hsync_start - mode->hdisplay;
+   }
+
spin_lock_irqsave(_encoder->intf_lock, flags);

mdp5_write(mdp5_kms, REG_MDP5_INTF_HSYNC_CTL(intf),
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index d6f7e42..5b50f06 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -210,14 +210,6 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
}
}

-   /* Construct encoder for HDMI: */
-   encoder = mdp5_encoder_init(dev, 3, INTF_HDMI);
-   if (IS_ERR(encoder)) {
-   dev_err(dev->dev, "failed to construct encoder\n");
-   ret = PTR_ERR(encoder);
-   goto fail;
-   }
-
/* NOTE: the vsync and error irq's are actually associated with
 * the INTF/encoder.. the easiest way to deal with this (ie. what
 * we do now) is assume a fixed relationship between crtc's and
@@ -226,13 +218,18 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
 * care of error and vblank irq's that the crtc has registered,
 * and also update user-requested vblank_mask.
 */
-   encoder->possible_crtcs = BIT(0);
-   mdp5_crtc_set_intf(priv->crtcs[0], 3, INTF_HDMI);
+   if (priv->hdmi) {
+   /* Construct encoder for HDMI: */
+   encoder = mdp5_encoder_init(dev, 3, INTF_HDMI);
+   if (IS_ERR(encoder)) {
+   dev_err(dev->dev, "failed to construc

[PATCH 1/2] drm/msm: Initial add eDP support in msm drm driver (V3)

2014-12-12 Thread Hai Li
This change adds a new eDP connector in msm drm driver. With this
change, eDP panel can work with msm platform under drm framework.

V1: Initial change

V2: Address Rob's comments
Use generated header file for register definitions
Change to devm_* APIs

V3: Address Thierry's comments and rebase on top of atomic changes
Remove edp_bridge_mode_fixup
Remove backlight control code and rely on pwm-backlight
Remove continuous splash screen support for now
Change to gpiod_* APIs

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/Makefile|6 +
 drivers/gpu/drm/msm/edp/edp.c   |  210 +
 drivers/gpu/drm/msm/edp/edp.h   |   84 ++
 drivers/gpu/drm/msm/edp/edp_aux.c   |  268 ++
 drivers/gpu/drm/msm/edp/edp_bridge.c|  124 +++
 drivers/gpu/drm/msm/edp/edp_connector.c |  161 
 drivers/gpu/drm/msm/edp/edp_ctrl.c  | 1390 +++
 drivers/gpu/drm/msm/edp/edp_phy.c   |  106 +++
 drivers/gpu/drm/msm/msm_drv.h   |6 +
 9 files changed, 2355 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/edp/edp.c
 create mode 100644 drivers/gpu/drm/msm/edp/edp.h
 create mode 100644 drivers/gpu/drm/msm/edp/edp_aux.c
 create mode 100644 drivers/gpu/drm/msm/edp/edp_bridge.c
 create mode 100644 drivers/gpu/drm/msm/edp/edp_connector.c
 create mode 100644 drivers/gpu/drm/msm/edp/edp_ctrl.c
 create mode 100644 drivers/gpu/drm/msm/edp/edp_phy.c

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 143d988..e5464a0 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -16,6 +16,12 @@ msm-y := \
hdmi/hdmi_phy_8960.o \
hdmi/hdmi_phy_8x60.o \
hdmi/hdmi_phy_8x74.o \
+   edp/edp.o \
+   edp/edp_aux.o \
+   edp/edp_bridge.o \
+   edp/edp_connector.o \
+   edp/edp_ctrl.o \
+   edp/edp_phy.o \
mdp/mdp_format.o \
mdp/mdp_kms.o \
mdp/mdp4/mdp4_crtc.o \
diff --git a/drivers/gpu/drm/msm/edp/edp.c b/drivers/gpu/drm/msm/edp/edp.c
new file mode 100644
index 000..16b8984
--- /dev/null
+++ b/drivers/gpu/drm/msm/edp/edp.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2014, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 
+#include "edp.h"
+
+static irqreturn_t edp_irq(int irq, void *dev_id)
+{
+   struct msm_edp *edp = dev_id;
+
+   /* Process eDP irq */
+   return msm_edp_ctrl_irq(edp->ctrl);
+}
+
+static void edp_destroy(struct platform_device *pdev)
+{
+   struct msm_edp *edp = platform_get_drvdata(pdev);
+
+   if (!edp)
+   return;
+
+   if (edp->ctrl) {
+   msm_edp_ctrl_destroy(edp->ctrl);
+   edp->ctrl = NULL;
+   }
+
+   platform_set_drvdata(pdev, NULL);
+}
+
+/* construct eDP at bind/probe time, grab all the resources. */
+static struct msm_edp *edp_init(struct platform_device *pdev)
+{
+   struct msm_edp *edp = NULL;
+   int ret;
+
+   if (!pdev) {
+   pr_err("no eDP device\n");
+   ret = -ENXIO;
+   goto fail;
+   }
+
+   edp = devm_kzalloc(>dev, sizeof(*edp), GFP_KERNEL);
+   if (!edp) {
+   ret = -ENOMEM;
+   goto fail;
+   }
+   DBG("eDP probed=%p", edp);
+
+   edp->pdev = pdev;
+   platform_set_drvdata(pdev, edp);
+
+   ret = msm_edp_ctrl_init(edp);
+   if (ret)
+   goto fail;
+
+   return edp;
+
+fail:
+   if (edp)
+   edp_destroy(pdev);
+
+   return ERR_PTR(ret);
+}
+
+static int edp_bind(struct device *dev, struct device *master, void *data)
+{
+   struct drm_device *drm = dev_get_drvdata(master);
+   struct msm_drm_private *priv = drm->dev_private;
+   struct msm_edp *edp;
+
+   DBG("");
+   edp = edp_init(to_platform_device(dev));
+   if (IS_ERR(edp))
+   return PTR_ERR(edp);
+   priv->edp = edp;
+
+   return 0;
+}
+
+static void edp_unbind(struct device *dev, struct device *master, void *data)
+{
+   struct drm_device *drm = dev_get_drvdata(master);
+   struct msm_drm_private *priv = drm->dev_private;
+
+   DBG("");
+   if (priv->edp) {
+   edp_destroy(to_platform_device(dev));
+   priv->edp = NULL;
+   }
+}
+
+static const struct component_ops edp_ops = {
+   .bind   = edp_bind,
+   .unbind = edp_unbind,
+};
+
+static int edp_dev_probe(

[PATCH 2/2] drm/msm: Add the eDP connector in msm drm driver

2014-12-05 Thread Hai Li
Modified the hard-coded hdmi connector/encoder implementations in msm drm
driver to support both edp and hdmi.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c | 38 +--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 47 -
 drivers/gpu/drm/msm/msm_drv.c   |  2 ++
 drivers/gpu/drm/msm/msm_drv.h   |  7 +
 4 files changed, 77 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
index 25c2fcb..f4159c2 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark 
  *
@@ -151,11 +152,13 @@ static void mdp5_encoder_mode_set(struct drm_encoder 
*encoder,
 {
struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
struct mdp5_kms *mdp5_kms = get_kms(encoder);
+   struct drm_device *dev = encoder->dev;
+   struct drm_connector *connector;
int intf = mdp5_encoder->intf;
uint32_t dtv_hsync_skew, vsync_period, vsync_len, ctrl_pol;
uint32_t display_v_start, display_v_end;
uint32_t hsync_start_x, hsync_end_x;
-   uint32_t format;
+   uint32_t format = 0x2100;
unsigned long flags;

mode = adjusted_mode;
@@ -177,7 +180,28 @@ static void mdp5_encoder_mode_set(struct drm_encoder 
*encoder,
/* probably need to get DATA_EN polarity from panel.. */

dtv_hsync_skew = 0;  /* get this from panel? */
-   format = 0x213f; /* get this from panel? */
+
+   /* Get color format from panel, default is 8bpc */
+   list_for_each_entry(connector, >mode_config.connector_list, head) {
+   if (connector->encoder == encoder) {
+   switch (connector->display_info.bpc) {
+   case 4:
+   format |= 0;
+   break;
+   case 5:
+   format |= 0x15;
+   break;
+   case 6:
+   format |= 0x2A;
+   break;
+   case 8:
+   default:
+   format |= 0x3F;
+   break;
+   }
+   break;
+   }
+   }

hsync_start_x = (mode->htotal - mode->hsync_start);
hsync_end_x = mode->htotal - (mode->hsync_start - mode->hdisplay) - 1;
@@ -187,6 +211,16 @@ static void mdp5_encoder_mode_set(struct drm_encoder 
*encoder,
display_v_start = (mode->vtotal - mode->vsync_start) * mode->htotal + 
dtv_hsync_skew;
display_v_end = vsync_period - ((mode->vsync_start - mode->vdisplay) * 
mode->htotal) + dtv_hsync_skew - 1;

+   /*
+* For edp only:
+* DISPLAY_V_START = (VBP * HCYCLE) + HBP
+* DISPLAY_V_END = (VBP + VACTIVE) * HCYCLE - 1 - HFP
+*/
+   if (mdp5_encoder->intf_id == INTF_eDP) {
+   display_v_start += (mode->htotal - mode->hsync_start);
+   display_v_end -= (mode->hsync_start - mode->hdisplay);
+   }
+
spin_lock_irqsave(_encoder->intf_lock, flags);

mdp5_write(mdp5_kms, REG_MDP5_INTF_HSYNC_CTL(intf),
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index ab5f8d2..9d891e2 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -157,7 +157,7 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
};
struct drm_device *dev = mdp5_kms->dev;
struct msm_drm_private *priv = dev->dev_private;
-   struct drm_encoder *encoder;
+   struct drm_encoder *edp_encoder = NULL, *hdmi_encoder = NULL;
const struct mdp5_cfg_hw *hw_cfg;
int i, ret;

@@ -208,14 +208,6 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
}
}

-   /* Construct encoder for HDMI: */
-   encoder = mdp5_encoder_init(dev, 3, INTF_HDMI);
-   if (IS_ERR(encoder)) {
-   dev_err(dev->dev, "failed to construct encoder\n");
-   ret = PTR_ERR(encoder);
-   goto fail;
-   }
-
/* NOTE: the vsync and error irq's are actually associated with
 * the INTF/encoder.. the easiest way to deal with this (ie. what
 * we do now) is assume a fixed relationship between crtc's and
@@ -224,20 +216,45 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
 * care of error and vblank irq's that the crtc has registered,
 * and also update user-requested vblank_mask.
 */
-   encoder->possible_crtcs = 

[PATCH 1/2] drm/msm: Initial add eDP support in msm drm driver (V2)

2014-12-05 Thread Hai Li
This change adds a new eDP connector in msm drm driver. With this
change, eDP panel can work with msm platform under drm framework.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/Makefile|6 +
 drivers/gpu/drm/msm/edp/edp.c   |  211 
 drivers/gpu/drm/msm/edp/edp.h   |   86 ++
 drivers/gpu/drm/msm/edp/edp_aux.c   |  297 +
 drivers/gpu/drm/msm/edp/edp_bridge.c|  206 
 drivers/gpu/drm/msm/edp/edp_connector.c |  159 +++
 drivers/gpu/drm/msm/edp/edp_ctrl.c  | 1810 +++
 drivers/gpu/drm/msm/edp/edp_phy.c   |  110 ++
 drivers/gpu/drm/msm/msm_drv.h   |6 +
 9 files changed, 2891 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/edp/edp.c
 create mode 100644 drivers/gpu/drm/msm/edp/edp.h
 create mode 100644 drivers/gpu/drm/msm/edp/edp_aux.c
 create mode 100644 drivers/gpu/drm/msm/edp/edp_bridge.c
 create mode 100644 drivers/gpu/drm/msm/edp/edp_connector.c
 create mode 100644 drivers/gpu/drm/msm/edp/edp_ctrl.c
 create mode 100644 drivers/gpu/drm/msm/edp/edp_phy.c

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 143d988..e5464a0 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -16,6 +16,12 @@ msm-y := \
hdmi/hdmi_phy_8960.o \
hdmi/hdmi_phy_8x60.o \
hdmi/hdmi_phy_8x74.o \
+   edp/edp.o \
+   edp/edp_aux.o \
+   edp/edp_bridge.o \
+   edp/edp_connector.o \
+   edp/edp_ctrl.o \
+   edp/edp_phy.o \
mdp/mdp_format.o \
mdp/mdp_kms.o \
mdp/mdp4/mdp4_crtc.o \
diff --git a/drivers/gpu/drm/msm/edp/edp.c b/drivers/gpu/drm/msm/edp/edp.c
new file mode 100644
index 000..32e21e1
--- /dev/null
+++ b/drivers/gpu/drm/msm/edp/edp.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2014, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 
+#include "edp.h"
+
+static irqreturn_t edp_irq(int irq, void *dev_id)
+{
+   struct msm_edp *edp = dev_id;
+
+   /* Process eDP irq */
+   return msm_edp_ctrl_irq(edp->ctrl);
+}
+
+static void edp_destroy(struct platform_device *pdev)
+{
+   struct msm_edp *edp = platform_get_drvdata(pdev);
+
+   if (!edp)
+   return;
+
+   if (edp->ctrl) {
+   msm_edp_ctrl_destroy(edp->ctrl);
+   edp->ctrl = NULL;
+   }
+
+   platform_set_drvdata(pdev, NULL);
+
+   devm_kfree(>dev, edp);
+}
+
+/* construct hdmi at bind/probe time, grab all the resources. */
+static struct msm_edp *edp_init(struct platform_device *pdev)
+{
+   struct msm_edp *edp = NULL;
+   int ret;
+
+   if (!pdev) {
+   pr_err("no edp device\n");
+   ret = -ENXIO;
+   goto fail;
+   }
+
+   edp = devm_kzalloc(>dev, sizeof(*edp), GFP_KERNEL);
+   if (!edp) {
+   ret = -ENOMEM;
+   goto fail;
+   }
+   DBG("edp probed=%p", edp);
+
+   edp->pdev = pdev;
+   platform_set_drvdata(pdev, edp);
+
+   ret = msm_edp_ctrl_init(edp);
+   if (ret)
+   goto fail;
+
+   return edp;
+
+fail:
+   if (edp)
+   edp_destroy(pdev);
+
+   return ERR_PTR(ret);
+}
+
+static int edp_bind(struct device *dev, struct device *master, void *data)
+{
+   struct drm_device *drm = dev_get_drvdata(master);
+   struct msm_drm_private *priv = drm->dev_private;
+   struct msm_edp *edp;
+
+   DBG("");
+   edp = edp_init(to_platform_device(dev));
+   if (IS_ERR(edp))
+   return PTR_ERR(edp);
+   priv->edp = edp;
+
+   return 0;
+}
+
+static void edp_unbind(struct device *dev, struct device *master,
+   void *data)
+{
+   struct drm_device *drm = dev_get_drvdata(master);
+   struct msm_drm_private *priv = drm->dev_private;
+
+   DBG("");
+   if (priv->edp) {
+   edp_destroy(to_platform_device(dev));
+   priv->edp = NULL;
+   }
+}
+
+static const struct component_ops edp_ops = {
+   .bind   = edp_bind,
+   .unbind = edp_unbind,
+};
+
+static int edp_dev_probe(struct platform_device *pdev)
+{
+   DBG("");
+   return component_add(>dev, _ops);
+}
+
+static int edp_dev_remove(struct platform_device *pdev)
+{
+   DBG("");
+   component_del(>dev, _ops);
+   return 0;
+}
+
+static const struct of_device_id dt_match[] = {
+   

[PATCH 2/2] drm/msm: Add the eDP connector in msm drm driver

2014-11-19 Thread Hai Li
Modified the hard-coded hdmi connector/encoder implementations in msm drm
driver to support both edp and hdmi.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c | 38 +--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 47 -
 drivers/gpu/drm/msm/msm_drv.c   |  2 ++
 drivers/gpu/drm/msm/msm_drv.h   |  7 +
 4 files changed, 77 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
index 25c2fcb..f4159c2 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark 
  *
@@ -151,11 +152,13 @@ static void mdp5_encoder_mode_set(struct drm_encoder 
*encoder,
 {
struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
struct mdp5_kms *mdp5_kms = get_kms(encoder);
+   struct drm_device *dev = encoder->dev;
+   struct drm_connector *connector;
int intf = mdp5_encoder->intf;
uint32_t dtv_hsync_skew, vsync_period, vsync_len, ctrl_pol;
uint32_t display_v_start, display_v_end;
uint32_t hsync_start_x, hsync_end_x;
-   uint32_t format;
+   uint32_t format = 0x2100;
unsigned long flags;

mode = adjusted_mode;
@@ -177,7 +180,28 @@ static void mdp5_encoder_mode_set(struct drm_encoder 
*encoder,
/* probably need to get DATA_EN polarity from panel.. */

dtv_hsync_skew = 0;  /* get this from panel? */
-   format = 0x213f; /* get this from panel? */
+
+   /* Get color format from panel, default is 8bpc */
+   list_for_each_entry(connector, >mode_config.connector_list, head) {
+   if (connector->encoder == encoder) {
+   switch (connector->display_info.bpc) {
+   case 4:
+   format |= 0;
+   break;
+   case 5:
+   format |= 0x15;
+   break;
+   case 6:
+   format |= 0x2A;
+   break;
+   case 8:
+   default:
+   format |= 0x3F;
+   break;
+   }
+   break;
+   }
+   }

hsync_start_x = (mode->htotal - mode->hsync_start);
hsync_end_x = mode->htotal - (mode->hsync_start - mode->hdisplay) - 1;
@@ -187,6 +211,16 @@ static void mdp5_encoder_mode_set(struct drm_encoder 
*encoder,
display_v_start = (mode->vtotal - mode->vsync_start) * mode->htotal + 
dtv_hsync_skew;
display_v_end = vsync_period - ((mode->vsync_start - mode->vdisplay) * 
mode->htotal) + dtv_hsync_skew - 1;

+   /*
+* For edp only:
+* DISPLAY_V_START = (VBP * HCYCLE) + HBP
+* DISPLAY_V_END = (VBP + VACTIVE) * HCYCLE - 1 - HFP
+*/
+   if (mdp5_encoder->intf_id == INTF_eDP) {
+   display_v_start += (mode->htotal - mode->hsync_start);
+   display_v_end -= (mode->hsync_start - mode->hdisplay);
+   }
+
spin_lock_irqsave(_encoder->intf_lock, flags);

mdp5_write(mdp5_kms, REG_MDP5_INTF_HSYNC_CTL(intf),
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index ab5f8d2..9d891e2 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -157,7 +157,7 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
};
struct drm_device *dev = mdp5_kms->dev;
struct msm_drm_private *priv = dev->dev_private;
-   struct drm_encoder *encoder;
+   struct drm_encoder *edp_encoder = NULL, *hdmi_encoder = NULL;
const struct mdp5_cfg_hw *hw_cfg;
int i, ret;

@@ -208,14 +208,6 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
}
}

-   /* Construct encoder for HDMI: */
-   encoder = mdp5_encoder_init(dev, 3, INTF_HDMI);
-   if (IS_ERR(encoder)) {
-   dev_err(dev->dev, "failed to construct encoder\n");
-   ret = PTR_ERR(encoder);
-   goto fail;
-   }
-
/* NOTE: the vsync and error irq's are actually associated with
 * the INTF/encoder.. the easiest way to deal with this (ie. what
 * we do now) is assume a fixed relationship between crtc's and
@@ -224,20 +216,45 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
 * care of error and vblank irq's that the crtc has registered,
 * and also update user-requested vblank_mask.
 */
-   encoder->possible_crtcs = 

[PATCH 1/2] drm/msm: Initial add eDP support in msm drm driver

2014-11-19 Thread Hai Li
This change adds a new eDP connector in msm drm driver. With this
change, eDP panel can work with msm platform under drm framework.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/Makefile|6 +
 drivers/gpu/drm/msm/edp/edp.c   |  211 
 drivers/gpu/drm/msm/edp/edp.h   |   83 ++
 drivers/gpu/drm/msm/edp/edp_aux.c   |  298 +
 drivers/gpu/drm/msm/edp/edp_bridge.c|  206 
 drivers/gpu/drm/msm/edp/edp_connector.c |  155 +++
 drivers/gpu/drm/msm/edp/edp_ctrl.c  | 1799 +++
 drivers/gpu/drm/msm/edp/edp_phy.c   |  123 +++
 drivers/gpu/drm/msm/edp/edp_reg.h   |   92 ++
 drivers/gpu/drm/msm/msm_drv.h   |6 +
 10 files changed, 2979 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/edp/edp.c
 create mode 100644 drivers/gpu/drm/msm/edp/edp.h
 create mode 100644 drivers/gpu/drm/msm/edp/edp_aux.c
 create mode 100644 drivers/gpu/drm/msm/edp/edp_bridge.c
 create mode 100644 drivers/gpu/drm/msm/edp/edp_connector.c
 create mode 100644 drivers/gpu/drm/msm/edp/edp_ctrl.c
 create mode 100644 drivers/gpu/drm/msm/edp/edp_phy.c
 create mode 100644 drivers/gpu/drm/msm/edp/edp_reg.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 143d988..e5464a0 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -16,6 +16,12 @@ msm-y := \
hdmi/hdmi_phy_8960.o \
hdmi/hdmi_phy_8x60.o \
hdmi/hdmi_phy_8x74.o \
+   edp/edp.o \
+   edp/edp_aux.o \
+   edp/edp_bridge.o \
+   edp/edp_connector.o \
+   edp/edp_ctrl.o \
+   edp/edp_phy.o \
mdp/mdp_format.o \
mdp/mdp_kms.o \
mdp/mdp4/mdp4_crtc.o \
diff --git a/drivers/gpu/drm/msm/edp/edp.c b/drivers/gpu/drm/msm/edp/edp.c
new file mode 100644
index 000..779706e
--- /dev/null
+++ b/drivers/gpu/drm/msm/edp/edp.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2014, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 
+#include "edp.h"
+
+static irqreturn_t edp_irq(int irq, void *dev_id)
+{
+   struct msm_edp *edp = dev_id;
+
+   /* Process eDP irq */
+   return msm_edp_ctrl_irq(edp->ctrl_priv);
+}
+
+static void edp_destroy(struct platform_device *pdev)
+{
+   struct msm_edp *edp = platform_get_drvdata(pdev);
+
+   if (!edp)
+   return;
+
+   if (edp->ctrl_priv) {
+   msm_edp_ctrl_destroy(edp->ctrl_priv);
+   edp->ctrl_priv = NULL;
+   }
+
+   platform_set_drvdata(pdev, NULL);
+
+   kfree(edp);
+}
+
+/* construct hdmi at bind/probe time, grab all the resources. */
+static struct msm_edp *edp_init(struct platform_device *pdev)
+{
+   struct msm_edp *edp = NULL;
+   int ret;
+
+   if (!pdev) {
+   pr_err("no edp device\n");
+   ret = -ENXIO;
+   goto fail;
+   }
+
+   edp = kzalloc(sizeof(*edp), GFP_KERNEL);
+   if (!edp) {
+   ret = -ENOMEM;
+   goto fail;
+   }
+   DBG("edp probed=%p", edp);
+
+   edp->pdev = pdev;
+   platform_set_drvdata(pdev, edp);
+
+   ret = msm_edp_ctrl_init(edp);
+   if (ret)
+   goto fail;
+
+   return edp;
+
+fail:
+   if (edp)
+   edp_destroy(pdev);
+
+   return ERR_PTR(ret);
+}
+
+static int edp_bind(struct device *dev, struct device *master, void *data)
+{
+   struct drm_device *drm = dev_get_drvdata(master);
+   struct msm_drm_private *priv = drm->dev_private;
+   struct msm_edp *edp;
+
+   DBG("");
+   edp = edp_init(to_platform_device(dev));
+   if (IS_ERR(edp))
+   return PTR_ERR(edp);
+   priv->edp = edp;
+
+   return 0;
+}
+
+static void edp_unbind(struct device *dev, struct device *master,
+   void *data)
+{
+   struct drm_device *drm = dev_get_drvdata(master);
+   struct msm_drm_private *priv = drm->dev_private;
+
+   DBG("");
+   if (priv->edp) {
+   edp_destroy(to_platform_device(dev));
+   priv->edp = NULL;
+   }
+}
+
+static const struct component_ops edp_ops = {
+   .bind   = edp_bind,
+   .unbind = edp_unbind,
+};
+
+static int edp_dev_probe(struct platform_device *pdev)
+{
+   DBG("");
+   return component_add(>dev, _ops);
+}
+
+static int edp_dev_remove(struct platform_device *pdev)
+{
+   DBG("");
+   component_del(>

[PATCH 2/2] drm/msm: Decouple hdmi driver from mdp driver

2014-11-14 Thread Hai Li
This change is to remove the hdmi structure from mdp kms data structure.

To do this, the initialization flow is re-arranged.
 - hdmi_init is moved from modeset_init to hdmi_bind.
 - hdmi_destroy is called by hdmi_unbind and the use of kref is abandoned.
 - A new interface hdmi_set_encoder is introduced to establish the links
   between hdmi connector, encoder and bridge.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/hdmi/hdmi.c   | 61 +++
 drivers/gpu/drm/msm/hdmi/hdmi.h   | 14 ---
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c|  3 +-
 drivers/gpu/drm/msm/hdmi/hdmi_connector.c |  6 +--
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c   | 14 ---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c   | 38 ++-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h   |  2 -
 drivers/gpu/drm/msm/msm_drv.c |  9 -
 drivers/gpu/drm/msm/msm_drv.h |  6 ++-
 9 files changed, 88 insertions(+), 65 deletions(-)

diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index aaf5e2b..2d2551f 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark 
  *
@@ -17,6 +18,29 @@

 #include "hdmi.h"

+int hdmi_set_encoder(struct platform_device *pdev,
+   struct drm_encoder *encoder)
+{
+   struct hdmi *hdmi = platform_get_drvdata(pdev);
+
+   if (!encoder && !hdmi->encoder) {
+   pr_err("%s:wrong encoder status,encoder=%p,hdmi->encoder=%p\n",
+   __func__, encoder, hdmi->encoder);
+   return -EINVAL;
+   }
+
+   /* Each connector has only one available encoder for now. */
+   hdmi->connector->encoder_ids[0] = 0;
+   hdmi->connector->encoder = NULL;
+   if (encoder) {
+   drm_mode_connector_attach_encoder(hdmi->connector, encoder);
+   encoder->bridge = hdmi->bridge;
+   }
+   hdmi->encoder = encoder;
+
+   return 0;
+}
+
 void hdmi_set_mode(struct hdmi *hdmi, bool power_on)
 {
uint32_t ctrl = 0;
@@ -54,10 +78,15 @@ static irqreturn_t hdmi_irq(int irq, void *dev_id)
return IRQ_HANDLED;
 }

-void hdmi_destroy(struct kref *kref)
+static void hdmi_destroy(struct platform_device *pdev)
 {
-   struct hdmi *hdmi = container_of(kref, struct hdmi, refcount);
-   struct hdmi_phy *phy = hdmi->phy;
+   struct hdmi *hdmi = platform_get_drvdata(pdev);
+   struct hdmi_phy *phy;
+
+   if (!hdmi)
+   return;
+
+   phy = hdmi->phy;

if (hdmi->config->shared_irq)
msm_shared_irq_unregister(MSM_SUBSYS_HDMI);
@@ -68,15 +97,14 @@ void hdmi_destroy(struct kref *kref)
if (hdmi->i2c)
hdmi_i2c_destroy(hdmi->i2c);

-   platform_set_drvdata(hdmi->pdev, NULL);
+   platform_set_drvdata(pdev, NULL);
 }

 /* initialize connector */
-struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
+static int hdmi_init(struct platform_device *pdev, struct drm_device *dev)
 {
struct hdmi *hdmi = NULL;
struct msm_drm_private *priv = dev->dev_private;
-   struct platform_device *pdev = priv->hdmi_pdev;
struct hdmi_platform_config *config;
int i, ret;

@@ -94,12 +122,11 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct 
drm_encoder *encoder)
goto fail;
}

-   kref_init(>refcount);
+   platform_set_drvdata(pdev, hdmi);

hdmi->dev = dev;
hdmi->pdev = pdev;
hdmi->config = config;
-   hdmi->encoder = encoder;

hdmi_audio_infoframe_init(>audio.infoframe);

@@ -233,14 +260,10 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct 
drm_encoder *encoder)
}
}

-   encoder->bridge = hdmi->bridge;
-
priv->bridges[priv->num_bridges++]   = hdmi->bridge;
priv->connectors[priv->num_connectors++] = hdmi->connector;

-   platform_set_drvdata(pdev, hdmi);
-
-   return hdmi;
+   return 0;

 fail:
if (hdmi) {
@@ -249,10 +272,10 @@ fail:
hdmi->bridge->funcs->destroy(hdmi->bridge);
if (hdmi->connector)
hdmi->connector->funcs->destroy(hdmi->connector);
-   hdmi_destroy(>refcount);
+   hdmi_destroy(pdev);
}

-   return ERR_PTR(ret);
+   return ret;
 }

 /*
@@ -289,6 +312,7 @@ static int get_gpio(struct device *dev, struct device_node 
*of_node, const char
 static int hdmi_bind(struct device *dev, struct device *master, void *data)
 {
static struct hdmi_platform_config config = {};
+   int ret;
 #ifdef CONFIG_OF
struct devic

[PATCH 1/2] drm/msm: Register irq handler for each sub-system in mdss

2014-11-14 Thread Hai Li
All the sub-systems in mdss share the same irq. This change provides
the sub-systems with the interfaces to register/unregister their own
irq handlers.

With this change, struct mdp5_kms does not have to keep the hdmi or
edp context.

Signed-off-by: Hai Li 
---
 drivers/gpu/drm/msm/hdmi/hdmi.c |  12 +++-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c | 107 ++--
 drivers/gpu/drm/msm/msm_drv.h   |  19 +-
 3 files changed, 130 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 9d00dcb..aaf5e2b 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -39,7 +39,7 @@ void hdmi_set_mode(struct hdmi *hdmi, bool power_on)
power_on ? "Enable" : "Disable", ctrl);
 }

-irqreturn_t hdmi_irq(int irq, void *dev_id)
+static irqreturn_t hdmi_irq(int irq, void *dev_id)
 {
struct hdmi *hdmi = dev_id;

@@ -59,6 +59,9 @@ void hdmi_destroy(struct kref *kref)
struct hdmi *hdmi = container_of(kref, struct hdmi, refcount);
struct hdmi_phy *phy = hdmi->phy;

+   if (hdmi->config->shared_irq)
+   msm_shared_irq_unregister(MSM_SUBSYS_HDMI);
+
if (phy)
phy->funcs->destroy(phy);

@@ -221,6 +224,13 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct 
drm_encoder *encoder)
hdmi->irq, ret);
goto fail;
}
+   } else {
+   ret = msm_shared_irq_register(MSM_SUBSYS_HDMI, hdmi_irq, hdmi);
+   if (ret < 0) {
+   dev_err(dev->dev, "failed to register shared IRQ: %d\n",
+   ret);
+   goto fail;
+   }
}

encoder->bridge = hdmi->bridge;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
index f2b985b..2973c1c 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark 
  *
@@ -19,6 +20,75 @@
 #include "msm_drv.h"
 #include "mdp5_kms.h"

+struct msm_subsys_shared_irq {
+   u32 mask;
+   u32 count;
+
+   /* Filled by sub system */
+   irqreturn_t (*handler)(int irq, void *dev_id);
+   void *data;
+};
+
+static struct msm_subsys_shared_irq msm_shared_irqs[MSM_SUBSYS_COUNT] = {
+   [MSM_SUBSYS_MDP] = {.mask = MDP5_HW_INTR_STATUS_INTR_MDP,
+   .count = 0},
+   [MSM_SUBSYS_DSI_0] = {.mask = MDP5_HW_INTR_STATUS_INTR_DSI0,
+   .count = 0},
+   [MSM_SUBSYS_DSI_1] = {.mask = MDP5_HW_INTR_STATUS_INTR_DSI1,
+   .count = 0},
+   [MSM_SUBSYS_HDMI] = {.mask = MDP5_HW_INTR_STATUS_INTR_HDMI,
+   .count = 0},
+   [MSM_SUBSYS_EDP] = {.mask = MDP5_HW_INTR_STATUS_INTR_EDP,
+   .count = 0},
+};
+
+static irqreturn_t mdp5_irq_mdp(int irq, void *dev_id);
+
+int msm_shared_irq_register(enum msm_sub_system sys_id,
+   irqreturn_t (*handler)(int irq, void *dev_id), void *data)
+{
+   if (sys_id >= MSM_SUBSYS_COUNT) {
+   DRM_ERROR("Invalid sys_id %d", sys_id);
+   return -EINVAL;
+   }
+
+   if (msm_shared_irqs[sys_id].handler != NULL) {
+   DRM_ERROR("sys %d irq already registered", sys_id);
+   return -EBUSY;
+   }
+
+   msm_shared_irqs[sys_id].data = data;
+   msm_shared_irqs[sys_id].handler = handler;
+
+   return 0;
+}
+
+/*
+ * This function should be called after the interrupt
+ * on the sub-system is disabled.
+ */
+int msm_shared_irq_unregister(enum msm_sub_system sys_id)
+{
+   if (sys_id >= MSM_SUBSYS_COUNT) {
+   DRM_ERROR("Invalid sys_id %d", sys_id);
+   return -EINVAL;
+   }
+
+   msm_shared_irqs[sys_id].handler = NULL;
+   msm_shared_irqs[sys_id].data = NULL;
+
+   /*
+* Make sure irq_handler and data is invalid.
+* Then we only need to wait until the last pending interrupt is done.
+*/
+   wmb();
+
+   while (msm_shared_irqs[sys_id].count & 0x1)
+   usleep_range(100, 1000);
+
+   return 0;
+}
+
 void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask)
 {
mdp5_write(to_mdp5_kms(mdp_kms), REG_MDP5_INTR_EN, irqmask);
@@ -47,6 +117,9 @@ int mdp5_irq_postinstall(struct msm_kms *kms)
MDP5_IRQ_INTF2_UNDER_RUN |
MDP5_IRQ_INTF3_UNDER_RUN;

+   /* Register mdp irq to mdss */
+   msm_shared_irq_register(MSM_SUBSYS_MDP, mdp5_irq_mdp, mdp_kms);
+
mdp_irq_register(mdp_kms

[PATCH] drm/msm: Implement msm drm fb_mmap callback function

2014-06-20 Thread Hai Li
This change implements msm drm specific fb_mmap function for fb device
to properly map the fb address to userspace.

Signed-off-by: Hai Li 
Signed-off-by: Stephane Viau 
---
 drivers/gpu/drm/msm/msm_fbdev.c | 38 --
 1 file changed, 36 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c
index a752ab8..2694e90 100644
--- a/drivers/gpu/drm/msm/msm_fbdev.c
+++ b/drivers/gpu/drm/msm/msm_fbdev.c
@@ -19,6 +19,11 @@

 #include "drm_crtc.h"
 #include "drm_fb_helper.h"
+#include "msm_gem.h"
+
+extern int msm_gem_mmap_obj(struct drm_gem_object *obj,
+   struct vm_area_struct *vma);
+static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma);

 /*
  * fbdev funcs, to implement legacy fbdev interface on top of drm driver
@@ -43,6 +48,7 @@ static struct fb_ops msm_fb_ops = {
.fb_fillrect = sys_fillrect,
.fb_copyarea = sys_copyarea,
.fb_imageblit = sys_imageblit,
+   .fb_mmap = msm_fbdev_mmap,

.fb_check_var = drm_fb_helper_check_var,
.fb_set_par = drm_fb_helper_set_par,
@@ -51,6 +57,31 @@ static struct fb_ops msm_fb_ops = {
.fb_setcmap = drm_fb_helper_setcmap,
 };

+static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+   struct drm_fb_helper *helper = (struct drm_fb_helper *)info->par;
+   struct msm_fbdev *fbdev = to_msm_fbdev(helper);
+   struct drm_gem_object *drm_obj = fbdev->bo;
+   struct drm_device *dev = helper->dev;
+   int ret;
+
+   if (drm_device_is_unplugged(dev))
+   return -ENODEV;
+
+   mutex_lock(>struct_mutex);
+
+   ret = drm_gem_mmap_obj(drm_obj, drm_obj->size, vma);
+
+   mutex_unlock(>struct_mutex);
+
+   if (ret) {
+   pr_err("%s:drm_gem_mmap_obj fail\n", __func__);
+   return ret;
+   }
+
+   return msm_gem_mmap_obj(drm_obj, vma);
+}
+
 static int msm_fbdev_create(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes)
 {
@@ -104,8 +135,11 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,

mutex_lock(>struct_mutex);

-   /* TODO implement our own fb_mmap so we don't need this: */
-   msm_gem_get_iova_locked(fbdev->bo, 0, );
+   ret = msm_gem_get_iova_locked(fbdev->bo, 0, );
+   if (ret) {
+   dev_err(dev->dev, "failed to get buffer obj iova: %d\n", ret);
+   goto fail;
+   }

fbi = framebuffer_alloc(0, dev->dev);
if (!fbi) {
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH] drm/msm: Implement msm drm fb_mmap callback function

2014-06-18 Thread Hai Li
This change implements msm drm specific fb_mmap function for fb device
to properly map the fb address to userspace.

Signed-off-by: Hai Li 
Signed-off-by: Stephane Viau 
---
 drivers/gpu/drm/msm/msm_fbdev.c | 37 -
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c
index 4f4e7b4..2522f51 100644
--- a/drivers/gpu/drm/msm/msm_fbdev.c
+++ b/drivers/gpu/drm/msm/msm_fbdev.c
@@ -19,6 +19,11 @@

 #include "drm_crtc.h"
 #include "drm_fb_helper.h"
+#include "msm_gem.h"
+
+extern int msm_gem_mmap_obj(struct drm_gem_object *obj,
+   struct vm_area_struct *vma);
+static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma);

 /*
  * fbdev funcs, to implement legacy fbdev interface on top of drm driver
@@ -43,6 +48,7 @@ static struct fb_ops msm_fb_ops = {
.fb_fillrect = sys_fillrect,
.fb_copyarea = sys_copyarea,
.fb_imageblit = sys_imageblit,
+   .fb_mmap = msm_fbdev_mmap,

.fb_check_var = drm_fb_helper_check_var,
.fb_set_par = drm_fb_helper_set_par,
@@ -51,6 +57,31 @@ static struct fb_ops msm_fb_ops = {
.fb_setcmap = drm_fb_helper_setcmap,
 };

+static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+   struct drm_fb_helper *helper = (struct drm_fb_helper *)info->par;
+   struct msm_fbdev *fbdev = to_msm_fbdev(helper);
+   struct drm_gem_object *drm_obj = fbdev->bo;
+   struct drm_device *dev = helper->dev;
+   int ret = 0;
+
+   if (drm_device_is_unplugged(dev))
+   return -ENODEV;
+
+   mutex_lock(>struct_mutex);
+
+   ret = drm_gem_mmap_obj(drm_obj, drm_obj->size, vma);
+
+   mutex_unlock(>struct_mutex);
+
+   if (ret) {
+   pr_err("%s:drm_gem_mmap_obj fail\n", __func__);
+   return ret;
+   }
+
+   return msm_gem_mmap_obj(drm_obj, vma);
+}
+
 static int msm_fbdev_create(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes)
 {
@@ -108,7 +139,11 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
mutex_lock(>struct_mutex);

/* TODO implement our own fb_mmap so we don't need this: */
-   msm_gem_get_iova_locked(fbdev->bo, 0, );
+   ret = msm_gem_get_iova_locked(fbdev->bo, 0, );
+   if (ret) {
+   dev_err(dev->dev, "failed to get buffer obj iova: %d\n", ret);
+   goto fail;
+   }

fbi = framebuffer_alloc(0, dev->dev);
if (!fbi) {
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation