1ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann/* 2ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann * Copyright (C) 2013 The Android Open Source Project 3ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann * 4ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann * Licensed under the Apache License, Version 2.0 (the "License"); 5ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann * you may not use this file except in compliance with the License. 6ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann * You may obtain a copy of the License at 7ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann * 8ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann * http://www.apache.org/licenses/LICENSE-2.0 9ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann * 10ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann * Unless required by applicable law or agreed to in writing, software 11ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann * distributed under the License is distributed on an "AS IS" BASIS, 12ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann * See the License for the specific language governing permissions and 14ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann * limitations under the License. 15ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann */ 16ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 17ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann#include <fcntl.h> 18a744b05984a963966cec08758ffe582d241be9d7Elliott Hughes#include <malloc.h> 19ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann#include <poll.h> 20ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann#include <pthread.h> 21ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann#include <sys/resource.h> 22ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 2330f991f251940be3ed11566fb71139852286f68aMark Salyzyn#include <log/log.h> 2466ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn#include <utils/Vector.h> 2566ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn 26ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann#include <adf/adf.h> 27ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann#include <adfhwc/adfhwc.h> 28ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 29ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmannstruct adf_hwc_helper { 30ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann adf_hwc_event_callbacks const *event_cb; 31ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann void *event_cb_data; 32ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 33ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann pthread_t event_thread; 34ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 35ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann android::Vector<int> intf_fds; 36ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann android::Vector<drm_mode_modeinfo> display_configs; 37ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann}; 38ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 39ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmanntemplate<typename T> inline T min(T a, T b) { return (a < b) ? a : b; } 40ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 41ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmannint adf_eventControl(struct adf_hwc_helper *dev, int disp, int event, 42ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann int enabled) 43ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann{ 44ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann if (enabled != !!enabled) 45ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return -EINVAL; 46ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 47ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann if ((size_t)disp >= dev->intf_fds.size()) 48ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return -EINVAL; 49ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 50ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann switch (event) { 51ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann case HWC_EVENT_VSYNC: 52ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return adf_set_event(dev->intf_fds[disp], ADF_EVENT_VSYNC, enabled); 53ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann } 54ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 55ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return -EINVAL; 56ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann} 57ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 58ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmannstatic inline int32_t dpi(uint16_t res, uint16_t size_mm) 59ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann{ 60ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann if (size_mm) 61ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return 1000 * (res * 25.4f) / size_mm; 62ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return 0; 63ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann} 64ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 65ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmannint adf_blank(struct adf_hwc_helper *dev, int disp, int blank) 66ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann{ 67ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann if ((size_t)disp >= dev->intf_fds.size()) 68ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return -EINVAL; 69ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 70ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann uint8_t dpms_mode = blank ? DRM_MODE_DPMS_OFF : DRM_MODE_DPMS_ON; 71ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return adf_interface_blank(dev->intf_fds[disp], dpms_mode); 72ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann} 73ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 74ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmannint adf_query_display_types_supported(struct adf_hwc_helper *dev, int *value) 75ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann{ 76ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann *value = 0; 77ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann if (dev->intf_fds.size() > 0) 78ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann *value |= HWC_DISPLAY_PRIMARY_BIT; 79ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann if (dev->intf_fds.size() > 1) 80ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann *value |= HWC_DISPLAY_EXTERNAL_BIT; 81ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 82ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return 0; 83ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann} 84ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 85ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmannint adf_getDisplayConfigs(struct adf_hwc_helper *dev, int disp, 86ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann uint32_t *configs, size_t *numConfigs) 87ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann{ 88ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann if ((size_t)disp >= dev->intf_fds.size()) 89ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return -EINVAL; 90ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 91ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann adf_interface_data data; 92ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann int err = adf_get_interface_data(dev->intf_fds[disp], &data); 93ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann if (err < 0) { 94ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann ALOGE("failed to get ADF interface data: %s", strerror(err)); 95ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return err; 96ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann } 97ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 98ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann if (!data.hotplug_detect) 99ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return -ENODEV; 100ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 101ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann android::Vector<drm_mode_modeinfo *> unique_configs; 102ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann unique_configs.push_back(&data.current_mode); 103ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann for (size_t i = 0; i < data.n_available_modes; i++) 104ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann if (memcmp(&data.available_modes[i], &data.current_mode, 105ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann sizeof(data.current_mode))) 106ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann unique_configs.push_back(&data.available_modes[i]); 107ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 108ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann for (size_t i = 0; i < min(*numConfigs, unique_configs.size()); i++) { 109ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann configs[i] = dev->display_configs.size(); 110ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann dev->display_configs.push_back(*unique_configs[i]); 111ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann } 112ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann *numConfigs = unique_configs.size(); 113ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 114ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann adf_free_interface_data(&data); 115ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return 0; 116ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann} 117ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 118ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmannstatic int32_t adf_display_attribute(const adf_interface_data &data, 119ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann const drm_mode_modeinfo &mode, const uint32_t attribute) 120ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann{ 121ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann switch (attribute) { 122ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann case HWC_DISPLAY_VSYNC_PERIOD: 123ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann if (mode.vrefresh) 124ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return 1000000000 / mode.vrefresh; 125ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return 0; 126ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 127ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann case HWC_DISPLAY_WIDTH: 128ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return mode.hdisplay; 129ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 130ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann case HWC_DISPLAY_HEIGHT: 131ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return mode.vdisplay; 132ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 133ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann case HWC_DISPLAY_DPI_X: 134ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return dpi(mode.hdisplay, data.width_mm); 135ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 136ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann case HWC_DISPLAY_DPI_Y: 137ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return dpi(mode.vdisplay, data.height_mm); 138ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 139ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann default: 140ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann ALOGE("unknown display attribute %u", attribute); 141ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return -EINVAL; 142ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann } 143ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann} 144ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 145ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmannint adf_getDisplayAttributes(struct adf_hwc_helper *dev, int disp, 146ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann uint32_t config, const uint32_t *attributes, int32_t *values) 147ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann{ 148ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann if ((size_t)disp >= dev->intf_fds.size()) 149ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return -EINVAL; 150ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 151ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann if (config >= dev->display_configs.size()) 152ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return -EINVAL; 153ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 154ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann adf_interface_data data; 155ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann int err = adf_get_interface_data(dev->intf_fds[disp], &data); 156ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann if (err < 0) { 157ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann ALOGE("failed to get ADF interface data: %s", strerror(err)); 158ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return err; 159ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann } 160ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 161ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) 162ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann values[i] = adf_display_attribute(data, dev->display_configs[config], 163ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann attributes[i]); 164ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 165ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann adf_free_interface_data(&data); 166ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return 0; 167ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann} 168ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 1699dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wallstatic int32_t adf_display_attribute_hwc2(const adf_interface_data &data, 1709dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall const drm_mode_modeinfo &mode, const uint32_t attribute) 1719dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall{ 1729dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall switch (attribute) { 1739dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall case HWC2_ATTRIBUTE_VSYNC_PERIOD: 1749dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall if (mode.vrefresh) 1759dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall return 1000000000 / mode.vrefresh; 1769dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall return 0; 1779dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall 1789dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall case HWC2_ATTRIBUTE_WIDTH: 1799dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall return mode.hdisplay; 1809dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall 1819dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall case HWC2_ATTRIBUTE_HEIGHT: 1829dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall return mode.vdisplay; 1839dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall 1849dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall case HWC2_ATTRIBUTE_DPI_X: 1859dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall return dpi(mode.hdisplay, data.width_mm); 1869dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall 1879dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall case HWC2_ATTRIBUTE_DPI_Y: 1889dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall return dpi(mode.vdisplay, data.height_mm); 1899dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall 1909dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall default: 1919dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall ALOGE("unknown display attribute %u", attribute); 1929dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall return -EINVAL; 1939dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall } 1949dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall} 1959dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall 1969dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wallint adf_getDisplayAttributes_hwc2(struct adf_hwc_helper *dev, int disp, 1979dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall uint32_t config, const uint32_t *attributes, int32_t *values) 1989dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall{ 1999dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall if ((size_t)disp >= dev->intf_fds.size()) 2009dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall return -EINVAL; 2019dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall 2029dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall if (config >= dev->display_configs.size()) 2039dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall return -EINVAL; 2049dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall 2059dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall adf_interface_data data; 2069dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall int err = adf_get_interface_data(dev->intf_fds[disp], &data); 2079dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall if (err < 0) { 2089dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall ALOGE("failed to get ADF interface data: %s", strerror(err)); 2099dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall return err; 2109dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall } 2119dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall 2129dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall for (int i = 0; attributes[i] != HWC2_ATTRIBUTE_INVALID; i++) 2139dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall values[i] = adf_display_attribute_hwc2(data, 2149dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall dev->display_configs[config], attributes[i]); 2159dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall 2169dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall adf_free_interface_data(&data); 2179dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall return 0; 2189dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall} 2199dcd750d8139b93272c9a49533b3bbde138ab6aaMarissa Wall 220b4f00414215183e41eb701e53289bfe0d4db0e8dMarissa Wallint adf_set_active_config_hwc2(struct adf_hwc_helper *dev, int disp, 221b4f00414215183e41eb701e53289bfe0d4db0e8dMarissa Wall uint32_t config) 222b4f00414215183e41eb701e53289bfe0d4db0e8dMarissa Wall{ 223b4f00414215183e41eb701e53289bfe0d4db0e8dMarissa Wall if ((size_t)disp >= dev->intf_fds.size()) 224b4f00414215183e41eb701e53289bfe0d4db0e8dMarissa Wall return -EINVAL; 225b4f00414215183e41eb701e53289bfe0d4db0e8dMarissa Wall 226b4f00414215183e41eb701e53289bfe0d4db0e8dMarissa Wall if (config >= dev->display_configs.size()) 227b4f00414215183e41eb701e53289bfe0d4db0e8dMarissa Wall return -EINVAL; 228b4f00414215183e41eb701e53289bfe0d4db0e8dMarissa Wall 229b4f00414215183e41eb701e53289bfe0d4db0e8dMarissa Wall struct drm_mode_modeinfo mode = dev->display_configs[config]; 230b4f00414215183e41eb701e53289bfe0d4db0e8dMarissa Wall 231b4f00414215183e41eb701e53289bfe0d4db0e8dMarissa Wall return adf_interface_set_mode(dev->intf_fds[disp], &mode); 232b4f00414215183e41eb701e53289bfe0d4db0e8dMarissa Wall} 233b4f00414215183e41eb701e53289bfe0d4db0e8dMarissa Wall 234ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmannstatic void handle_adf_event(struct adf_hwc_helper *dev, int disp) 235ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann{ 236ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann adf_event *event; 237ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann int err = adf_read_event(dev->intf_fds[disp], &event); 238ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann if (err < 0) { 239ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann ALOGE("error reading event from display %d: %s", disp, strerror(err)); 240ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return; 241ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann } 242ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 243ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann void *vsync_temp; 244ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann adf_vsync_event *vsync; 245ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann adf_hotplug_event *hotplug; 246ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 247ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann switch (event->type) { 248ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann case ADF_EVENT_VSYNC: 249ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann vsync_temp = event; 250ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann vsync = static_cast<adf_vsync_event *>(vsync_temp); 251ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann // casting directly to adf_vsync_event * makes g++ warn about 252ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann // potential alignment issues that don't apply here 253ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann dev->event_cb->vsync(dev->event_cb_data, disp, vsync->timestamp); 254ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann break; 255ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann case ADF_EVENT_HOTPLUG: 256ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann hotplug = reinterpret_cast<adf_hotplug_event *>(event); 257ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann dev->event_cb->hotplug(dev->event_cb_data, disp, hotplug->connected); 258ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann break; 259ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann default: 260ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann if (event->type < ADF_EVENT_DEVICE_CUSTOM) 261ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann ALOGW("unrecognized event type %u", event->type); 262ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann else if (!dev->event_cb || !dev->event_cb->custom_event) 263ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann ALOGW("unhandled event type %u", event->type); 264ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann else 265ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann dev->event_cb->custom_event(dev->event_cb_data, disp, event); 266ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann } 267ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann free(event); 268ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann} 269ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 270ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmannstatic void *adf_event_thread(void *data) 271ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann{ 272ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann adf_hwc_helper *dev = static_cast<adf_hwc_helper *>(data); 273ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 274ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY); 275ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 276956f1f64a13593581ca83946d33910e4623bd657Marissa Wall struct sigaction action = { }; 277956f1f64a13593581ca83946d33910e4623bd657Marissa Wall sigemptyset(&action.sa_mask); 278956f1f64a13593581ca83946d33910e4623bd657Marissa Wall action.sa_flags = 0; 279956f1f64a13593581ca83946d33910e4623bd657Marissa Wall action.sa_handler = [](int) { pthread_exit(0); }; 280956f1f64a13593581ca83946d33910e4623bd657Marissa Wall 281956f1f64a13593581ca83946d33910e4623bd657Marissa Wall if (sigaction(SIGUSR2, &action, NULL) < 0) { 282956f1f64a13593581ca83946d33910e4623bd657Marissa Wall ALOGE("failed to set thread exit action %s", strerror(errno)); 283956f1f64a13593581ca83946d33910e4623bd657Marissa Wall return NULL; 284956f1f64a13593581ca83946d33910e4623bd657Marissa Wall } 285956f1f64a13593581ca83946d33910e4623bd657Marissa Wall 286956f1f64a13593581ca83946d33910e4623bd657Marissa Wall sigset_t signal_set; 287956f1f64a13593581ca83946d33910e4623bd657Marissa Wall sigemptyset(&signal_set); 288956f1f64a13593581ca83946d33910e4623bd657Marissa Wall sigaddset(&signal_set, SIGUSR2); 289956f1f64a13593581ca83946d33910e4623bd657Marissa Wall 290956f1f64a13593581ca83946d33910e4623bd657Marissa Wall pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL); 291956f1f64a13593581ca83946d33910e4623bd657Marissa Wall 292956f1f64a13593581ca83946d33910e4623bd657Marissa Wall pollfd fds[dev->intf_fds.size()]; 293ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann for (size_t i = 0; i < dev->intf_fds.size(); i++) { 294ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann fds[i].fd = dev->intf_fds[i]; 295ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann fds[i].events = POLLIN | POLLPRI; 296ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann } 297ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 298ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann while (true) { 299956f1f64a13593581ca83946d33910e4623bd657Marissa Wall if (TEMP_FAILURE_RETRY(poll(fds, dev->intf_fds.size(), -1)) < 0) { 300ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann ALOGE("error in event thread: %s", strerror(errno)); 301956f1f64a13593581ca83946d33910e4623bd657Marissa Wall break; 302ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann } 303956f1f64a13593581ca83946d33910e4623bd657Marissa Wall 304956f1f64a13593581ca83946d33910e4623bd657Marissa Wall for (size_t i = 0; i < dev->intf_fds.size(); i++) 305956f1f64a13593581ca83946d33910e4623bd657Marissa Wall if (fds[i].revents & (POLLIN | POLLPRI)) 306956f1f64a13593581ca83946d33910e4623bd657Marissa Wall handle_adf_event(dev, i); 307ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann } 308ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 309ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return NULL; 310ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann} 311ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 312ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmannint adf_hwc_open(int *intf_fds, size_t n_intfs, 313ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann const struct adf_hwc_event_callbacks *event_cb, void *event_cb_data, 314ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann struct adf_hwc_helper **dev) 315ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann{ 316ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann if (!n_intfs) 317ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return -EINVAL; 318ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 319ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann adf_hwc_helper *dev_ret = new adf_hwc_helper; 320ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann dev_ret->event_cb = event_cb; 321ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann dev_ret->event_cb_data = event_cb_data; 322ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 323ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann int ret; 324ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 325ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann for (size_t i = 0; i < n_intfs; i++) { 326ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann int dup_intf_fd = dup(intf_fds[i]); 327ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann if (dup_intf_fd < 0) { 328ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann ALOGE("failed to dup interface fd: %s", strerror(errno)); 329ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann ret = -errno; 330ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann goto err; 331ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann } 332ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 333ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann dev_ret->intf_fds.push_back(dup_intf_fd); 334ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 335ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann ret = adf_set_event(dup_intf_fd, ADF_EVENT_HOTPLUG, 1); 336ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann if (ret < 0 && ret != -EINVAL) { 33718b712784558747a16dcf200818b9a48ffc606a2Greg Hackmann ALOGE("failed to enable hotplug event on display %zu: %s", 338ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann i, strerror(errno)); 339ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann goto err; 340ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann } 341ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann } 342ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 343956f1f64a13593581ca83946d33910e4623bd657Marissa Wall sigset_t signal_set; 344956f1f64a13593581ca83946d33910e4623bd657Marissa Wall sigemptyset(&signal_set); 345956f1f64a13593581ca83946d33910e4623bd657Marissa Wall sigaddset(&signal_set, SIGUSR2); 346956f1f64a13593581ca83946d33910e4623bd657Marissa Wall 347956f1f64a13593581ca83946d33910e4623bd657Marissa Wall pthread_sigmask(SIG_BLOCK, &signal_set, NULL); 348956f1f64a13593581ca83946d33910e4623bd657Marissa Wall 349ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann ret = pthread_create(&dev_ret->event_thread, NULL, adf_event_thread, 350ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann dev_ret); 351ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann if (ret) { 352ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann ALOGE("failed to create event thread: %s", strerror(ret)); 353ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann goto err; 354ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann } 355ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 356ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann *dev = dev_ret; 357ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return 0; 358ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 359ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmannerr: 360ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann for (size_t i = 0; i < dev_ret->intf_fds.size(); i++) 361ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann close(dev_ret->intf_fds[i]); 362ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 363ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann delete dev_ret; 364ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann return ret; 365ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann} 366ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 367ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmannvoid adf_hwc_close(struct adf_hwc_helper *dev) 368ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann{ 369956f1f64a13593581ca83946d33910e4623bd657Marissa Wall pthread_kill(dev->event_thread, SIGUSR2); 370ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann pthread_join(dev->event_thread, NULL); 371ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 372ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann for (size_t i = 0; i < dev->intf_fds.size(); i++) 373ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann close(dev->intf_fds[i]); 374ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann 375ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann delete dev; 376ebb26c71fe59c1904dc198b00948c581d31bd412Greg Hackmann} 377