blob: a0a0c82d83e02bb283bf42bb2da20e2ab73001f1 [file] [log] [blame]
Naseer Ahmed29a26812012-06-14 00:56:20 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
Saurabh Shah56f610d2012-08-07 15:27:06 -07003 * Copyright (C) 2012, The Linux Foundation. All rights reserved.
Naseer Ahmed29a26812012-06-14 00:56:20 -07004 *
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 Ahmed72cf9762012-07-21 12:17:13 -070023#include <EGL/egl.h>
Naseer Ahmed29a26812012-06-14 00:56:20 -070024
Naseer Ahmed72cf9762012-07-21 12:17:13 -070025#include <overlay.h>
26#include <fb_priv.h>
Naseer Ahmed96c4c952012-07-25 18:27:14 -070027#include <mdp_version.h>
Naseer Ahmed29a26812012-06-14 00:56:20 -070028#include "hwc_utils.h"
Naseer Ahmedf48aef62012-07-20 09:05:53 -070029#include "hwc_video.h"
Naseer Ahmed758bfc52012-11-28 17:02:08 -050030#include "hwc_fbupdate.h"
Naseer Ahmed54821fe2012-11-28 18:44:38 -050031#include "hwc_mdpcomp.h"
Saurabh Shah56f610d2012-08-07 15:27:06 -070032#include "external.h"
Naseer Ahmed29a26812012-06-14 00:56:20 -070033
34using namespace qhwc;
Naseer Ahmed758bfc52012-11-28 17:02:08 -050035#define VSYNC_DEBUG 0
Naseer Ahmed29a26812012-06-14 00:56:20 -070036
37static int hwc_device_open(const struct hw_module_t* module,
38 const char* name,
39 struct hw_device_t** device);
40
41static struct hw_module_methods_t hwc_module_methods = {
42 open: hwc_device_open
43};
44
45hwc_module_t HAL_MODULE_INFO_SYM = {
46 common: {
47 tag: HARDWARE_MODULE_TAG,
48 version_major: 2,
49 version_minor: 0,
50 id: HWC_HARDWARE_MODULE_ID,
51 name: "Qualcomm Hardware Composer Module",
52 author: "CodeAurora Forum",
53 methods: &hwc_module_methods,
54 dso: 0,
55 reserved: {0},
56 }
57};
58
59/*
60 * Save callback functions registered to HWC
61 */
Naseer Ahmed5b6708a2012-08-02 13:46:08 -070062static void hwc_registerProcs(struct hwc_composer_device_1* dev,
Naseer Ahmed29a26812012-06-14 00:56:20 -070063 hwc_procs_t const* procs)
64{
Iliyan Malchev0f9c3972012-10-11 15:16:15 -070065 ALOGI("%s", __FUNCTION__);
Naseer Ahmed29a26812012-06-14 00:56:20 -070066 hwc_context_t* ctx = (hwc_context_t*)(dev);
67 if(!ctx) {
68 ALOGE("%s: Invalid context", __FUNCTION__);
69 return;
70 }
Jesse Hall3be78d92012-08-21 15:12:23 -070071 ctx->proc = procs;
72
Naseer Ahmedff4f0252012-10-01 13:03:01 -040073 // Now that we have the functions needed, kick off
74 // the uevent & vsync threads
Jesse Hall3be78d92012-08-21 15:12:23 -070075 init_uevent_thread(ctx);
Naseer Ahmedff4f0252012-10-01 13:03:01 -040076 init_vsync_thread(ctx);
Naseer Ahmed29a26812012-06-14 00:56:20 -070077}
78
Saurabh Shah649cda62012-09-16 16:05:58 -070079//Helper
Naseer Ahmedb1c76322012-10-17 00:32:50 -040080static void reset(hwc_context_t *ctx, int numDisplays,
81 hwc_display_contents_1_t** displays) {
Saurabh Shah3e858eb2012-09-17 16:53:21 -070082 memset(ctx->listStats, 0, sizeof(ctx->listStats));
Saurabh Shah1a8cda02012-10-12 17:00:39 -070083 for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++){
Saurabh Shah3e858eb2012-09-17 16:53:21 -070084 ctx->listStats[i].yuvIndex = -1;
Naseer Ahmedb1c76322012-10-17 00:32:50 -040085 hwc_display_contents_1_t *list = displays[i];
86 // XXX:SurfaceFlinger no longer guarantees that this
87 // value is reset on every prepare. However, for the layer
88 // cache we need to reset it.
89 // We can probably rethink that later on
90 if (LIKELY(list && list->numHwLayers > 1)) {
91 for(uint32_t j = 0; j < list->numHwLayers; j++) {
92 if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET)
93 list->hwLayers[j].compositionType = HWC_FRAMEBUFFER;
94 }
95 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -070096 }
Naseer Ahmed758bfc52012-11-28 17:02:08 -050097 VideoOverlay::reset();
98 FBUpdate::reset();
Saurabh Shah3e858eb2012-09-17 16:53:21 -070099}
100
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500101//clear prev layer prop flags and realloc for current frame
102static void reset_layer_prop(hwc_context_t* ctx, int dpy) {
103 int layer_count = ctx->listStats[dpy].numAppLayers;
104
105 if(ctx->layerProp[dpy]) {
106 delete[] ctx->layerProp[dpy];
107 ctx->layerProp[dpy] = NULL;
108 }
109
110 if(layer_count) {
111 ctx->layerProp[dpy] = new LayerProp[layer_count];
112 }
113}
114
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700115static int hwc_prepare_primary(hwc_composer_device_1 *dev,
116 hwc_display_contents_1_t *list) {
117 hwc_context_t* ctx = (hwc_context_t*)(dev);
Saurabh Shah1a8cda02012-10-12 17:00:39 -0700118
119 if (LIKELY(list && list->numHwLayers > 1) &&
120 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) {
121
Saurabh Shah86623d72012-09-25 19:39:17 -0700122 uint32_t last = list->numHwLayers - 1;
Saurabh Shah1a8cda02012-10-12 17:00:39 -0700123 hwc_layer_1_t *fbLayer = &list->hwLayers[last];
124 if(fbLayer->handle) {
125 setListStats(ctx, list, HWC_DISPLAY_PRIMARY);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500126 reset_layer_prop(ctx, HWC_DISPLAY_PRIMARY);
127 if(!MDPComp::configure(ctx, list)) {
128 VideoOverlay::prepare(ctx, list, HWC_DISPLAY_PRIMARY);
129 FBUpdate::prepare(ctx, fbLayer, HWC_DISPLAY_PRIMARY);
130 }
Naseer Ahmed8df2ebf2012-12-12 11:26:18 -0500131 ctx->mLayerCache[HWC_DISPLAY_PRIMARY]->updateLayerCache(list);
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700132 }
133 }
134 return 0;
135}
136
137static int hwc_prepare_external(hwc_composer_device_1 *dev,
138 hwc_display_contents_1_t *list) {
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700139 hwc_context_t* ctx = (hwc_context_t*)(dev);
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700140
Saurabh Shahae823e72012-10-05 00:08:11 -0400141 if (LIKELY(list && list->numHwLayers > 1) &&
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700142 ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive &&
143 ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected) {
144
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700145 uint32_t last = list->numHwLayers - 1;
Saurabh Shah1a8cda02012-10-12 17:00:39 -0700146 hwc_layer_1_t *fbLayer = &list->hwLayers[last];
147 if(fbLayer->handle) {
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500148 setListStats(ctx, list, HWC_DISPLAY_EXTERNAL);
149 reset_layer_prop(ctx, HWC_DISPLAY_EXTERNAL);
150
Naseer Ahmed758bfc52012-11-28 17:02:08 -0500151 VideoOverlay::prepare(ctx, list, HWC_DISPLAY_EXTERNAL);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500152 FBUpdate::prepare(ctx, fbLayer, HWC_DISPLAY_EXTERNAL);
Naseer Ahmede78f0522012-12-07 18:24:28 -0500153 ctx->mLayerCache[HWC_DISPLAY_EXTERNAL]->updateLayerCache(list);
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700154 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700155 }
156 return 0;
Saurabh Shah649cda62012-09-16 16:05:58 -0700157}
158
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700159static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
160 hwc_display_contents_1_t** displays)
Naseer Ahmed29a26812012-06-14 00:56:20 -0700161{
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700162 int ret = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700163 hwc_context_t* ctx = (hwc_context_t*)(dev);
Naseer Ahmed758bfc52012-11-28 17:02:08 -0500164 Locker::Autolock _l(ctx->mBlankLock);
Naseer Ahmedb1c76322012-10-17 00:32:50 -0400165 reset(ctx, numDisplays, displays);
Saurabh Shah56f610d2012-08-07 15:27:06 -0700166
Naseer Ahmed758bfc52012-11-28 17:02:08 -0500167 ctx->mOverlay->configBegin();
Saurabh Shah56f610d2012-08-07 15:27:06 -0700168
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500169 for (int32_t i = numDisplays - 1; i >= 0; i--) {
170 hwc_display_contents_1_t *list = displays[i];
171 switch(i) {
172 case HWC_DISPLAY_PRIMARY:
173 ret = hwc_prepare_primary(dev, list);
174 break;
175 case HWC_DISPLAY_EXTERNAL:
176
177 ret = hwc_prepare_external(dev, list);
178 break;
179 default:
180 ret = -EINVAL;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700181 }
182 }
Naseer Ahmed758bfc52012-11-28 17:02:08 -0500183 ctx->mOverlay->configDone();
184
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700185 return ret;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700186}
187
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700188static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700189 int event, int enabled)
190{
191 int ret = 0;
Naseer Ahmedff4f0252012-10-01 13:03:01 -0400192
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700193 hwc_context_t* ctx = (hwc_context_t*)(dev);
194 private_module_t* m = reinterpret_cast<private_module_t*>(
195 ctx->mFbDev->common.module);
Iliyan Malcheveac89652012-10-04 10:38:28 -0700196 pthread_mutex_lock(&ctx->vstate.lock);
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700197 switch(event) {
198 case HWC_EVENT_VSYNC:
Omprakash Dhyade1ef881c2012-10-03 02:26:55 -0700199 if (ctx->vstate.enable == enabled)
200 break;
Iliyan Malcheveac89652012-10-04 10:38:28 -0700201 ctx->vstate.enable = !!enabled;
Naseer Ahmedc7faa702012-10-04 15:10:30 -0400202 pthread_cond_signal(&ctx->vstate.cond);
Iliyan Malcheveac89652012-10-04 10:38:28 -0700203 ALOGD_IF (VSYNC_DEBUG, "VSYNC state changed to %s",
204 (enabled)?"ENABLED":"DISABLED");
205 break;
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700206 default:
207 ret = -EINVAL;
208 }
Iliyan Malcheveac89652012-10-04 10:38:28 -0700209 pthread_mutex_unlock(&ctx->vstate.lock);
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700210 return ret;
211}
212
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700213static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank)
214{
Naseer Ahmed934790c2012-08-16 18:11:09 -0700215 hwc_context_t* ctx = (hwc_context_t*)(dev);
216 private_module_t* m = reinterpret_cast<private_module_t*>(
217 ctx->mFbDev->common.module);
Naseer Ahmed758bfc52012-11-28 17:02:08 -0500218 Locker::Autolock _l(ctx->mBlankLock);
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700219 int ret = 0;
220 ALOGD("%s: Doing Dpy=%d, blank=%d", __FUNCTION__, dpy, blank);
221 switch(dpy) {
222 case HWC_DISPLAY_PRIMARY:
223 if(blank) {
Naseer Ahmed758bfc52012-11-28 17:02:08 -0500224 ctx->mOverlay->configBegin();
225 ctx->mOverlay->configDone();
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700226 ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN);
227 } else {
228 ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_UNBLANK);
229 }
230 break;
231 case HWC_DISPLAY_EXTERNAL:
232 if(blank) {
233 //TODO actual
234 } else {
235 }
236 break;
237 default:
238 return -EINVAL;
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700239 }
Arun Kumar K.Rf6f49a12012-11-27 11:46:50 -0800240 // Enable HPD here, as during bootup unblank is called
241 // when SF is completely initialized
242 ctx->mExtDisplay->setHPD(1);
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700243
244 if(ret < 0) {
245 ALOGE("%s: failed. Dpy=%d, blank=%d : %s",
246 __FUNCTION__, dpy, blank, strerror(errno));
247 return ret;
248 }
249 ALOGD("%s: Done Dpy=%d, blank=%d", __FUNCTION__, dpy, blank);
250 ctx->dpyAttr[dpy].isActive = !blank;
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700251 return 0;
252}
253
254static int hwc_query(struct hwc_composer_device_1* dev,
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700255 int param, int* value)
256{
257 hwc_context_t* ctx = (hwc_context_t*)(dev);
258 private_module_t* m = reinterpret_cast<private_module_t*>(
259 ctx->mFbDev->common.module);
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700260 int supported = HWC_DISPLAY_PRIMARY_BIT;
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700261
262 switch (param) {
263 case HWC_BACKGROUND_LAYER_SUPPORTED:
264 // Not supported for now
265 value[0] = 0;
266 break;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700267 case HWC_VSYNC_PERIOD: //Not used for hwc > 1.1
Saurabh Shah2e2798c2012-08-30 14:47:10 -0700268 value[0] = m->fps;
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700269 ALOGI("fps: %d", value[0]);
270 break;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700271 case HWC_DISPLAY_TYPES_SUPPORTED:
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700272 if(ctx->mMDP.hasOverlay)
273 supported |= HWC_DISPLAY_EXTERNAL_BIT;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700274 value[0] = supported;
275 break;
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700276 default:
277 return -EINVAL;
278 }
279 return 0;
280
281}
282
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700283static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Saurabh Shaheaf67912012-10-10 17:33:14 -0700284 int ret = 0;
285
Saurabh Shahae823e72012-10-05 00:08:11 -0400286 if (LIKELY(list && list->numHwLayers > 1) &&
287 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) {
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700288 uint32_t last = list->numHwLayers - 1;
289 hwc_layer_1_t *fbLayer = &list->hwLayers[last];
290
Saurabh Shah8c8bfd22012-09-26 21:09:40 -0700291 hwc_sync(ctx, list, HWC_DISPLAY_PRIMARY);
Saurabh Shaheaf67912012-10-10 17:33:14 -0700292 if (!VideoOverlay::draw(ctx, list, HWC_DISPLAY_PRIMARY)) {
293 ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__);
294 ret = -1;
295 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500296 if (!MDPComp::draw(ctx, list)) {
297 ALOGE("%s: MDPComp::draw fail!", __FUNCTION__);
298 ret = -1;
299 }
300
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700301 //TODO We dont check for SKIP flag on this layer because we need PAN
302 //always. Last layer is always FB
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500303 private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
304 if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET && hnd) {
305 if(!(fbLayer->flags & HWC_SKIP_LAYER)) {
306 if (!FBUpdate::draw(ctx, fbLayer, HWC_DISPLAY_PRIMARY)) {
307 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
308 ret = -1;
309 }
310 }
Saurabh Shaheaf67912012-10-10 17:33:14 -0700311 if (ctx->mFbDev->post(ctx->mFbDev, fbLayer->handle)) {
312 ALOGE("%s: ctx->mFbDev->post fail!", __FUNCTION__);
313 return -1;
314 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700315 }
316 }
Saurabh Shaheaf67912012-10-10 17:33:14 -0700317 return ret;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700318}
319
320static int hwc_set_external(hwc_context_t *ctx,
321 hwc_display_contents_1_t* list) {
Saurabh Shaheaf67912012-10-10 17:33:14 -0700322 int ret = 0;
Kinjal Bhavsarf83d4482012-10-10 15:56:21 -0700323 Locker::Autolock _l(ctx->mExtSetLock);
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700324
Saurabh Shahae823e72012-10-05 00:08:11 -0400325 if (LIKELY(list && list->numHwLayers > 1) &&
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700326 ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive &&
327 ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected) {
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700328 uint32_t last = list->numHwLayers - 1;
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700329 hwc_layer_1_t *fbLayer = &list->hwLayers[last];
330
331 hwc_sync(ctx, list, HWC_DISPLAY_EXTERNAL);
332
Saurabh Shaheaf67912012-10-10 17:33:14 -0700333 if (!VideoOverlay::draw(ctx, list, HWC_DISPLAY_EXTERNAL)) {
334 ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__);
335 ret = -1;
336 }
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700337
338 private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
Saurabh Shah150806a2012-10-09 15:38:23 -0700339 if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET &&
340 !(fbLayer->flags & HWC_SKIP_LAYER) && hnd) {
Naseer Ahmed758bfc52012-11-28 17:02:08 -0500341 if (!FBUpdate::draw(ctx, fbLayer, HWC_DISPLAY_EXTERNAL)) {
342 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
Saurabh Shaheaf67912012-10-10 17:33:14 -0700343 ret = -1;
344 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700345 }
Saurabh Shaheaf67912012-10-10 17:33:14 -0700346 if (!ctx->mExtDisplay->post()) {
347 ALOGE("%s: ctx->mExtDisplay->post fail!", __FUNCTION__);
348 return -1;
349 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700350 }
Saurabh Shaheaf67912012-10-10 17:33:14 -0700351 return ret;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700352}
353
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700354static int hwc_set(hwc_composer_device_1 *dev,
355 size_t numDisplays,
356 hwc_display_contents_1_t** displays)
Naseer Ahmed29a26812012-06-14 00:56:20 -0700357{
358 int ret = 0;
359 hwc_context_t* ctx = (hwc_context_t*)(dev);
Naseer Ahmed32ff2252012-09-29 01:41:21 -0400360 Locker::Autolock _l(ctx->mBlankLock);
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700361
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700362 for (uint32_t i = 0; i < numDisplays; i++) {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700363 hwc_display_contents_1_t* list = displays[i];
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700364 switch(i) {
365 case HWC_DISPLAY_PRIMARY:
366 ret = hwc_set_primary(ctx, list);
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700367 break;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700368 case HWC_DISPLAY_EXTERNAL:
369 ret = hwc_set_external(ctx, list);
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700370 break;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700371 default:
372 ret = -EINVAL;
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700373 }
Naseer Ahmed29a26812012-06-14 00:56:20 -0700374 }
Naseer Ahmed29a26812012-06-14 00:56:20 -0700375 return ret;
376}
377
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700378int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp,
379 uint32_t* configs, size_t* numConfigs) {
380 int ret = 0;
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700381 hwc_context_t* ctx = (hwc_context_t*)(dev);
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700382 //in 1.1 there is no way to choose a config, report as config id # 0
383 //This config is passed to getDisplayAttributes. Ignore for now.
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700384 switch(disp) {
385 case HWC_DISPLAY_PRIMARY:
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700386 if(*numConfigs > 0) {
387 configs[0] = 0;
388 *numConfigs = 1;
389 }
390 ret = 0; //NO_ERROR
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700391 break;
392 case HWC_DISPLAY_EXTERNAL:
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700393 ret = -1; //Not connected
394 if(ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected) {
395 ret = 0; //NO_ERROR
396 if(*numConfigs > 0) {
397 configs[0] = 0;
398 *numConfigs = 1;
399 }
400 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700401 break;
402 }
403 return ret;
404}
405
406int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp,
407 uint32_t config, const uint32_t* attributes, int32_t* values) {
408
409 hwc_context_t* ctx = (hwc_context_t*)(dev);
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700410 //If hotpluggable displays are inactive return error
411 if(disp == HWC_DISPLAY_EXTERNAL && !ctx->dpyAttr[disp].connected) {
412 return -1;
413 }
414
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700415 //From HWComposer
416 static const uint32_t DISPLAY_ATTRIBUTES[] = {
417 HWC_DISPLAY_VSYNC_PERIOD,
418 HWC_DISPLAY_WIDTH,
419 HWC_DISPLAY_HEIGHT,
420 HWC_DISPLAY_DPI_X,
421 HWC_DISPLAY_DPI_Y,
422 HWC_DISPLAY_NO_ATTRIBUTE,
423 };
424
425 const int NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
426 sizeof(DISPLAY_ATTRIBUTES)[0]);
427
428 for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
429 switch (attributes[i]) {
430 case HWC_DISPLAY_VSYNC_PERIOD:
431 values[i] = ctx->dpyAttr[disp].vsync_period;
432 break;
433 case HWC_DISPLAY_WIDTH:
434 values[i] = ctx->dpyAttr[disp].xres;
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700435 ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp,
436 ctx->dpyAttr[disp].xres);
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700437 break;
438 case HWC_DISPLAY_HEIGHT:
439 values[i] = ctx->dpyAttr[disp].yres;
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700440 ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp,
441 ctx->dpyAttr[disp].yres);
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700442 break;
443 case HWC_DISPLAY_DPI_X:
Naseer Ahmed7b80d9c2012-09-26 20:14:38 -0400444 values[i] = (int32_t) (ctx->dpyAttr[disp].xdpi*1000.0);
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700445 break;
446 case HWC_DISPLAY_DPI_Y:
Naseer Ahmed7b80d9c2012-09-26 20:14:38 -0400447 values[i] = (int32_t) (ctx->dpyAttr[disp].ydpi*1000.0);
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700448 break;
449 default:
450 ALOGE("Unknown display attribute %d",
451 attributes[i]);
452 return -EINVAL;
453 }
454 }
455 return 0;
456}
457
Naseer Ahmed1d183f52012-11-26 12:35:16 -0500458void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len)
459{
460 hwc_context_t* ctx = (hwc_context_t*)(dev);
461 android::String8 buf("");
462 dumpsys_log(buf, "Qualcomm HWC state:\n");
463 dumpsys_log(buf, " MDPVersion=%d\n", ctx->mMDP.version);
464 dumpsys_log(buf, " DisplayPanel=%c\n", ctx->mMDP.panel);
465 MDPComp::dump(buf);
466 //XXX: Call Other dump functions
467 strlcpy(buff, buf.string(), buff_len);
468}
469
Naseer Ahmed29a26812012-06-14 00:56:20 -0700470static int hwc_device_close(struct hw_device_t *dev)
471{
472 if(!dev) {
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700473 ALOGE("%s: NULL device pointer", __FUNCTION__);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700474 return -1;
475 }
476 closeContext((hwc_context_t*)dev);
477 free(dev);
478
479 return 0;
480}
481
482static int hwc_device_open(const struct hw_module_t* module, const char* name,
483 struct hw_device_t** device)
484{
485 int status = -EINVAL;
486
487 if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
488 struct hwc_context_t *dev;
489 dev = (hwc_context_t*)malloc(sizeof(*dev));
490 memset(dev, 0, sizeof(*dev));
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700491
492 //Initialize hwc context
Naseer Ahmed29a26812012-06-14 00:56:20 -0700493 initContext(dev);
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700494
495 //Setup HWC methods
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700496 dev->device.common.tag = HARDWARE_DEVICE_TAG;
497 dev->device.common.version = HWC_DEVICE_API_VERSION_1_1;
498 dev->device.common.module = const_cast<hw_module_t*>(module);
499 dev->device.common.close = hwc_device_close;
500 dev->device.prepare = hwc_prepare;
501 dev->device.set = hwc_set;
502 dev->device.eventControl = hwc_eventControl;
503 dev->device.blank = hwc_blank;
504 dev->device.query = hwc_query;
505 dev->device.registerProcs = hwc_registerProcs;
Naseer Ahmed1d183f52012-11-26 12:35:16 -0500506 dev->device.dump = hwc_dump;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700507 dev->device.getDisplayConfigs = hwc_getDisplayConfigs;
508 dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
509 *device = &dev->device.common;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700510 status = 0;
511 }
512 return status;
513}