Lloyd Atkinson | 7715873 | 2016-10-23 13:02:00 -0400 | [diff] [blame] | 1 | /* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 2 | * |
| 3 | * This program is free software; you can redistribute it and/or modify |
| 4 | * it under the terms of the GNU General Public License version 2 and |
| 5 | * only version 2 as published by the Free Software Foundation. |
| 6 | * |
| 7 | * This program is distributed in the hope that it will be useful, |
| 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 10 | * GNU General Public License for more details. |
| 11 | */ |
| 12 | |
| 13 | #include "sde_hwio.h" |
| 14 | #include "sde_hw_catalog.h" |
Clarence Ip | c475b08 | 2016-06-26 09:27:23 -0400 | [diff] [blame] | 15 | #include "sde_hw_top.h" |
Lloyd Atkinson | 113aefd | 2016-10-23 13:15:18 -0400 | [diff] [blame] | 16 | #include "sde_dbg.h" |
Lloyd Atkinson | 652e59b | 2017-05-03 11:20:30 -0400 | [diff] [blame] | 17 | #include "sde_kms.h" |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 18 | |
Clarence Ip | 110d15c | 2016-08-16 14:44:41 -0400 | [diff] [blame] | 19 | #define SSPP_SPARE 0x28 |
Clarence Ip | 32bcb00 | 2017-03-13 12:26:44 -0700 | [diff] [blame] | 20 | #define UBWC_STATIC 0x144 |
Abhijit Kulkarni | 43eafcc | 2016-06-28 17:48:41 -0400 | [diff] [blame] | 21 | |
Abhijit Kulkarni | 43eafcc | 2016-06-28 17:48:41 -0400 | [diff] [blame] | 22 | #define FLD_SPLIT_DISPLAY_CMD BIT(1) |
| 23 | #define FLD_SMART_PANEL_FREE_RUN BIT(2) |
| 24 | #define FLD_INTF_1_SW_TRG_MUX BIT(4) |
| 25 | #define FLD_INTF_2_SW_TRG_MUX BIT(8) |
| 26 | #define FLD_TE_LINE_INTER_WATERLEVEL_MASK 0xFFFF |
| 27 | |
Alan Kwong | f0fd851 | 2016-10-24 21:39:26 -0400 | [diff] [blame] | 28 | #define DANGER_STATUS 0x360 |
| 29 | #define SAFE_STATUS 0x364 |
| 30 | |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 31 | #define TE_LINE_INTERVAL 0x3F4 |
| 32 | |
Alan Kwong | 3232ca5 | 2016-07-29 02:27:47 -0400 | [diff] [blame] | 33 | #define TRAFFIC_SHAPER_EN BIT(31) |
| 34 | #define TRAFFIC_SHAPER_RD_CLIENT(num) (0x030 + (num * 4)) |
| 35 | #define TRAFFIC_SHAPER_WR_CLIENT(num) (0x060 + (num * 4)) |
| 36 | #define TRAFFIC_SHAPER_FIXPOINT_FACTOR 4 |
| 37 | |
Narendra Muppalla | d4081e1 | 2017-04-20 19:24:08 -0700 | [diff] [blame] | 38 | #define MDP_WD_TIMER_0_CTL 0x380 |
| 39 | #define MDP_WD_TIMER_0_CTL2 0x384 |
| 40 | #define MDP_WD_TIMER_0_LOAD_VALUE 0x388 |
Dhaval Patel | aab9b52 | 2017-07-20 12:38:46 -0700 | [diff] [blame] | 41 | #define MDP_WD_TIMER_1_CTL 0x390 |
| 42 | #define MDP_WD_TIMER_1_CTL2 0x394 |
| 43 | #define MDP_WD_TIMER_1_LOAD_VALUE 0x398 |
| 44 | #define MDP_WD_TIMER_2_CTL 0x420 |
| 45 | #define MDP_WD_TIMER_2_CTL2 0x424 |
| 46 | #define MDP_WD_TIMER_2_LOAD_VALUE 0x428 |
| 47 | #define MDP_WD_TIMER_3_CTL 0x430 |
| 48 | #define MDP_WD_TIMER_3_CTL2 0x434 |
| 49 | #define MDP_WD_TIMER_3_LOAD_VALUE 0x438 |
| 50 | #define MDP_WD_TIMER_4_CTL 0x440 |
| 51 | #define MDP_WD_TIMER_4_CTL2 0x444 |
| 52 | #define MDP_WD_TIMER_4_LOAD_VALUE 0x448 |
Narendra Muppalla | d4081e1 | 2017-04-20 19:24:08 -0700 | [diff] [blame] | 53 | |
| 54 | #define MDP_TICK_COUNT 16 |
| 55 | #define XO_CLK_RATE 19200 |
| 56 | #define MS_TICKS_IN_SEC 1000 |
| 57 | |
| 58 | #define CALCULATE_WD_LOAD_VALUE(fps) \ |
| 59 | ((uint32_t)((MS_TICKS_IN_SEC * XO_CLK_RATE)/(MDP_TICK_COUNT * fps))) |
| 60 | |
Jeykumar Sankaran | 5c2f070 | 2017-03-09 18:03:15 -0800 | [diff] [blame] | 61 | #define DCE_SEL 0x450 |
| 62 | |
Clarence Ip | 8e69ad0 | 2016-12-09 09:43:57 -0500 | [diff] [blame] | 63 | static void sde_hw_setup_split_pipe(struct sde_hw_mdp *mdp, |
Abhijit Kulkarni | 43eafcc | 2016-06-28 17:48:41 -0400 | [diff] [blame] | 64 | struct split_pipe_cfg *cfg) |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 65 | { |
Lloyd Atkinson | 20c9ecd | 2017-04-18 10:33:47 -0700 | [diff] [blame] | 66 | struct sde_hw_blk_reg_map *c; |
Abhijit Kulkarni | 43eafcc | 2016-06-28 17:48:41 -0400 | [diff] [blame] | 67 | u32 upper_pipe = 0; |
| 68 | u32 lower_pipe = 0; |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 69 | |
Clarence Ip | 8e69ad0 | 2016-12-09 09:43:57 -0500 | [diff] [blame] | 70 | if (!mdp || !cfg) |
| 71 | return; |
| 72 | |
Lloyd Atkinson | 20c9ecd | 2017-04-18 10:33:47 -0700 | [diff] [blame] | 73 | c = &mdp->hw; |
| 74 | |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 75 | if (cfg->en) { |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 76 | if (cfg->mode == INTF_MODE_CMD) { |
Abhijit Kulkarni | 43eafcc | 2016-06-28 17:48:41 -0400 | [diff] [blame] | 77 | lower_pipe = FLD_SPLIT_DISPLAY_CMD; |
| 78 | /* interface controlling sw trigger */ |
| 79 | if (cfg->intf == INTF_2) |
| 80 | lower_pipe |= FLD_INTF_1_SW_TRG_MUX; |
| 81 | else |
| 82 | lower_pipe |= FLD_INTF_2_SW_TRG_MUX; |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 83 | |
Abhijit Kulkarni | 43eafcc | 2016-06-28 17:48:41 -0400 | [diff] [blame] | 84 | /* free run */ |
Clarence Ip | 8e69ad0 | 2016-12-09 09:43:57 -0500 | [diff] [blame] | 85 | if (cfg->pp_split_slave != INTF_MAX) |
Abhijit Kulkarni | 43eafcc | 2016-06-28 17:48:41 -0400 | [diff] [blame] | 86 | lower_pipe = FLD_SMART_PANEL_FREE_RUN; |
| 87 | |
| 88 | upper_pipe = lower_pipe; |
| 89 | } else { |
| 90 | if (cfg->intf == INTF_2) { |
| 91 | lower_pipe = FLD_INTF_1_SW_TRG_MUX; |
| 92 | upper_pipe = FLD_INTF_2_SW_TRG_MUX; |
| 93 | } else { |
| 94 | lower_pipe = FLD_INTF_2_SW_TRG_MUX; |
| 95 | upper_pipe = FLD_INTF_1_SW_TRG_MUX; |
| 96 | } |
| 97 | } |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 98 | } |
| 99 | |
Clarence Ip | 8e69ad0 | 2016-12-09 09:43:57 -0500 | [diff] [blame] | 100 | SDE_REG_WRITE(c, SSPP_SPARE, cfg->split_flush_en ? 0x1 : 0x0); |
Clarence Ip | 110d15c | 2016-08-16 14:44:41 -0400 | [diff] [blame] | 101 | SDE_REG_WRITE(c, SPLIT_DISPLAY_LOWER_PIPE_CTRL, lower_pipe); |
| 102 | SDE_REG_WRITE(c, SPLIT_DISPLAY_UPPER_PIPE_CTRL, upper_pipe); |
| 103 | SDE_REG_WRITE(c, SPLIT_DISPLAY_EN, cfg->en & 0x1); |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 104 | } |
| 105 | |
Clarence Ip | 8e69ad0 | 2016-12-09 09:43:57 -0500 | [diff] [blame] | 106 | static void sde_hw_setup_pp_split(struct sde_hw_mdp *mdp, |
| 107 | struct split_pipe_cfg *cfg) |
| 108 | { |
| 109 | u32 ppb_config = 0x0; |
| 110 | u32 ppb_control = 0x0; |
| 111 | |
| 112 | if (!mdp || !cfg) |
| 113 | return; |
| 114 | |
| 115 | if (cfg->en && cfg->pp_split_slave != INTF_MAX) { |
| 116 | ppb_config |= (cfg->pp_split_slave - INTF_0 + 1) << 20; |
| 117 | ppb_config |= BIT(16); /* split enable */ |
| 118 | ppb_control = BIT(5); /* horz split*/ |
| 119 | } |
| 120 | if (cfg->pp_split_index) { |
| 121 | SDE_REG_WRITE(&mdp->hw, PPB0_CONFIG, 0x0); |
| 122 | SDE_REG_WRITE(&mdp->hw, PPB0_CNTL, 0x0); |
| 123 | SDE_REG_WRITE(&mdp->hw, PPB1_CONFIG, ppb_config); |
| 124 | SDE_REG_WRITE(&mdp->hw, PPB1_CNTL, ppb_control); |
| 125 | } else { |
| 126 | SDE_REG_WRITE(&mdp->hw, PPB0_CONFIG, ppb_config); |
| 127 | SDE_REG_WRITE(&mdp->hw, PPB0_CNTL, ppb_control); |
| 128 | SDE_REG_WRITE(&mdp->hw, PPB1_CONFIG, 0x0); |
| 129 | SDE_REG_WRITE(&mdp->hw, PPB1_CNTL, 0x0); |
| 130 | } |
| 131 | } |
| 132 | |
Alan Kwong | dcc96ff | 2016-07-29 03:06:44 -0400 | [diff] [blame] | 133 | static void sde_hw_setup_cdm_output(struct sde_hw_mdp *mdp, |
| 134 | struct cdm_output_cfg *cfg) |
| 135 | { |
Lloyd Atkinson | 20c9ecd | 2017-04-18 10:33:47 -0700 | [diff] [blame] | 136 | struct sde_hw_blk_reg_map *c; |
Alan Kwong | dcc96ff | 2016-07-29 03:06:44 -0400 | [diff] [blame] | 137 | u32 out_ctl = 0; |
| 138 | |
Lloyd Atkinson | 20c9ecd | 2017-04-18 10:33:47 -0700 | [diff] [blame] | 139 | if (!mdp || !cfg) |
| 140 | return; |
| 141 | |
| 142 | c = &mdp->hw; |
| 143 | |
Alan Kwong | dcc96ff | 2016-07-29 03:06:44 -0400 | [diff] [blame] | 144 | if (cfg->wb_en) |
| 145 | out_ctl |= BIT(24); |
| 146 | else if (cfg->intf_en) |
| 147 | out_ctl |= BIT(19); |
| 148 | |
| 149 | SDE_REG_WRITE(c, MDP_OUT_CTL_0, out_ctl); |
| 150 | } |
| 151 | |
Alan Kwong | 5d324e4 | 2016-07-28 22:56:18 -0400 | [diff] [blame] | 152 | static bool sde_hw_setup_clk_force_ctrl(struct sde_hw_mdp *mdp, |
| 153 | enum sde_clk_ctrl_type clk_ctrl, bool enable) |
| 154 | { |
Lloyd Atkinson | 20c9ecd | 2017-04-18 10:33:47 -0700 | [diff] [blame] | 155 | struct sde_hw_blk_reg_map *c; |
Alan Kwong | 5d324e4 | 2016-07-28 22:56:18 -0400 | [diff] [blame] | 156 | u32 reg_off, bit_off; |
| 157 | u32 reg_val, new_val; |
| 158 | bool clk_forced_on; |
| 159 | |
Lloyd Atkinson | 20c9ecd | 2017-04-18 10:33:47 -0700 | [diff] [blame] | 160 | if (!mdp) |
| 161 | return false; |
| 162 | |
| 163 | c = &mdp->hw; |
| 164 | |
Alan Kwong | 5d324e4 | 2016-07-28 22:56:18 -0400 | [diff] [blame] | 165 | if (clk_ctrl <= SDE_CLK_CTRL_NONE || clk_ctrl >= SDE_CLK_CTRL_MAX) |
| 166 | return false; |
| 167 | |
Lloyd Atkinson | 4a752fc | 2017-05-19 16:09:17 -0400 | [diff] [blame] | 168 | reg_off = mdp->caps->clk_ctrls[clk_ctrl].reg_off; |
| 169 | bit_off = mdp->caps->clk_ctrls[clk_ctrl].bit_off; |
Alan Kwong | 5d324e4 | 2016-07-28 22:56:18 -0400 | [diff] [blame] | 170 | |
| 171 | reg_val = SDE_REG_READ(c, reg_off); |
| 172 | |
| 173 | if (enable) |
| 174 | new_val = reg_val | BIT(bit_off); |
| 175 | else |
| 176 | new_val = reg_val & ~BIT(bit_off); |
| 177 | |
| 178 | SDE_REG_WRITE(c, reg_off, new_val); |
| 179 | |
| 180 | clk_forced_on = !(reg_val & BIT(bit_off)); |
| 181 | |
| 182 | return clk_forced_on; |
| 183 | } |
| 184 | |
Alan Kwong | f0fd851 | 2016-10-24 21:39:26 -0400 | [diff] [blame] | 185 | |
| 186 | static void sde_hw_get_danger_status(struct sde_hw_mdp *mdp, |
| 187 | struct sde_danger_safe_status *status) |
| 188 | { |
Lloyd Atkinson | 20c9ecd | 2017-04-18 10:33:47 -0700 | [diff] [blame] | 189 | struct sde_hw_blk_reg_map *c; |
Alan Kwong | f0fd851 | 2016-10-24 21:39:26 -0400 | [diff] [blame] | 190 | u32 value; |
| 191 | |
Lloyd Atkinson | 20c9ecd | 2017-04-18 10:33:47 -0700 | [diff] [blame] | 192 | if (!mdp || !status) |
| 193 | return; |
| 194 | |
| 195 | c = &mdp->hw; |
| 196 | |
Alan Kwong | f0fd851 | 2016-10-24 21:39:26 -0400 | [diff] [blame] | 197 | value = SDE_REG_READ(c, DANGER_STATUS); |
| 198 | status->mdp = (value >> 0) & 0x3; |
| 199 | status->sspp[SSPP_VIG0] = (value >> 4) & 0x3; |
| 200 | status->sspp[SSPP_VIG1] = (value >> 6) & 0x3; |
| 201 | status->sspp[SSPP_VIG2] = (value >> 8) & 0x3; |
| 202 | status->sspp[SSPP_VIG3] = (value >> 10) & 0x3; |
| 203 | status->sspp[SSPP_RGB0] = (value >> 12) & 0x3; |
| 204 | status->sspp[SSPP_RGB1] = (value >> 14) & 0x3; |
| 205 | status->sspp[SSPP_RGB2] = (value >> 16) & 0x3; |
| 206 | status->sspp[SSPP_RGB3] = (value >> 18) & 0x3; |
| 207 | status->sspp[SSPP_DMA0] = (value >> 20) & 0x3; |
| 208 | status->sspp[SSPP_DMA1] = (value >> 22) & 0x3; |
| 209 | status->sspp[SSPP_DMA2] = (value >> 28) & 0x3; |
| 210 | status->sspp[SSPP_DMA3] = (value >> 30) & 0x3; |
| 211 | status->sspp[SSPP_CURSOR0] = (value >> 24) & 0x3; |
| 212 | status->sspp[SSPP_CURSOR1] = (value >> 26) & 0x3; |
| 213 | status->wb[WB_0] = 0; |
| 214 | status->wb[WB_1] = 0; |
| 215 | status->wb[WB_2] = (value >> 2) & 0x3; |
| 216 | status->wb[WB_3] = 0; |
| 217 | } |
| 218 | |
Dhaval Patel | aab9b52 | 2017-07-20 12:38:46 -0700 | [diff] [blame] | 219 | static void sde_hw_setup_vsync_source(struct sde_hw_mdp *mdp, |
| 220 | struct sde_vsync_source_cfg *cfg) |
Narendra Muppalla | d4081e1 | 2017-04-20 19:24:08 -0700 | [diff] [blame] | 221 | { |
Dhaval Patel | aab9b52 | 2017-07-20 12:38:46 -0700 | [diff] [blame] | 222 | struct sde_hw_blk_reg_map *c; |
| 223 | u32 reg, wd_load_value, wd_ctl, wd_ctl2, i; |
| 224 | static const u32 pp_offset[PINGPONG_MAX] = {0xC, 0x8, 0x4, 0x13, 0x18}; |
Narendra Muppalla | d4081e1 | 2017-04-20 19:24:08 -0700 | [diff] [blame] | 225 | |
Alan Kwong | 095c713 | 2017-07-04 11:35:43 -0400 | [diff] [blame] | 226 | if (!mdp || !cfg || (cfg->pp_count > ARRAY_SIZE(cfg->ppnumber))) |
Narendra Muppalla | d4081e1 | 2017-04-20 19:24:08 -0700 | [diff] [blame] | 227 | return; |
| 228 | |
Dhaval Patel | aab9b52 | 2017-07-20 12:38:46 -0700 | [diff] [blame] | 229 | c = &mdp->hw; |
Narendra Muppalla | d4081e1 | 2017-04-20 19:24:08 -0700 | [diff] [blame] | 230 | reg = SDE_REG_READ(c, MDP_VSYNC_SEL); |
| 231 | for (i = 0; i < cfg->pp_count; i++) { |
Lloyd Atkinson | 8413f9a | 2017-05-26 15:47:25 -0400 | [diff] [blame] | 232 | int pp_idx = cfg->ppnumber[i] - PINGPONG_0; |
Dhaval Patel | aab9b52 | 2017-07-20 12:38:46 -0700 | [diff] [blame] | 233 | if (pp_idx >= ARRAY_SIZE(pp_offset)) |
| 234 | continue; |
Lloyd Atkinson | 8413f9a | 2017-05-26 15:47:25 -0400 | [diff] [blame] | 235 | |
Dhaval Patel | aab9b52 | 2017-07-20 12:38:46 -0700 | [diff] [blame] | 236 | reg &= ~(0xf << pp_offset[pp_idx]); |
| 237 | reg |= (cfg->vsync_source & 0xf) << pp_offset[pp_idx]; |
Narendra Muppalla | d4081e1 | 2017-04-20 19:24:08 -0700 | [diff] [blame] | 238 | } |
Narendra Muppalla | d4081e1 | 2017-04-20 19:24:08 -0700 | [diff] [blame] | 239 | SDE_REG_WRITE(c, MDP_VSYNC_SEL, reg); |
| 240 | |
Dhaval Patel | aab9b52 | 2017-07-20 12:38:46 -0700 | [diff] [blame] | 241 | if (cfg->vsync_source >= SDE_VSYNC_SOURCE_WD_TIMER_4 && |
| 242 | cfg->vsync_source <= SDE_VSYNC_SOURCE_WD_TIMER_0) { |
| 243 | switch (cfg->vsync_source) { |
| 244 | case SDE_VSYNC_SOURCE_WD_TIMER_4: |
| 245 | wd_load_value = MDP_WD_TIMER_4_LOAD_VALUE; |
| 246 | wd_ctl = MDP_WD_TIMER_4_CTL; |
| 247 | wd_ctl2 = MDP_WD_TIMER_4_CTL2; |
| 248 | break; |
| 249 | case SDE_VSYNC_SOURCE_WD_TIMER_3: |
| 250 | wd_load_value = MDP_WD_TIMER_3_LOAD_VALUE; |
| 251 | wd_ctl = MDP_WD_TIMER_3_CTL; |
| 252 | wd_ctl2 = MDP_WD_TIMER_3_CTL2; |
| 253 | break; |
| 254 | case SDE_VSYNC_SOURCE_WD_TIMER_2: |
| 255 | wd_load_value = MDP_WD_TIMER_2_LOAD_VALUE; |
| 256 | wd_ctl = MDP_WD_TIMER_2_CTL; |
| 257 | wd_ctl2 = MDP_WD_TIMER_2_CTL2; |
| 258 | break; |
| 259 | case SDE_VSYNC_SOURCE_WD_TIMER_1: |
| 260 | wd_load_value = MDP_WD_TIMER_1_LOAD_VALUE; |
| 261 | wd_ctl = MDP_WD_TIMER_1_CTL; |
| 262 | wd_ctl2 = MDP_WD_TIMER_1_CTL2; |
| 263 | break; |
| 264 | case SDE_VSYNC_SOURCE_WD_TIMER_0: |
| 265 | default: |
| 266 | wd_load_value = MDP_WD_TIMER_0_LOAD_VALUE; |
| 267 | wd_ctl = MDP_WD_TIMER_0_CTL; |
| 268 | wd_ctl2 = MDP_WD_TIMER_0_CTL2; |
| 269 | break; |
| 270 | } |
| 271 | |
| 272 | if (cfg->is_dummy) { |
| 273 | SDE_REG_WRITE(c, wd_ctl2, 0x0); |
| 274 | } else { |
| 275 | SDE_REG_WRITE(c, wd_load_value, |
Narendra Muppalla | d4081e1 | 2017-04-20 19:24:08 -0700 | [diff] [blame] | 276 | CALCULATE_WD_LOAD_VALUE(cfg->frame_rate)); |
| 277 | |
Dhaval Patel | aab9b52 | 2017-07-20 12:38:46 -0700 | [diff] [blame] | 278 | SDE_REG_WRITE(c, wd_ctl, BIT(0)); /* clear timer */ |
| 279 | reg = SDE_REG_READ(c, wd_ctl2); |
| 280 | reg |= BIT(8); /* enable heartbeat timer */ |
| 281 | reg |= BIT(0); /* enable WD timer */ |
| 282 | SDE_REG_WRITE(c, wd_ctl2, reg); |
| 283 | } |
| 284 | |
| 285 | /* make sure that timers are enabled/disabled for vsync state */ |
| 286 | wmb(); |
Narendra Muppalla | d4081e1 | 2017-04-20 19:24:08 -0700 | [diff] [blame] | 287 | } |
| 288 | } |
| 289 | |
Alan Kwong | f0fd851 | 2016-10-24 21:39:26 -0400 | [diff] [blame] | 290 | static void sde_hw_get_safe_status(struct sde_hw_mdp *mdp, |
| 291 | struct sde_danger_safe_status *status) |
| 292 | { |
Lloyd Atkinson | 20c9ecd | 2017-04-18 10:33:47 -0700 | [diff] [blame] | 293 | struct sde_hw_blk_reg_map *c; |
Alan Kwong | f0fd851 | 2016-10-24 21:39:26 -0400 | [diff] [blame] | 294 | u32 value; |
| 295 | |
Lloyd Atkinson | 20c9ecd | 2017-04-18 10:33:47 -0700 | [diff] [blame] | 296 | if (!mdp || !status) |
| 297 | return; |
| 298 | |
| 299 | c = &mdp->hw; |
| 300 | |
Alan Kwong | f0fd851 | 2016-10-24 21:39:26 -0400 | [diff] [blame] | 301 | value = SDE_REG_READ(c, SAFE_STATUS); |
| 302 | status->mdp = (value >> 0) & 0x1; |
| 303 | status->sspp[SSPP_VIG0] = (value >> 4) & 0x1; |
| 304 | status->sspp[SSPP_VIG1] = (value >> 6) & 0x1; |
| 305 | status->sspp[SSPP_VIG2] = (value >> 8) & 0x1; |
| 306 | status->sspp[SSPP_VIG3] = (value >> 10) & 0x1; |
| 307 | status->sspp[SSPP_RGB0] = (value >> 12) & 0x1; |
| 308 | status->sspp[SSPP_RGB1] = (value >> 14) & 0x1; |
| 309 | status->sspp[SSPP_RGB2] = (value >> 16) & 0x1; |
| 310 | status->sspp[SSPP_RGB3] = (value >> 18) & 0x1; |
| 311 | status->sspp[SSPP_DMA0] = (value >> 20) & 0x1; |
| 312 | status->sspp[SSPP_DMA1] = (value >> 22) & 0x1; |
| 313 | status->sspp[SSPP_DMA2] = (value >> 28) & 0x1; |
| 314 | status->sspp[SSPP_DMA3] = (value >> 30) & 0x1; |
| 315 | status->sspp[SSPP_CURSOR0] = (value >> 24) & 0x1; |
| 316 | status->sspp[SSPP_CURSOR1] = (value >> 26) & 0x1; |
| 317 | status->wb[WB_0] = 0; |
| 318 | status->wb[WB_1] = 0; |
| 319 | status->wb[WB_2] = (value >> 2) & 0x1; |
| 320 | status->wb[WB_3] = 0; |
| 321 | } |
| 322 | |
Jeykumar Sankaran | 5c2f070 | 2017-03-09 18:03:15 -0800 | [diff] [blame] | 323 | static void sde_hw_setup_dce(struct sde_hw_mdp *mdp, u32 dce_sel) |
| 324 | { |
Lloyd Atkinson | 20c9ecd | 2017-04-18 10:33:47 -0700 | [diff] [blame] | 325 | struct sde_hw_blk_reg_map *c; |
| 326 | |
| 327 | if (!mdp) |
| 328 | return; |
| 329 | |
| 330 | c = &mdp->hw; |
Jeykumar Sankaran | 5c2f070 | 2017-03-09 18:03:15 -0800 | [diff] [blame] | 331 | |
| 332 | SDE_REG_WRITE(c, DCE_SEL, dce_sel); |
| 333 | } |
| 334 | |
Clarence Ip | 3534826 | 2017-04-28 16:10:46 -0700 | [diff] [blame] | 335 | void sde_hw_reset_ubwc(struct sde_hw_mdp *mdp, struct sde_mdss_cfg *m) |
| 336 | { |
| 337 | struct sde_hw_blk_reg_map c; |
| 338 | |
| 339 | if (!mdp || !m) |
| 340 | return; |
| 341 | |
| 342 | if (!IS_UBWC_20_SUPPORTED(m->ubwc_version)) |
| 343 | return; |
| 344 | |
| 345 | /* force blk offset to zero to access beginning of register region */ |
| 346 | c = mdp->hw; |
| 347 | c.blk_off = 0x0; |
| 348 | SDE_REG_WRITE(&c, UBWC_STATIC, m->mdp[0].ubwc_static); |
| 349 | } |
| 350 | |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 351 | static void _setup_mdp_ops(struct sde_hw_mdp_ops *ops, |
| 352 | unsigned long cap) |
| 353 | { |
Clarence Ip | 8e69ad0 | 2016-12-09 09:43:57 -0500 | [diff] [blame] | 354 | ops->setup_split_pipe = sde_hw_setup_split_pipe; |
| 355 | ops->setup_pp_split = sde_hw_setup_pp_split; |
Alan Kwong | dcc96ff | 2016-07-29 03:06:44 -0400 | [diff] [blame] | 356 | ops->setup_cdm_output = sde_hw_setup_cdm_output; |
Alan Kwong | 5d324e4 | 2016-07-28 22:56:18 -0400 | [diff] [blame] | 357 | ops->setup_clk_force_ctrl = sde_hw_setup_clk_force_ctrl; |
Alan Kwong | f0fd851 | 2016-10-24 21:39:26 -0400 | [diff] [blame] | 358 | ops->get_danger_status = sde_hw_get_danger_status; |
Dhaval Patel | aab9b52 | 2017-07-20 12:38:46 -0700 | [diff] [blame] | 359 | ops->setup_vsync_source = sde_hw_setup_vsync_source; |
Alan Kwong | f0fd851 | 2016-10-24 21:39:26 -0400 | [diff] [blame] | 360 | ops->get_safe_status = sde_hw_get_safe_status; |
Jeykumar Sankaran | 5c2f070 | 2017-03-09 18:03:15 -0800 | [diff] [blame] | 361 | ops->setup_dce = sde_hw_setup_dce; |
Clarence Ip | 3534826 | 2017-04-28 16:10:46 -0700 | [diff] [blame] | 362 | ops->reset_ubwc = sde_hw_reset_ubwc; |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 363 | } |
| 364 | |
| 365 | static const struct sde_mdp_cfg *_top_offset(enum sde_mdp mdp, |
| 366 | const struct sde_mdss_cfg *m, |
| 367 | void __iomem *addr, |
| 368 | struct sde_hw_blk_reg_map *b) |
| 369 | { |
| 370 | int i; |
| 371 | |
Lloyd Atkinson | 20c9ecd | 2017-04-18 10:33:47 -0700 | [diff] [blame] | 372 | if (!m || !addr || !b) |
| 373 | return ERR_PTR(-EINVAL); |
| 374 | |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 375 | for (i = 0; i < m->mdp_count; i++) { |
| 376 | if (mdp == m->mdp[i].id) { |
| 377 | b->base_off = addr; |
| 378 | b->blk_off = m->mdp[i].base; |
Lloyd Atkinson | 7715873 | 2016-10-23 13:02:00 -0400 | [diff] [blame] | 379 | b->length = m->mdp[i].len; |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 380 | b->hwversion = m->hwversion; |
Lloyd Atkinson | bb87b5b | 2016-06-13 18:31:15 -0400 | [diff] [blame] | 381 | b->log_mask = SDE_DBG_MASK_TOP; |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 382 | return &m->mdp[i]; |
| 383 | } |
| 384 | } |
| 385 | |
| 386 | return ERR_PTR(-EINVAL); |
| 387 | } |
| 388 | |
Lloyd Atkinson | 652e59b | 2017-05-03 11:20:30 -0400 | [diff] [blame] | 389 | static struct sde_hw_blk_ops sde_hw_ops = { |
| 390 | .start = NULL, |
| 391 | .stop = NULL, |
| 392 | }; |
| 393 | |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 394 | struct sde_hw_mdp *sde_hw_mdptop_init(enum sde_mdp idx, |
| 395 | void __iomem *addr, |
| 396 | const struct sde_mdss_cfg *m) |
| 397 | { |
Lloyd Atkinson | 85ef3fe | 2016-10-04 09:47:46 -0400 | [diff] [blame] | 398 | struct sde_hw_mdp *mdp; |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 399 | const struct sde_mdp_cfg *cfg; |
Lloyd Atkinson | 652e59b | 2017-05-03 11:20:30 -0400 | [diff] [blame] | 400 | int rc; |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 401 | |
Clarence Ip | 32bcb00 | 2017-03-13 12:26:44 -0700 | [diff] [blame] | 402 | if (!addr || !m) |
| 403 | return ERR_PTR(-EINVAL); |
| 404 | |
Lloyd Atkinson | 85ef3fe | 2016-10-04 09:47:46 -0400 | [diff] [blame] | 405 | mdp = kzalloc(sizeof(*mdp), GFP_KERNEL); |
| 406 | if (!mdp) |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 407 | return ERR_PTR(-ENOMEM); |
| 408 | |
Lloyd Atkinson | 85ef3fe | 2016-10-04 09:47:46 -0400 | [diff] [blame] | 409 | cfg = _top_offset(idx, m, addr, &mdp->hw); |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 410 | if (IS_ERR_OR_NULL(cfg)) { |
Lloyd Atkinson | 85ef3fe | 2016-10-04 09:47:46 -0400 | [diff] [blame] | 411 | kfree(mdp); |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 412 | return ERR_PTR(-EINVAL); |
| 413 | } |
| 414 | |
| 415 | /* |
| 416 | * Assign ops |
| 417 | */ |
Lloyd Atkinson | 85ef3fe | 2016-10-04 09:47:46 -0400 | [diff] [blame] | 418 | mdp->idx = idx; |
Lloyd Atkinson | 4a752fc | 2017-05-19 16:09:17 -0400 | [diff] [blame] | 419 | mdp->caps = cfg; |
| 420 | _setup_mdp_ops(&mdp->ops, mdp->caps->features); |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 421 | |
Lloyd Atkinson | 652e59b | 2017-05-03 11:20:30 -0400 | [diff] [blame] | 422 | rc = sde_hw_blk_init(&mdp->base, SDE_HW_BLK_TOP, idx, &sde_hw_ops); |
| 423 | if (rc) { |
| 424 | SDE_ERROR("failed to init hw blk %d\n", rc); |
| 425 | goto blk_init_error; |
| 426 | } |
| 427 | |
Lloyd Atkinson | 113aefd | 2016-10-23 13:15:18 -0400 | [diff] [blame] | 428 | sde_dbg_reg_register_dump_range(SDE_DBG_NAME, cfg->name, |
| 429 | mdp->hw.blk_off, mdp->hw.blk_off + mdp->hw.length, |
| 430 | mdp->hw.xin_id); |
Lloyd Atkinson | ac4b6e0 | 2017-03-23 11:43:48 -0700 | [diff] [blame] | 431 | sde_dbg_set_sde_top_offset(mdp->hw.blk_off); |
Lloyd Atkinson | 85ef3fe | 2016-10-04 09:47:46 -0400 | [diff] [blame] | 432 | |
| 433 | return mdp; |
Lloyd Atkinson | 652e59b | 2017-05-03 11:20:30 -0400 | [diff] [blame] | 434 | |
| 435 | blk_init_error: |
| 436 | kzfree(mdp); |
| 437 | |
| 438 | return ERR_PTR(rc); |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 439 | } |
| 440 | |
| 441 | void sde_hw_mdp_destroy(struct sde_hw_mdp *mdp) |
| 442 | { |
Lloyd Atkinson | 652e59b | 2017-05-03 11:20:30 -0400 | [diff] [blame] | 443 | if (mdp) |
| 444 | sde_hw_blk_destroy(&mdp->base); |
Lloyd Atkinson | e5c2c0b | 2016-07-05 12:23:29 -0400 | [diff] [blame] | 445 | kfree(mdp); |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 446 | } |
| 447 | |