• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 and
6  * only version 2 as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13 
14 #include "edp.h"
15 #include "edp.xml.h"
16 
17 #define EDP_MAX_LANE	4
18 
19 struct edp_phy {
20 	void __iomem *base;
21 };
22 
msm_edp_phy_ready(struct edp_phy * phy)23 bool msm_edp_phy_ready(struct edp_phy *phy)
24 {
25 	u32 status;
26 	int cnt = 100;
27 
28 	while (--cnt) {
29 		status = edp_read(phy->base +
30 				REG_EDP_PHY_GLB_PHY_STATUS);
31 		if (status & 0x01)
32 			break;
33 		usleep_range(500, 1000);
34 	}
35 
36 	if (cnt == 0) {
37 		pr_err("%s: PHY NOT ready\n", __func__);
38 		return false;
39 	} else {
40 		return true;
41 	}
42 }
43 
msm_edp_phy_ctrl(struct edp_phy * phy,int enable)44 void msm_edp_phy_ctrl(struct edp_phy *phy, int enable)
45 {
46 	DBG("enable=%d", enable);
47 	if (enable) {
48 		/* Reset */
49 		edp_write(phy->base + REG_EDP_PHY_CTRL,
50 			EDP_PHY_CTRL_SW_RESET | EDP_PHY_CTRL_SW_RESET_PLL);
51 		/* Make sure fully reset */
52 		wmb();
53 		usleep_range(500, 1000);
54 		edp_write(phy->base + REG_EDP_PHY_CTRL, 0x000);
55 		edp_write(phy->base + REG_EDP_PHY_GLB_PD_CTL, 0x3f);
56 		edp_write(phy->base + REG_EDP_PHY_GLB_CFG, 0x1);
57 	} else {
58 		edp_write(phy->base + REG_EDP_PHY_GLB_PD_CTL, 0xc0);
59 	}
60 }
61 
62 /* voltage mode and pre emphasis cfg */
msm_edp_phy_vm_pe_init(struct edp_phy * phy)63 void msm_edp_phy_vm_pe_init(struct edp_phy *phy)
64 {
65 	edp_write(phy->base + REG_EDP_PHY_GLB_VM_CFG0, 0x3);
66 	edp_write(phy->base + REG_EDP_PHY_GLB_VM_CFG1, 0x64);
67 	edp_write(phy->base + REG_EDP_PHY_GLB_MISC9, 0x6c);
68 }
69 
msm_edp_phy_vm_pe_cfg(struct edp_phy * phy,u32 v0,u32 v1)70 void msm_edp_phy_vm_pe_cfg(struct edp_phy *phy, u32 v0, u32 v1)
71 {
72 	edp_write(phy->base + REG_EDP_PHY_GLB_VM_CFG0, v0);
73 	edp_write(phy->base + REG_EDP_PHY_GLB_VM_CFG1, v1);
74 }
75 
msm_edp_phy_lane_power_ctrl(struct edp_phy * phy,bool up,u32 max_lane)76 void msm_edp_phy_lane_power_ctrl(struct edp_phy *phy, bool up, u32 max_lane)
77 {
78 	u32 i;
79 	u32 data;
80 
81 	if (up)
82 		data = 0;	/* power up */
83 	else
84 		data = 0x7;	/* power down */
85 
86 	for (i = 0; i < max_lane; i++)
87 		edp_write(phy->base + REG_EDP_PHY_LN_PD_CTL(i) , data);
88 
89 	/* power down unused lane */
90 	data = 0x7;	/* power down */
91 	for (i = max_lane; i < EDP_MAX_LANE; i++)
92 		edp_write(phy->base + REG_EDP_PHY_LN_PD_CTL(i) , data);
93 }
94 
msm_edp_phy_init(struct device * dev,void __iomem * regbase)95 void *msm_edp_phy_init(struct device *dev, void __iomem *regbase)
96 {
97 	struct edp_phy *phy = NULL;
98 
99 	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
100 	if (!phy)
101 		return NULL;
102 
103 	phy->base = regbase;
104 	return phy;
105 }
106 
107