+ if (obj) {
+ for (i = 0; i < num_planes; i++)
+ rockchip_fb->obj[i] = obj[i];
+
+ for (i = 0; i < num_planes; i++) {
+ rk_obj = to_rockchip_obj(obj[i]);
+ rockchip_fb->dma_addr[i] = rk_obj->dma_addr;
+ }
+ } else if (res) {
+ unsigned long nr_pages;
+ struct page **pages;
+ struct sg_table *sgt;
+ DEFINE_DMA_ATTRS(attrs);
+ phys_addr_t start = res->start;
+ phys_addr_t size = res->end - res->start;
+
+ nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+ pages = kmalloc_array(nr_pages, sizeof(*pages), GFP_KERNEL);
+ if (!pages) {
+ ret = -ENOMEM;
+ goto err_deinit_drm_fb;
+ }
+ 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)) {
+ kfree(pages);
+ ret = PTR_ERR(sgt);
+ goto err_deinit_drm_fb;
+ }
+
+ dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
+ dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
+ dma_map_sg_attrs(dev->dev, sgt->sgl, sgt->nents,
+ DMA_TO_DEVICE, &attrs);
+ rockchip_fb->dma_addr[0] = sg_dma_address(sgt->sgl);
+ rockchip_fb->sgt = sgt;
+ rockchip_fb->start = res->start;
+ rockchip_fb->size = size;
+ } else {
+ ret = -EINVAL;
+ dev_err(dev->dev, "Failed to find available buffer\n");
+ goto err_deinit_drm_fb;
+ }
+
+ return &rockchip_fb->fb;
+
+err_deinit_drm_fb:
+ drm_framebuffer_cleanup(&rockchip_fb->fb);
+err_free_fb:
+ kfree(rockchip_fb);
+ return ERR_PTR(ret);