]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
drm/msm: add multiple CRTC and overlay support
[mirror_ubuntu-artful-kernel.git] / drivers / gpu / drm / msm / mdp / mdp5 / mdp5_cfg.c
CommitLineData
2e362e17
SV
1/*
2 * Copyright (c) 2014 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#include "mdp5_kms.h"
15#include "mdp5_cfg.h"
16
17struct mdp5_cfg_handler {
18 int revision;
19 struct mdp5_cfg config;
20};
21
22/* mdp5_cfg must be exposed (used in mdp5.xml.h) */
23const struct mdp5_cfg_hw *mdp5_cfg = NULL;
24
25const struct mdp5_cfg_hw msm8x74_config = {
26 .name = "msm8x74",
27 .smp = {
28 .mmb_count = 22,
29 .mmb_size = 4096,
30 },
31 .ctl = {
32 .count = 5,
33 .base = { 0x00600, 0x00700, 0x00800, 0x00900, 0x00a00 },
34 },
35 .pipe_vig = {
36 .count = 3,
37 .base = { 0x01200, 0x01600, 0x01a00 },
38 },
39 .pipe_rgb = {
40 .count = 3,
41 .base = { 0x01e00, 0x02200, 0x02600 },
42 },
43 .pipe_dma = {
44 .count = 2,
45 .base = { 0x02a00, 0x02e00 },
46 },
47 .lm = {
48 .count = 5,
49 .base = { 0x03200, 0x03600, 0x03a00, 0x03e00, 0x04200 },
50 .nb_stages = 5,
51 },
52 .dspp = {
53 .count = 3,
54 .base = { 0x04600, 0x04a00, 0x04e00 },
55 },
56 .ad = {
57 .count = 2,
58 .base = { 0x13100, 0x13300 }, /* NOTE: no ad in v1.0 */
59 },
60 .intf = {
61 .count = 4,
62 .base = { 0x12500, 0x12700, 0x12900, 0x12b00 },
63 },
64 .max_clk = 200000000,
65};
66
67const struct mdp5_cfg_hw apq8084_config = {
68 .name = "apq8084",
69 .smp = {
70 .mmb_count = 44,
71 .mmb_size = 8192,
72 .reserved_state[0] = GENMASK(7, 0), /* first 8 MMBs */
73 .reserved[CID_RGB0] = 2,
74 .reserved[CID_RGB1] = 2,
75 .reserved[CID_RGB2] = 2,
76 .reserved[CID_RGB3] = 2,
77 },
78 .ctl = {
79 .count = 5,
80 .base = { 0x00600, 0x00700, 0x00800, 0x00900, 0x00a00 },
81 },
82 .pipe_vig = {
83 .count = 4,
84 .base = { 0x01200, 0x01600, 0x01a00, 0x01e00 },
85 },
86 .pipe_rgb = {
87 .count = 4,
88 .base = { 0x02200, 0x02600, 0x02a00, 0x02e00 },
89 },
90 .pipe_dma = {
91 .count = 2,
92 .base = { 0x03200, 0x03600 },
93 },
94 .lm = {
95 .count = 6,
96 .base = { 0x03a00, 0x03e00, 0x04200, 0x04600, 0x04a00, 0x04e00 },
97 .nb_stages = 5,
98 },
99 .dspp = {
100 .count = 4,
101 .base = { 0x05200, 0x05600, 0x05a00, 0x05e00 },
102
103 },
104 .ad = {
105 .count = 3,
106 .base = { 0x13500, 0x13700, 0x13900 },
107 },
108 .intf = {
109 .count = 5,
110 .base = { 0x12500, 0x12700, 0x12900, 0x12b00, 0x12d00 },
111 },
112 .max_clk = 320000000,
113};
114
115static const struct mdp5_cfg_handler cfg_handlers[] = {
116 { .revision = 0, .config = { .hw = &msm8x74_config } },
117 { .revision = 2, .config = { .hw = &msm8x74_config } },
118 { .revision = 3, .config = { .hw = &apq8084_config } },
119};
120
121
122static struct mdp5_cfg_platform *mdp5_get_config(struct platform_device *dev);
123
124const struct mdp5_cfg_hw *mdp5_cfg_get_hw_config(void *cfg_hnd)
125{
126 struct mdp5_cfg_handler *cfg_handler = cfg_hnd;
127
128 return cfg_handler->config.hw;
129}
130
131struct mdp5_cfg *mdp5_cfg_get_config(void *cfg_hnd)
132{
133 struct mdp5_cfg_handler *cfg_handler = cfg_hnd;
134
135 return &cfg_handler->config;
136}
137
138int mdp5_cfg_get_hw_rev(void *cfg_hnd)
139{
140 struct mdp5_cfg_handler *cfg_handler = cfg_hnd;
141
142 return cfg_handler->revision;
143}
144
145void mdp5_cfg_destroy(void *cfg_hnd)
146{
147 struct mdp5_cfg_handler *cfg_handler = cfg_hnd;
148
149 kfree(cfg_handler);
150}
151
152void *mdp5_cfg_init(struct mdp5_kms *mdp5_kms,
153 uint32_t major, uint32_t minor)
154{
155 struct drm_device *dev = mdp5_kms->dev;
156 struct platform_device *pdev = dev->platformdev;
157 struct mdp5_cfg_handler *cfg_handler;
158 struct mdp5_cfg_platform *pconfig;
159 int i, ret = 0;
160
161 cfg_handler = kzalloc(sizeof(*cfg_handler), GFP_KERNEL);
162 if (unlikely(!cfg_handler)) {
163 ret = -ENOMEM;
164 goto fail;
165 }
166
167 if (major != 1) {
168 dev_err(dev->dev, "unexpected MDP major version: v%d.%d\n",
169 major, minor);
170 ret = -ENXIO;
171 goto fail;
172 }
173
174 /* only after mdp5_cfg global pointer's init can we access the hw */
175 for (i = 0; i < ARRAY_SIZE(cfg_handlers); i++) {
176 if (cfg_handlers[i].revision != minor)
177 continue;
178 mdp5_cfg = cfg_handlers[i].config.hw;
179
180 break;
181 }
182 if (unlikely(!mdp5_cfg)) {
183 dev_err(dev->dev, "unexpected MDP minor revision: v%d.%d\n",
184 major, minor);
185 ret = -ENXIO;
186 goto fail;
187 }
188
189 cfg_handler->revision = minor;
190 cfg_handler->config.hw = mdp5_cfg;
191
192 pconfig = mdp5_get_config(pdev);
193 memcpy(&cfg_handler->config.platform, pconfig, sizeof(*pconfig));
194
195 DBG("MDP5: %s hw config selected", mdp5_cfg->name);
196
197 return cfg_handler;
198
199fail:
200 if (cfg_handler)
201 mdp5_cfg_destroy(cfg_handler);
202
203 return NULL;
204}
205
206static struct mdp5_cfg_platform *mdp5_get_config(struct platform_device *dev)
207{
208 static struct mdp5_cfg_platform config = {};
209#ifdef CONFIG_OF
210 /* TODO */
211#endif
212 config.iommu = iommu_domain_alloc(&platform_bus_type);
213
214 return &config;
215}