Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 1 | /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. |
| 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" |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 16 | |
Clarence Ip | 110d15c | 2016-08-16 14:44:41 -0400 | [diff] [blame] | 17 | #define SSPP_SPARE 0x28 |
Abhijit Kulkarni | 43eafcc | 2016-06-28 17:48:41 -0400 | [diff] [blame] | 18 | |
Abhijit Kulkarni | 43eafcc | 2016-06-28 17:48:41 -0400 | [diff] [blame] | 19 | #define FLD_SPLIT_DISPLAY_CMD BIT(1) |
| 20 | #define FLD_SMART_PANEL_FREE_RUN BIT(2) |
| 21 | #define FLD_INTF_1_SW_TRG_MUX BIT(4) |
| 22 | #define FLD_INTF_2_SW_TRG_MUX BIT(8) |
| 23 | #define FLD_TE_LINE_INTER_WATERLEVEL_MASK 0xFFFF |
| 24 | |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 25 | #define TE_LINE_INTERVAL 0x3F4 |
| 26 | |
Alan Kwong | 3232ca5 | 2016-07-29 02:27:47 -0400 | [diff] [blame] | 27 | #define TRAFFIC_SHAPER_EN BIT(31) |
| 28 | #define TRAFFIC_SHAPER_RD_CLIENT(num) (0x030 + (num * 4)) |
| 29 | #define TRAFFIC_SHAPER_WR_CLIENT(num) (0x060 + (num * 4)) |
| 30 | #define TRAFFIC_SHAPER_FIXPOINT_FACTOR 4 |
| 31 | |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 32 | static void sde_hw_setup_split_pipe_control(struct sde_hw_mdp *mdp, |
Abhijit Kulkarni | 43eafcc | 2016-06-28 17:48:41 -0400 | [diff] [blame] | 33 | struct split_pipe_cfg *cfg) |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 34 | { |
| 35 | struct sde_hw_blk_reg_map *c = &mdp->hw; |
Abhijit Kulkarni | 43eafcc | 2016-06-28 17:48:41 -0400 | [diff] [blame] | 36 | u32 upper_pipe = 0; |
| 37 | u32 lower_pipe = 0; |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 38 | |
| 39 | if (cfg->en) { |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 40 | if (cfg->mode == INTF_MODE_CMD) { |
Abhijit Kulkarni | 43eafcc | 2016-06-28 17:48:41 -0400 | [diff] [blame] | 41 | lower_pipe = FLD_SPLIT_DISPLAY_CMD; |
| 42 | /* interface controlling sw trigger */ |
| 43 | if (cfg->intf == INTF_2) |
| 44 | lower_pipe |= FLD_INTF_1_SW_TRG_MUX; |
| 45 | else |
| 46 | lower_pipe |= FLD_INTF_2_SW_TRG_MUX; |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 47 | |
Abhijit Kulkarni | 43eafcc | 2016-06-28 17:48:41 -0400 | [diff] [blame] | 48 | /* free run */ |
| 49 | if (cfg->pp_split) |
| 50 | lower_pipe = FLD_SMART_PANEL_FREE_RUN; |
| 51 | |
| 52 | upper_pipe = lower_pipe; |
| 53 | } else { |
| 54 | if (cfg->intf == INTF_2) { |
| 55 | lower_pipe = FLD_INTF_1_SW_TRG_MUX; |
| 56 | upper_pipe = FLD_INTF_2_SW_TRG_MUX; |
| 57 | } else { |
| 58 | lower_pipe = FLD_INTF_2_SW_TRG_MUX; |
| 59 | upper_pipe = FLD_INTF_1_SW_TRG_MUX; |
| 60 | } |
| 61 | } |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 62 | } |
| 63 | |
Abhijit Kulkarni | 43eafcc | 2016-06-28 17:48:41 -0400 | [diff] [blame] | 64 | SDE_REG_WRITE(c, SSPP_SPARE, (cfg->split_flush_en) ? 0x1 : 0x0); |
Clarence Ip | 110d15c | 2016-08-16 14:44:41 -0400 | [diff] [blame] | 65 | SDE_REG_WRITE(c, SPLIT_DISPLAY_LOWER_PIPE_CTRL, lower_pipe); |
| 66 | SDE_REG_WRITE(c, SPLIT_DISPLAY_UPPER_PIPE_CTRL, upper_pipe); |
| 67 | SDE_REG_WRITE(c, SPLIT_DISPLAY_EN, cfg->en & 0x1); |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 68 | } |
| 69 | |
Alan Kwong | dcc96ff | 2016-07-29 03:06:44 -0400 | [diff] [blame] | 70 | static void sde_hw_setup_cdm_output(struct sde_hw_mdp *mdp, |
| 71 | struct cdm_output_cfg *cfg) |
| 72 | { |
| 73 | struct sde_hw_blk_reg_map *c = &mdp->hw; |
| 74 | u32 out_ctl = 0; |
| 75 | |
| 76 | if (cfg->wb_en) |
| 77 | out_ctl |= BIT(24); |
| 78 | else if (cfg->intf_en) |
| 79 | out_ctl |= BIT(19); |
| 80 | |
| 81 | SDE_REG_WRITE(c, MDP_OUT_CTL_0, out_ctl); |
| 82 | } |
| 83 | |
Alan Kwong | 5d324e4 | 2016-07-28 22:56:18 -0400 | [diff] [blame] | 84 | static bool sde_hw_setup_clk_force_ctrl(struct sde_hw_mdp *mdp, |
| 85 | enum sde_clk_ctrl_type clk_ctrl, bool enable) |
| 86 | { |
| 87 | struct sde_hw_blk_reg_map *c = &mdp->hw; |
| 88 | u32 reg_off, bit_off; |
| 89 | u32 reg_val, new_val; |
| 90 | bool clk_forced_on; |
| 91 | |
| 92 | if (clk_ctrl <= SDE_CLK_CTRL_NONE || clk_ctrl >= SDE_CLK_CTRL_MAX) |
| 93 | return false; |
| 94 | |
| 95 | reg_off = mdp->cap->clk_ctrls[clk_ctrl].reg_off; |
| 96 | bit_off = mdp->cap->clk_ctrls[clk_ctrl].bit_off; |
| 97 | |
| 98 | reg_val = SDE_REG_READ(c, reg_off); |
| 99 | |
| 100 | if (enable) |
| 101 | new_val = reg_val | BIT(bit_off); |
| 102 | else |
| 103 | new_val = reg_val & ~BIT(bit_off); |
| 104 | |
| 105 | SDE_REG_WRITE(c, reg_off, new_val); |
| 106 | |
| 107 | clk_forced_on = !(reg_val & BIT(bit_off)); |
| 108 | |
| 109 | return clk_forced_on; |
| 110 | } |
| 111 | |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 112 | static void _setup_mdp_ops(struct sde_hw_mdp_ops *ops, |
| 113 | unsigned long cap) |
| 114 | { |
| 115 | ops->setup_split_pipe = sde_hw_setup_split_pipe_control; |
Alan Kwong | dcc96ff | 2016-07-29 03:06:44 -0400 | [diff] [blame] | 116 | ops->setup_cdm_output = sde_hw_setup_cdm_output; |
Alan Kwong | 5d324e4 | 2016-07-28 22:56:18 -0400 | [diff] [blame] | 117 | ops->setup_clk_force_ctrl = sde_hw_setup_clk_force_ctrl; |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 118 | } |
| 119 | |
| 120 | static const struct sde_mdp_cfg *_top_offset(enum sde_mdp mdp, |
| 121 | const struct sde_mdss_cfg *m, |
| 122 | void __iomem *addr, |
| 123 | struct sde_hw_blk_reg_map *b) |
| 124 | { |
| 125 | int i; |
| 126 | |
| 127 | for (i = 0; i < m->mdp_count; i++) { |
| 128 | if (mdp == m->mdp[i].id) { |
| 129 | b->base_off = addr; |
| 130 | b->blk_off = m->mdp[i].base; |
| 131 | b->hwversion = m->hwversion; |
Lloyd Atkinson | bb87b5b | 2016-06-13 18:31:15 -0400 | [diff] [blame] | 132 | b->log_mask = SDE_DBG_MASK_TOP; |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 133 | return &m->mdp[i]; |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | return ERR_PTR(-EINVAL); |
| 138 | } |
| 139 | |
| 140 | struct sde_hw_mdp *sde_hw_mdptop_init(enum sde_mdp idx, |
| 141 | void __iomem *addr, |
| 142 | const struct sde_mdss_cfg *m) |
| 143 | { |
Lloyd Atkinson | 85ef3fe | 2016-10-04 09:47:46 -0400 | [diff] [blame] | 144 | struct sde_hw_mdp *mdp; |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 145 | const struct sde_mdp_cfg *cfg; |
| 146 | |
Lloyd Atkinson | 85ef3fe | 2016-10-04 09:47:46 -0400 | [diff] [blame] | 147 | mdp = kzalloc(sizeof(*mdp), GFP_KERNEL); |
| 148 | if (!mdp) |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 149 | return ERR_PTR(-ENOMEM); |
| 150 | |
Lloyd Atkinson | 85ef3fe | 2016-10-04 09:47:46 -0400 | [diff] [blame] | 151 | cfg = _top_offset(idx, m, addr, &mdp->hw); |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 152 | if (IS_ERR_OR_NULL(cfg)) { |
Lloyd Atkinson | 85ef3fe | 2016-10-04 09:47:46 -0400 | [diff] [blame] | 153 | kfree(mdp); |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 154 | return ERR_PTR(-EINVAL); |
| 155 | } |
| 156 | |
| 157 | /* |
| 158 | * Assign ops |
| 159 | */ |
Lloyd Atkinson | 85ef3fe | 2016-10-04 09:47:46 -0400 | [diff] [blame] | 160 | mdp->idx = idx; |
| 161 | mdp->cap = cfg; |
| 162 | _setup_mdp_ops(&mdp->ops, mdp->cap->features); |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 163 | |
| 164 | /* |
| 165 | * Perform any default initialization for the intf |
| 166 | */ |
Lloyd Atkinson | 85ef3fe | 2016-10-04 09:47:46 -0400 | [diff] [blame] | 167 | |
| 168 | return mdp; |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 169 | } |
| 170 | |
| 171 | void sde_hw_mdp_destroy(struct sde_hw_mdp *mdp) |
| 172 | { |
Lloyd Atkinson | e5c2c0b | 2016-07-05 12:23:29 -0400 | [diff] [blame] | 173 | kfree(mdp); |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 174 | } |
| 175 | |