Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.16-rc6 165 lines 3.9 kB view raw
1/* 2 * Copyright (c) 2015 MediaTek Inc. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 */ 13 14#include <drm/drmP.h> 15#include <drm/drm_crtc_helper.h> 16#include <drm/drm_fb_helper.h> 17#include <drm/drm_gem.h> 18#include <linux/dma-buf.h> 19#include <linux/reservation.h> 20 21#include "mtk_drm_drv.h" 22#include "mtk_drm_fb.h" 23#include "mtk_drm_gem.h" 24 25/* 26 * mtk specific framebuffer structure. 27 * 28 * @fb: drm framebuffer object. 29 * @gem_obj: array of gem objects. 30 */ 31struct mtk_drm_fb { 32 struct drm_framebuffer base; 33 /* For now we only support a single plane */ 34 struct drm_gem_object *gem_obj; 35}; 36 37#define to_mtk_fb(x) container_of(x, struct mtk_drm_fb, base) 38 39struct drm_gem_object *mtk_fb_get_gem_obj(struct drm_framebuffer *fb) 40{ 41 struct mtk_drm_fb *mtk_fb = to_mtk_fb(fb); 42 43 return mtk_fb->gem_obj; 44} 45 46static int mtk_drm_fb_create_handle(struct drm_framebuffer *fb, 47 struct drm_file *file_priv, 48 unsigned int *handle) 49{ 50 struct mtk_drm_fb *mtk_fb = to_mtk_fb(fb); 51 52 return drm_gem_handle_create(file_priv, mtk_fb->gem_obj, handle); 53} 54 55static void mtk_drm_fb_destroy(struct drm_framebuffer *fb) 56{ 57 struct mtk_drm_fb *mtk_fb = to_mtk_fb(fb); 58 59 drm_framebuffer_cleanup(fb); 60 61 drm_gem_object_put_unlocked(mtk_fb->gem_obj); 62 63 kfree(mtk_fb); 64} 65 66static const struct drm_framebuffer_funcs mtk_drm_fb_funcs = { 67 .create_handle = mtk_drm_fb_create_handle, 68 .destroy = mtk_drm_fb_destroy, 69}; 70 71static struct mtk_drm_fb *mtk_drm_framebuffer_init(struct drm_device *dev, 72 const struct drm_mode_fb_cmd2 *mode, 73 struct drm_gem_object *obj) 74{ 75 struct mtk_drm_fb *mtk_fb; 76 int ret; 77 78 if (drm_format_num_planes(mode->pixel_format) != 1) 79 return ERR_PTR(-EINVAL); 80 81 mtk_fb = kzalloc(sizeof(*mtk_fb), GFP_KERNEL); 82 if (!mtk_fb) 83 return ERR_PTR(-ENOMEM); 84 85 drm_helper_mode_fill_fb_struct(dev, &mtk_fb->base, mode); 86 87 mtk_fb->gem_obj = obj; 88 89 ret = drm_framebuffer_init(dev, &mtk_fb->base, &mtk_drm_fb_funcs); 90 if (ret) { 91 DRM_ERROR("failed to initialize framebuffer\n"); 92 kfree(mtk_fb); 93 return ERR_PTR(ret); 94 } 95 96 return mtk_fb; 97} 98 99/* 100 * Wait for any exclusive fence in fb's gem object's reservation object. 101 * 102 * Returns -ERESTARTSYS if interrupted, else 0. 103 */ 104int mtk_fb_wait(struct drm_framebuffer *fb) 105{ 106 struct drm_gem_object *gem; 107 struct reservation_object *resv; 108 long ret; 109 110 if (!fb) 111 return 0; 112 113 gem = mtk_fb_get_gem_obj(fb); 114 if (!gem || !gem->dma_buf || !gem->dma_buf->resv) 115 return 0; 116 117 resv = gem->dma_buf->resv; 118 ret = reservation_object_wait_timeout_rcu(resv, false, true, 119 MAX_SCHEDULE_TIMEOUT); 120 /* MAX_SCHEDULE_TIMEOUT on success, -ERESTARTSYS if interrupted */ 121 if (WARN_ON(ret < 0)) 122 return ret; 123 124 return 0; 125} 126 127struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev, 128 struct drm_file *file, 129 const struct drm_mode_fb_cmd2 *cmd) 130{ 131 struct mtk_drm_fb *mtk_fb; 132 struct drm_gem_object *gem; 133 unsigned int width = cmd->width; 134 unsigned int height = cmd->height; 135 unsigned int size, bpp; 136 int ret; 137 138 if (drm_format_num_planes(cmd->pixel_format) != 1) 139 return ERR_PTR(-EINVAL); 140 141 gem = drm_gem_object_lookup(file, cmd->handles[0]); 142 if (!gem) 143 return ERR_PTR(-ENOENT); 144 145 bpp = drm_format_plane_cpp(cmd->pixel_format, 0); 146 size = (height - 1) * cmd->pitches[0] + width * bpp; 147 size += cmd->offsets[0]; 148 149 if (gem->size < size) { 150 ret = -EINVAL; 151 goto unreference; 152 } 153 154 mtk_fb = mtk_drm_framebuffer_init(dev, cmd, gem); 155 if (IS_ERR(mtk_fb)) { 156 ret = PTR_ERR(mtk_fb); 157 goto unreference; 158 } 159 160 return &mtk_fb->base; 161 162unreference: 163 drm_gem_object_put_unlocked(gem); 164 return ERR_PTR(ret); 165}