diff options
Diffstat (limited to 'drivers/gpu/drm/bochs/bochs_hw.c')
-rw-r--r-- | drivers/gpu/drm/bochs/bochs_hw.c | 323 |
1 files changed, 0 insertions, 323 deletions
diff --git a/drivers/gpu/drm/bochs/bochs_hw.c b/drivers/gpu/drm/bochs/bochs_hw.c deleted file mode 100644 index 7d3426d8cc69..000000000000 --- a/drivers/gpu/drm/bochs/bochs_hw.c +++ /dev/null @@ -1,323 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - */ - -#include <linux/pci.h> - -#include <drm/drm_drv.h> -#include <drm/drm_fourcc.h> - -#include <video/vga.h> -#include "bochs.h" - -/* ---------------------------------------------------------------------- */ - -static void bochs_vga_writeb(struct bochs_device *bochs, u16 ioport, u8 val) -{ - if (WARN_ON(ioport < 0x3c0 || ioport > 0x3df)) - return; - - if (bochs->mmio) { - int offset = ioport - 0x3c0 + 0x400; - writeb(val, bochs->mmio + offset); - } else { - outb(val, ioport); - } -} - -static u8 bochs_vga_readb(struct bochs_device *bochs, u16 ioport) -{ - if (WARN_ON(ioport < 0x3c0 || ioport > 0x3df)) - return 0xff; - - if (bochs->mmio) { - int offset = ioport - 0x3c0 + 0x400; - return readb(bochs->mmio + offset); - } else { - return inb(ioport); - } -} - -static u16 bochs_dispi_read(struct bochs_device *bochs, u16 reg) -{ - u16 ret = 0; - - if (bochs->mmio) { - int offset = 0x500 + (reg << 1); - ret = readw(bochs->mmio + offset); - } else { - outw(reg, VBE_DISPI_IOPORT_INDEX); - ret = inw(VBE_DISPI_IOPORT_DATA); - } - return ret; -} - -static void bochs_dispi_write(struct bochs_device *bochs, u16 reg, u16 val) -{ - if (bochs->mmio) { - int offset = 0x500 + (reg << 1); - writew(val, bochs->mmio + offset); - } else { - outw(reg, VBE_DISPI_IOPORT_INDEX); - outw(val, VBE_DISPI_IOPORT_DATA); - } -} - -static void bochs_hw_set_big_endian(struct bochs_device *bochs) -{ - if (bochs->qext_size < 8) - return; - - writel(0xbebebebe, bochs->mmio + 0x604); -} - -static void bochs_hw_set_little_endian(struct bochs_device *bochs) -{ - if (bochs->qext_size < 8) - return; - - writel(0x1e1e1e1e, bochs->mmio + 0x604); -} - -#ifdef __BIG_ENDIAN -#define bochs_hw_set_native_endian(_b) bochs_hw_set_big_endian(_b) -#else -#define bochs_hw_set_native_endian(_b) bochs_hw_set_little_endian(_b) -#endif - -static int bochs_get_edid_block(void *data, u8 *buf, - unsigned int block, size_t len) -{ - struct bochs_device *bochs = data; - size_t i, start = block * EDID_LENGTH; - - if (start + len > 0x400 /* vga register offset */) - return -1; - - for (i = 0; i < len; i++) { - buf[i] = readb(bochs->mmio + start + i); - } - return 0; -} - -int bochs_hw_load_edid(struct bochs_device *bochs) -{ - u8 header[8]; - - if (!bochs->mmio) - return -1; - - /* check header to detect whenever edid support is enabled in qemu */ - bochs_get_edid_block(bochs, header, 0, ARRAY_SIZE(header)); - if (drm_edid_header_is_valid(header) != 8) - return -1; - - kfree(bochs->edid); - bochs->edid = drm_do_get_edid(&bochs->connector, - bochs_get_edid_block, bochs); - if (bochs->edid == NULL) - return -1; - - return 0; -} - -int bochs_hw_init(struct drm_device *dev) -{ - struct bochs_device *bochs = dev->dev_private; - struct pci_dev *pdev = to_pci_dev(dev->dev); - unsigned long addr, size, mem, ioaddr, iosize; - u16 id; - - if (pdev->resource[2].flags & IORESOURCE_MEM) { - /* mmio bar with vga and bochs registers present */ - if (pci_request_region(pdev, 2, "bochs-drm") != 0) { - DRM_ERROR("Cannot request mmio region\n"); - return -EBUSY; - } - ioaddr = pci_resource_start(pdev, 2); - iosize = pci_resource_len(pdev, 2); - bochs->mmio = ioremap(ioaddr, iosize); - if (bochs->mmio == NULL) { - DRM_ERROR("Cannot map mmio region\n"); - return -ENOMEM; - } - } else { - ioaddr = VBE_DISPI_IOPORT_INDEX; - iosize = 2; - if (!request_region(ioaddr, iosize, "bochs-drm")) { - DRM_ERROR("Cannot request ioports\n"); - return -EBUSY; - } - bochs->ioports = 1; - } - - id = bochs_dispi_read(bochs, VBE_DISPI_INDEX_ID); - mem = bochs_dispi_read(bochs, VBE_DISPI_INDEX_VIDEO_MEMORY_64K) - * 64 * 1024; - if ((id & 0xfff0) != VBE_DISPI_ID0) { - DRM_ERROR("ID mismatch\n"); - return -ENODEV; - } - - if ((pdev->resource[0].flags & IORESOURCE_MEM) == 0) - return -ENODEV; - addr = pci_resource_start(pdev, 0); - size = pci_resource_len(pdev, 0); - if (addr == 0) - return -ENODEV; - if (size != mem) { - DRM_ERROR("Size mismatch: pci=%ld, bochs=%ld\n", - size, mem); - size = min(size, mem); - } - - if (pci_request_region(pdev, 0, "bochs-drm") != 0) - DRM_WARN("Cannot request framebuffer, boot fb still active?\n"); - - bochs->fb_map = ioremap(addr, size); - if (bochs->fb_map == NULL) { - DRM_ERROR("Cannot map framebuffer\n"); - return -ENOMEM; - } - bochs->fb_base = addr; - bochs->fb_size = size; - - DRM_INFO("Found bochs VGA, ID 0x%x.\n", id); - DRM_INFO("Framebuffer size %ld kB @ 0x%lx, %s @ 0x%lx.\n", - size / 1024, addr, - bochs->ioports ? "ioports" : "mmio", - ioaddr); - - if (bochs->mmio && pdev->revision >= 2) { - bochs->qext_size = readl(bochs->mmio + 0x600); - if (bochs->qext_size < 4 || bochs->qext_size > iosize) { - bochs->qext_size = 0; - goto noext; - } - DRM_DEBUG("Found qemu ext regs, size %ld\n", - bochs->qext_size); - bochs_hw_set_native_endian(bochs); - } - -noext: - return 0; -} - -void bochs_hw_fini(struct drm_device *dev) -{ - struct bochs_device *bochs = dev->dev_private; - - /* TODO: shot down existing vram mappings */ - - if (bochs->mmio) - iounmap(bochs->mmio); - if (bochs->ioports) - release_region(VBE_DISPI_IOPORT_INDEX, 2); - if (bochs->fb_map) - iounmap(bochs->fb_map); - pci_release_regions(to_pci_dev(dev->dev)); - kfree(bochs->edid); -} - -void bochs_hw_blank(struct bochs_device *bochs, bool blank) -{ - DRM_DEBUG_DRIVER("hw_blank %d\n", blank); - /* discard ar_flip_flop */ - (void)bochs_vga_readb(bochs, VGA_IS1_RC); - /* blank or unblank; we need only update index and set 0x20 */ - bochs_vga_writeb(bochs, VGA_ATT_W, blank ? 0 : 0x20); -} - -void bochs_hw_setmode(struct bochs_device *bochs, - struct drm_display_mode *mode) -{ - int idx; - - if (!drm_dev_enter(bochs->dev, &idx)) - return; - - bochs->xres = mode->hdisplay; - bochs->yres = mode->vdisplay; - bochs->bpp = 32; - bochs->stride = mode->hdisplay * (bochs->bpp / 8); - bochs->yres_virtual = bochs->fb_size / bochs->stride; - - DRM_DEBUG_DRIVER("%dx%d @ %d bpp, vy %d\n", - bochs->xres, bochs->yres, bochs->bpp, - bochs->yres_virtual); - - bochs_hw_blank(bochs, false); - - bochs_dispi_write(bochs, VBE_DISPI_INDEX_ENABLE, 0); - bochs_dispi_write(bochs, VBE_DISPI_INDEX_BPP, bochs->bpp); - bochs_dispi_write(bochs, VBE_DISPI_INDEX_XRES, bochs->xres); - bochs_dispi_write(bochs, VBE_DISPI_INDEX_YRES, bochs->yres); - bochs_dispi_write(bochs, VBE_DISPI_INDEX_BANK, 0); - bochs_dispi_write(bochs, VBE_DISPI_INDEX_VIRT_WIDTH, bochs->xres); - bochs_dispi_write(bochs, VBE_DISPI_INDEX_VIRT_HEIGHT, - bochs->yres_virtual); - bochs_dispi_write(bochs, VBE_DISPI_INDEX_X_OFFSET, 0); - bochs_dispi_write(bochs, VBE_DISPI_INDEX_Y_OFFSET, 0); - - bochs_dispi_write(bochs, VBE_DISPI_INDEX_ENABLE, - VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED); - - drm_dev_exit(idx); -} - -void bochs_hw_setformat(struct bochs_device *bochs, - const struct drm_format_info *format) -{ - int idx; - - if (!drm_dev_enter(bochs->dev, &idx)) - return; - - DRM_DEBUG_DRIVER("format %c%c%c%c\n", - (format->format >> 0) & 0xff, - (format->format >> 8) & 0xff, - (format->format >> 16) & 0xff, - (format->format >> 24) & 0xff); - - switch (format->format) { - case DRM_FORMAT_XRGB8888: - bochs_hw_set_little_endian(bochs); - break; - case DRM_FORMAT_BGRX8888: - bochs_hw_set_big_endian(bochs); - break; - default: - /* should not happen */ - DRM_ERROR("%s: Huh? Got framebuffer format 0x%x", - __func__, format->format); - break; - } - - drm_dev_exit(idx); -} - -void bochs_hw_setbase(struct bochs_device *bochs, - int x, int y, int stride, u64 addr) -{ - unsigned long offset; - unsigned int vx, vy, vwidth, idx; - - if (!drm_dev_enter(bochs->dev, &idx)) - return; - - bochs->stride = stride; - offset = (unsigned long)addr + - y * bochs->stride + - x * (bochs->bpp / 8); - vy = offset / bochs->stride; - vx = (offset % bochs->stride) * 8 / bochs->bpp; - vwidth = stride * 8 / bochs->bpp; - - DRM_DEBUG_DRIVER("x %d, y %d, addr %llx -> offset %lx, vx %d, vy %d\n", - x, y, addr, offset, vx, vy); - bochs_dispi_write(bochs, VBE_DISPI_INDEX_VIRT_WIDTH, vwidth); - bochs_dispi_write(bochs, VBE_DISPI_INDEX_X_OFFSET, vx); - bochs_dispi_write(bochs, VBE_DISPI_INDEX_Y_OFFSET, vy); - - drm_dev_exit(idx); -} |