diff --git a/drivers/gpu/drm/phytium/phytium_display_drv.c b/drivers/gpu/drm/phytium/phytium_display_drv.c index 231e6af69e0d..4d813f8f6a9f 100644 --- a/drivers/gpu/drm/phytium/phytium_display_drv.c +++ b/drivers/gpu/drm/phytium/phytium_display_drv.c @@ -250,7 +250,7 @@ static int phytium_display_load(struct drm_device *dev, unsigned long flags) goto failed_modeset_init; } - if (priv->support_memory_type & MEMORY_TYPE_VRAM) + if (priv->support_memory_type & (MEMORY_TYPE_VRAM_WC | MEMORY_TYPE_VRAM_DEVICE)) priv->vram_hw_init(priv); ret = drm_irq_install(dev, priv->irq); @@ -281,8 +281,25 @@ static void phytium_display_unload(struct drm_device *dev) drm_mode_config_cleanup(dev); } +/* phytium display specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ +#define DRM_PHYTIUM_VRAM_TYPE_DEVICE 0x0 +#define DRM_IOCTL_PHYTIUM_VRAM_TYPE_DEVICE DRM_IO(DRM_COMMAND_BASE\ + + DRM_PHYTIUM_VRAM_TYPE_DEVICE) + +static int phytium_ioctl_check_vram_device(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct phytium_display_private *priv = dev->dev_private; + + return ((priv->support_memory_type == MEMORY_TYPE_VRAM_DEVICE) ? 1 : 0); +} + static const struct drm_ioctl_desc phytium_ioctls[] = { /* for test, none so far */ + DRM_IOCTL_DEF_DRV(PHYTIUM_VRAM_TYPE_DEVICE, phytium_ioctl_check_vram_device, + DRM_AUTH|DRM_UNLOCKED), }; static const struct file_operations phytium_drm_driver_fops = { @@ -382,7 +399,7 @@ static int phytium_display_pm_resume(struct drm_device *dev) phytium_crtc_resume(dev); phytium_gem_resume(dev); - if (priv->support_memory_type & MEMORY_TYPE_VRAM) + if (priv->support_memory_type & (MEMORY_TYPE_VRAM_WC | MEMORY_TYPE_VRAM_DEVICE)) priv->vram_hw_init(priv); ret = drm_atomic_helper_resume(dev, dev->mode_config.suspend_state); diff --git a/drivers/gpu/drm/phytium/phytium_display_drv.h b/drivers/gpu/drm/phytium/phytium_display_drv.h index 70080dad8621..9038bf6ebd8c 100644 --- a/drivers/gpu/drm/phytium/phytium_display_drv.h +++ b/drivers/gpu/drm/phytium/phytium_display_drv.h @@ -49,9 +49,10 @@ enum phytium_mem_state_type { PHYTIUM_MEM_STATE_TYPE_COUNT, }; -#define MEMORY_TYPE_VRAM 0x1 +#define MEMORY_TYPE_VRAM_WC 0x1 #define MEMORY_TYPE_SYSTEM_CARVEOUT 0x2 #define MEMORY_TYPE_SYSTEM_UNIFIED 0x4 +#define MEMORY_TYPE_VRAM_DEVICE 0x8 #define IS_PLATFORM(priv, p) ((priv)->info.platform_mask & BIT(p)) diff --git a/drivers/gpu/drm/phytium/phytium_gem.c b/drivers/gpu/drm/phytium/phytium_gem.c index 913fe2d6062b..3ebeedc4131e 100644 --- a/drivers/gpu/drm/phytium/phytium_gem.c +++ b/drivers/gpu/drm/phytium/phytium_gem.c @@ -86,7 +86,8 @@ phytium_gem_prime_get_sg_table(struct drm_gem_object *obj) return ERR_PTR(-ENOMEM); } - if ((phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM) || + if ((phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM_WC) || + (phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM_DEVICE) || (phytium_gem_obj->memory_type == MEMORY_TYPE_SYSTEM_CARVEOUT)) { ret = sg_alloc_table(sgt, 1, GFP_KERNEL); if (ret) { @@ -280,7 +281,8 @@ int phytium_gem_suspend(struct drm_device *drm_dev) int ret = 0; list_for_each_entry(phytium_gem_obj, &priv->gem_list_head, list) { - if (phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM) + if ((phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM_WC) && + (phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM_DEVICE)) continue; phytium_gem_obj->vaddr_save = vmalloc(phytium_gem_obj->size); @@ -299,7 +301,8 @@ int phytium_gem_suspend(struct drm_device *drm_dev) return 0; malloc_failed: list_for_each_entry(phytium_gem_obj, &priv->gem_list_head, list) { - if (phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM) + if ((phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM_WC) && + (phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM_DEVICE)) continue; if (phytium_gem_obj->vaddr_save) { @@ -316,7 +319,8 @@ void phytium_gem_resume(struct drm_device *drm_dev) struct phytium_gem_object *phytium_gem_obj = NULL; list_for_each_entry(phytium_gem_obj, &priv->gem_list_head, list) { - if (phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM) + if ((phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM_WC) && + (phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM_DEVICE)) continue; memcpy(phytium_gem_obj->vaddr, phytium_gem_obj->vaddr_save, phytium_gem_obj->size); @@ -335,7 +339,8 @@ void phytium_gem_free_object(struct drm_gem_object *obj) DRM_DEBUG_KMS("free phytium_gem_obj iova:0x%pa size:0x%lx\n", &phytium_gem_obj->iova, phytium_gem_obj->size); if (phytium_gem_obj->vaddr) { - if (phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM) { + if ((phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM_WC) || + (phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM_DEVICE)) { phytium_memory_pool_free(priv, phytium_gem_obj->vaddr, size); priv->mem_state[PHYTIUM_MEM_VRAM_ALLOC] -= size; } else if (phytium_gem_obj->memory_type == MEMORY_TYPE_SYSTEM_CARVEOUT) { @@ -368,10 +373,14 @@ int phytium_gem_mmap_obj(struct drm_gem_object *obj, struct vm_area_struct *vma) vma->vm_pgoff = 0; vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); - if (phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM) { + if (phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM_WC) { vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); ret = remap_pfn_range(vma, vma->vm_start, pfn, vma->vm_end - vma->vm_start, vma->vm_page_prot); + } else if (phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM_DEVICE) { + vma->vm_page_prot = pgprot_device(vma->vm_page_prot); + ret = remap_pfn_range(vma, vma->vm_start, pfn, + vma->vm_end - vma->vm_start, vma->vm_page_prot); } else if (phytium_gem_obj->memory_type == MEMORY_TYPE_SYSTEM_CARVEOUT) { ret = remap_pfn_range(vma, vma->vm_start, pfn, vma->vm_end - vma->vm_start, vma->vm_page_prot); @@ -434,7 +443,7 @@ struct phytium_gem_object *phytium_gem_create_object(struct drm_device *dev, uns goto failed_object_init; } - if (priv->support_memory_type & MEMORY_TYPE_VRAM) { + if (priv->support_memory_type & (MEMORY_TYPE_VRAM_WC | MEMORY_TYPE_VRAM_DEVICE)) { ret = phytium_memory_pool_alloc(priv, &phytium_gem_obj->vaddr, &phytium_gem_obj->phys_addr, size); if (ret) { @@ -442,7 +451,7 @@ struct phytium_gem_object *phytium_gem_create_object(struct drm_device *dev, uns goto failed_dma_alloc; } phytium_gem_obj->iova = phytium_gem_obj->phys_addr; - phytium_gem_obj->memory_type = MEMORY_TYPE_VRAM; + phytium_gem_obj->memory_type = priv->support_memory_type; priv->mem_state[PHYTIUM_MEM_VRAM_ALLOC] += size; } else if (priv->support_memory_type & MEMORY_TYPE_SYSTEM_CARVEOUT) { ret = phytium_memory_pool_alloc(priv, &phytium_gem_obj->vaddr, diff --git a/drivers/gpu/drm/phytium/phytium_pci.c b/drivers/gpu/drm/phytium/phytium_pci.c index 68a386d26982..68a32647a27e 100644 --- a/drivers/gpu/drm/phytium/phytium_pci.c +++ b/drivers/gpu/drm/phytium/phytium_pci.c @@ -27,6 +27,24 @@ void phytium_pci_vram_hw_init(struct phytium_display_private *priv) pci_priv->dc_hw_vram_init(priv, priv->pool_phys_addr, priv->pool_size); } +static bool phytium_pci_host_is_5c01(struct pci_bus *bus) +{ + struct pci_bus *child = bus; + struct pci_dev *root = NULL; + + while (child) { + if (child->parent->parent) + child = child->parent; + else + break; + } + + root = child->self; + if ((root->vendor == 0x1db7) && (root->device == 0x5c01)) + return true; + return false; +} + int phytium_pci_vram_init(struct pci_dev *pdev, struct phytium_display_private *priv) { int ret = 0; @@ -34,8 +52,15 @@ int phytium_pci_vram_init(struct pci_dev *pdev, struct phytium_display_private * priv->pool_phys_addr = pci_resource_start(pdev, 2); priv->pool_size = pci_resource_len(pdev, 2); if ((priv->pool_phys_addr != 0) && (priv->pool_size != 0)) { - priv->pool_virt_addr = devm_ioremap_wc(&pdev->dev, priv->pool_phys_addr, - priv->pool_size); + if ((pdev->device == 0xdc3e) && phytium_pci_host_is_5c01(pdev->bus)) { + priv->pool_virt_addr = devm_ioremap(&pdev->dev, priv->pool_phys_addr, + priv->pool_size); + priv->support_memory_type = MEMORY_TYPE_VRAM_DEVICE; + } else { + priv->pool_virt_addr = devm_ioremap_wc(&pdev->dev, priv->pool_phys_addr, + priv->pool_size); + priv->support_memory_type = MEMORY_TYPE_VRAM_WC; + } if (priv->pool_virt_addr == NULL) { DRM_ERROR("pci vram ioremap fail, addr:0x%llx, size:0x%llx\n", priv->pool_phys_addr, priv->pool_size); @@ -47,7 +72,6 @@ int phytium_pci_vram_init(struct pci_dev *pdev, struct phytium_display_private * goto failed_init_memory_pool; priv->mem_state[PHYTIUM_MEM_VRAM_TOTAL] = priv->pool_size; - priv->support_memory_type = MEMORY_TYPE_VRAM; priv->vram_hw_init = phytium_pci_vram_hw_init; } else { DRM_DEBUG_KMS("not support vram\n"); @@ -67,7 +91,8 @@ failed_ioremap: void phytium_pci_vram_fini(struct pci_dev *pdev, struct phytium_display_private *priv) { - if (priv->support_memory_type == MEMORY_TYPE_VRAM) { + if ((priv->support_memory_type == MEMORY_TYPE_VRAM_WC) || + (priv->support_memory_type == MEMORY_TYPE_VRAM_DEVICE)) { phytium_memory_pool_fini(&pdev->dev, priv); devm_iounmap(&pdev->dev, priv->pool_virt_addr); }