blob: 12096924e12990659eb2ef7c389c2efa68eb8a36 [file] [log] [blame]
Naseer Ahmed73417992012-06-14 00:56:20 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 * Copyright (C) 2012, Code Aurora Forum. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include <fcntl.h>
19#include <errno.h>
20
21#include <cutils/log.h>
22#include <cutils/atomic.h>
Naseer Ahmed9ccb3972012-07-21 12:17:13 -070023#include <EGL/egl.h>
Naseer Ahmed73417992012-06-14 00:56:20 -070024
Naseer Ahmed9ccb3972012-07-21 12:17:13 -070025#include <overlay.h>
26#include <fb_priv.h>
Naseer Ahmed912842f2012-07-25 18:27:14 -070027#include <mdp_version.h>
Naseer Ahmed73417992012-06-14 00:56:20 -070028#include "hwc_utils.h"
Naseer Ahmed9ccb3972012-07-21 12:17:13 -070029#include "hwc_qbuf.h"
Saurabh Shah57045012012-07-10 18:33:17 -070030#include "hwc_video.h"
Prashant Suranacc5cb172012-08-13 11:49:01 +053031#include "hwc_pip.h"
Arun Kumar K.R59d5b622012-06-25 17:34:58 -070032#include "hwc_uimirror.h"
Sravan Kumar D.V.Nc80da702012-07-19 15:03:29 +053033#include "hwc_copybit.h"
Arun Kumar K.Ra72904b2012-07-23 13:44:38 -070034#include "hwc_external.h"
Jeykumar Sankaranbd86fcf2012-07-23 12:22:21 -070035#include "hwc_mdpcomp.h"
Saurabh Shahbf3c4542012-07-21 19:06:55 -070036#include "hwc_extonly.h"
Jeykumar Sankarancfb095e2012-08-28 17:56:00 -070037#include "qcom_ui.h"
Naseer Ahmed73417992012-06-14 00:56:20 -070038
Neti Ravi Kumarc356c1c2012-09-16 01:35:41 +053039#define VSYNC_DEBUG 0
Naseer Ahmed73417992012-06-14 00:56:20 -070040using namespace qhwc;
41
42static int hwc_device_open(const struct hw_module_t* module,
43 const char* name,
44 struct hw_device_t** device);
45
46static struct hw_module_methods_t hwc_module_methods = {
47 open: hwc_device_open
48};
49
50hwc_module_t HAL_MODULE_INFO_SYM = {
51 common: {
52 tag: HARDWARE_MODULE_TAG,
53 version_major: 2,
54 version_minor: 0,
55 id: HWC_HARDWARE_MODULE_ID,
56 name: "Qualcomm Hardware Composer Module",
57 author: "CodeAurora Forum",
58 methods: &hwc_module_methods,
59 dso: 0,
60 reserved: {0},
61 }
62};
63
64/*
65 * Save callback functions registered to HWC
66 */
67static void hwc_registerProcs(struct hwc_composer_device* dev,
68 hwc_procs_t const* procs)
69{
70 hwc_context_t* ctx = (hwc_context_t*)(dev);
71 if(!ctx) {
72 ALOGE("%s: Invalid context", __FUNCTION__);
73 return;
74 }
75 ctx->device.reserved_proc[0] = (void*)procs;
Arun Kumar K.Rb25918a2012-08-22 16:09:48 -070076
Neti Ravi Kumar673e4932012-09-12 18:14:25 +053077 // Now that we have the functions needed, kick off
78 // the uevent & vsync threads
Arun Kumar K.Rb25918a2012-08-22 16:09:48 -070079 init_uevent_thread(ctx);
Neti Ravi Kumar673e4932012-09-12 18:14:25 +053080 init_vsync_thread(ctx);
Naseer Ahmed73417992012-06-14 00:56:20 -070081}
82
83static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list)
84{
85 hwc_context_t* ctx = (hwc_context_t*)(dev);
Saurabh Shah57045012012-07-10 18:33:17 -070086 ctx->overlayInUse = false;
87
Amara Venkata Mastan Manoj Kumara4b03402012-09-05 18:18:51 -070088 if(ctx->mSecureConfig == true) {
89 // This will tear down External Display Device.
90 return 0;
91 }
92
Amara Venkata Mastan Manoj Kumar211f9f42012-08-02 08:26:21 -070093 if(ctx->mExtDisplay->getExternalDisplay())
94 ovutils::setExtType(ctx->mExtDisplay->getExternalDisplay());
Pawan Kumar9d128872012-09-22 14:30:29 +053095 if (ctx->hdmi_pending == true) {
96 if ((qdutils::MDPVersion::getInstance().getMDPVersion() >=
97 qdutils::MDP_V4_2) || (ctx->mOverlay->getState() !=
98 ovutils::OV_BYPASS_3_LAYER)) {
99 ctx->mExtDisplay->processUEventOnline((const char*)ctx->mHDMIEvent);
100 ctx->hdmi_pending = false;
101 }
102 }
Naseer Ahmed73417992012-06-14 00:56:20 -0700103 if (LIKELY(list)) {
Saurabh Shahbf3c4542012-07-21 19:06:55 -0700104 //reset for this draw round
105 VideoOverlay::reset();
Prashant Suranacc5cb172012-08-13 11:49:01 +0530106 VideoPIP::reset();
Saurabh Shahbf3c4542012-07-21 19:06:55 -0700107 ExtOnly::reset();
108
Naseer Ahmed73417992012-06-14 00:56:20 -0700109 getLayerStats(ctx, list);
Neti Ravi Kumar97d34842012-07-21 21:02:05 +0530110 // Mark all layers to COPYBIT initially
111 CopyBit::prepare(ctx, list);
Saurabh Shah57045012012-07-10 18:33:17 -0700112 if(VideoOverlay::prepare(ctx, list)) {
113 ctx->overlayInUse = true;
114 //Nothing here
Prashant Suranacc5cb172012-08-13 11:49:01 +0530115 } else if(VideoPIP::prepare(ctx, list)) {
116 ctx->overlayInUse = true;
Saurabh Shahbf3c4542012-07-21 19:06:55 -0700117 } else if(ExtOnly::prepare(ctx, list)) {
118 ctx->overlayInUse = true;
Arun Kumar K.R59d5b622012-06-25 17:34:58 -0700119 } else if(UIMirrorOverlay::prepare(ctx, list)) {
120 ctx->overlayInUse = true;
Jeykumar Sankaranbd86fcf2012-07-23 12:22:21 -0700121 } else if(MDPComp::configure(dev, list)) {
122 ctx->overlayInUse = true;
Saurabh Shah57045012012-07-10 18:33:17 -0700123 } else if (0) {
124 //Other features
125 ctx->overlayInUse = true;
Sravan Kumar D.V.Nc80da702012-07-19 15:03:29 +0530126 } else { // Else set this flag to false, otherwise video cases
127 // fail in non-overlay targets.
128 ctx->overlayInUse = false;
Jeykumar Sankarane8c4c542012-08-23 11:07:40 -0700129 ctx->mOverlay->setState(ovutils::OV_CLOSED);
Naseer Ahmed73417992012-06-14 00:56:20 -0700130 }
Steve Kondik1a8d9862012-10-31 14:20:41 -0700131 qdutils::CBUtils::checkforGPULayer(list);
132
Steve Kondik2657e2e2012-09-14 10:34:58 -0700133 } else {
134 ctx->overlayInUse = false;
135 ctx->mOverlay->setState(ovutils::OV_CLOSED);
136 ctx->qbuf->unlockAll();
Jeykumar Sankarancfb095e2012-08-28 17:56:00 -0700137
Naseer Ahmed73417992012-06-14 00:56:20 -0700138 }
139 return 0;
140}
141
Naseer Ahmed9ccb3972012-07-21 12:17:13 -0700142static int hwc_eventControl(struct hwc_composer_device* dev,
Arun Kumar K.R9813cf32012-07-27 19:49:03 -0700143 int event, int value)
Naseer Ahmed9ccb3972012-07-21 12:17:13 -0700144{
145 int ret = 0;
Neti Ravi Kumarc356c1c2012-09-16 01:35:41 +0530146 static int prev_value, temp;
147
Naseer Ahmed9ccb3972012-07-21 12:17:13 -0700148 hwc_context_t* ctx = (hwc_context_t*)(dev);
149 private_module_t* m = reinterpret_cast<private_module_t*>(
150 ctx->mFbDev->common.module);
151 switch(event) {
Steve Kondik85ff2df2012-08-07 19:56:31 -0700152#ifndef NO_HW_VSYNC
Naseer Ahmed9ccb3972012-07-21 12:17:13 -0700153 case HWC_EVENT_VSYNC:
Neti Ravi Kumarc356c1c2012-09-16 01:35:41 +0530154 if (value == prev_value){
155 //TODO see why HWC gets repeated events
156 ALOGD_IF(VSYNC_DEBUG, "%s - VSYNC is already %s",
157 __FUNCTION__, (value)?"ENABLED":"DISABLED");
158 }
159 temp = ctx->vstate.enable;
Arun Kumar K.R9813cf32012-07-27 19:49:03 -0700160 if(ioctl(m->framebuffer->fd, MSMFB_OVERLAY_VSYNC_CTRL, &value) < 0)
Naseer Ahmed9ccb3972012-07-21 12:17:13 -0700161 ret = -errno;
Arun Kumar K.Ra72904b2012-07-23 13:44:38 -0700162
Neti Ravi Kumarc356c1c2012-09-16 01:35:41 +0530163 /* vsync state change logic */
164 if (value == 1) {
165 //unblock vsync thread
166 pthread_mutex_lock(&ctx->vstate.lock);
167 ctx->vstate.enable = true;
168 pthread_cond_signal(&ctx->vstate.cond);
169 pthread_mutex_unlock(&ctx->vstate.lock);
Arun Kumar K.Ra72904b2012-07-23 13:44:38 -0700170 }
Neti Ravi Kumarc356c1c2012-09-16 01:35:41 +0530171 if (value == 0 && temp) {
172 //vsync thread will block
173 pthread_mutex_lock(&ctx->vstate.lock);
174 ctx->vstate.enable = false;
175 pthread_mutex_unlock(&ctx->vstate.lock);
176 }
177 ALOGD_IF (VSYNC_DEBUG, "VSYNC state changed from %s to %s",
178 (prev_value)?"ENABLED":"DISABLED", (value)?"ENABLED":"DISABLED");
179 prev_value = value;
180 /* vsync state change logic - end*/
181
182 if(ctx->mExtDisplay->isHDMIConfigured() &&
183 (ctx->mExtDisplay->getExternalDisplay()==EXTERN_DISPLAY_FB1)) {
Arun Kumar K.Rc3dafd12012-09-20 11:01:09 -0700184 // enableHDMIVsync will return -errno on error
Neti Ravi Kumarc356c1c2012-09-16 01:35:41 +0530185 ret = ctx->mExtDisplay->enableHDMIVsync(value);
186 }
Naseer Ahmed9ccb3972012-07-21 12:17:13 -0700187 break;
Steve Kondik85ff2df2012-08-07 19:56:31 -0700188#endif
Arun Kumar K.R9813cf32012-07-27 19:49:03 -0700189 case HWC_EVENT_ORIENTATION:
190 ctx->deviceOrientation = value;
191 break;
Naseer Ahmed9ccb3972012-07-21 12:17:13 -0700192 default:
193 ret = -EINVAL;
194 }
195 return ret;
196}
197
198static int hwc_query(struct hwc_composer_device* dev,
199 int param, int* value)
200{
201 hwc_context_t* ctx = (hwc_context_t*)(dev);
202 private_module_t* m = reinterpret_cast<private_module_t*>(
203 ctx->mFbDev->common.module);
204
205 switch (param) {
206 case HWC_BACKGROUND_LAYER_SUPPORTED:
207 // Not supported for now
208 value[0] = 0;
209 break;
210 case HWC_VSYNC_PERIOD:
211 value[0] = 1000000000.0 / m->fps;
212 ALOGI("fps: %d", value[0]);
213 break;
214 default:
215 return -EINVAL;
216 }
217 return 0;
218
219}
220
Naseer Ahmed73417992012-06-14 00:56:20 -0700221static int hwc_set(hwc_composer_device_t *dev,
222 hwc_display_t dpy,
223 hwc_surface_t sur,
224 hwc_layer_list_t* list)
225{
226 int ret = 0;
227 hwc_context_t* ctx = (hwc_context_t*)(dev);
Naseer Ahmed357ee6d2012-08-27 13:49:18 -0400228 if (dpy && sur) {
229 if (LIKELY(list)) {
230 VideoOverlay::draw(ctx, list);
231 VideoPIP::draw(ctx,list);
232 ExtOnly::draw(ctx, list);
233 CopyBit::draw(ctx, list, (EGLDisplay)dpy, (EGLSurface)sur);
234 MDPComp::draw(ctx, list);
235 }
236 eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur);
Saurabh Shah43dfffc2012-09-10 11:39:45 -0700237 if (ctx->mMDP.hasOverlay) {
238 wait4fbPost(ctx);
239 //Can draw to HDMI only when fb_post is reached
240 UIMirrorOverlay::draw(ctx);
241 //HDMI commit and primary commit (PAN) happening in parallel
242 if(ctx->mExtDisplay->getExternalDisplay())
243 ctx->mExtDisplay->commit();
244 //Virtual barrier for threads to finish
245 wait4Pan(ctx);
246 }
Naseer Ahmed73417992012-06-14 00:56:20 -0700247 } else {
Saurabh Shah57045012012-07-10 18:33:17 -0700248 ctx->mOverlay->setState(ovutils::OV_CLOSED);
Saurabh Shah1be2fcd2012-08-16 10:19:07 -0700249 ctx->qbuf->unlockAll();
Naseer Ahmed73417992012-06-14 00:56:20 -0700250 }
Saurabh Shah57045012012-07-10 18:33:17 -0700251
Saurabh Shah57045012012-07-10 18:33:17 -0700252
Saurabh Shah0a2352a2012-08-23 08:41:05 -0700253 ctx->qbuf->unlockAllPrevious();
Naseer Ahmed73417992012-06-14 00:56:20 -0700254 return ret;
255}
256
257static int hwc_device_close(struct hw_device_t *dev)
258{
259 if(!dev) {
Naseer Ahmed9ccb3972012-07-21 12:17:13 -0700260 ALOGE("%s: NULL device pointer", __FUNCTION__);
Naseer Ahmed73417992012-06-14 00:56:20 -0700261 return -1;
262 }
263 closeContext((hwc_context_t*)dev);
264 free(dev);
265
266 return 0;
267}
268
269static int hwc_device_open(const struct hw_module_t* module, const char* name,
270 struct hw_device_t** device)
271{
272 int status = -EINVAL;
273
274 if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
275 struct hwc_context_t *dev;
276 dev = (hwc_context_t*)malloc(sizeof(*dev));
277 memset(dev, 0, sizeof(*dev));
Naseer Ahmed9ccb3972012-07-21 12:17:13 -0700278
279 //Initialize hwc context
Naseer Ahmed73417992012-06-14 00:56:20 -0700280 initContext(dev);
Naseer Ahmed9ccb3972012-07-21 12:17:13 -0700281
282 //Setup HWC methods
283 hwc_methods_t *methods;
284 methods = (hwc_methods_t *)malloc(sizeof(*methods));
285 memset(methods, 0, sizeof(*methods));
286 methods->eventControl = hwc_eventControl;
287
Naseer Ahmed73417992012-06-14 00:56:20 -0700288 dev->device.common.tag = HARDWARE_DEVICE_TAG;
Neti Ravi Kumar673e4932012-09-12 18:14:25 +0530289#ifndef NO_HW_VSYNC
290 //XXX: This disables hardware vsync on 8x55
291 // Fix when HW vsync is available on 8x55
292 if(dev->mMDP.version == 400 || (dev->mMDP.version >= 500)) {
293#endif
294 dev->device.common.version = 0;
295 ALOGI("%s: Hardware VSYNC not supported", __FUNCTION__);
296#ifndef NO_HW_VSYNC
297 } else {
298 dev->device.common.version = HWC_DEVICE_API_VERSION_0_3;
299 ALOGI("%s: Hardware VSYNC supported", __FUNCTION__);
300 }
Steve Kondik85ff2df2012-08-07 19:56:31 -0700301#endif
Naseer Ahmed73417992012-06-14 00:56:20 -0700302 dev->device.common.module = const_cast<hw_module_t*>(module);
303 dev->device.common.close = hwc_device_close;
304 dev->device.prepare = hwc_prepare;
305 dev->device.set = hwc_set;
306 dev->device.registerProcs = hwc_registerProcs;
Naseer Ahmed9ccb3972012-07-21 12:17:13 -0700307 dev->device.query = hwc_query;
308 dev->device.methods = methods;
Naseer Ahmed73417992012-06-14 00:56:20 -0700309 *device = &dev->device.common;
310 status = 0;
311 }
312 return status;
313}