drm/rockchip: add support drm logo buffer 1:1 mapping

we reserved the DDR last 32M as uboot logo and kernel logo, here we
create 1:1 mapping for this buffer, this is prepare for uboot logo phy
addr switch to kernel logo vir addr and iommu enable.

Change-Id: I090665f29f7f4f7cf5456b9edbddea60485376cf
Signed-off-by: Sandy Huang <hjc@rock-chips.com>
This commit is contained in:
Sandy Huang 2020-06-02 17:05:13 +08:00 committed by Tao Huang
parent 4600ef8027
commit f831f246a0
2 changed files with 17 additions and 67 deletions

View File

@ -208,22 +208,15 @@ void rockchip_free_loader_memory(struct drm_device *drm)
return;
logo = private->logo;
start = phys_to_virt(logo->start);
end = phys_to_virt(logo->start + logo->size);
start = phys_to_virt(logo->dma_addr);
end = phys_to_virt(logo->dma_addr + logo->size);
if (private->domain) {
iommu_unmap(private->domain, logo->dma_addr,
logo->iommu_map_size);
mutex_lock(&private->mm_lock);
drm_mm_remove_node(&logo->mm);
mutex_unlock(&private->mm_lock);
} else {
dma_unmap_sg(drm->dev, logo->sgt->sgl,
logo->sgt->nents, DMA_TO_DEVICE);
u32 pg_size = 1UL << __ffs(private->domain->pgsize_bitmap);
iommu_unmap(private->domain, logo->dma_addr, ALIGN(logo->size, pg_size));
}
kfree(logo->pages);
sg_free_table(logo->sgt);
kfree(logo->sgt);
memblock_free(logo->start, logo->size);
free_reserved_area(start, end, -1, "drm_logo");
kfree(logo);
@ -237,12 +230,10 @@ static int init_loader_memory(struct drm_device *drm_dev)
struct rockchip_logo *logo;
struct device_node *np = drm_dev->dev->of_node;
struct device_node *node;
unsigned long nr_pages;
struct page **pages;
struct sg_table *sgt;
phys_addr_t start, size;
u32 pg_size = PAGE_SIZE;
struct resource res;
int i, ret;
int ret;
node = of_parse_phandle(np, "logo-memory-region", 0);
if (!node)
@ -251,7 +242,9 @@ static int init_loader_memory(struct drm_device *drm_dev)
ret = of_address_to_resource(node, 0, &res);
if (ret)
return ret;
start = res.start;
if (private->domain)
pg_size = 1UL << __ffs(private->domain->pgsize_bitmap);
start = ALIGN_DOWN(res.start, pg_size);
size = resource_size(&res);
if (!size)
return -ENOMEM;
@ -261,62 +254,23 @@ static int init_loader_memory(struct drm_device *drm_dev)
return -ENOMEM;
logo->kvaddr = phys_to_virt(start);
nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
pages = kmalloc_array(nr_pages, sizeof(*pages), GFP_KERNEL);
if (!pages)
goto err_free_logo;
i = 0;
while (i < nr_pages) {
pages[i] = phys_to_page(start);
start += PAGE_SIZE;
i++;
}
sgt = drm_prime_pages_to_sg(pages, nr_pages);
if (IS_ERR(sgt)) {
ret = PTR_ERR(sgt);
goto err_free_pages;
}
if (private->domain) {
memset(&logo->mm, 0, sizeof(logo->mm));
mutex_lock(&private->mm_lock);
ret = drm_mm_insert_node_generic(&private->mm, &logo->mm,
size, PAGE_SIZE,
0, 0);
mutex_unlock(&private->mm_lock);
if (ret < 0) {
DRM_ERROR("out of I/O virtual memory: %d\n", ret);
goto err_free_pages;
ret = iommu_map(private->domain, start, start, ALIGN(size, pg_size),
IOMMU_WRITE | IOMMU_READ);
if (ret) {
dev_err(drm_dev->dev, "failed to create 1v1 mapping\n");
goto err_free_logo;
}
logo->dma_addr = logo->mm.start;
logo->iommu_map_size = iommu_map_sg(private->domain,
logo->dma_addr, sgt->sgl,
sgt->nents, IOMMU_READ);
if (logo->iommu_map_size < size) {
DRM_ERROR("failed to map buffer");
ret = -ENOMEM;
goto err_remove_node;
}
} else {
dma_map_sg(drm_dev->dev, sgt->sgl, sgt->nents, DMA_TO_DEVICE);
logo->dma_addr = sg_dma_address(sgt->sgl);
}
logo->sgt = sgt;
logo->start = res.start;
logo->dma_addr = start;
logo->size = size;
logo->count = 1;
private->logo = logo;
logo->pages = pages;
return 0;
err_remove_node:
drm_mm_remove_node(&logo->mm);
err_free_pages:
kfree(pages);
err_free_logo:
kfree(logo);

View File

@ -127,15 +127,11 @@ struct rockchip_crtc_state {
container_of(s, struct rockchip_crtc_state, base)
struct rockchip_logo {
struct sg_table *sgt;
struct drm_mm_node mm;
dma_addr_t dma_addr;
void *kvaddr;
phys_addr_t start;
phys_addr_t size;
size_t iommu_map_size;
int count;
struct page **pages;
};
/*