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 | |
Abhijit Kulkarni | 43eafcc | 2016-06-28 17:48:41 -0400 | [diff] [blame] | 17 | #define SSPP_SPARE 0x24 |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 18 | #define SPLIT_DISPLAY_ENABLE 0x2F4 |
Abhijit Kulkarni | 43eafcc | 2016-06-28 17:48:41 -0400 | [diff] [blame] | 19 | |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 20 | #define LOWER_PIPE_CTRL 0x2F8 |
Abhijit Kulkarni | 43eafcc | 2016-06-28 17:48:41 -0400 | [diff] [blame] | 21 | #define FLD_SPLIT_DISPLAY_CMD BIT(1) |
| 22 | #define FLD_SMART_PANEL_FREE_RUN BIT(2) |
| 23 | #define FLD_INTF_1_SW_TRG_MUX BIT(4) |
| 24 | #define FLD_INTF_2_SW_TRG_MUX BIT(8) |
| 25 | #define FLD_TE_LINE_INTER_WATERLEVEL_MASK 0xFFFF |
| 26 | |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 27 | #define UPPER_PIPE_CTRL 0x3F0 |
| 28 | #define TE_LINE_INTERVAL 0x3F4 |
| 29 | |
| 30 | 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] | 31 | struct split_pipe_cfg *cfg) |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 32 | { |
| 33 | struct sde_hw_blk_reg_map *c = &mdp->hw; |
Abhijit Kulkarni | 43eafcc | 2016-06-28 17:48:41 -0400 | [diff] [blame] | 34 | u32 upper_pipe = 0; |
| 35 | u32 lower_pipe = 0; |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 36 | |
| 37 | if (cfg->en) { |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 38 | if (cfg->mode == INTF_MODE_CMD) { |
Abhijit Kulkarni | 43eafcc | 2016-06-28 17:48:41 -0400 | [diff] [blame] | 39 | lower_pipe = FLD_SPLIT_DISPLAY_CMD; |
| 40 | /* interface controlling sw trigger */ |
| 41 | if (cfg->intf == INTF_2) |
| 42 | lower_pipe |= FLD_INTF_1_SW_TRG_MUX; |
| 43 | else |
| 44 | lower_pipe |= FLD_INTF_2_SW_TRG_MUX; |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 45 | |
Abhijit Kulkarni | 43eafcc | 2016-06-28 17:48:41 -0400 | [diff] [blame] | 46 | /* free run */ |
| 47 | if (cfg->pp_split) |
| 48 | lower_pipe = FLD_SMART_PANEL_FREE_RUN; |
| 49 | |
| 50 | upper_pipe = lower_pipe; |
| 51 | } else { |
| 52 | if (cfg->intf == INTF_2) { |
| 53 | lower_pipe = FLD_INTF_1_SW_TRG_MUX; |
| 54 | upper_pipe = FLD_INTF_2_SW_TRG_MUX; |
| 55 | } else { |
| 56 | lower_pipe = FLD_INTF_2_SW_TRG_MUX; |
| 57 | upper_pipe = FLD_INTF_1_SW_TRG_MUX; |
| 58 | } |
| 59 | } |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 60 | } |
| 61 | |
Abhijit Kulkarni | 43eafcc | 2016-06-28 17:48:41 -0400 | [diff] [blame] | 62 | SDE_REG_WRITE(c, SSPP_SPARE, (cfg->split_flush_en) ? 0x1 : 0x0); |
| 63 | SDE_REG_WRITE(c, LOWER_PIPE_CTRL, lower_pipe); |
| 64 | SDE_REG_WRITE(c, UPPER_PIPE_CTRL, upper_pipe); |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 65 | SDE_REG_WRITE(c, SPLIT_DISPLAY_ENABLE, cfg->en & 0x1); |
| 66 | } |
| 67 | |
| 68 | static void _setup_mdp_ops(struct sde_hw_mdp_ops *ops, |
| 69 | unsigned long cap) |
| 70 | { |
| 71 | ops->setup_split_pipe = sde_hw_setup_split_pipe_control; |
| 72 | } |
| 73 | |
| 74 | static const struct sde_mdp_cfg *_top_offset(enum sde_mdp mdp, |
| 75 | const struct sde_mdss_cfg *m, |
| 76 | void __iomem *addr, |
| 77 | struct sde_hw_blk_reg_map *b) |
| 78 | { |
| 79 | int i; |
| 80 | |
| 81 | for (i = 0; i < m->mdp_count; i++) { |
| 82 | if (mdp == m->mdp[i].id) { |
| 83 | b->base_off = addr; |
| 84 | b->blk_off = m->mdp[i].base; |
| 85 | b->hwversion = m->hwversion; |
| 86 | return &m->mdp[i]; |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | return ERR_PTR(-EINVAL); |
| 91 | } |
| 92 | |
| 93 | struct sde_hw_mdp *sde_hw_mdptop_init(enum sde_mdp idx, |
| 94 | void __iomem *addr, |
| 95 | const struct sde_mdss_cfg *m) |
| 96 | { |
| 97 | static struct sde_hw_mdp *c; |
| 98 | const struct sde_mdp_cfg *cfg; |
| 99 | |
| 100 | /* mdp top is singleton */ |
Abhijit Kulkarni | 7acb326 | 2016-07-05 15:27:25 -0400 | [diff] [blame] | 101 | if (c) |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 102 | return c; |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 103 | |
| 104 | c = kzalloc(sizeof(*c), GFP_KERNEL); |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 105 | if (!c) |
| 106 | return ERR_PTR(-ENOMEM); |
| 107 | |
| 108 | cfg = _top_offset(idx, m, addr, &c->hw); |
| 109 | if (IS_ERR_OR_NULL(cfg)) { |
| 110 | kfree(c); |
| 111 | return ERR_PTR(-EINVAL); |
| 112 | } |
| 113 | |
| 114 | /* |
| 115 | * Assign ops |
| 116 | */ |
| 117 | c->idx = idx; |
| 118 | c->cap = cfg; |
| 119 | _setup_mdp_ops(&c->ops, c->cap->features); |
| 120 | |
| 121 | /* |
| 122 | * Perform any default initialization for the intf |
| 123 | */ |
| 124 | return c; |
| 125 | } |
| 126 | |
| 127 | void sde_hw_mdp_destroy(struct sde_hw_mdp *mdp) |
| 128 | { |
Lloyd Atkinson | e5c2c0b | 2016-07-05 12:23:29 -0400 | [diff] [blame] | 129 | kfree(mdp); |
Abhijit Kulkarni | 94954d5 | 2016-06-24 18:27:48 -0400 | [diff] [blame] | 130 | } |
| 131 | |