Loading drivers/gpu/drm/msm/msm_drv.h +1 −0 Original line number Diff line number Diff line Loading @@ -441,6 +441,7 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev, struct drm_gem_object *msm_gem_import(struct drm_device *dev, struct dma_buf *dmabuf, struct sg_table *sgt); void msm_framebuffer_set_kmap(struct drm_framebuffer *fb, bool enable); int msm_framebuffer_prepare(struct drm_framebuffer *fb, int id); void msm_framebuffer_cleanup(struct drm_framebuffer *fb, int id); uint32_t msm_framebuffer_iova(struct drm_framebuffer *fb, int id, int plane); Loading drivers/gpu/drm/msm/msm_fb.c +71 −0 Original line number Diff line number Diff line /* * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark <robdclark@gmail.com> * Loading @@ -15,16 +16,24 @@ * this program. If not, see <http://www.gnu.org/licenses/>. */ #include <linux/dma-mapping.h> #include <linux/dma-buf.h> #include "msm_drv.h" #include "msm_kms.h" #include "drm_crtc.h" #include "drm_crtc_helper.h" #define MSM_FRAMEBUFFER_FLAG_KMAP BIT(0) struct msm_framebuffer { struct drm_framebuffer base; const struct msm_format *format; struct drm_gem_object *planes[MAX_PLANE]; void *vaddr[MAX_PLANE]; atomic_t kmap_count; u32 flags; }; #define to_msm_framebuffer(x) container_of(x, struct msm_framebuffer, base) Loading Loading @@ -79,6 +88,61 @@ void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m) } #endif void msm_framebuffer_set_kmap(struct drm_framebuffer *fb, bool enable) { struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); if (enable) msm_fb->flags |= MSM_FRAMEBUFFER_FLAG_KMAP; else msm_fb->flags &= ~MSM_FRAMEBUFFER_FLAG_KMAP; } static int msm_framebuffer_kmap(struct drm_framebuffer *fb) { struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); int i, n = drm_format_num_planes(fb->pixel_format); struct drm_gem_object *bo; if (atomic_inc_return(&msm_fb->kmap_count) > 1) return 0; for (i = 0; i < n; i++) { bo = msm_framebuffer_bo(fb, i); if (!bo || !bo->dma_buf) { msm_fb->vaddr[i] = NULL; continue; } dma_buf_begin_cpu_access(bo->dma_buf, DMA_BIDIRECTIONAL); msm_fb->vaddr[i] = dma_buf_kmap(bo->dma_buf, 0); DRM_INFO("FB[%u]: vaddr[%d]:%ux%u:0x%llx\n", fb->base.id, i, fb->width, fb->height, (u64) msm_fb->vaddr[i]); } return 0; } static void msm_framebuffer_kunmap(struct drm_framebuffer *fb) { struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); int i, n = drm_format_num_planes(fb->pixel_format); struct drm_gem_object *bo; if (atomic_dec_return(&msm_fb->kmap_count) > 0) return; for (i = 0; i < n; i++) { bo = msm_framebuffer_bo(fb, i); if (!bo || !msm_fb->vaddr[i]) continue; if (bo->dma_buf) { dma_buf_kunmap(bo->dma_buf, 0, msm_fb->vaddr[i]); dma_buf_end_cpu_access(bo->dma_buf, DMA_BIDIRECTIONAL); } msm_fb->vaddr[i] = NULL; } } /* prepare/pin all the fb's bo's for scanout. Note that it is not valid * to prepare an fb more multiple different initiator 'id's. But that * should be fine, since only the scanout (mdpN) side of things needs Loading @@ -97,6 +161,9 @@ int msm_framebuffer_prepare(struct drm_framebuffer *fb, int id) return ret; } if (msm_fb->flags & MSM_FRAMEBUFFER_FLAG_KMAP) msm_framebuffer_kmap(fb); return 0; } Loading @@ -105,6 +172,9 @@ void msm_framebuffer_cleanup(struct drm_framebuffer *fb, int id) struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); int i, n = drm_format_num_planes(fb->pixel_format); if (msm_fb->flags & MSM_FRAMEBUFFER_FLAG_KMAP) msm_framebuffer_kunmap(fb); for (i = 0; i < n; i++) msm_gem_put_iova(msm_fb->planes[i], id); } Loading Loading @@ -195,6 +265,7 @@ struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, fb = &msm_fb->base; msm_fb->format = format; atomic_set(&msm_fb->kmap_count, 0); if (mode_cmd->flags & DRM_MODE_FB_MODIFIERS) { for (i = 0; i < ARRAY_SIZE(mode_cmd->modifier); i++) { Loading drivers/gpu/drm/msm/sde/sde_connector.c +40 −0 Original line number Diff line number Diff line Loading @@ -323,6 +323,9 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector, SDE_ERROR("failed to look up fb %lld\n", val); rc = -EFAULT; } else { msm_framebuffer_set_kmap(c_state->out_fb, c_conn->fb_kmap); if (c_state->out_fb->flags & DRM_MODE_FB_SECURE) c_state->mmu_id = c_conn->mmu_id[SDE_IOMMU_DOMAIN_SECURE]; Loading Loading @@ -456,6 +459,42 @@ sde_connector_detect(struct drm_connector *connector, bool force) return status; } #ifdef CONFIG_DEBUG_FS /** * sde_connector_init_debugfs - initialize connector debugfs * @connector: Pointer to drm connector */ static int sde_connector_init_debugfs(struct drm_connector *connector) { struct sde_connector *sde_connector; if (!connector || !connector->debugfs_entry) { SDE_ERROR("invalid connector\n"); return -EINVAL; } sde_connector = to_sde_connector(connector); if (!debugfs_create_bool("fb_kmap", 0644, connector->debugfs_entry, &sde_connector->fb_kmap)) { SDE_ERROR("failed to create connector fb_kmap\n"); return -ENOMEM; } return 0; } #else static int sde_connector_init_debugfs(struct drm_connector *connector) { return 0; } #endif static int sde_connector_late_register(struct drm_connector *connector) { return sde_connector_init_debugfs(connector); } static const struct drm_connector_funcs sde_connector_ops = { .dpms = drm_atomic_helper_connector_dpms, .reset = sde_connector_atomic_reset, Loading @@ -467,6 +506,7 @@ static const struct drm_connector_funcs sde_connector_ops = { .atomic_set_property = sde_connector_atomic_set_property, .atomic_get_property = sde_connector_atomic_get_property, .set_property = sde_connector_set_property, .late_register = sde_connector_late_register, }; static int sde_connector_get_modes(struct drm_connector *connector) Loading drivers/gpu/drm/msm/sde/sde_connector.h +3 −0 Original line number Diff line number Diff line Loading @@ -137,6 +137,7 @@ struct sde_connector_ops { * @property_info: Private structure for generic property handling * @property_data: Array of private data for generic property handling * @blob_caps: Pointer to blob structure for 'capabilities' property * @fb_kmap: true if kernel mapping of framebuffer is requested */ struct sde_connector { struct drm_connector base; Loading @@ -157,6 +158,8 @@ struct sde_connector { struct msm_property_info property_info; struct msm_property_data property_data[CONNECTOR_PROP_COUNT]; struct drm_property_blob *blob_caps; bool fb_kmap; }; /** Loading Loading
drivers/gpu/drm/msm/msm_drv.h +1 −0 Original line number Diff line number Diff line Loading @@ -441,6 +441,7 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev, struct drm_gem_object *msm_gem_import(struct drm_device *dev, struct dma_buf *dmabuf, struct sg_table *sgt); void msm_framebuffer_set_kmap(struct drm_framebuffer *fb, bool enable); int msm_framebuffer_prepare(struct drm_framebuffer *fb, int id); void msm_framebuffer_cleanup(struct drm_framebuffer *fb, int id); uint32_t msm_framebuffer_iova(struct drm_framebuffer *fb, int id, int plane); Loading
drivers/gpu/drm/msm/msm_fb.c +71 −0 Original line number Diff line number Diff line /* * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark <robdclark@gmail.com> * Loading @@ -15,16 +16,24 @@ * this program. If not, see <http://www.gnu.org/licenses/>. */ #include <linux/dma-mapping.h> #include <linux/dma-buf.h> #include "msm_drv.h" #include "msm_kms.h" #include "drm_crtc.h" #include "drm_crtc_helper.h" #define MSM_FRAMEBUFFER_FLAG_KMAP BIT(0) struct msm_framebuffer { struct drm_framebuffer base; const struct msm_format *format; struct drm_gem_object *planes[MAX_PLANE]; void *vaddr[MAX_PLANE]; atomic_t kmap_count; u32 flags; }; #define to_msm_framebuffer(x) container_of(x, struct msm_framebuffer, base) Loading Loading @@ -79,6 +88,61 @@ void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m) } #endif void msm_framebuffer_set_kmap(struct drm_framebuffer *fb, bool enable) { struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); if (enable) msm_fb->flags |= MSM_FRAMEBUFFER_FLAG_KMAP; else msm_fb->flags &= ~MSM_FRAMEBUFFER_FLAG_KMAP; } static int msm_framebuffer_kmap(struct drm_framebuffer *fb) { struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); int i, n = drm_format_num_planes(fb->pixel_format); struct drm_gem_object *bo; if (atomic_inc_return(&msm_fb->kmap_count) > 1) return 0; for (i = 0; i < n; i++) { bo = msm_framebuffer_bo(fb, i); if (!bo || !bo->dma_buf) { msm_fb->vaddr[i] = NULL; continue; } dma_buf_begin_cpu_access(bo->dma_buf, DMA_BIDIRECTIONAL); msm_fb->vaddr[i] = dma_buf_kmap(bo->dma_buf, 0); DRM_INFO("FB[%u]: vaddr[%d]:%ux%u:0x%llx\n", fb->base.id, i, fb->width, fb->height, (u64) msm_fb->vaddr[i]); } return 0; } static void msm_framebuffer_kunmap(struct drm_framebuffer *fb) { struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); int i, n = drm_format_num_planes(fb->pixel_format); struct drm_gem_object *bo; if (atomic_dec_return(&msm_fb->kmap_count) > 0) return; for (i = 0; i < n; i++) { bo = msm_framebuffer_bo(fb, i); if (!bo || !msm_fb->vaddr[i]) continue; if (bo->dma_buf) { dma_buf_kunmap(bo->dma_buf, 0, msm_fb->vaddr[i]); dma_buf_end_cpu_access(bo->dma_buf, DMA_BIDIRECTIONAL); } msm_fb->vaddr[i] = NULL; } } /* prepare/pin all the fb's bo's for scanout. Note that it is not valid * to prepare an fb more multiple different initiator 'id's. But that * should be fine, since only the scanout (mdpN) side of things needs Loading @@ -97,6 +161,9 @@ int msm_framebuffer_prepare(struct drm_framebuffer *fb, int id) return ret; } if (msm_fb->flags & MSM_FRAMEBUFFER_FLAG_KMAP) msm_framebuffer_kmap(fb); return 0; } Loading @@ -105,6 +172,9 @@ void msm_framebuffer_cleanup(struct drm_framebuffer *fb, int id) struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); int i, n = drm_format_num_planes(fb->pixel_format); if (msm_fb->flags & MSM_FRAMEBUFFER_FLAG_KMAP) msm_framebuffer_kunmap(fb); for (i = 0; i < n; i++) msm_gem_put_iova(msm_fb->planes[i], id); } Loading Loading @@ -195,6 +265,7 @@ struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, fb = &msm_fb->base; msm_fb->format = format; atomic_set(&msm_fb->kmap_count, 0); if (mode_cmd->flags & DRM_MODE_FB_MODIFIERS) { for (i = 0; i < ARRAY_SIZE(mode_cmd->modifier); i++) { Loading
drivers/gpu/drm/msm/sde/sde_connector.c +40 −0 Original line number Diff line number Diff line Loading @@ -323,6 +323,9 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector, SDE_ERROR("failed to look up fb %lld\n", val); rc = -EFAULT; } else { msm_framebuffer_set_kmap(c_state->out_fb, c_conn->fb_kmap); if (c_state->out_fb->flags & DRM_MODE_FB_SECURE) c_state->mmu_id = c_conn->mmu_id[SDE_IOMMU_DOMAIN_SECURE]; Loading Loading @@ -456,6 +459,42 @@ sde_connector_detect(struct drm_connector *connector, bool force) return status; } #ifdef CONFIG_DEBUG_FS /** * sde_connector_init_debugfs - initialize connector debugfs * @connector: Pointer to drm connector */ static int sde_connector_init_debugfs(struct drm_connector *connector) { struct sde_connector *sde_connector; if (!connector || !connector->debugfs_entry) { SDE_ERROR("invalid connector\n"); return -EINVAL; } sde_connector = to_sde_connector(connector); if (!debugfs_create_bool("fb_kmap", 0644, connector->debugfs_entry, &sde_connector->fb_kmap)) { SDE_ERROR("failed to create connector fb_kmap\n"); return -ENOMEM; } return 0; } #else static int sde_connector_init_debugfs(struct drm_connector *connector) { return 0; } #endif static int sde_connector_late_register(struct drm_connector *connector) { return sde_connector_init_debugfs(connector); } static const struct drm_connector_funcs sde_connector_ops = { .dpms = drm_atomic_helper_connector_dpms, .reset = sde_connector_atomic_reset, Loading @@ -467,6 +506,7 @@ static const struct drm_connector_funcs sde_connector_ops = { .atomic_set_property = sde_connector_atomic_set_property, .atomic_get_property = sde_connector_atomic_get_property, .set_property = sde_connector_set_property, .late_register = sde_connector_late_register, }; static int sde_connector_get_modes(struct drm_connector *connector) Loading
drivers/gpu/drm/msm/sde/sde_connector.h +3 −0 Original line number Diff line number Diff line Loading @@ -137,6 +137,7 @@ struct sde_connector_ops { * @property_info: Private structure for generic property handling * @property_data: Array of private data for generic property handling * @blob_caps: Pointer to blob structure for 'capabilities' property * @fb_kmap: true if kernel mapping of framebuffer is requested */ struct sde_connector { struct drm_connector base; Loading @@ -157,6 +158,8 @@ struct sde_connector { struct msm_property_info property_info; struct msm_property_data property_data[CONNECTOR_PROP_COUNT]; struct drm_property_blob *blob_caps; bool fb_kmap; }; /** Loading