Padmanabhan Komanduru | 56611ef | 2016-12-19 12:21:11 +0530 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2015-2017, 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 | #define pr_fmt(fmt) "dsi-phy-hw:" fmt |
| 15 | #include <linux/math64.h> |
| 16 | #include <linux/delay.h> |
| 17 | #include "dsi_hw.h" |
| 18 | #include "dsi_phy_hw.h" |
| 19 | |
| 20 | #define DSIPHY_CMN_REVISION_ID0 0x0000 |
| 21 | #define DSIPHY_CMN_REVISION_ID1 0x0004 |
| 22 | #define DSIPHY_CMN_REVISION_ID2 0x0008 |
| 23 | #define DSIPHY_CMN_REVISION_ID3 0x000C |
| 24 | #define DSIPHY_CMN_CLK_CFG0 0x0010 |
| 25 | #define DSIPHY_CMN_CLK_CFG1 0x0014 |
| 26 | #define DSIPHY_CMN_GLBL_TEST_CTRL 0x0018 |
| 27 | #define DSIPHY_CMN_CTRL_0 0x001C |
| 28 | #define DSIPHY_CMN_CTRL_1 0x0020 |
| 29 | #define DSIPHY_CMN_CAL_HW_TRIGGER 0x0024 |
| 30 | #define DSIPHY_CMN_CAL_SW_CFG0 0x0028 |
| 31 | #define DSIPHY_CMN_CAL_SW_CFG1 0x002C |
| 32 | #define DSIPHY_CMN_CAL_SW_CFG2 0x0030 |
| 33 | #define DSIPHY_CMN_CAL_HW_CFG0 0x0034 |
| 34 | #define DSIPHY_CMN_CAL_HW_CFG1 0x0038 |
| 35 | #define DSIPHY_CMN_CAL_HW_CFG2 0x003C |
| 36 | #define DSIPHY_CMN_CAL_HW_CFG3 0x0040 |
| 37 | #define DSIPHY_CMN_CAL_HW_CFG4 0x0044 |
| 38 | #define DSIPHY_CMN_PLL_CNTRL 0x0048 |
| 39 | #define DSIPHY_CMN_LDO_CNTRL 0x004C |
| 40 | |
| 41 | #define DSIPHY_CMN_REGULATOR_CAL_STATUS0 0x0064 |
| 42 | #define DSIPHY_CMN_REGULATOR_CAL_STATUS1 0x0068 |
| 43 | |
| 44 | /* n = 0..3 for data lanes and n = 4 for clock lane */ |
| 45 | #define DSIPHY_DLNX_CFG0(n) (0x100 + ((n) * 0x80)) |
| 46 | #define DSIPHY_DLNX_CFG1(n) (0x104 + ((n) * 0x80)) |
| 47 | #define DSIPHY_DLNX_CFG2(n) (0x108 + ((n) * 0x80)) |
| 48 | #define DSIPHY_DLNX_CFG3(n) (0x10C + ((n) * 0x80)) |
| 49 | #define DSIPHY_DLNX_TEST_DATAPATH(n) (0x110 + ((n) * 0x80)) |
| 50 | #define DSIPHY_DLNX_TEST_STR(n) (0x114 + ((n) * 0x80)) |
| 51 | #define DSIPHY_DLNX_TIMING_CTRL_4(n) (0x118 + ((n) * 0x80)) |
| 52 | #define DSIPHY_DLNX_TIMING_CTRL_5(n) (0x11C + ((n) * 0x80)) |
| 53 | #define DSIPHY_DLNX_TIMING_CTRL_6(n) (0x120 + ((n) * 0x80)) |
| 54 | #define DSIPHY_DLNX_TIMING_CTRL_7(n) (0x124 + ((n) * 0x80)) |
| 55 | #define DSIPHY_DLNX_TIMING_CTRL_8(n) (0x128 + ((n) * 0x80)) |
| 56 | #define DSIPHY_DLNX_TIMING_CTRL_9(n) (0x12C + ((n) * 0x80)) |
| 57 | #define DSIPHY_DLNX_TIMING_CTRL_10(n) (0x130 + ((n) * 0x80)) |
| 58 | #define DSIPHY_DLNX_TIMING_CTRL_11(n) (0x134 + ((n) * 0x80)) |
| 59 | #define DSIPHY_DLNX_STRENGTH_CTRL_0(n) (0x138 + ((n) * 0x80)) |
| 60 | #define DSIPHY_DLNX_STRENGTH_CTRL_1(n) (0x13C + ((n) * 0x80)) |
| 61 | #define DSIPHY_DLNX_BIST_POLY(n) (0x140 + ((n) * 0x80)) |
| 62 | #define DSIPHY_DLNX_BIST_SEED0(n) (0x144 + ((n) * 0x80)) |
| 63 | #define DSIPHY_DLNX_BIST_SEED1(n) (0x148 + ((n) * 0x80)) |
| 64 | #define DSIPHY_DLNX_BIST_HEAD(n) (0x14C + ((n) * 0x80)) |
| 65 | #define DSIPHY_DLNX_BIST_SOT(n) (0x150 + ((n) * 0x80)) |
| 66 | #define DSIPHY_DLNX_BIST_CTRL0(n) (0x154 + ((n) * 0x80)) |
| 67 | #define DSIPHY_DLNX_BIST_CTRL1(n) (0x158 + ((n) * 0x80)) |
| 68 | #define DSIPHY_DLNX_BIST_CTRL2(n) (0x15C + ((n) * 0x80)) |
| 69 | #define DSIPHY_DLNX_BIST_CTRL3(n) (0x160 + ((n) * 0x80)) |
| 70 | #define DSIPHY_DLNX_VREG_CNTRL(n) (0x164 + ((n) * 0x80)) |
| 71 | #define DSIPHY_DLNX_HSTX_STR_STATUS(n) (0x168 + ((n) * 0x80)) |
| 72 | #define DSIPHY_DLNX_BIST_STATUS0(n) (0x16C + ((n) * 0x80)) |
| 73 | #define DSIPHY_DLNX_BIST_STATUS1(n) (0x170 + ((n) * 0x80)) |
| 74 | #define DSIPHY_DLNX_BIST_STATUS2(n) (0x174 + ((n) * 0x80)) |
| 75 | #define DSIPHY_DLNX_BIST_STATUS3(n) (0x178 + ((n) * 0x80)) |
| 76 | #define DSIPHY_DLNX_MISR_STATUS(n) (0x17C + ((n) * 0x80)) |
| 77 | |
| 78 | #define DSIPHY_PLL_CLKBUFLR_EN 0x041C |
| 79 | #define DSIPHY_PLL_PLL_BANDGAP 0x0508 |
| 80 | |
| 81 | /** |
| 82 | * regulator_enable() - enable regulators for DSI PHY |
| 83 | * @phy: Pointer to DSI PHY hardware object. |
| 84 | * @reg_cfg: Regulator configuration for all DSI lanes. |
| 85 | */ |
| 86 | void dsi_phy_hw_v2_0_regulator_enable(struct dsi_phy_hw *phy, |
| 87 | struct dsi_phy_per_lane_cfgs *reg_cfg) |
| 88 | { |
| 89 | int i; |
| 90 | |
| 91 | for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) |
| 92 | DSI_W32(phy, DSIPHY_DLNX_VREG_CNTRL(i), reg_cfg->lane[i][0]); |
| 93 | |
| 94 | /* make sure all values are written to hardware */ |
| 95 | wmb(); |
| 96 | |
| 97 | pr_debug("[DSI_%d] Phy regulators enabled\n", phy->index); |
| 98 | } |
| 99 | |
| 100 | /** |
| 101 | * regulator_disable() - disable regulators |
| 102 | * @phy: Pointer to DSI PHY hardware object. |
| 103 | */ |
| 104 | void dsi_phy_hw_v2_0_regulator_disable(struct dsi_phy_hw *phy) |
| 105 | { |
| 106 | pr_debug("[DSI_%d] Phy regulators disabled\n", phy->index); |
| 107 | } |
| 108 | |
| 109 | /** |
| 110 | * enable() - Enable PHY hardware |
| 111 | * @phy: Pointer to DSI PHY hardware object. |
| 112 | * @cfg: Per lane configurations for timing, strength and lane |
| 113 | * configurations. |
| 114 | */ |
| 115 | void dsi_phy_hw_v2_0_enable(struct dsi_phy_hw *phy, |
| 116 | struct dsi_phy_cfg *cfg) |
| 117 | { |
| 118 | int i; |
| 119 | struct dsi_phy_per_lane_cfgs *timing = &cfg->timing; |
| 120 | u32 data; |
| 121 | |
| 122 | DSI_W32(phy, DSIPHY_CMN_LDO_CNTRL, 0x1C); |
| 123 | |
| 124 | DSI_W32(phy, DSIPHY_CMN_GLBL_TEST_CTRL, 0x1); |
| 125 | for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) { |
| 126 | |
| 127 | DSI_W32(phy, DSIPHY_DLNX_CFG0(i), cfg->lanecfg.lane[i][0]); |
| 128 | DSI_W32(phy, DSIPHY_DLNX_CFG1(i), cfg->lanecfg.lane[i][1]); |
| 129 | DSI_W32(phy, DSIPHY_DLNX_CFG2(i), cfg->lanecfg.lane[i][2]); |
| 130 | DSI_W32(phy, DSIPHY_DLNX_CFG3(i), cfg->lanecfg.lane[i][3]); |
| 131 | |
| 132 | DSI_W32(phy, DSIPHY_DLNX_TEST_STR(i), 0x88); |
| 133 | |
| 134 | DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_4(i), timing->lane[i][0]); |
| 135 | DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_5(i), timing->lane[i][1]); |
| 136 | DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_6(i), timing->lane[i][2]); |
| 137 | DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_7(i), timing->lane[i][3]); |
| 138 | DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_8(i), timing->lane[i][4]); |
| 139 | DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_9(i), timing->lane[i][5]); |
| 140 | DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_10(i), timing->lane[i][6]); |
| 141 | DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_11(i), timing->lane[i][7]); |
| 142 | |
| 143 | DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL_0(i), |
| 144 | cfg->strength.lane[i][0]); |
| 145 | DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL_1(i), |
| 146 | cfg->strength.lane[i][1]); |
| 147 | } |
| 148 | |
| 149 | /* make sure all values are written to hardware before enabling phy */ |
| 150 | wmb(); |
| 151 | |
| 152 | DSI_W32(phy, DSIPHY_CMN_CTRL_1, 0x80); |
| 153 | udelay(100); |
| 154 | DSI_W32(phy, DSIPHY_CMN_CTRL_1, 0x00); |
| 155 | |
| 156 | data = DSI_R32(phy, DSIPHY_CMN_GLBL_TEST_CTRL); |
| 157 | |
| 158 | switch (cfg->pll_source) { |
| 159 | case DSI_PLL_SOURCE_STANDALONE: |
| 160 | DSI_W32(phy, DSIPHY_PLL_CLKBUFLR_EN, 0x01); |
| 161 | data &= ~BIT(2); |
| 162 | break; |
| 163 | case DSI_PLL_SOURCE_NATIVE: |
| 164 | DSI_W32(phy, DSIPHY_PLL_CLKBUFLR_EN, 0x03); |
| 165 | data &= ~BIT(2); |
| 166 | break; |
| 167 | case DSI_PLL_SOURCE_NON_NATIVE: |
| 168 | DSI_W32(phy, DSIPHY_PLL_CLKBUFLR_EN, 0x00); |
| 169 | data |= BIT(2); |
| 170 | break; |
| 171 | default: |
| 172 | break; |
| 173 | } |
| 174 | |
| 175 | DSI_W32(phy, DSIPHY_CMN_GLBL_TEST_CTRL, data); |
| 176 | |
| 177 | /* Enable bias current for pll1 during split display case */ |
| 178 | if (cfg->pll_source == DSI_PLL_SOURCE_NON_NATIVE) |
| 179 | DSI_W32(phy, DSIPHY_PLL_PLL_BANDGAP, 0x3); |
| 180 | |
| 181 | pr_debug("[DSI_%d]Phy enabled ", phy->index); |
| 182 | } |
| 183 | |
| 184 | /** |
| 185 | * disable() - Disable PHY hardware |
| 186 | * @phy: Pointer to DSI PHY hardware object. |
| 187 | */ |
| 188 | void dsi_phy_hw_v2_0_disable(struct dsi_phy_hw *phy, |
| 189 | struct dsi_phy_cfg *cfg) |
| 190 | { |
| 191 | DSI_W32(phy, DSIPHY_PLL_CLKBUFLR_EN, 0); |
| 192 | DSI_W32(phy, DSIPHY_CMN_GLBL_TEST_CTRL, 0); |
| 193 | DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0); |
| 194 | pr_debug("[DSI_%d]Phy disabled ", phy->index); |
| 195 | } |
| 196 | |
| 197 | /** |
| 198 | * dsi_phy_hw_v2_0_idle_on() - Enable DSI PHY hardware during idle screen |
| 199 | * @phy: Pointer to DSI PHY hardware object. |
| 200 | */ |
| 201 | void dsi_phy_hw_v2_0_idle_on(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg) |
| 202 | { |
| 203 | int i = 0; |
| 204 | |
| 205 | for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) { |
| 206 | DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL_0(i), |
| 207 | cfg->strength.lane[i][0]); |
| 208 | DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL_1(i), |
| 209 | cfg->strength.lane[i][1]); |
| 210 | } |
| 211 | wmb(); /* make sure write happens */ |
| 212 | pr_debug("[DSI_%d]Phy enabled out of idle screen\n", phy->index); |
| 213 | } |
| 214 | |
| 215 | |
| 216 | /** |
| 217 | * dsi_phy_hw_v2_0_idle_off() - Disable DSI PHY hardware during idle screen |
| 218 | * @phy: Pointer to DSI PHY hardware object. |
| 219 | */ |
| 220 | void dsi_phy_hw_v2_0_idle_off(struct dsi_phy_hw *phy) |
| 221 | { |
| 222 | int i = 0; |
| 223 | |
| 224 | DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0x7f); |
| 225 | for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) |
| 226 | DSI_W32(phy, DSIPHY_DLNX_VREG_CNTRL(i), 0x1c); |
| 227 | DSI_W32(phy, DSIPHY_CMN_LDO_CNTRL, 0x1C); |
| 228 | |
| 229 | for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) |
| 230 | DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL_1(i), 0x0); |
| 231 | wmb(); /* make sure write happens */ |
| 232 | pr_debug("[DSI_%d]Phy disabled during idle screen\n", phy->index); |
| 233 | } |
| 234 | |
Padmanabhan Komanduru | ee89d21 | 2016-12-19 12:51:31 +0530 | [diff] [blame] | 235 | int dsi_phy_hw_timing_val_v2_0(struct dsi_phy_per_lane_cfgs *timing_cfg, |
| 236 | u32 *timing_val, u32 size) |
| 237 | { |
| 238 | int i = 0, j = 0; |
| 239 | |
| 240 | if (size != (DSI_LANE_MAX * DSI_MAX_SETTINGS)) { |
| 241 | pr_err("Unexpected timing array size %d\n", size); |
| 242 | return -EINVAL; |
| 243 | } |
| 244 | |
| 245 | for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) { |
| 246 | for (j = 0; j < DSI_MAX_SETTINGS; j++) { |
| 247 | timing_cfg->lane[i][j] = *timing_val; |
| 248 | timing_val++; |
| 249 | } |
| 250 | } |
| 251 | return 0; |
| 252 | } |