1 /* 2 * Copyright (C) 2011 Samsung Electronics Co.Ltd 3 * Authors: Joonyoung Shim <jy0922.shim@samsung.com> 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License as published by the 7 * Free Software Foundation; either version 2 of the License, or (at your 8 * option) any later version. 9 * 10 */ 11 12 #include "drmP.h" 13 14 #include "exynos_drm.h" 15 #include "exynos_drm_crtc.h" 16 #include "exynos_drm_drv.h" 17 #include "exynos_drm_encoder.h" 18 19 struct exynos_plane { 20 struct drm_plane base; 21 struct exynos_drm_overlay overlay; 22 bool enabled; 23 }; 24 25 static int 26 exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, 27 struct drm_framebuffer *fb, int crtc_x, int crtc_y, 28 unsigned int crtc_w, unsigned int crtc_h, 29 uint32_t src_x, uint32_t src_y, 30 uint32_t src_w, uint32_t src_h) 31 { 32 struct exynos_plane *exynos_plane = 33 container_of(plane, struct exynos_plane, base); 34 struct exynos_drm_overlay *overlay = &exynos_plane->overlay; 35 struct exynos_drm_crtc_pos pos; 36 unsigned int x = src_x >> 16; 37 unsigned int y = src_y >> 16; 38 int ret; 39 40 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); 41 42 memset(&pos, 0, sizeof(struct exynos_drm_crtc_pos)); 43 pos.crtc_x = crtc_x; 44 pos.crtc_y = crtc_y; 45 pos.crtc_w = crtc_w; 46 pos.crtc_h = crtc_h; 47 48 pos.fb_x = x; 49 pos.fb_y = y; 50 51 /* TODO: scale feature */ 52 ret = exynos_drm_overlay_update(overlay, fb, &crtc->mode, &pos); 53 if (ret < 0) 54 return ret; 55 56 exynos_drm_fn_encoder(crtc, overlay, 57 exynos_drm_encoder_crtc_mode_set); 58 exynos_drm_fn_encoder(crtc, &overlay->zpos, 59 exynos_drm_encoder_crtc_plane_commit); 60 61 exynos_plane->enabled = true; 62 63 return 0; 64 } 65 66 static int exynos_disable_plane(struct drm_plane *plane) 67 { 68 struct exynos_plane *exynos_plane = 69 container_of(plane, struct exynos_plane, base); 70 struct exynos_drm_overlay *overlay = &exynos_plane->overlay; 71 72 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); 73 74 if (!exynos_plane->enabled) 75 return 0; 76 77 exynos_drm_fn_encoder(plane->crtc, &overlay->zpos, 78 exynos_drm_encoder_crtc_disable); 79 80 exynos_plane->enabled = false; 81 exynos_plane->overlay.zpos = DEFAULT_ZPOS; 82 83 return 0; 84 } 85 86 static void exynos_plane_destroy(struct drm_plane *plane) 87 { 88 struct exynos_plane *exynos_plane = 89 container_of(plane, struct exynos_plane, base); 90 91 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); 92 93 exynos_disable_plane(plane); 94 drm_plane_cleanup(plane); 95 kfree(exynos_plane); 96 } 97 98 static struct drm_plane_funcs exynos_plane_funcs = { 99 .update_plane = exynos_update_plane, 100 .disable_plane = exynos_disable_plane, 101 .destroy = exynos_plane_destroy, 102 }; 103 104 int exynos_plane_init(struct drm_device *dev, unsigned int nr) 105 { 106 struct exynos_plane *exynos_plane; 107 uint32_t possible_crtcs; 108 109 exynos_plane = kzalloc(sizeof(struct exynos_plane), GFP_KERNEL); 110 if (!exynos_plane) 111 return -ENOMEM; 112 113 /* all CRTCs are available */ 114 possible_crtcs = (1 << MAX_CRTC) - 1; 115 116 exynos_plane->overlay.zpos = DEFAULT_ZPOS; 117 118 /* TODO: format */ 119 return drm_plane_init(dev, &exynos_plane->base, possible_crtcs, 120 &exynos_plane_funcs, NULL, 0, false); 121 } 122 123 int exynos_plane_set_zpos_ioctl(struct drm_device *dev, void *data, 124 struct drm_file *file_priv) 125 { 126 struct drm_exynos_plane_set_zpos *zpos_req = data; 127 struct drm_mode_object *obj; 128 struct drm_plane *plane; 129 struct exynos_plane *exynos_plane; 130 int ret = 0; 131 132 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); 133 134 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 135 return -EINVAL; 136 137 if (zpos_req->zpos < 0 || zpos_req->zpos >= MAX_PLANE) { 138 if (zpos_req->zpos != DEFAULT_ZPOS) { 139 DRM_ERROR("zpos not within limits\n"); 140 return -EINVAL; 141 } 142 } 143 144 mutex_lock(&dev->mode_config.mutex); 145 146 obj = drm_mode_object_find(dev, zpos_req->plane_id, 147 DRM_MODE_OBJECT_PLANE); 148 if (!obj) { 149 DRM_DEBUG_KMS("Unknown plane ID %d\n", 150 zpos_req->plane_id); 151 ret = -EINVAL; 152 goto out; 153 } 154 155 plane = obj_to_plane(obj); 156 exynos_plane = container_of(plane, struct exynos_plane, base); 157 158 exynos_plane->overlay.zpos = zpos_req->zpos; 159 160 out: 161 mutex_unlock(&dev->mode_config.mutex); 162 return ret; 163 } 164