blob: 82a8fcdcaf81ae4f8f4c1d8669c87c28034c497c [file] [log] [blame]
Abhijit Kulkarni94954d52016-06-24 18:27:48 -04001/* 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 Ipc475b082016-06-26 09:27:23 -040015#include "sde_hw_top.h"
Abhijit Kulkarni94954d52016-06-24 18:27:48 -040016
Abhijit Kulkarni43eafcc2016-06-28 17:48:41 -040017#define SSPP_SPARE 0x24
Abhijit Kulkarni94954d52016-06-24 18:27:48 -040018#define SPLIT_DISPLAY_ENABLE 0x2F4
Abhijit Kulkarni43eafcc2016-06-28 17:48:41 -040019
Abhijit Kulkarni94954d52016-06-24 18:27:48 -040020#define LOWER_PIPE_CTRL 0x2F8
Abhijit Kulkarni43eafcc2016-06-28 17:48:41 -040021#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 Kulkarni94954d52016-06-24 18:27:48 -040027#define UPPER_PIPE_CTRL 0x3F0
28#define TE_LINE_INTERVAL 0x3F4
29
30static void sde_hw_setup_split_pipe_control(struct sde_hw_mdp *mdp,
Abhijit Kulkarni43eafcc2016-06-28 17:48:41 -040031 struct split_pipe_cfg *cfg)
Abhijit Kulkarni94954d52016-06-24 18:27:48 -040032{
33 struct sde_hw_blk_reg_map *c = &mdp->hw;
Abhijit Kulkarni43eafcc2016-06-28 17:48:41 -040034 u32 upper_pipe = 0;
35 u32 lower_pipe = 0;
Abhijit Kulkarni94954d52016-06-24 18:27:48 -040036
37 if (cfg->en) {
Abhijit Kulkarni94954d52016-06-24 18:27:48 -040038 if (cfg->mode == INTF_MODE_CMD) {
Abhijit Kulkarni43eafcc2016-06-28 17:48:41 -040039 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 Kulkarni94954d52016-06-24 18:27:48 -040045
Abhijit Kulkarni43eafcc2016-06-28 17:48:41 -040046 /* 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 Kulkarni94954d52016-06-24 18:27:48 -040060 }
61
Abhijit Kulkarni43eafcc2016-06-28 17:48:41 -040062 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 Kulkarni94954d52016-06-24 18:27:48 -040065 SDE_REG_WRITE(c, SPLIT_DISPLAY_ENABLE, cfg->en & 0x1);
66}
67
68static 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
74static 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
93struct 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 Kulkarni7acb3262016-07-05 15:27:25 -0400101 if (c)
Abhijit Kulkarni94954d52016-06-24 18:27:48 -0400102 return c;
Abhijit Kulkarni94954d52016-06-24 18:27:48 -0400103
104 c = kzalloc(sizeof(*c), GFP_KERNEL);
Abhijit Kulkarni94954d52016-06-24 18:27:48 -0400105 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
127void sde_hw_mdp_destroy(struct sde_hw_mdp *mdp)
128{
Lloyd Atkinsone5c2c0b2016-07-05 12:23:29 -0400129 kfree(mdp);
Abhijit Kulkarni94954d52016-06-24 18:27:48 -0400130}
131