From: Mark Yao Date: Thu, 18 Aug 2016 03:50:06 +0000 (+0800) Subject: drm/rockchip: optimize the loader display X-Git-Tag: firefly_0821_release~1593 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=firefly-linux-kernel-4.4.55.git;a=commitdiff_plain;h=0c46062f94714c0947431771caaab6fa3e5b3e40 drm/rockchip: optimize the loader display Change-Id: Iaa3066a5f1eb2e76a30c887823aba489776cb68a Signed-off-by: Mark Yao --- diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 4027fa91c8ab..0b602a6452e3 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -58,6 +58,7 @@ struct rockchip_drm_mode_set { int vrefresh; bool mode_changed; + bool ymirror; int ratio; }; @@ -97,23 +98,76 @@ static struct drm_connector *find_connector_by_node(struct drm_device *drm_dev, return NULL; } +static int init_loader_memory(struct drm_device *drm_dev) +{ + struct rockchip_drm_private *private = drm_dev->dev_private; + 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; + DEFINE_DMA_ATTRS(attrs); + phys_addr_t start, size; + struct resource res; + int i, ret; + + logo = devm_kmalloc(drm_dev->dev, sizeof(*logo), GFP_KERNEL); + if (!logo) + return -ENOMEM; + + node = of_parse_phandle(np, "memory-region", 0); + if (!node) + return -ENOMEM; + + ret = of_address_to_resource(node, 0, &res); + if (ret) + return ret; + start = res.start; + size = resource_size(&res); + if (!size) + return -ENOMEM; + + nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT; + pages = kmalloc_array(nr_pages, sizeof(*pages), GFP_KERNEL); + if (!pages) + return -ENOMEM; + 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); + return PTR_ERR(sgt); + } + + dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs); + dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs); + dma_map_sg_attrs(drm_dev->dev, sgt->sgl, sgt->nents, + DMA_TO_DEVICE, &attrs); + logo->dma_addr = sg_dma_address(sgt->sgl); + logo->sgt = sgt; + logo->start = res.start; + logo->size = size; + logo->count = 0; + private->logo = logo; + + return 0; +} + static struct drm_framebuffer * get_framebuffer_by_node(struct drm_device *drm_dev, struct device_node *node) { + struct rockchip_drm_private *private = drm_dev->dev_private; struct drm_mode_fb_cmd2 mode_cmd = { 0 }; - struct device_node *memory; - struct resource res; u32 val; int bpp; - memory = of_parse_phandle(node, "logo,mem", 0); - if (!memory) - return NULL; - - if (of_address_to_resource(memory, 0, &res)) { - pr_err("%s: could not get bootram phy addr\n", __func__); + if (WARN_ON(!private->logo)) return NULL; - } if (of_property_read_u32(node, "logo,offset", &val)) { pr_err("%s: failed to get logo,offset\n", __func__); @@ -140,9 +194,23 @@ get_framebuffer_by_node(struct drm_device *drm_dev, struct device_node *node) bpp = val; mode_cmd.pitches[0] = mode_cmd.width * bpp / 8; - mode_cmd.pixel_format = DRM_FORMAT_BGR888; - return rockchip_fb_alloc(drm_dev, &mode_cmd, NULL, &res, 1); + switch (bpp) { + case 16: + mode_cmd.pixel_format = DRM_FORMAT_BGR565; + break; + case 24: + mode_cmd.pixel_format = DRM_FORMAT_BGR888; + break; + case 32: + mode_cmd.pixel_format = DRM_FORMAT_XBGR8888; + break; + default: + pr_err("%s: unsupport to logo bpp %d\n", __func__, bpp); + return NULL; + } + + return rockchip_fb_alloc(drm_dev, &mode_cmd, NULL, private->logo, 1); } static struct rockchip_drm_mode_set * @@ -185,6 +253,9 @@ of_parse_display_resource(struct drm_device *drm_dev, struct device_node *route) if (!of_property_read_u32(route, "video,vrefresh", &val)) set->vrefresh = val; + if (!of_property_read_u32(route, "logo,ymirror", &val)) + set->ymirror = val; + set->fb = fb; set->crtc = crtc; set->connector = connector; @@ -370,13 +441,14 @@ static int update_state(struct drm_device *drm_dev, drm_framebuffer_unreference(set->fb); ret = drm_atomic_set_crtc_for_plane(primary_state, crtc); - /* - * TODO: - * some vop maybe not support ymirror, but force use it now. - */ - drm_atomic_plane_set_property(crtc->primary, primary_state, - mode_config->rotation_property, - BIT(DRM_REFLECT_Y)); + if (set->ymirror) + /* + * TODO: + * some vop maybe not support ymirror, but force use it now. + */ + drm_atomic_plane_set_property(crtc->primary, primary_state, + mode_config->rotation_property, + BIT(DRM_REFLECT_Y)); return ret; } @@ -398,6 +470,11 @@ static void show_loader_logo(struct drm_device *drm_dev) return; } + if (init_loader_memory(drm_dev)) { + dev_warn(drm_dev->dev, "failed to parse loader memory\n"); + return; + } + INIT_LIST_HEAD(&mode_set_list); drm_modeset_lock_all(drm_dev); state = drm_atomic_state_alloc(drm_dev); @@ -408,6 +485,7 @@ static void show_loader_logo(struct drm_device *drm_dev) } state->acquire_ctx = mode_config->acquire_ctx; + for_each_child_of_node(root, route) { set = of_parse_display_resource(drm_dev, route); if (!set) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index f0d5567780b7..d3e6c5ae0214 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -81,6 +81,14 @@ struct rockchip_drm_file_private { struct rockchip_drm_rga_private *rga_priv; }; +struct rockchip_logo { + struct sg_table *sgt; + dma_addr_t dma_addr; + phys_addr_t start; + phys_addr_t size; + int count; +}; + /* * Rockchip drm private structure. * @@ -90,6 +98,7 @@ struct rockchip_drm_file_private { * @cpu_fence_seqno: fence sequence number */ struct rockchip_drm_private { + struct rockchip_logo *logo; struct drm_fb_helper *fbdev_helper; struct drm_gem_object *fbdev_bo; const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC]; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index c440bb062d12..b385525b95e1 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -29,9 +29,7 @@ struct rockchip_drm_fb { struct drm_framebuffer fb; dma_addr_t dma_addr[ROCKCHIP_MAX_FB_BUFFER]; struct drm_gem_object *obj[ROCKCHIP_MAX_FB_BUFFER]; - struct sg_table *sgt; - phys_addr_t start; - phys_addr_t size; + struct rockchip_logo *logo; }; dma_addr_t rockchip_fb_get_dma_addr(struct drm_framebuffer *fb, @@ -58,15 +56,19 @@ static void rockchip_drm_fb_destroy(struct drm_framebuffer *fb) } #ifndef MODULE - if (rockchip_fb->sgt) { - void *start = phys_to_virt(rockchip_fb->start); - void *end = phys_to_virt(rockchip_fb->size); - - dma_unmap_sg(fb->dev->dev, rockchip_fb->sgt->sgl, - rockchip_fb->sgt->nents, DMA_TO_DEVICE); - sg_free_table(rockchip_fb->sgt); - memblock_free(rockchip_fb->start, rockchip_fb->size); - free_reserved_area(start, end, -1, "drm_fb"); + if (rockchip_fb->logo) { + struct rockchip_logo *logo = rockchip_fb->logo; + + if (!--logo->count) { + void *start = phys_to_virt(logo->start); + void *end = phys_to_virt(logo->size); + + dma_unmap_sg(fb->dev->dev, logo->sgt->sgl, + logo->sgt->nents, DMA_TO_DEVICE); + sg_free_table(logo->sgt); + memblock_free(logo->start, logo->size); + free_reserved_area(start, end, -1, "drm_logo"); + } } #else WARN_ON(rockchip_fb->sgt); @@ -93,7 +95,7 @@ static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = { struct drm_framebuffer * rockchip_fb_alloc(struct drm_device *dev, struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object **obj, struct resource *res, + struct drm_gem_object **obj, struct rockchip_logo *logo, unsigned int num_planes) { struct rockchip_drm_fb *rockchip_fb; @@ -124,41 +126,10 @@ rockchip_fb_alloc(struct drm_device *dev, struct drm_mode_fb_cmd2 *mode_cmd, rockchip_fb->dma_addr[i] = rk_obj->dma_addr; } #ifndef MODULE - } 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 if (logo) { + rockchip_fb->dma_addr[0] = logo->dma_addr; + rockchip_fb->logo = logo; + logo->count++; #endif } else { ret = -EINVAL; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.h b/drivers/gpu/drm/rockchip/rockchip_drm_fb.h index df6111ef2a58..31feb1a19dd3 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.h @@ -25,7 +25,7 @@ void rockchip_drm_mode_config_init(struct drm_device *dev); struct drm_framebuffer * rockchip_fb_alloc(struct drm_device *dev, struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object **obj, struct resource *res, + struct drm_gem_object **obj, struct rockchip_logo *logo, unsigned int num_planes); dma_addr_t rockchip_fb_get_dma_addr(struct drm_framebuffer *fb,