brintos

brintos / linux-shallow public Read only

0
0
Text · 7.2 KiB · 9f59256 Raw
310 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright 2012 Red Hat4 *5 * Authors: Matthew Garrett6 *          Dave Airlie7 */8 9#include <linux/module.h>10#include <linux/pci.h>11 12#include <drm/drm_aperture.h>13#include <drm/drm_atomic_helper.h>14#include <drm/drm_drv.h>15#include <drm/drm_fbdev_shmem.h>16#include <drm/drm_file.h>17#include <drm/drm_ioctl.h>18#include <drm/drm_managed.h>19#include <drm/drm_module.h>20#include <drm/drm_pciids.h>21 22#include "mgag200_drv.h"23 24static int mgag200_modeset = -1;25MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");26module_param_named(modeset, mgag200_modeset, int, 0400);27 28int mgag200_init_pci_options(struct pci_dev *pdev, u32 option, u32 option2)29{30	struct device *dev = &pdev->dev;31	int err;32 33	err = pci_write_config_dword(pdev, PCI_MGA_OPTION, option);34	if (err != PCIBIOS_SUCCESSFUL) {35		dev_err(dev, "pci_write_config_dword(PCI_MGA_OPTION) failed: %d\n", err);36		return pcibios_err_to_errno(err);37	}38 39	err = pci_write_config_dword(pdev, PCI_MGA_OPTION2, option2);40	if (err != PCIBIOS_SUCCESSFUL) {41		dev_err(dev, "pci_write_config_dword(PCI_MGA_OPTION2) failed: %d\n", err);42		return pcibios_err_to_errno(err);43	}44 45	return 0;46}47 48resource_size_t mgag200_probe_vram(void __iomem *mem, resource_size_t size)49{50	int offset;51	int orig;52	int test1, test2;53	int orig1, orig2;54	size_t vram_size;55 56	/* Probe */57	orig = ioread16(mem);58	iowrite16(0, mem);59 60	vram_size = size;61 62	for (offset = 0x100000; offset < vram_size; offset += 0x4000) {63		orig1 = ioread8(mem + offset);64		orig2 = ioread8(mem + offset + 0x100);65 66		iowrite16(0xaa55, mem + offset);67		iowrite16(0xaa55, mem + offset + 0x100);68 69		test1 = ioread16(mem + offset);70		test2 = ioread16(mem);71 72		iowrite16(orig1, mem + offset);73		iowrite16(orig2, mem + offset + 0x100);74 75		if (test1 != 0xaa55)76			break;77 78		if (test2)79			break;80	}81 82	iowrite16(orig, mem);83 84	return offset - 65536;85}86 87/*88 * DRM driver89 */90 91DEFINE_DRM_GEM_FOPS(mgag200_driver_fops);92 93static const struct drm_driver mgag200_driver = {94	.driver_features = DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET,95	.fops = &mgag200_driver_fops,96	.name = DRIVER_NAME,97	.desc = DRIVER_DESC,98	.date = DRIVER_DATE,99	.major = DRIVER_MAJOR,100	.minor = DRIVER_MINOR,101	.patchlevel = DRIVER_PATCHLEVEL,102	DRM_GEM_SHMEM_DRIVER_OPS,103};104 105/*106 * DRM device107 */108 109resource_size_t mgag200_device_probe_vram(struct mga_device *mdev)110{111	return mgag200_probe_vram(mdev->vram, resource_size(mdev->vram_res));112}113 114int mgag200_device_preinit(struct mga_device *mdev)115{116	struct drm_device *dev = &mdev->base;117	struct pci_dev *pdev = to_pci_dev(dev->dev);118	resource_size_t start, len;119	struct resource *res;120 121	/* BAR 1 contains registers */122 123	start = pci_resource_start(pdev, 1);124	len = pci_resource_len(pdev, 1);125 126	res = devm_request_mem_region(dev->dev, start, len, "mgadrmfb_mmio");127	if (!res) {128		drm_err(dev, "devm_request_mem_region(MMIO) failed\n");129		return -ENXIO;130	}131	mdev->rmmio_res = res;132 133	mdev->rmmio = pcim_iomap(pdev, 1, 0);134	if (!mdev->rmmio)135		return -ENOMEM;136 137	/* BAR 0 is VRAM */138 139	start = pci_resource_start(pdev, 0);140	len = pci_resource_len(pdev, 0);141 142	res = devm_request_mem_region(dev->dev, start, len, "mgadrmfb_vram");143	if (!res) {144		drm_err(dev, "devm_request_mem_region(VRAM) failed\n");145		return -ENXIO;146	}147	mdev->vram_res = res;148 149#if defined(CONFIG_DRM_MGAG200_DISABLE_WRITECOMBINE)150	mdev->vram = devm_ioremap(dev->dev, res->start, resource_size(res));151	if (!mdev->vram)152		return -ENOMEM;153#else154	mdev->vram = devm_ioremap_wc(dev->dev, res->start, resource_size(res));155	if (!mdev->vram)156		return -ENOMEM;157 158	/* Don't fail on errors, but performance might be reduced. */159	devm_arch_phys_wc_add(dev->dev, res->start, resource_size(res));160#endif161 162	return 0;163}164 165int mgag200_device_init(struct mga_device *mdev,166			const struct mgag200_device_info *info,167			const struct mgag200_device_funcs *funcs)168{169	struct drm_device *dev = &mdev->base;170	u8 crtcext3, misc;171	int ret;172 173	mdev->info = info;174	mdev->funcs = funcs;175 176	ret = drmm_mutex_init(dev, &mdev->rmmio_lock);177	if (ret)178		return ret;179 180	mutex_lock(&mdev->rmmio_lock);181 182	RREG_ECRT(0x03, crtcext3);183	crtcext3 |= MGAREG_CRTCEXT3_MGAMODE;184	WREG_ECRT(0x03, crtcext3);185 186	WREG_ECRT(0x04, 0x00);187 188	misc = RREG8(MGA_MISC_IN);189	misc |= MGAREG_MISC_RAMMAPEN |190		MGAREG_MISC_HIGH_PG_SEL;191	WREG8(MGA_MISC_OUT, misc);192 193	mutex_unlock(&mdev->rmmio_lock);194 195	WREG32(MGAREG_IEN, 0);196 197	return 0;198}199 200/*201 * PCI driver202 */203 204static const struct pci_device_id mgag200_pciidlist[] = {205	{ PCI_VENDOR_ID_MATROX, 0x520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_PCI },206	{ PCI_VENDOR_ID_MATROX, 0x521, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_AGP },207	{ PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_A },208	{ PCI_VENDOR_ID_MATROX, 0x524, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_B },209	{ PCI_VENDOR_ID_MATROX, 0x530, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EV },210	{ PCI_VENDOR_ID_MATROX, 0x532, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_WB },211	{ PCI_VENDOR_ID_MATROX, 0x533, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EH },212	{ PCI_VENDOR_ID_MATROX, 0x534, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_ER },213	{ PCI_VENDOR_ID_MATROX, 0x536, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EW3 },214	{ PCI_VENDOR_ID_MATROX, 0x538, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EH3 },215	{0,}216};217 218MODULE_DEVICE_TABLE(pci, mgag200_pciidlist);219 220static int221mgag200_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)222{223	enum mga_type type = (enum mga_type)ent->driver_data;224	struct mga_device *mdev;225	struct drm_device *dev;226	int ret;227 228	ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &mgag200_driver);229	if (ret)230		return ret;231 232	ret = pcim_enable_device(pdev);233	if (ret)234		return ret;235 236	switch (type) {237	case G200_PCI:238	case G200_AGP:239		mdev = mgag200_g200_device_create(pdev, &mgag200_driver);240		break;241	case G200_SE_A:242	case G200_SE_B:243		mdev = mgag200_g200se_device_create(pdev, &mgag200_driver, type);244		break;245	case G200_WB:246		mdev = mgag200_g200wb_device_create(pdev, &mgag200_driver);247		break;248	case G200_EV:249		mdev = mgag200_g200ev_device_create(pdev, &mgag200_driver);250		break;251	case G200_EH:252		mdev = mgag200_g200eh_device_create(pdev, &mgag200_driver);253		break;254	case G200_EH3:255		mdev = mgag200_g200eh3_device_create(pdev, &mgag200_driver);256		break;257	case G200_ER:258		mdev = mgag200_g200er_device_create(pdev, &mgag200_driver);259		break;260	case G200_EW3:261		mdev = mgag200_g200ew3_device_create(pdev, &mgag200_driver);262		break;263	default:264		dev_err(&pdev->dev, "Device type %d is unsupported\n", type);265		return -ENODEV;266	}267	if (IS_ERR(mdev))268		return PTR_ERR(mdev);269	dev = &mdev->base;270 271	ret = drm_dev_register(dev, 0);272	if (ret)273		return ret;274 275	/*276	 * FIXME: A 24-bit color depth does not work with 24 bpp on277	 * G200ER. Force 32 bpp.278	 */279	drm_fbdev_shmem_setup(dev, 32);280 281	return 0;282}283 284static void mgag200_pci_remove(struct pci_dev *pdev)285{286	struct drm_device *dev = pci_get_drvdata(pdev);287 288	drm_dev_unregister(dev);289	drm_atomic_helper_shutdown(dev);290}291 292static void mgag200_pci_shutdown(struct pci_dev *pdev)293{294	drm_atomic_helper_shutdown(pci_get_drvdata(pdev));295}296 297static struct pci_driver mgag200_pci_driver = {298	.name = DRIVER_NAME,299	.id_table = mgag200_pciidlist,300	.probe = mgag200_pci_probe,301	.remove = mgag200_pci_remove,302	.shutdown = mgag200_pci_shutdown,303};304 305drm_module_pci_driver_if_modeset(mgag200_pci_driver, mgag200_modeset);306 307MODULE_AUTHOR(DRIVER_AUTHOR);308MODULE_DESCRIPTION(DRIVER_DESC);309MODULE_LICENSE("GPL");310