]> Git Repo - linux.git/blob - drivers/gpu/drm/ast/ast_main.c
Merge branch 'pm-cpufreq'
[linux.git] / drivers / gpu / drm / ast / ast_main.c
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/pci.h>
30
31 #include <drm/drm_atomic_helper.h>
32 #include <drm/drm_drv.h>
33 #include <drm/drm_gem.h>
34 #include <drm/drm_managed.h>
35
36 #include "ast_drv.h"
37
38 static bool ast_is_vga_enabled(struct drm_device *dev)
39 {
40         struct ast_device *ast = to_ast_device(dev);
41         u8 ch;
42
43         ch = ast_io_read8(ast, AST_IO_VGAER);
44
45         return !!(ch & 0x01);
46 }
47
48 static void ast_enable_vga(struct drm_device *dev)
49 {
50         struct ast_device *ast = to_ast_device(dev);
51
52         ast_io_write8(ast, AST_IO_VGAER, 0x01);
53         ast_io_write8(ast, AST_IO_VGAMR_W, 0x01);
54 }
55
56 /*
57  * Run this function as part of the HW device cleanup; not
58  * when the DRM device gets released.
59  */
60 static void ast_enable_mmio_release(void *data)
61 {
62         struct ast_device *ast = data;
63
64         /* enable standard VGA decode */
65         ast_set_index_reg(ast, AST_IO_VGACRI, 0xa1, 0x04);
66 }
67
68 static int ast_enable_mmio(struct ast_device *ast)
69 {
70         struct drm_device *dev = &ast->base;
71
72         ast_set_index_reg(ast, AST_IO_VGACRI, 0xa1, 0x06);
73
74         return devm_add_action_or_reset(dev->dev, ast_enable_mmio_release, ast);
75 }
76
77 static void ast_open_key(struct ast_device *ast)
78 {
79         ast_set_index_reg(ast, AST_IO_VGACRI, 0x80, 0xA8);
80 }
81
82 static int ast_device_config_init(struct ast_device *ast)
83 {
84         struct drm_device *dev = &ast->base;
85         struct pci_dev *pdev = to_pci_dev(dev->dev);
86         struct device_node *np = dev->dev->of_node;
87         uint32_t scu_rev = 0xffffffff;
88         u32 data;
89         u8 jregd0, jregd1;
90
91         /*
92          * Find configuration mode and read SCU revision
93          */
94
95         ast->config_mode = ast_use_defaults;
96
97         /* Check if we have device-tree properties */
98         if (np && !of_property_read_u32(np, "aspeed,scu-revision-id", &data)) {
99                 /* We do, disable P2A access */
100                 ast->config_mode = ast_use_dt;
101                 scu_rev = data;
102         } else if (pdev->device == PCI_CHIP_AST2000) { // Not all families have a P2A bridge
103                 /*
104                  * The BMC will set SCU 0x40 D[12] to 1 if the P2 bridge
105                  * is disabled. We force using P2A if VGA only mode bit
106                  * is set D[7]
107                  */
108                 jregd0 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff);
109                 jregd1 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1, 0xff);
110                 if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) {
111
112                         /*
113                          * We have a P2A bridge and it is enabled.
114                          */
115
116                         /* Patch AST2500/AST2510 */
117                         if ((pdev->revision & 0xf0) == 0x40) {
118                                 if (!(jregd0 & AST_VRAM_INIT_STATUS_MASK))
119                                         ast_patch_ahb_2500(ast);
120                         }
121
122                         /* Double check that it's actually working */
123                         data = ast_read32(ast, 0xf004);
124                         if ((data != 0xffffffff) && (data != 0x00)) {
125                                 ast->config_mode = ast_use_p2a;
126
127                                 /* Read SCU7c (silicon revision register) */
128                                 ast_write32(ast, 0xf004, 0x1e6e0000);
129                                 ast_write32(ast, 0xf000, 0x1);
130                                 scu_rev = ast_read32(ast, 0x1207c);
131                         }
132                 }
133         }
134
135         switch (ast->config_mode) {
136         case ast_use_defaults:
137                 drm_info(dev, "Using default configuration\n");
138                 break;
139         case ast_use_dt:
140                 drm_info(dev, "Using device-tree for configuration\n");
141                 break;
142         case ast_use_p2a:
143                 drm_info(dev, "Using P2A bridge for configuration\n");
144                 break;
145         }
146
147         /*
148          * Identify chipset
149          */
150
151         if (pdev->revision >= 0x50) {
152                 ast->chip = AST2600;
153                 drm_info(dev, "AST 2600 detected\n");
154         } else if (pdev->revision >= 0x40) {
155                 switch (scu_rev & 0x300) {
156                 case 0x0100:
157                         ast->chip = AST2510;
158                         drm_info(dev, "AST 2510 detected\n");
159                         break;
160                 default:
161                         ast->chip = AST2500;
162                         drm_info(dev, "AST 2500 detected\n");
163                 }
164         } else if (pdev->revision >= 0x30) {
165                 switch (scu_rev & 0x300) {
166                 case 0x0100:
167                         ast->chip = AST1400;
168                         drm_info(dev, "AST 1400 detected\n");
169                         break;
170                 default:
171                         ast->chip = AST2400;
172                         drm_info(dev, "AST 2400 detected\n");
173                 }
174         } else if (pdev->revision >= 0x20) {
175                 switch (scu_rev & 0x300) {
176                 case 0x0000:
177                         ast->chip = AST1300;
178                         drm_info(dev, "AST 1300 detected\n");
179                         break;
180                 default:
181                         ast->chip = AST2300;
182                         drm_info(dev, "AST 2300 detected\n");
183                         break;
184                 }
185         } else if (pdev->revision >= 0x10) {
186                 switch (scu_rev & 0x0300) {
187                 case 0x0200:
188                         ast->chip = AST1100;
189                         drm_info(dev, "AST 1100 detected\n");
190                         break;
191                 case 0x0100:
192                         ast->chip = AST2200;
193                         drm_info(dev, "AST 2200 detected\n");
194                         break;
195                 case 0x0000:
196                         ast->chip = AST2150;
197                         drm_info(dev, "AST 2150 detected\n");
198                         break;
199                 default:
200                         ast->chip = AST2100;
201                         drm_info(dev, "AST 2100 detected\n");
202                         break;
203                 }
204         } else {
205                 ast->chip = AST2000;
206                 drm_info(dev, "AST 2000 detected\n");
207         }
208
209         return 0;
210 }
211
212 static void ast_detect_widescreen(struct ast_device *ast)
213 {
214         u8 jreg;
215
216         /* Check if we support wide screen */
217         switch (AST_GEN(ast)) {
218         case 1:
219                 ast->support_wide_screen = false;
220                 break;
221         default:
222                 jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff);
223                 if (!(jreg & 0x80))
224                         ast->support_wide_screen = true;
225                 else if (jreg & 0x01)
226                         ast->support_wide_screen = true;
227                 else {
228                         ast->support_wide_screen = false;
229                         if (ast->chip == AST1300)
230                                 ast->support_wide_screen = true;
231                         if (ast->chip == AST1400)
232                                 ast->support_wide_screen = true;
233                         if (ast->chip == AST2510)
234                                 ast->support_wide_screen = true;
235                         if (IS_AST_GEN7(ast))
236                                 ast->support_wide_screen = true;
237                 }
238                 break;
239         }
240 }
241
242 static void ast_detect_tx_chip(struct ast_device *ast, bool need_post)
243 {
244         struct drm_device *dev = &ast->base;
245         u8 jreg;
246
247         /* Check 3rd Tx option (digital output afaik) */
248         ast->tx_chip_types |= AST_TX_NONE_BIT;
249
250         /*
251          * VGACRA3 Enhanced Color Mode Register, check if DVO is already
252          * enabled, in that case, assume we have a SIL164 TMDS transmitter
253          *
254          * Don't make that assumption if we the chip wasn't enabled and
255          * is at power-on reset, otherwise we'll incorrectly "detect" a
256          * SIL164 when there is none.
257          */
258         if (!need_post) {
259                 jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xff);
260                 if (jreg & 0x80)
261                         ast->tx_chip_types = AST_TX_SIL164_BIT;
262         }
263
264         if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast) || IS_AST_GEN6(ast)) {
265                 /*
266                  * On AST GEN4+, look the configuration set by the SoC in
267                  * the SOC scratch register #1 bits 11:8 (interestingly marked
268                  * as "reserved" in the spec)
269                  */
270                 jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1, 0xff);
271                 switch (jreg) {
272                 case 0x04:
273                         ast->tx_chip_types = AST_TX_SIL164_BIT;
274                         break;
275                 case 0x08:
276                         ast->dp501_fw_addr = drmm_kzalloc(dev, 32*1024, GFP_KERNEL);
277                         if (ast->dp501_fw_addr) {
278                                 /* backup firmware */
279                                 if (ast_backup_fw(dev, ast->dp501_fw_addr, 32*1024)) {
280                                         drmm_kfree(dev, ast->dp501_fw_addr);
281                                         ast->dp501_fw_addr = NULL;
282                                 }
283                         }
284                         fallthrough;
285                 case 0x0c:
286                         ast->tx_chip_types = AST_TX_DP501_BIT;
287                 }
288         } else if (IS_AST_GEN7(ast)) {
289                 if (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xD1, TX_TYPE_MASK) ==
290                     ASTDP_DPMCU_TX) {
291                         ast->tx_chip_types = AST_TX_ASTDP_BIT;
292                         ast_dp_launch(&ast->base);
293                 }
294         }
295
296         /* Print stuff for diagnostic purposes */
297         if (ast->tx_chip_types & AST_TX_NONE_BIT)
298                 drm_info(dev, "Using analog VGA\n");
299         if (ast->tx_chip_types & AST_TX_SIL164_BIT)
300                 drm_info(dev, "Using Sil164 TMDS transmitter\n");
301         if (ast->tx_chip_types & AST_TX_DP501_BIT)
302                 drm_info(dev, "Using DP501 DisplayPort transmitter\n");
303         if (ast->tx_chip_types & AST_TX_ASTDP_BIT)
304                 drm_info(dev, "Using ASPEED DisplayPort transmitter\n");
305 }
306
307 static int ast_get_dram_info(struct drm_device *dev)
308 {
309         struct device_node *np = dev->dev->of_node;
310         struct ast_device *ast = to_ast_device(dev);
311         uint32_t mcr_cfg, mcr_scu_mpll, mcr_scu_strap;
312         uint32_t denum, num, div, ref_pll, dsel;
313
314         switch (ast->config_mode) {
315         case ast_use_dt:
316                 /*
317                  * If some properties are missing, use reasonable
318                  * defaults for GEN5
319                  */
320                 if (of_property_read_u32(np, "aspeed,mcr-configuration",
321                                          &mcr_cfg))
322                         mcr_cfg = 0x00000577;
323                 if (of_property_read_u32(np, "aspeed,mcr-scu-mpll",
324                                          &mcr_scu_mpll))
325                         mcr_scu_mpll = 0x000050C0;
326                 if (of_property_read_u32(np, "aspeed,mcr-scu-strap",
327                                          &mcr_scu_strap))
328                         mcr_scu_strap = 0;
329                 break;
330         case ast_use_p2a:
331                 ast_write32(ast, 0xf004, 0x1e6e0000);
332                 ast_write32(ast, 0xf000, 0x1);
333                 mcr_cfg = ast_read32(ast, 0x10004);
334                 mcr_scu_mpll = ast_read32(ast, 0x10120);
335                 mcr_scu_strap = ast_read32(ast, 0x10170);
336                 break;
337         case ast_use_defaults:
338         default:
339                 ast->dram_bus_width = 16;
340                 ast->dram_type = AST_DRAM_1Gx16;
341                 if (IS_AST_GEN6(ast))
342                         ast->mclk = 800;
343                 else
344                         ast->mclk = 396;
345                 return 0;
346         }
347
348         if (mcr_cfg & 0x40)
349                 ast->dram_bus_width = 16;
350         else
351                 ast->dram_bus_width = 32;
352
353         if (IS_AST_GEN6(ast)) {
354                 switch (mcr_cfg & 0x03) {
355                 case 0:
356                         ast->dram_type = AST_DRAM_1Gx16;
357                         break;
358                 default:
359                 case 1:
360                         ast->dram_type = AST_DRAM_2Gx16;
361                         break;
362                 case 2:
363                         ast->dram_type = AST_DRAM_4Gx16;
364                         break;
365                 case 3:
366                         ast->dram_type = AST_DRAM_8Gx16;
367                         break;
368                 }
369         } else if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast)) {
370                 switch (mcr_cfg & 0x03) {
371                 case 0:
372                         ast->dram_type = AST_DRAM_512Mx16;
373                         break;
374                 default:
375                 case 1:
376                         ast->dram_type = AST_DRAM_1Gx16;
377                         break;
378                 case 2:
379                         ast->dram_type = AST_DRAM_2Gx16;
380                         break;
381                 case 3:
382                         ast->dram_type = AST_DRAM_4Gx16;
383                         break;
384                 }
385         } else {
386                 switch (mcr_cfg & 0x0c) {
387                 case 0:
388                 case 4:
389                         ast->dram_type = AST_DRAM_512Mx16;
390                         break;
391                 case 8:
392                         if (mcr_cfg & 0x40)
393                                 ast->dram_type = AST_DRAM_1Gx16;
394                         else
395                                 ast->dram_type = AST_DRAM_512Mx32;
396                         break;
397                 case 0xc:
398                         ast->dram_type = AST_DRAM_1Gx32;
399                         break;
400                 }
401         }
402
403         if (mcr_scu_strap & 0x2000)
404                 ref_pll = 14318;
405         else
406                 ref_pll = 12000;
407
408         denum = mcr_scu_mpll & 0x1f;
409         num = (mcr_scu_mpll & 0x3fe0) >> 5;
410         dsel = (mcr_scu_mpll & 0xc000) >> 14;
411         switch (dsel) {
412         case 3:
413                 div = 0x4;
414                 break;
415         case 2:
416         case 1:
417                 div = 0x2;
418                 break;
419         default:
420                 div = 0x1;
421                 break;
422         }
423         ast->mclk = ref_pll * (num + 2) / ((denum + 2) * (div * 1000));
424         return 0;
425 }
426
427 struct ast_device *ast_device_create(const struct drm_driver *drv,
428                                      struct pci_dev *pdev,
429                                      unsigned long flags)
430 {
431         struct drm_device *dev;
432         struct ast_device *ast;
433         bool need_post = false;
434         int ret = 0;
435
436         ast = devm_drm_dev_alloc(&pdev->dev, drv, struct ast_device, base);
437         if (IS_ERR(ast))
438                 return ast;
439         dev = &ast->base;
440
441         pci_set_drvdata(pdev, dev);
442
443         ret = drmm_mutex_init(dev, &ast->ioregs_lock);
444         if (ret)
445                 return ERR_PTR(ret);
446
447         ast->regs = pcim_iomap(pdev, 1, 0);
448         if (!ast->regs)
449                 return ERR_PTR(-EIO);
450
451         /*
452          * After AST2500, MMIO is enabled by default, and it should be adopted
453          * to be compatible with Arm.
454          */
455         if (pdev->revision >= 0x40) {
456                 ast->ioregs = ast->regs + AST_IO_MM_OFFSET;
457         } else if (!(pci_resource_flags(pdev, 2) & IORESOURCE_IO)) {
458                 drm_info(dev, "platform has no IO space, trying MMIO\n");
459                 ast->ioregs = ast->regs + AST_IO_MM_OFFSET;
460         }
461
462         /* "map" IO regs if the above hasn't done so already */
463         if (!ast->ioregs) {
464                 ast->ioregs = pcim_iomap(pdev, 2, 0);
465                 if (!ast->ioregs)
466                         return ERR_PTR(-EIO);
467         }
468
469         if (!ast_is_vga_enabled(dev)) {
470                 drm_info(dev, "VGA not enabled on entry, requesting chip POST\n");
471                 need_post = true;
472         }
473
474         /*
475          * If VGA isn't enabled, we need to enable now or subsequent
476          * access to the scratch registers will fail.
477          */
478         if (need_post)
479                 ast_enable_vga(dev);
480
481         /* Enable extended register access */
482         ast_open_key(ast);
483         ret = ast_enable_mmio(ast);
484         if (ret)
485                 return ERR_PTR(ret);
486
487         ret = ast_device_config_init(ast);
488         if (ret)
489                 return ERR_PTR(ret);
490
491         ast_detect_widescreen(ast);
492         ast_detect_tx_chip(ast, need_post);
493
494         ret = ast_get_dram_info(dev);
495         if (ret)
496                 return ERR_PTR(ret);
497
498         drm_info(dev, "dram MCLK=%u Mhz type=%d bus_width=%d\n",
499                  ast->mclk, ast->dram_type, ast->dram_bus_width);
500
501         if (need_post)
502                 ast_post_gpu(dev);
503
504         ret = ast_mm_init(ast);
505         if (ret)
506                 return ERR_PTR(ret);
507
508         /* map reserved buffer */
509         ast->dp501_fw_buf = NULL;
510         if (ast->vram_size < pci_resource_len(pdev, 0)) {
511                 ast->dp501_fw_buf = pci_iomap_range(pdev, 0, ast->vram_size, 0);
512                 if (!ast->dp501_fw_buf)
513                         drm_info(dev, "failed to map reserved buffer!\n");
514         }
515
516         ret = ast_mode_config_init(ast);
517         if (ret)
518                 return ERR_PTR(ret);
519
520         return ast;
521 }
This page took 0.063538 seconds and 4 git commands to generate.