1 // SPDX-License-Identifier: GPL-2.0-only 2 3 #include <linux/pci.h> 4 5 #include <drm/drm_drv.h> 6 7 #include "mgag200_drv.h" 8 9 static int mgag200_g200se_init_pci_options(struct pci_dev *pdev) 10 { 11 struct device *dev = &pdev->dev; 12 bool has_sgram; 13 u32 option; 14 int err; 15 16 err = pci_read_config_dword(pdev, PCI_MGA_OPTION, &option); 17 if (err != PCIBIOS_SUCCESSFUL) { 18 dev_err(dev, "pci_read_config_dword(PCI_MGA_OPTION) failed: %d\n", err); 19 return pcibios_err_to_errno(err); 20 } 21 22 has_sgram = !!(option & PCI_MGA_OPTION_HARDPWMSK); 23 24 option = 0x40049120; 25 if (has_sgram) 26 option |= PCI_MGA_OPTION_HARDPWMSK; 27 28 return mgag200_init_pci_options(pdev, option, 0x00008000); 29 } 30 31 /* 32 * DRM device 33 */ 34 35 static const struct mgag200_device_info mgag200_g200se_a_01_device_info = 36 MGAG200_DEVICE_INFO_INIT(1600, 1200, 24400, false, 0, 1, true); 37 38 static const struct mgag200_device_info mgag200_g200se_a_02_device_info = 39 MGAG200_DEVICE_INFO_INIT(1920, 1200, 30100, false, 0, 1, true); 40 41 static const struct mgag200_device_info mgag200_g200se_a_03_device_info = 42 MGAG200_DEVICE_INFO_INIT(2048, 2048, 55000, false, 0, 1, false); 43 44 static const struct mgag200_device_info mgag200_g200se_b_01_device_info = 45 MGAG200_DEVICE_INFO_INIT(1600, 1200, 24400, false, 0, 1, false); 46 47 static const struct mgag200_device_info mgag200_g200se_b_02_device_info = 48 MGAG200_DEVICE_INFO_INIT(1920, 1200, 30100, false, 0, 1, false); 49 50 static const struct mgag200_device_info mgag200_g200se_b_03_device_info = 51 MGAG200_DEVICE_INFO_INIT(2048, 2048, 55000, false, 0, 1, false); 52 53 static int mgag200_g200se_init_unique_rev_id(struct mgag200_g200se_device *g200se) 54 { 55 struct mga_device *mdev = &g200se->base; 56 struct drm_device *dev = &mdev->base; 57 58 /* stash G200 SE model number for later use */ 59 g200se->unique_rev_id = RREG32(0x1e24); 60 if (!g200se->unique_rev_id) 61 return -ENODEV; 62 63 drm_dbg(dev, "G200 SE unique revision id is 0x%x\n", g200se->unique_rev_id); 64 65 return 0; 66 } 67 68 struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv, 69 enum mga_type type) 70 { 71 struct mgag200_g200se_device *g200se; 72 const struct mgag200_device_info *info; 73 struct mga_device *mdev; 74 struct drm_device *dev; 75 resource_size_t vram_available; 76 int ret; 77 78 g200se = devm_drm_dev_alloc(&pdev->dev, drv, struct mgag200_g200se_device, base.base); 79 if (IS_ERR(g200se)) 80 return ERR_CAST(g200se); 81 mdev = &g200se->base; 82 dev = &mdev->base; 83 84 pci_set_drvdata(pdev, dev); 85 86 ret = mgag200_g200se_init_pci_options(pdev); 87 if (ret) 88 return ERR_PTR(ret); 89 90 ret = mgag200_device_preinit(mdev); 91 if (ret) 92 return ERR_PTR(ret); 93 94 ret = mgag200_g200se_init_unique_rev_id(g200se); 95 if (ret) 96 return ERR_PTR(ret); 97 98 switch (type) { 99 case G200_SE_A: 100 if (g200se->unique_rev_id >= 0x03) 101 info = &mgag200_g200se_a_03_device_info; 102 else if (g200se->unique_rev_id >= 0x02) 103 info = &mgag200_g200se_a_02_device_info; 104 else 105 info = &mgag200_g200se_a_01_device_info; 106 break; 107 case G200_SE_B: 108 if (g200se->unique_rev_id >= 0x03) 109 info = &mgag200_g200se_b_03_device_info; 110 else if (g200se->unique_rev_id >= 0x02) 111 info = &mgag200_g200se_b_02_device_info; 112 else 113 info = &mgag200_g200se_b_01_device_info; 114 break; 115 default: 116 return ERR_PTR(-EINVAL); 117 } 118 119 ret = mgag200_device_init(mdev, type, info); 120 if (ret) 121 return ERR_PTR(ret); 122 123 vram_available = mgag200_device_probe_vram(mdev); 124 125 ret = mgag200_modeset_init(mdev, vram_available); 126 if (ret) 127 return ERR_PTR(ret); 128 129 return mdev; 130 } 131