Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/gpu/drm/ast/ast_main.c
26493 views
1
/*
2
* Copyright 2012 Red Hat Inc.
3
*
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the
6
* "Software"), to deal in the Software without restriction, including
7
* without limitation the rights to use, copy, modify, merge, publish,
8
* distribute, sub license, and/or sell copies of the Software, and to
9
* permit persons to whom the Software is furnished to do so, subject to
10
* the following conditions:
11
*
12
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
15
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
16
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
17
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
18
* USE OR OTHER DEALINGS IN THE SOFTWARE.
19
*
20
* The above copyright notice and this permission notice (including the
21
* next paragraph) shall be included in all copies or substantial portions
22
* of the Software.
23
*
24
*/
25
/*
26
* Authors: Dave Airlie <[email protected]>
27
*/
28
29
#include <linux/of.h>
30
#include <linux/pci.h>
31
32
#include <drm/drm_atomic_helper.h>
33
#include <drm/drm_drv.h>
34
#include <drm/drm_gem.h>
35
#include <drm/drm_managed.h>
36
37
#include "ast_drv.h"
38
39
/* Try to detect WSXGA+ on Gen2+ */
40
static bool __ast_2100_detect_wsxga_p(struct ast_device *ast)
41
{
42
u8 vgacrd0 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd0);
43
44
if (!(vgacrd0 & AST_IO_VGACRD0_VRAM_INIT_BY_BMC))
45
return true;
46
if (vgacrd0 & AST_IO_VGACRD0_IKVM_WIDESCREEN)
47
return true;
48
49
return false;
50
}
51
52
/* Try to detect WUXGA on Gen2+ */
53
static bool __ast_2100_detect_wuxga(struct ast_device *ast)
54
{
55
u8 vgacrd1;
56
57
if (ast->support_fullhd) {
58
vgacrd1 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd1);
59
if (!(vgacrd1 & AST_IO_VGACRD1_SUPPORTS_WUXGA))
60
return true;
61
}
62
63
return false;
64
}
65
66
static void ast_detect_widescreen(struct ast_device *ast)
67
{
68
ast->support_wsxga_p = false;
69
ast->support_fullhd = false;
70
ast->support_wuxga = false;
71
72
if (AST_GEN(ast) >= 7) {
73
ast->support_wsxga_p = true;
74
ast->support_fullhd = true;
75
if (__ast_2100_detect_wuxga(ast))
76
ast->support_wuxga = true;
77
} else if (AST_GEN(ast) >= 6) {
78
if (__ast_2100_detect_wsxga_p(ast))
79
ast->support_wsxga_p = true;
80
else if (ast->chip == AST2510)
81
ast->support_wsxga_p = true;
82
if (ast->support_wsxga_p)
83
ast->support_fullhd = true;
84
if (__ast_2100_detect_wuxga(ast))
85
ast->support_wuxga = true;
86
} else if (AST_GEN(ast) >= 5) {
87
if (__ast_2100_detect_wsxga_p(ast))
88
ast->support_wsxga_p = true;
89
else if (ast->chip == AST1400)
90
ast->support_wsxga_p = true;
91
if (ast->support_wsxga_p)
92
ast->support_fullhd = true;
93
if (__ast_2100_detect_wuxga(ast))
94
ast->support_wuxga = true;
95
} else if (AST_GEN(ast) >= 4) {
96
if (__ast_2100_detect_wsxga_p(ast))
97
ast->support_wsxga_p = true;
98
else if (ast->chip == AST1300)
99
ast->support_wsxga_p = true;
100
if (ast->support_wsxga_p)
101
ast->support_fullhd = true;
102
if (__ast_2100_detect_wuxga(ast))
103
ast->support_wuxga = true;
104
} else if (AST_GEN(ast) >= 3) {
105
if (__ast_2100_detect_wsxga_p(ast))
106
ast->support_wsxga_p = true;
107
if (ast->support_wsxga_p) {
108
if (ast->chip == AST2200)
109
ast->support_fullhd = true;
110
}
111
if (__ast_2100_detect_wuxga(ast))
112
ast->support_wuxga = true;
113
} else if (AST_GEN(ast) >= 2) {
114
if (__ast_2100_detect_wsxga_p(ast))
115
ast->support_wsxga_p = true;
116
if (ast->support_wsxga_p) {
117
if (ast->chip == AST2100)
118
ast->support_fullhd = true;
119
}
120
if (__ast_2100_detect_wuxga(ast))
121
ast->support_wuxga = true;
122
}
123
}
124
125
static void ast_detect_tx_chip(struct ast_device *ast, bool need_post)
126
{
127
static const char * const info_str[] = {
128
"analog VGA",
129
"Sil164 TMDS transmitter",
130
"DP501 DisplayPort transmitter",
131
"ASPEED DisplayPort transmitter",
132
};
133
134
struct drm_device *dev = &ast->base;
135
u8 vgacra3, vgacrd1;
136
137
/* Check 3rd Tx option (digital output afaik) */
138
ast->tx_chip = AST_TX_NONE;
139
140
if (AST_GEN(ast) <= 3) {
141
/*
142
* VGACRA3 Enhanced Color Mode Register, check if DVO is already
143
* enabled, in that case, assume we have a SIL164 TMDS transmitter
144
*
145
* Don't make that assumption if we the chip wasn't enabled and
146
* is at power-on reset, otherwise we'll incorrectly "detect" a
147
* SIL164 when there is none.
148
*/
149
if (!need_post) {
150
vgacra3 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xff);
151
if (vgacra3 & AST_IO_VGACRA3_DVO_ENABLED)
152
ast->tx_chip = AST_TX_SIL164;
153
}
154
} else {
155
/*
156
* On AST GEN4+, look at the configuration set by the SoC in
157
* the SOC scratch register #1 bits 11:8 (interestingly marked
158
* as "reserved" in the spec)
159
*/
160
vgacrd1 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1,
161
AST_IO_VGACRD1_TX_TYPE_MASK);
162
switch (vgacrd1) {
163
/*
164
* GEN4 to GEN6
165
*/
166
case AST_IO_VGACRD1_TX_SIL164_VBIOS:
167
ast->tx_chip = AST_TX_SIL164;
168
break;
169
case AST_IO_VGACRD1_TX_DP501_VBIOS:
170
ast->dp501_fw_addr = drmm_kzalloc(dev, 32*1024, GFP_KERNEL);
171
if (ast->dp501_fw_addr) {
172
/* backup firmware */
173
if (ast_backup_fw(ast, ast->dp501_fw_addr, 32*1024)) {
174
drmm_kfree(dev, ast->dp501_fw_addr);
175
ast->dp501_fw_addr = NULL;
176
}
177
}
178
fallthrough;
179
case AST_IO_VGACRD1_TX_FW_EMBEDDED_FW:
180
ast->tx_chip = AST_TX_DP501;
181
break;
182
/*
183
* GEN7+
184
*/
185
case AST_IO_VGACRD1_TX_ASTDP:
186
ast->tx_chip = AST_TX_ASTDP;
187
break;
188
/*
189
* Several of the listed TX chips are not explicitly supported
190
* by the ast driver. If these exist in real-world devices, they
191
* are most likely reported as VGA or SIL164 outputs. We warn here
192
* to get bug reports for these devices. If none come in for some
193
* time, we can begin to fail device probing on these values.
194
*/
195
case AST_IO_VGACRD1_TX_ITE66121_VBIOS:
196
drm_warn(dev, "ITE IT66121 detected, 0x%x, Gen%lu\n",
197
vgacrd1, AST_GEN(ast));
198
break;
199
case AST_IO_VGACRD1_TX_CH7003_VBIOS:
200
drm_warn(dev, "Chrontel CH7003 detected, 0x%x, Gen%lu\n",
201
vgacrd1, AST_GEN(ast));
202
break;
203
case AST_IO_VGACRD1_TX_ANX9807_VBIOS:
204
drm_warn(dev, "Analogix ANX9807 detected, 0x%x, Gen%lu\n",
205
vgacrd1, AST_GEN(ast));
206
break;
207
}
208
}
209
210
drm_info(dev, "Using %s\n", info_str[ast->tx_chip]);
211
}
212
213
static int ast_get_dram_info(struct ast_device *ast)
214
{
215
struct drm_device *dev = &ast->base;
216
struct device_node *np = dev->dev->of_node;
217
uint32_t mcr_cfg, mcr_scu_mpll, mcr_scu_strap;
218
uint32_t denum, num, div, ref_pll, dsel;
219
220
switch (ast->config_mode) {
221
case ast_use_dt:
222
/*
223
* If some properties are missing, use reasonable
224
* defaults for GEN5
225
*/
226
if (of_property_read_u32(np, "aspeed,mcr-configuration",
227
&mcr_cfg))
228
mcr_cfg = 0x00000577;
229
if (of_property_read_u32(np, "aspeed,mcr-scu-mpll",
230
&mcr_scu_mpll))
231
mcr_scu_mpll = 0x000050C0;
232
if (of_property_read_u32(np, "aspeed,mcr-scu-strap",
233
&mcr_scu_strap))
234
mcr_scu_strap = 0;
235
break;
236
case ast_use_p2a:
237
ast_write32(ast, 0xf004, 0x1e6e0000);
238
ast_write32(ast, 0xf000, 0x1);
239
mcr_cfg = ast_read32(ast, 0x10004);
240
mcr_scu_mpll = ast_read32(ast, 0x10120);
241
mcr_scu_strap = ast_read32(ast, 0x10170);
242
break;
243
case ast_use_defaults:
244
default:
245
ast->dram_bus_width = 16;
246
ast->dram_type = AST_DRAM_1Gx16;
247
if (IS_AST_GEN6(ast))
248
ast->mclk = 800;
249
else
250
ast->mclk = 396;
251
return 0;
252
}
253
254
if (mcr_cfg & 0x40)
255
ast->dram_bus_width = 16;
256
else
257
ast->dram_bus_width = 32;
258
259
if (IS_AST_GEN6(ast)) {
260
switch (mcr_cfg & 0x03) {
261
case 0:
262
ast->dram_type = AST_DRAM_1Gx16;
263
break;
264
default:
265
case 1:
266
ast->dram_type = AST_DRAM_2Gx16;
267
break;
268
case 2:
269
ast->dram_type = AST_DRAM_4Gx16;
270
break;
271
case 3:
272
ast->dram_type = AST_DRAM_8Gx16;
273
break;
274
}
275
} else if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast)) {
276
switch (mcr_cfg & 0x03) {
277
case 0:
278
ast->dram_type = AST_DRAM_512Mx16;
279
break;
280
default:
281
case 1:
282
ast->dram_type = AST_DRAM_1Gx16;
283
break;
284
case 2:
285
ast->dram_type = AST_DRAM_2Gx16;
286
break;
287
case 3:
288
ast->dram_type = AST_DRAM_4Gx16;
289
break;
290
}
291
} else {
292
switch (mcr_cfg & 0x0c) {
293
case 0:
294
case 4:
295
ast->dram_type = AST_DRAM_512Mx16;
296
break;
297
case 8:
298
if (mcr_cfg & 0x40)
299
ast->dram_type = AST_DRAM_1Gx16;
300
else
301
ast->dram_type = AST_DRAM_512Mx32;
302
break;
303
case 0xc:
304
ast->dram_type = AST_DRAM_1Gx32;
305
break;
306
}
307
}
308
309
if (mcr_scu_strap & 0x2000)
310
ref_pll = 14318;
311
else
312
ref_pll = 12000;
313
314
denum = mcr_scu_mpll & 0x1f;
315
num = (mcr_scu_mpll & 0x3fe0) >> 5;
316
dsel = (mcr_scu_mpll & 0xc000) >> 14;
317
switch (dsel) {
318
case 3:
319
div = 0x4;
320
break;
321
case 2:
322
case 1:
323
div = 0x2;
324
break;
325
default:
326
div = 0x1;
327
break;
328
}
329
ast->mclk = ref_pll * (num + 2) / ((denum + 2) * (div * 1000));
330
return 0;
331
}
332
333
struct drm_device *ast_device_create(struct pci_dev *pdev,
334
const struct drm_driver *drv,
335
enum ast_chip chip,
336
enum ast_config_mode config_mode,
337
void __iomem *regs,
338
void __iomem *ioregs,
339
bool need_post)
340
{
341
struct drm_device *dev;
342
struct ast_device *ast;
343
int ret;
344
345
ast = devm_drm_dev_alloc(&pdev->dev, drv, struct ast_device, base);
346
if (IS_ERR(ast))
347
return ERR_CAST(ast);
348
dev = &ast->base;
349
350
ast->chip = chip;
351
ast->config_mode = config_mode;
352
ast->regs = regs;
353
ast->ioregs = ioregs;
354
355
ret = ast_get_dram_info(ast);
356
if (ret)
357
return ERR_PTR(ret);
358
drm_info(dev, "dram MCLK=%u Mhz type=%d bus_width=%d\n",
359
ast->mclk, ast->dram_type, ast->dram_bus_width);
360
361
ast_detect_tx_chip(ast, need_post);
362
switch (ast->tx_chip) {
363
case AST_TX_ASTDP:
364
ret = ast_post_gpu(ast);
365
break;
366
default:
367
ret = 0;
368
if (need_post)
369
ret = ast_post_gpu(ast);
370
break;
371
}
372
if (ret)
373
return ERR_PTR(ret);
374
375
ret = ast_mm_init(ast);
376
if (ret)
377
return ERR_PTR(ret);
378
379
/* map reserved buffer */
380
ast->dp501_fw_buf = NULL;
381
if (ast->vram_size < pci_resource_len(pdev, 0)) {
382
ast->dp501_fw_buf = pci_iomap_range(pdev, 0, ast->vram_size, 0);
383
if (!ast->dp501_fw_buf)
384
drm_info(dev, "failed to map reserved buffer!\n");
385
}
386
387
ast_detect_widescreen(ast);
388
389
ret = ast_mode_config_init(ast);
390
if (ret)
391
return ERR_PTR(ret);
392
393
return dev;
394
}
395
396