-/**************************************************************************
-
-libtdm_nexell
-
-Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved.
-
-Contact: SooChan Lim <sc1.lim@samsung.com>
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sub license, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
-IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
-ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <drm_fourcc.h>
-#include <tdm_helper.h>
-
-#include "tdm_nexell.h"
-#include "tdm_nexell_pp.h"
-
-#define MIN_WIDTH 32
-
-static drmModeModeInfoPtr
-_tdm_nexell_display_get_mode(tdm_nexell_output_data *output_data)
-{
- int i;
-
- if (!output_data->current_mode) {
- TDM_ERR("no output_data->current_mode");
- return NULL;
- }
-
- for (i = 0; i < output_data->count_modes; i++) {
- drmModeModeInfoPtr drm_mode = &output_data->drm_modes[i];
- if ((drm_mode->hdisplay == output_data->current_mode->hdisplay) &&
- (drm_mode->vdisplay == output_data->current_mode->vdisplay) &&
- (drm_mode->vrefresh == output_data->current_mode->vrefresh) &&
- (drm_mode->flags == output_data->current_mode->flags) &&
- (drm_mode->type == output_data->current_mode->type) &&
- !(strncmp(drm_mode->name, output_data->current_mode->name, TDM_NAME_LEN)))
- return drm_mode;
- }
-
- return NULL;
-}
-
-static void
-_tdm_nexell_display_to_tdm_mode(drmModeModeInfoPtr drm_mode,
- tdm_output_mode *tdm_mode)
-{
- tdm_mode->clock = drm_mode->clock;
- tdm_mode->hdisplay = drm_mode->hdisplay;
- tdm_mode->hsync_start = drm_mode->hsync_start;
- tdm_mode->hsync_end = drm_mode->hsync_end;
- tdm_mode->htotal = drm_mode->htotal;
- tdm_mode->hskew = drm_mode->hskew;
- tdm_mode->vdisplay = drm_mode->vdisplay;
- tdm_mode->vsync_start = drm_mode->vsync_start;
- tdm_mode->vsync_end = drm_mode->vsync_end;
- tdm_mode->vtotal = drm_mode->vtotal;
- tdm_mode->vscan = drm_mode->vscan;
- tdm_mode->vrefresh = drm_mode->vrefresh;
- tdm_mode->flags = drm_mode->flags;
- tdm_mode->type = drm_mode->type;
- snprintf(tdm_mode->name, TDM_NAME_LEN, "%s", drm_mode->name);
-}
-
-static tdm_error
-_tdm_nexell_display_get_cur_msc (int fd, int pipe, uint *msc)
-{
- drmVBlank vbl;
-
- vbl.request.type = DRM_VBLANK_RELATIVE;
- if (pipe == 1)
- vbl.request.type |= DRM_VBLANK_SECONDARY;
- else if (pipe > 1)
- vbl.request.type |= pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
-
- vbl.request.sequence = 0;
- if (drmWaitVBlank(fd, &vbl)) {
- TDM_ERR("get vblank counter failed: %m");
- *msc = 0;
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- *msc = vbl.reply.sequence;
-
- return TDM_ERROR_NONE;
-}
-
-static tdm_error
-_tdm_nexell_display_wait_vblank(int fd, int pipe, uint *target_msc, void *data)
-{
- drmVBlank vbl;
-
- vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
- if (pipe == 1)
- vbl.request.type |= DRM_VBLANK_SECONDARY;
- else if (pipe > 1)
- vbl.request.type |= pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
-
- vbl.request.sequence = *target_msc;
- vbl.request.signal = (unsigned long)(uintptr_t)data;
-
- if (drmWaitVBlank(fd, &vbl)) {
- TDM_ERR("wait vblank failed: %m");
- *target_msc = 0;
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- *target_msc = vbl.reply.sequence;
-
- return TDM_ERROR_NONE;
-}
-
-static tdm_error
-_tdm_nexell_output_update_status(tdm_nexell_output_data *output_data,
- tdm_output_conn_status status)
-{
- RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
-
- if (output_data->status == status)
- return TDM_ERROR_NONE;
-
- output_data->status = status;
-
- if (output_data->status_func)
- output_data->status_func(output_data, status,
- output_data->status_user_data);
-
- return TDM_ERROR_NONE;
-}
-
-static tdm_error
-_tdm_nexell_display_commit_primary_layer(tdm_nexell_layer_data *layer_data,
- void *user_data, int *do_waitvblank)
-{
- tdm_nexell_data *nexell_data = layer_data->nexell_data;
- tdm_nexell_output_data *output_data = layer_data->output_data;
-
- if (output_data->mode_changed && layer_data->display_buffer_changed) {
- drmModeModeInfoPtr mode;
-
- if (!layer_data->display_buffer) {
- TDM_ERR("primary layer should have a buffer for modestting");
- return TDM_ERROR_BAD_REQUEST;
- }
-
- output_data->mode_changed = 0;
- layer_data->display_buffer_changed = 0;
- layer_data->info_changed = 0;
-
- mode = _tdm_nexell_display_get_mode(output_data);
- if (!mode) {
- TDM_ERR("couldn't find proper mode");
- return TDM_ERROR_BAD_REQUEST;
- }
-
- if (drmModeSetCrtc(nexell_data->drm_fd, output_data->crtc_id,
- layer_data->display_buffer->fb_id, 0, 0,
- &output_data->connector_id, 1, mode)) {
- TDM_ERR("set crtc failed: %m");
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- _tdm_nexell_output_update_status(output_data, TDM_OUTPUT_CONN_STATUS_MODE_SETTED);
-
- *do_waitvblank = 1;
- return TDM_ERROR_NONE;
- } else if (layer_data->display_buffer_changed) {
- layer_data->display_buffer_changed = 0;
-
- if (layer_data->display_buffer) {
- tdm_nexell_event_data *event_data = calloc(1, sizeof(tdm_nexell_event_data));
-
- if (!event_data) {
- TDM_ERR("alloc failed");
- return TDM_ERROR_OUT_OF_MEMORY;
- }
-
- event_data->type = TDM_NEXELL_EVENT_TYPE_COMMIT;
- event_data->output_data = output_data;
- event_data->user_data = user_data;
- if (drmModePageFlip(nexell_data->drm_fd, output_data->crtc_id,
- layer_data->display_buffer->fb_id, DRM_MODE_PAGE_FLIP_EVENT, event_data)) {
- TDM_ERR("pageflip failed: %m");
- free(event_data);
- return TDM_ERROR_OPERATION_FAILED;
- }
- *do_waitvblank = 0;
- }
- }else {
- /* to call a user commit handler whenever committed */
- *do_waitvblank = 1;
- }
-
- return TDM_ERROR_NONE;
-}
-
-static tdm_error
-_tdm_nexell_display_commit_layer(tdm_nexell_layer_data *layer_data)
-{
- tdm_nexell_data *nexell_data = layer_data->nexell_data;
- tdm_nexell_output_data *output_data = layer_data->output_data;
- uint32_t fx, fy, fw, fh;
- int crtc_w;
-
- if (!layer_data->display_buffer_changed && !layer_data->info_changed)
- return TDM_ERROR_NONE;
-
- if (output_data->current_mode)
- crtc_w = output_data->current_mode->hdisplay;
- else {
- drmModeCrtcPtr crtc = drmModeGetCrtc(nexell_data->drm_fd, output_data->crtc_id);
- if (!crtc) {
- TDM_ERR("getting crtc failed");
- return TDM_ERROR_OPERATION_FAILED;
- }
- crtc_w = crtc->width;
- if (crtc_w == 0) {
- TDM_ERR("getting crtc width failed");
- drmModeFreeCrtc(crtc);
- return TDM_ERROR_OPERATION_FAILED;
- }
- drmModeFreeCrtc(crtc);
- }
-
- // reset the changed flags
- layer_data->display_buffer_changed = 0;
- layer_data->info_changed = 0;
-
- if (layer_data->display_buffer) { // set plane
- /* Source values are 16.16 fixed point */
- fx = ((unsigned int)layer_data->info.src_config.pos.x) << 16;
- fy = ((unsigned int)layer_data->info.src_config.pos.y) << 16;
- fw = ((unsigned int)layer_data->info.src_config.pos.w) << 16;
- fh = ((unsigned int)layer_data->info.src_config.pos.h) << 16;
-
- TDM_DBG("plane(%d) crtc(%d) pos(%d) on: fb(%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n",
- layer_data->plane_id, output_data->crtc_id, layer_data->zpos,
- layer_data->display_buffer->fb_id,
- layer_data->info.src_config.pos.x, layer_data->info.src_config.pos.y,
- layer_data->info.src_config.pos.w, layer_data->info.src_config.pos.h,
- layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
- layer_data->info.dst_pos.w, layer_data->info.dst_pos.h);
-
- if (drmModeSetPlane(nexell_data->drm_fd, layer_data->plane_id,
- output_data->crtc_id, layer_data->display_buffer->fb_id, 0,
- layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
- layer_data->info.dst_pos.w, layer_data->info.dst_pos.h,
- fx, fy, fw, fh) < 0) {
- TDM_ERR("set plane(%d) failed: %m", layer_data->plane_id);
- return TDM_ERROR_OPERATION_FAILED;
- }
- } else { // unset plane
- TDM_DBG("plane(%d) crtc(%d) pos(%d) : unset plane\n",
- layer_data->plane_id, output_data->crtc_id, layer_data->zpos);
-
- if (drmModeSetPlane(nexell_data->drm_fd, layer_data->plane_id,
- output_data->crtc_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
- TDM_ERR("unset plane(%d) filed: %m", layer_data->plane_id);
- }
-
- return TDM_ERROR_NONE;
-}
-
-static void
-_tdm_nexell_display_cb_event(int fd, unsigned int sequence,
- unsigned int tv_sec, unsigned int tv_usec,
- void *user_data)
-{
- tdm_nexell_event_data *event_data = user_data;
- tdm_nexell_output_data *output_data;
- tdm_nexell_hwc_data *hwc_data;
-
- if (!event_data) {
- TDM_ERR("no event data");
- return;
- }
-
- output_data = event_data->output_data;
-
- switch (event_data->type) {
- case TDM_NEXELL_EVENT_TYPE_PAGEFLIP:
- if (output_data->commit_func)
- output_data->commit_func(output_data, sequence, tv_sec, tv_usec,
- event_data->user_data);
- break;
- case TDM_NEXELL_EVENT_TYPE_WAIT:
- if (output_data->vblank_func)
- output_data->vblank_func(output_data, sequence, tv_sec, tv_usec,
- event_data->user_data);
- break;
- case TDM_NEXELL_EVENT_TYPE_COMMIT:
- if (output_data->hwc_enable) {
- hwc_data = output_data->hwc_data;
- if (!hwc_data) {
- TDM_ERR("no hwc_data");
- break;
- }
-
- if (hwc_data->commit_func)
- hwc_data->commit_func(hwc_data, sequence, tv_sec, tv_usec,
- event_data->user_data);
- } else {
- if (output_data->commit_func)
- output_data->commit_func(output_data, sequence, tv_sec, tv_usec,
- event_data->user_data);
- }
- break;
- default:
- break;
- }
-
- free(event_data);
-}
-
-static tdm_error
-_tdm_nexell_display_create_layer_list(tdm_nexell_data *nexell_data)
-{
- tdm_nexell_output_data *output_data = NULL;
- int i;
-
- if (LIST_IS_EMPTY(&nexell_data->output_list)) {
- TDM_ERR("no output");
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- /* The TDM drm backend only support one output. */
- LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) {
- break;
- }
-
- if (nexell_data->plane_res->count_planes == 0) {
- TDM_ERR("no layer error");
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- for (i = 0; i < nexell_data->plane_res->count_planes; i++) {
- tdm_nexell_layer_data *layer_data;
- drmModePlanePtr plane;
-
- plane = drmModeGetPlane(nexell_data->drm_fd, nexell_data->plane_res->planes[i]);
- if (!plane) {
- TDM_ERR("no plane");
- continue;
- }
-
- if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) {
- drmModeFreePlane(plane);
- continue;
- }
-
- layer_data = calloc(1, sizeof(tdm_nexell_layer_data));
- if (!layer_data) {
- TDM_ERR("alloc failed");
- drmModeFreePlane(plane);
- continue;
- }
-
- layer_data->nexell_data = nexell_data;
- layer_data->output_data = output_data;
- layer_data->plane_id = nexell_data->plane_res->planes[i];
-
- layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY |
- TDM_LAYER_CAPABILITY_GRAPHIC;
- output_data->primary_layer = layer_data;
-
- TDM_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) capabilities(%x)",
- layer_data, layer_data->plane_id, layer_data->output_data->crtc_id,
- layer_data->capabilities);
-
- LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
-
- drmModeFreePlane(plane);
-
- /* can't take care of other planes for various hardware devices */
- break;
- }
-
- return TDM_ERROR_NONE;
-}
-
-#if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47
-
-static tdm_error
-_tdm_nexell_display_get_property(tdm_nexell_data *nexell_data,
- unsigned int obj_id, unsigned int obj_type,
- const char *name, unsigned int *value,
- int *is_immutable)
-{
- drmModeObjectPropertiesPtr props = NULL;
- int i;
-
- props = drmModeObjectGetProperties(nexell_data->drm_fd, obj_id, obj_type);
- if (!props)
- return TDM_ERROR_OPERATION_FAILED;
-
- for (i = 0; i < props->count_props; i++) {
- drmModePropertyPtr prop = drmModeGetProperty(nexell_data->drm_fd,
- props->props[i]);
-
- if (!prop)
- continue;
-
- if (!strcmp(prop->name, name)) {
- if (is_immutable)
- *is_immutable = prop->flags & DRM_MODE_PROP_IMMUTABLE;
- if (value)
- *value = (unsigned int)props->prop_values[i];
- drmModeFreeProperty(prop);
- drmModeFreeObjectProperties(props);
- return TDM_ERROR_NONE;
- }
-
- drmModeFreeProperty(prop);
- }
- drmModeFreeObjectProperties(props);
- TDM_DBG("coundn't find '%s' property", name);
- return TDM_ERROR_OPERATION_FAILED;
-}
-
-static tdm_error
-_nexell_output_get_atomic_prop_id(int drm_fd, uint32_t object_id, uint32_t object_type, const char *name, uint32_t *id)
-{
- drmModeObjectPropertiesPtr properties = NULL;
- drmModePropertyPtr property = NULL;
- int i;
-
- properties = drmModeObjectGetProperties(drm_fd, object_id, object_type);
- if (properties == NULL) {
- TDM_ERR("drmModeObjectGetProperties failed");
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- for (i = 0; i < properties->count_props; i++) {
- property = drmModeGetProperty(drm_fd, properties->props[i]);
- if (property == NULL) {
- continue;
- }
-
- if (strcmp(property->name, name) == 0) {
- *id = property->prop_id;
- drmModeFreeProperty(property);
- break;
- }
- drmModeFreeProperty(property);
- }
-
- drmModeFreeObjectProperties(properties);
-
- return TDM_ERROR_NONE;
-}
-
-static tdm_error
-_tdm_nexell_display_create_layer_list_type(tdm_nexell_data *nexell_data)
-{
- tdm_nexell_output_data *output_data = NULL;
- drmModePlanePtr *planes = NULL;
- unsigned int *types = NULL;
- unsigned int type = 0;
- int plane_cnt, primary_cnt, ovl_cnt, cursor_cnt;
- int opos_next, cpos_next;
- tdm_error ret;
- int i;
-
- if (LIST_IS_EMPTY(&nexell_data->output_list)) {
- TDM_ERR("no output");
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- /* The TDM drm backend only support one output. */
- LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) {
- break;
- }
-
- ret = _tdm_nexell_display_get_property(nexell_data,
- nexell_data->plane_res->planes[0],
- DRM_MODE_OBJECT_PLANE, "type", &type,
- NULL);
- if (ret != TDM_ERROR_NONE) {
- TDM_ERR("plane doesn't have 'type' property. Call a fallback function");
-
- /* if a plane doesn't have "type" property, we call a fallback function
- * as default
- */
- return _tdm_nexell_display_create_layer_list(nexell_data);
- }
-
- planes = calloc(nexell_data->plane_res->count_planes, sizeof(drmModePlanePtr));
- if (!planes) {
- TDM_ERR("alloc failed");
- goto failed;
- }
-
- types = calloc(nexell_data->plane_res->count_planes, sizeof(unsigned int));
- if (!types) {
- TDM_ERR("alloc failed");
- goto failed;
- }
-
- plane_cnt = 0;
- for (i = 0; i < nexell_data->plane_res->count_planes; i++) {
- drmModePlanePtr plane;
-
- plane = drmModeGetPlane(nexell_data->drm_fd, nexell_data->plane_res->planes[i]);
- if (!plane) {
- TDM_ERR("no plane(%d)", nexell_data->plane_res->planes[i]);
- goto failed;
- }
-
- if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) {
- drmModeFreePlane(plane);
- continue;
- }
-
- ret = _tdm_nexell_display_get_property(nexell_data,
- nexell_data->plane_res->planes[i],
- DRM_MODE_OBJECT_PLANE, "type", &type,
- NULL);
- if (ret != TDM_ERROR_NONE) {
- drmModeFreePlane(plane);
- TDM_ERR("plane(%d) doesn't have 'type' info",
- nexell_data->plane_res->planes[i]);
- goto failed;
- }
-
- planes[plane_cnt] = plane;
- types[plane_cnt] = type;
- plane_cnt++;
- }
-
- primary_cnt = ovl_cnt = cursor_cnt = 0;
- for (i = 0; i < plane_cnt; i++) {
- if (types[i] == DRM_PLANE_TYPE_CURSOR)
- cursor_cnt++;
- else if (types[i] == DRM_PLANE_TYPE_OVERLAY)
- ovl_cnt++;
- else if (types[i] == DRM_PLANE_TYPE_PRIMARY)
- primary_cnt++;
- else
- TDM_ERR("invalid type(%d)", types[i]);
- }
-
- if (primary_cnt != 1) {
- TDM_ERR("primary layer count(%d) should be one", primary_cnt);
- goto failed;
- }
-
- opos_next = 0;
- cpos_next = ovl_cnt;
- if (plane_cnt < 1) {
- TDM_ERR("plane count(%d) should be over 1", plane_cnt);
- goto failed;
- }
-
- for (i = plane_cnt - 1; i >= 0; i--) {
- tdm_nexell_layer_data *layer_data;
-
- layer_data = calloc(1, sizeof(tdm_nexell_layer_data));
- if (!layer_data) {
- TDM_ERR("alloc failed");
- goto failed;
- }
-
- layer_data->nexell_data = nexell_data;
- layer_data->output_data = output_data;
- layer_data->plane_id = planes[i]->plane_id;
-
- if (types[i] == DRM_PLANE_TYPE_CURSOR) {
- layer_data->capabilities = TDM_LAYER_CAPABILITY_CURSOR |
- TDM_LAYER_CAPABILITY_GRAPHIC |
- TDM_LAYER_CAPABILITY_SCANOUT;
- layer_data->zpos = cpos_next++;
- TDM_INFO("layer_data(%p): cursor zpos(%d)", layer_data, layer_data->zpos);
- } else if (types[i] == DRM_PLANE_TYPE_OVERLAY) {
- if (opos_next == 0) {
- layer_data->capabilities = TDM_LAYER_CAPABILITY_OVERLAY |
- TDM_LAYER_CAPABILITY_SCALE |
- TDM_LAYER_CAPABILITY_SCANOUT;
- } else {
- layer_data->capabilities = TDM_LAYER_CAPABILITY_OVERLAY |
- TDM_LAYER_CAPABILITY_GRAPHIC |
- TDM_LAYER_CAPABILITY_RESEVED_MEMORY |
- TDM_LAYER_CAPABILITY_SCANOUT;
- }
- if (opos_next == 1) {
- layer_data->zpos = 2;
- opos_next = 2;
- } else {
- layer_data->zpos = opos_next++;
- }
-
- TDM_INFO("layer_data(%p): overlay zpos(%d)", layer_data, layer_data->zpos);
- } else if (types[i] == DRM_PLANE_TYPE_PRIMARY) {
- layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY |
- TDM_LAYER_CAPABILITY_GRAPHIC |
- TDM_LAYER_CAPABILITY_RESEVED_MEMORY |
- TDM_LAYER_CAPABILITY_SCANOUT;
- layer_data->zpos = 1;
- output_data->primary_layer = layer_data;
-
- TDM_INFO("layer_data(%p): primary zpos(%d)", layer_data, layer_data->zpos);
- } else {
- free(layer_data);
- continue;
- }
-
- TDM_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) zpos(%d) capabilities(%x)",
- layer_data, layer_data->plane_id, layer_data->output_data->crtc_id,
- layer_data->zpos, layer_data->capabilities);
-
- LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
-
- /* get the atomic prop ids*/
- if (nexell_data->has_atomic) {
- ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
- DRM_MODE_OBJECT_PLANE, "FB_ID", &layer_data->atomic_props_ids.fb_id);
- if (ret != TDM_ERROR_NONE) {
- free(layer_data);
- goto failed;
- }
-
- ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
- DRM_MODE_OBJECT_PLANE, "CRTC_ID", &layer_data->atomic_props_ids.crtc_id);
- if (ret != TDM_ERROR_NONE) {
- free(layer_data);
- goto failed;
- }
-
- ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
- DRM_MODE_OBJECT_PLANE, "SRC_X", &layer_data->atomic_props_ids.src_x);
- if (ret != TDM_ERROR_NONE) {
- free(layer_data);
- goto failed;
- }
-
- ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
- DRM_MODE_OBJECT_PLANE, "SRC_Y", &layer_data->atomic_props_ids.src_y);
- if (ret != TDM_ERROR_NONE) {
- free(layer_data);
- goto failed;
- }
-
- ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
- DRM_MODE_OBJECT_PLANE, "SRC_W", &layer_data->atomic_props_ids.src_w);
- if (ret != TDM_ERROR_NONE) {
- free(layer_data);
- goto failed;
- }
-
- ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
- DRM_MODE_OBJECT_PLANE, "SRC_H", &layer_data->atomic_props_ids.src_h);
- if (ret != TDM_ERROR_NONE) {
- free(layer_data);
- goto failed;
- }
-
- ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
- DRM_MODE_OBJECT_PLANE, "CRTC_X", &layer_data->atomic_props_ids.crtc_x);
- if (ret != TDM_ERROR_NONE) {
- free(layer_data);
- goto failed;
- }
-
- ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
- DRM_MODE_OBJECT_PLANE, "CRTC_Y", &layer_data->atomic_props_ids.crtc_y);
- if (ret != TDM_ERROR_NONE) {
- free(layer_data);
- goto failed;
- }
-
- ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
- DRM_MODE_OBJECT_PLANE, "CRTC_W", &layer_data->atomic_props_ids.crtc_w);
- if (ret != TDM_ERROR_NONE) {
- free(layer_data);
- goto failed;
- }
-
- ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
- DRM_MODE_OBJECT_PLANE, "CRTC_H", &layer_data->atomic_props_ids.crtc_h);
- if (ret != TDM_ERROR_NONE) {
- free(layer_data);
- goto failed;
- }
- }
- }
-
- for (i = 0; i < plane_cnt; i++)
- if (planes[i])
- drmModeFreePlane(planes[i]);
-
- free(planes);
- free(types);
-
- return TDM_ERROR_NONE;
-
-failed:
- if (planes) {
- for (i = 0; i < nexell_data->plane_res->count_planes; i++)
- if (planes[i])
- drmModeFreePlane(planes[i]);
- free(planes);
- }
-
- free(types);
-
- return TDM_ERROR_OPERATION_FAILED;
-}
-#endif
-
-tdm_error
-tdm_nexell_display_create_layer_list(tdm_nexell_data *nexell_data)
-{
- tdm_nexell_output_data *output_data = NULL;
- tdm_error ret;
-
-#if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47
- if (nexell_data->has_universal_plane)
- ret = _tdm_nexell_display_create_layer_list_type(nexell_data);
- else
-#endif
- ret = _tdm_nexell_display_create_layer_list(nexell_data);
-
- if (ret != TDM_ERROR_NONE)
- return ret;
-
- LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) {
- if (!output_data->primary_layer) {
- TDM_ERR("output(%d) no primary layer", output_data->pipe);
- return TDM_ERROR_OPERATION_FAILED;
- }
- }
-
- return TDM_ERROR_NONE;
-}
-
-void
-tdm_nexell_display_destroy_output_list(tdm_nexell_data *nexell_data)
-{
- tdm_nexell_output_data *o = NULL, *oo = NULL;
- tdm_nexell_hwc_data *hwc_data = NULL;
-
- if (LIST_IS_EMPTY(&nexell_data->output_list))
- return;
-
- LIST_FOR_EACH_ENTRY_SAFE(o, oo, &nexell_data->output_list, link) {
- hwc_data = o->hwc_data;
- if (hwc_data && hwc_data->target_hwc_window)
- nexell_hwc_window_destroy(hwc_data->target_hwc_window);
-
- LIST_DEL(&o->link);
- if (!LIST_IS_EMPTY(&o->layer_list)) {
- tdm_nexell_layer_data *l = NULL, *ll = NULL;
- LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) {
- LIST_DEL(&l->link);
- if (l->display_buffer)
- tbm_surface_internal_unref(l->display_buffer->buffer);
- free(l);
- }
- }
- free(o->drm_modes);
- free(o->output_modes);
- free(o);
- }
-}
-
-void
-tdm_nexell_display_update_output_status(tdm_nexell_data *nexell_data)
-{
- tdm_nexell_output_data *output_data = NULL;
-
- if (LIST_IS_EMPTY(&nexell_data->output_list))
- return;
-
- LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) {
- drmModeConnectorPtr connector;
- tdm_output_conn_status new_status;
-
- connector = drmModeGetConnector(nexell_data->drm_fd,
- output_data->connector_id);
- if (!connector) {
- TDM_ERR("no connector: %d", output_data->connector_id);
- continue;
- }
-
- if (connector->connection == DRM_MODE_CONNECTED)
- new_status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
- else
- new_status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
-
- _tdm_nexell_output_update_status(output_data, new_status);
-
- drmModeFreeConnector(connector);
- }
-}
-
-tdm_error
-tdm_nexell_display_create_output_list(tdm_nexell_data *nexell_data)
-{
- tdm_nexell_output_data *output_data;
- int i;
- tdm_error ret;
- int allocated = 0;
- drmModeConnectorPtr connector;
- drmModeEncoderPtr encoder;
- int conn_idx = -1;
- int hdmia_idx = -1, hdmib_idx = -1;
- int crtc_id = 0, c, j;
-
- RETURN_VAL_IF_FAIL(LIST_IS_EMPTY(&nexell_data->output_list),
- TDM_ERROR_OPERATION_FAILED);
-
- /* check if there is a connected output */
- for (i = 0; i < nexell_data->mode_res->count_connectors; i++) {
- connector = drmModeGetConnector(nexell_data->drm_fd,
- nexell_data->mode_res->connectors[i]);
- if (!connector) {
- TDM_ERR("no connector");
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- /* The TDM drm backend considers only 1 connector because it is the TDM
- * reference backend and can't take care of all hardware devices.
- * To support various connectors, planes and crtcs, the new TDM backend
- * should be implemented.
- */
- if (connector->connection == DRM_MODE_CONNECTED) {
- conn_idx = i;
- drmModeFreeConnector(connector);
- break;
- }
-
- if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA)
- hdmia_idx = i;
- if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIB)
- hdmib_idx = i;
-
- drmModeFreeConnector(connector);
- }
-
- /* use the hdmi connector if there is no connected connector. */
- /* if there is no hdmi connector, use first connector. */
- if (conn_idx == -1) {
- if (hdmia_idx != -1)
- conn_idx = hdmia_idx;
- else if (hdmib_idx != -1)
- conn_idx = hdmib_idx;
- else
- conn_idx = 0;
- }
-
- /* The TDM drm backend considers only 1 connector because it is the TDM
- * reference backend and can't take care of all hardware devices.
- * To support various connectors, planes and crtcs, the new TDM backend
- * should be implemented.
- */
- connector = drmModeGetConnector(nexell_data->drm_fd,
- nexell_data->mode_res->connectors[conn_idx]);
- if (!connector) {
- TDM_ERR("no connector");
- ret = TDM_ERROR_OPERATION_FAILED;
- goto failed_create;
- }
-
- if (connector->count_encoders != 1) {
- TDM_ERR("too many encoders: %d", connector->count_encoders);
- drmModeFreeConnector(connector);
- ret = TDM_ERROR_OPERATION_FAILED;
- goto failed_create;
- }
-
- encoder = drmModeGetEncoder(nexell_data->drm_fd, connector->encoders[0]);
- if (!encoder) {
- TDM_ERR("no encoder");
- drmModeFreeConnector(connector);
- ret = TDM_ERROR_OPERATION_FAILED;
- goto failed_create;
- }
-
- for (c = 0; c < nexell_data->mode_res->count_crtcs; c++) {
- if ((encoder->possible_crtcs & (1 << c)) == 0)
- continue;
-
- crtc_id = nexell_data->mode_res->crtcs[c];
- allocated |= (1 << c);
- break;
- }
-
- if (crtc_id == 0) {
- TDM_ERR("no possible crtc");
- drmModeFreeConnector(connector);
- drmModeFreeEncoder(encoder);
- ret = TDM_ERROR_OPERATION_FAILED;
- goto failed_create;
- }
-
- output_data = calloc(1, sizeof(tdm_nexell_output_data));
- if (!output_data) {
- TDM_ERR("alloc failed");
- drmModeFreeConnector(connector);
- drmModeFreeEncoder(encoder);
- ret = TDM_ERROR_OUT_OF_MEMORY;
- goto failed_create;
- }
-
- LIST_INITHEAD(&output_data->layer_list);
-
- output_data->nexell_data = nexell_data;
- output_data->connector_id = nexell_data->mode_res->connectors[conn_idx];
- output_data->encoder_id = encoder->encoder_id;
- output_data->crtc_id = crtc_id;
- output_data->pipe = c;
- output_data->connector_type = connector->connector_type;
- output_data->connector_type_id = connector->connector_type_id;
-
- if (connector->connection == DRM_MODE_CONNECTED)
- output_data->status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
- else
- output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
-
- for (j = 0; j < connector->count_props; j++) {
- drmModePropertyPtr prop = drmModeGetProperty(nexell_data->drm_fd,
- connector->props[j]);
- if (!prop)
- continue;
- if (!strcmp(prop->name, "DPMS")) {
- output_data->dpms_prop_id = connector->props[j];
- drmModeFreeProperty(prop);
- break;
- }
- drmModeFreeProperty(prop);
- }
-
- if (output_data->dpms_prop_id == 0)
- TDM_WRN("not support DPMS");
-
- output_data->count_modes = connector->count_modes;
- output_data->drm_modes = calloc(connector->count_modes,
- sizeof(drmModeModeInfo));
- if (!output_data->drm_modes) {
- TDM_ERR("alloc failed");
- free(output_data);
- drmModeFreeConnector(connector);
- drmModeFreeEncoder(encoder);
- ret = TDM_ERROR_OUT_OF_MEMORY;
- goto failed_create;
- }
- output_data->output_modes = calloc(connector->count_modes,
- sizeof(tdm_output_mode));
- if (!output_data->output_modes) {
- TDM_ERR("alloc failed");
- free(output_data->drm_modes);
- free(output_data);
- drmModeFreeConnector(connector);
- drmModeFreeEncoder(encoder);
- ret = TDM_ERROR_OUT_OF_MEMORY;
- goto failed_create;
- }
- for (j = 0; j < connector->count_modes; j++) {
- output_data->drm_modes[j] = connector->modes[j];
- _tdm_nexell_display_to_tdm_mode(&output_data->drm_modes[j],
- &output_data->output_modes[j]);
- }
-
- if (nexell_data->hwc_mode)
- output_data->hwc_enable = 1;
-
- LIST_ADDTAIL(&output_data->link, &nexell_data->output_list);
-
- TDM_DBG("output_data(%p) connector_id(%d:%d:%d-%d) encoder_id(%d) crtc_id(%d) pipe(%d) dpms_id(%d)",
- output_data, output_data->connector_id, output_data->status,
- output_data->connector_type,
- output_data->connector_type_id, output_data->encoder_id, output_data->crtc_id,
- output_data->pipe, output_data->dpms_prop_id);
-
- drmModeFreeEncoder(encoder);
- drmModeFreeConnector(connector);
-
- /* get the atomic prop ids*/
- if (nexell_data->has_atomic) {
- ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, output_data->connector_id,
- DRM_MODE_OBJECT_CONNECTOR, "CRTC_ID", &output_data->atomic_props_ids.crtc_id);
- if (ret != TDM_ERROR_NONE)
- goto failed_create;
-
- ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, output_data->crtc_id,
- DRM_MODE_OBJECT_CRTC, "MODE_ID", &output_data->atomic_props_ids.crtc_mode_id);
- if (ret != TDM_ERROR_NONE)
- goto failed_create;
-
- ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, output_data->crtc_id,
- DRM_MODE_OBJECT_CRTC, "ACTIVE", &output_data->atomic_props_ids.crtc_active);
- if (ret != TDM_ERROR_NONE)
- goto failed_create;
- }
-
- TDM_DBG("output count: %d", nexell_data->mode_res->count_connectors);
-
- return TDM_ERROR_NONE;
-failed_create:
- tdm_nexell_display_destroy_output_list(nexell_data);
- return ret;
-}
-
-tdm_error
-nexell_display_get_capability(tdm_backend_data *bdata, tdm_caps_display *caps)
-{
- RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
-
- caps->max_layer_count = -1; /* not defined */
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-nexell_display_get_pp_capability(tdm_backend_data *bdata, tdm_caps_pp *caps)
-{
- return tdm_nexell_pp_get_capability(bdata, caps);
-}
-
-tdm_output **
-nexell_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error)
-{
- tdm_nexell_data *nexell_data = bdata;
- tdm_nexell_output_data *output_data = NULL;
- tdm_output **outputs;
- tdm_error ret;
- int i;
-
- RETURN_VAL_IF_FAIL(nexell_data, NULL);
- RETURN_VAL_IF_FAIL(count, NULL);
-
- *count = 0;
- LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link)
- (*count)++;
-
- if (*count == 0) {
- ret = TDM_ERROR_NONE;
- goto failed_get;
- }
-
- /* will be freed in frontend */
- outputs = calloc(*count, sizeof(tdm_nexell_output_data *));
- if (!outputs) {
- TDM_ERR("failed: alloc memory");
- *count = 0;
- ret = TDM_ERROR_OUT_OF_MEMORY;
- goto failed_get;
- }
-
- i = 0;
- LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link)
- outputs[i++] = output_data;
-
- if (error)
- *error = TDM_ERROR_NONE;
-
- return outputs;
-failed_get:
- if (error)
- *error = ret;
- return NULL;
-}
-
-tdm_error
-nexell_display_get_fd(tdm_backend_data *bdata, int *fd)
-{
- tdm_nexell_data *nexell_data = bdata;
-
- RETURN_VAL_IF_FAIL(nexell_data, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(fd, TDM_ERROR_INVALID_PARAMETER);
-
- *fd = nexell_data->drm_fd;
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-nexell_display_handle_events(tdm_backend_data *bdata)
-{
- tdm_nexell_data *nexell_data = bdata;
- drmEventContext ctx;
-
- RETURN_VAL_IF_FAIL(nexell_data, TDM_ERROR_INVALID_PARAMETER);
-
- memset(&ctx, 0, sizeof(drmEventContext));
-
- ctx.version = DRM_EVENT_CONTEXT_VERSION;
- ctx.page_flip_handler = _tdm_nexell_display_cb_event;
- ctx.vblank_handler = _tdm_nexell_display_cb_event;
-
- drmHandleEvent(nexell_data->drm_fd, &ctx);
-
- return TDM_ERROR_NONE;
-}
-
-tdm_pp *
-nexell_display_create_pp(tdm_backend_data *bdata, tdm_error *error)
-{
- tdm_nexell_data *nexell_data = bdata;
-
- RETURN_VAL_IF_FAIL(nexell_data, NULL);
-
- return tdm_nexell_pp_create(nexell_data, error);
-}
-
-tdm_error
-nexell_output_get_capability(tdm_output *output, tdm_caps_output *caps)
-{
- tdm_nexell_output_data *output_data = output;
- tdm_nexell_data *nexell_data;
- drmModeConnectorPtr connector = NULL;
- drmModeCrtcPtr crtc = NULL;
- drmModeObjectPropertiesPtr props = NULL;
- int i;
- tdm_error ret;
-
- RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
-
- memset(caps, 0, sizeof(tdm_caps_output));
-
- nexell_data = output_data->nexell_data;
-
- snprintf(caps->maker, TDM_NAME_LEN, "unknown");
- snprintf(caps->model, TDM_NAME_LEN, "unknown");
- snprintf(caps->name, TDM_NAME_LEN, "unknown");
-
- caps->status = output_data->status;
- caps->type = output_data->connector_type;
- caps->type_id = output_data->connector_type_id;
-
- connector = drmModeGetConnector(nexell_data->drm_fd, output_data->connector_id);
- RETURN_VAL_IF_FAIL(connector, TDM_ERROR_OPERATION_FAILED);
-
- caps->mode_count = connector->count_modes;
- caps->modes = calloc(1, sizeof(tdm_output_mode) * caps->mode_count);
- if (!caps->modes) {
- ret = TDM_ERROR_OUT_OF_MEMORY;
- TDM_ERR("alloc failed\n");
- goto failed_get;
- }
-
- if (caps->mode_count != output_data->count_modes) {
- drmModeModeInfoPtr new_drm_modes;
- tdm_output_mode *new_output_modes;
-
- new_drm_modes = calloc(connector->count_modes,
- sizeof(drmModeModeInfo));
- if (!new_drm_modes) {
- ret = TDM_ERROR_OUT_OF_MEMORY;
- TDM_ERR("alloc failed drm_modes\n");
- goto failed_get;
- }
- new_output_modes = calloc(connector->count_modes,
- sizeof(tdm_output_mode));
- if (!new_output_modes) {
- ret = TDM_ERROR_OUT_OF_MEMORY;
- TDM_ERR("alloc failed output_modes\n");
- free(new_drm_modes);
- goto failed_get;
- }
- free(output_data->drm_modes);
- free(output_data->output_modes);
-
- output_data->drm_modes = new_drm_modes;
- output_data->output_modes = new_output_modes;
- output_data->count_modes = caps->mode_count;
- }
-
- for (i = 0; i < caps->mode_count; i++) {
- output_data->drm_modes[i] = connector->modes[i];
- _tdm_nexell_display_to_tdm_mode(&output_data->drm_modes[i],
- &output_data->output_modes[i]);
- caps->modes[i] = output_data->output_modes[i];
- }
-
- caps->mmWidth = connector->mmWidth;
- caps->mmHeight = connector->mmHeight;
- caps->subpixel = connector->subpixel;
-
- caps->min_w = nexell_data->mode_res->min_width;
- caps->min_h = nexell_data->mode_res->min_height;
- caps->max_w = nexell_data->mode_res->max_width;
- caps->max_h = nexell_data->mode_res->max_height;
- caps->preferred_align = -1;
-
- crtc = drmModeGetCrtc(nexell_data->drm_fd, output_data->crtc_id);
- if (!crtc) {
- ret = TDM_ERROR_OPERATION_FAILED;
- TDM_ERR("get crtc failed: %m\n");
- goto failed_get;
- }
-
- props = drmModeObjectGetProperties(nexell_data->drm_fd, output_data->crtc_id,
- DRM_MODE_OBJECT_CRTC);
- if (!props) {
- ret = TDM_ERROR_OPERATION_FAILED;
- TDM_ERR("get crtc properties failed: %m\n");
- goto failed_get;
- }
-
- caps->props = calloc(1, sizeof(tdm_prop) * props->count_props);
- if (!caps->props) {
- ret = TDM_ERROR_OUT_OF_MEMORY;
- TDM_ERR("alloc failed\n");
- goto failed_get;
- }
-
- caps->prop_count = 0;
- for (i = 0; i < props->count_props; i++) {
- drmModePropertyPtr prop = drmModeGetProperty(nexell_data->drm_fd, props->props[i]);
- if (!prop)
- continue;
- snprintf(caps->props[caps->prop_count].name, TDM_NAME_LEN, "%s", prop->name);
- caps->props[caps->prop_count].id = props->props[i];
- caps->prop_count++;
- drmModeFreeProperty(prop);
- }
-
- if (output_data->hwc_enable) {
- caps->capabilities |= TDM_OUTPUT_CAPABILITY_HWC;
- }
-
- drmModeFreeObjectProperties(props);
- drmModeFreeCrtc(crtc);
- drmModeFreeConnector(connector);
-
- return TDM_ERROR_NONE;
-failed_get:
- drmModeFreeCrtc(crtc);
- drmModeFreeObjectProperties(props);
- drmModeFreeConnector(connector);
- free(caps->modes);
- free(caps->props);
- memset(caps, 0, sizeof(tdm_caps_output));
- return ret;
-}
-
-tdm_layer **
-nexell_output_get_layers(tdm_output *output, int *count, tdm_error *error)
-{
- tdm_nexell_output_data *output_data = output;
- tdm_nexell_layer_data *layer_data = NULL;
- tdm_layer **layers;
- tdm_error ret;
- int i;
-
- RETURN_VAL_IF_FAIL(output_data, NULL);
- RETURN_VAL_IF_FAIL(count, NULL);
-
- *count = 0;
- LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
- (*count)++;
-
- if (output_data->hwc_enable) {
- *count = 0;
- ret = TDM_ERROR_NONE;
- goto failed_get;
- }
-
- if (*count == 0) {
- ret = TDM_ERROR_NONE;
- goto failed_get;
- }
-
- /* will be freed in frontend */
- layers = calloc(*count, sizeof(tdm_nexell_layer_data *));
- if (!layers) {
- TDM_ERR("failed: alloc memory");
- *count = 0;
- ret = TDM_ERROR_OUT_OF_MEMORY;
- goto failed_get;
- }
-
- i = 0;
- LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
- layers[i++] = layer_data;
-
- if (error)
- *error = TDM_ERROR_NONE;
-
- return layers;
-failed_get:
- if (error)
- *error = ret;
- return NULL;
-}
-
-tdm_error
-nexell_output_set_property(tdm_output *output, unsigned int id, tdm_value value)
-{
- tdm_nexell_output_data *output_data = output;
- tdm_nexell_data *nexell_data;
- int ret;
-
- RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, TDM_ERROR_INVALID_PARAMETER);
-
- nexell_data = output_data->nexell_data;
- ret = drmModeObjectSetProperty(nexell_data->drm_fd,
- output_data->crtc_id, DRM_MODE_OBJECT_CRTC,
- id, value.u32);
- if (ret < 0) {
- TDM_ERR("set property failed: %m");
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-nexell_output_get_property(tdm_output *output, unsigned int id, tdm_value *value)
-{
- tdm_nexell_output_data *output_data = output;
- tdm_nexell_data *nexell_data;
- drmModeObjectPropertiesPtr props;
- int i;
-
- RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(value, TDM_ERROR_INVALID_PARAMETER);
-
- nexell_data = output_data->nexell_data;
- props = drmModeObjectGetProperties(nexell_data->drm_fd, output_data->crtc_id,
- DRM_MODE_OBJECT_CRTC);
- if (props == NULL) {
- TDM_ERR("get property failed: %m");
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- for (i = 0; i < props->count_props; i++)
- if (props->props[i] == id) {
- (*value).u32 = (uint)props->prop_values[i];
- break;
- }
-
- drmModeFreeObjectProperties(props);
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-nexell_output_wait_vblank(tdm_output *output, int interval, int sync,
- void *user_data)
-{
- tdm_nexell_output_data *output_data = output;
- tdm_nexell_data *nexell_data;
- tdm_nexell_event_data *event_data;
- uint target_msc;
- tdm_error ret;
-
- RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
-
- event_data = calloc(1, sizeof(tdm_nexell_event_data));
- if (!event_data) {
- TDM_ERR("alloc failed");
- return TDM_ERROR_OUT_OF_MEMORY;
- }
-
- nexell_data = output_data->nexell_data;
-
- ret = _tdm_nexell_display_get_cur_msc(nexell_data->drm_fd, output_data->pipe,
- &target_msc);
- if (ret != TDM_ERROR_NONE)
- goto failed_vblank;
-
- target_msc += interval;
-
- event_data->type = TDM_NEXELL_EVENT_TYPE_WAIT;
- event_data->output_data = output_data;
- event_data->user_data = user_data;
-
- ret = _tdm_nexell_display_wait_vblank(nexell_data->drm_fd, output_data->pipe,
- &target_msc, event_data);
- if (ret != TDM_ERROR_NONE)
- goto failed_vblank;
-
- return TDM_ERROR_NONE;
-failed_vblank:
- free(event_data);
- return ret;
-}
-
-tdm_error
-nexell_output_set_vblank_handler(tdm_output *output,
- tdm_output_vblank_handler func)
-{
- tdm_nexell_output_data *output_data = output;
-
- RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
-
- output_data->vblank_func = func;
-
- return TDM_ERROR_NONE;
-}
-
-static tdm_error
-_nexell_layer_add_atomic_properties(tdm_nexell_layer_data *layer_data, drmModeAtomicReqPtr request,
- uint32_t fb_id, uint32_t crtc_id, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h,
- uint32_t crtc_x, uint32_t crtc_y, uint32_t crtc_w, uint32_t crtc_h)
-{
- tdm_error ret = TDM_ERROR_NONE;
-
- ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.fb_id, fb_id);
- if (ret < 0) {
- TDM_ERR("fail to add the atomic prop. fb_id(%u)", fb_id);
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_id, crtc_id);
- if (ret < 0) {
- TDM_ERR("fail to add the atomic prop. crtc_id(%u)", crtc_id);
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_x, src_x);
- if (ret < 0) {
- TDM_ERR("fail to add the atomic prop. src_x(%u)", src_x);
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_y, src_y);
- if (ret < 0) {
- TDM_ERR("fail to add the atomic prop. src_y(%u)", src_y);
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_w, src_w);
- if (ret < 0) {
- TDM_ERR("fail to add the atomic prop. src_w(%u)", src_w);
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_h, src_h);
- if (ret < 0) {
- TDM_ERR("fail to add the atomic prop. src_h(%u)", src_h);
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_x, crtc_x);
- if (ret < 0) {
- TDM_ERR("fail to add the atomic prop. crtc_x(%u)", crtc_x);
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_y, crtc_y);
- if (ret < 0) {
- TDM_ERR("fail to add the atomic prop. crtc_y(%u)", crtc_y);
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_w, crtc_w);
- if (ret < 0) {
- TDM_ERR("fail to add the atomic prop. crtc_w(%u)", crtc_w);
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_h, crtc_h);
- if (ret < 0) {
- TDM_ERR("fail to add the atomic prop. crtc_h(%u)", crtc_h);
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- return TDM_ERROR_NONE;
-}
-
-static tdm_error
-_nexell_layer_make_atomic_request(tdm_nexell_layer_data *layer_data, drmModeAtomicReqPtr request)
-{
- tdm_nexell_data *nexell_data = layer_data->nexell_data;
- tdm_nexell_output_data *output_data = layer_data->output_data;
- uint32_t fx, fy, fw, fh;
- tdm_info_layer layer_info = layer_data->info;
- tdm_error ret = TDM_ERROR_NONE;
-
- if (!layer_data->display_buffer_changed && !layer_data->info_changed)
- return TDM_ERROR_NONE;
-
- layer_data->display_buffer_changed = 0;
- layer_data->info_changed = 0;
-
- if (!layer_data->display_buffer) {
- TDM_DBG("MakeAtomicRequest: drm_fd(%d) plane_id(%u) crtc_id(%u) off",
- nexell_data->drm_fd, layer_data->plane_id, output_data->crtc_id);
-
- ret = _nexell_layer_add_atomic_properties(layer_data, request, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
- if (ret != TDM_ERROR_NONE) {
- TDM_ERR("_nexell_layer_add_atomic_properties failed.");
- return ret;
- }
-
- return TDM_ERROR_NONE;
- }
-
- /* Source values are 16.16 fixed point */
- fx = ((unsigned int)layer_info.src_config.pos.x) << 16;
- fy = ((unsigned int)layer_info.src_config.pos.y) << 16;
- fw = ((unsigned int)layer_info.src_config.pos.w) << 16;
- fh = ((unsigned int)layer_info.src_config.pos.h) << 16;
-
- TDM_DBG("MakeAtomicRequest: drm_fd(%d) plane_id(%u) zpos(%d) crtc_id(%u) fb_id(%u) src(%u,%u %ux%u) dst(%u,%u %ux%u)",
- nexell_data->drm_fd, layer_data->plane_id, layer_data->zpos,
- output_data->crtc_id, layer_data->display_buffer->fb_id,
- layer_info.src_config.pos.x, layer_info.src_config.pos.y,
- layer_info.src_config.pos.w, layer_info.src_config.pos.h,
- layer_info.dst_pos.x, layer_info.dst_pos.y,
- layer_info.dst_pos.w, layer_info.dst_pos.h);
-
- ret = _nexell_layer_add_atomic_properties(layer_data, request,
- layer_data->display_buffer->fb_id, output_data->crtc_id,
- fx, fy, fw, fh,
- layer_info.dst_pos.x, layer_info.dst_pos.y,
- layer_info.dst_pos.w, layer_info.dst_pos.h);
- if (ret != TDM_ERROR_NONE) {
- TDM_ERR("MakeAtomicRequest failed");
- return ret;
- }
-
- return TDM_ERROR_NONE;
-}
-
-static tdm_error
-_nexell_output_atomic_commit(tdm_output *output, int sync, void *user_data)
-{
- tdm_nexell_output_data *output_data = output;
- tdm_nexell_layer_data *layer_data = NULL;
- tdm_nexell_event_data *event_data;
- drmModeAtomicReqPtr request;
- uint32_t flags = 0;
- tdm_error ret;
-
- RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
-
- if (!output_data->crtc_enabled || output_data->mode_changed) {
- drmModeModeInfoPtr mode;
-
- layer_data = output_data->primary_layer;
- if (!layer_data->display_buffer) {
- TDM_ERR("primary layer should have a buffer for modestting");
- return TDM_ERROR_BAD_REQUEST;
- }
-
- mode = _tdm_nexell_display_get_mode(output_data);
- if (!mode) {
- TDM_ERR("couldn't find proper mode");
- return TDM_ERROR_BAD_REQUEST;
- }
-
- if (drmModeSetCrtc(output_data->nexell_data->drm_fd, output_data->crtc_id,
- layer_data->display_buffer->fb_id, 0, 0,
- &output_data->connector_id, 1, mode)) {
- TDM_ERR("set crtc failed: %m");
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- _tdm_nexell_output_update_status(output_data, TDM_OUTPUT_CONN_STATUS_MODE_SETTED);
-
- output_data->crtc_enabled = 1;
- output_data->mode_changed = 0;
- }
-
- request = drmModeAtomicAlloc();
- if (!request) {
- TDM_ERR("drmModeAtomicAlloc failed.");
- return TDM_ERROR_OUT_OF_MEMORY;
- }
-
- flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK;
-
- LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
- ret = _nexell_layer_make_atomic_request(layer_data, request);
- if (ret != TDM_ERROR_NONE) {
- TDM_ERR("_nexell_layer_make_atomic_request failed.");
- drmModeAtomicFree(request);
- return ret;
- }
- }
-
- event_data = calloc(1, sizeof(tdm_nexell_event_data));
- if (!event_data) {
- TDM_ERR("fail to alloc event_data.");
- drmModeAtomicFree(request);
- return TDM_ERROR_OUT_OF_MEMORY;
- }
-
- event_data->type = TDM_NEXELL_EVENT_TYPE_COMMIT;
- event_data->output_data = output_data;
- event_data->user_data = user_data;
-
- TDM_DBG("==== Atomic Commit pipe, %u, crtc_id, %u connector_id, %u",
- output_data->pipe, output_data->crtc_id, output_data->connector_id);
-
- if (drmModeAtomicCommit(output_data->nexell_data->drm_fd, request, flags, event_data) < 0) {
- TDM_ERR("drmModeAtomicCommit failed.");
- free(event_data);
- drmModeAtomicFree(request);
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- drmModeAtomicFree(request);
-
- return TDM_ERROR_NONE;
-}
-
-static tdm_error
-_nexell_output_layers_commit(tdm_output *output, int sync, void *user_data)
-{
- tdm_nexell_output_data *output_data = output;
- tdm_nexell_data *nexell_data;
- tdm_nexell_layer_data *layer_data = NULL;
- tdm_error ret;
- int do_waitvblank = 1;
-
- RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
-
- nexell_data = output_data->nexell_data;
-
- LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
- if (layer_data == output_data->primary_layer) {
- ret = _tdm_nexell_display_commit_primary_layer(layer_data, user_data,
- &do_waitvblank);
- if (ret != TDM_ERROR_NONE)
- return ret;
- } else {
- ret = _tdm_nexell_display_commit_layer(layer_data);
- if (ret != TDM_ERROR_NONE)
- return ret;
- }
- }
-
- if (do_waitvblank == 1) {
- tdm_nexell_event_data *event_data = calloc(1, sizeof(tdm_nexell_event_data));
- uint target_msc;
-
- if (!event_data) {
- TDM_ERR("alloc failed");
- return TDM_ERROR_OUT_OF_MEMORY;
- }
-
- ret = _tdm_nexell_display_get_cur_msc(nexell_data->drm_fd, output_data->pipe,
- &target_msc);
- if (ret != TDM_ERROR_NONE) {
- free(event_data);
- return ret;
- }
-
- target_msc++;
-
- event_data->type = TDM_NEXELL_EVENT_TYPE_COMMIT;
- event_data->output_data = output_data;
- event_data->user_data = user_data;
-
- ret = _tdm_nexell_display_wait_vblank(nexell_data->drm_fd, output_data->pipe,
- &target_msc, event_data);
- if (ret != TDM_ERROR_NONE) {
- free(event_data);
- return ret;
- }
- }
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-nexell_output_commit(tdm_output *output, int sync, void *user_data)
-{
- tdm_nexell_output_data *output_data = output;
- tdm_nexell_data *nexell_data;
- tdm_error ret;
-
- RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
-
- nexell_data = output_data->nexell_data;
-
- /* check the atomic pageflip */
- if (nexell_data->has_atomic) {
- ret = _nexell_output_atomic_commit(output, sync, user_data);
- if (ret != TDM_ERROR_NONE) {
- TDM_ERR("_nexell_output_atomic_commit failed.");
- return ret;
- }
- } else {
- ret = _nexell_output_layers_commit(output, sync, user_data);
- if (ret != TDM_ERROR_NONE) {
- TDM_ERR("_nexell_output_layers_commit failed.");
- return ret;
- }
- }
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-nexell_output_set_commit_handler(tdm_output *output,
- tdm_output_commit_handler func)
-{
- tdm_nexell_output_data *output_data = output;
-
- RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
-
- output_data->commit_func = func;
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-nexell_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
-{
- tdm_nexell_output_data *output_data = output;
- tdm_nexell_data *nexell_data;
- int ret;
-
- RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
-
- if (output_data->dpms_prop_id == 0) {
- TDM_WRN("not support DPMS");
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- nexell_data = output_data->nexell_data;
- ret = drmModeObjectSetProperty(nexell_data->drm_fd,
- output_data->connector_id, DRM_MODE_OBJECT_CONNECTOR,
- output_data->dpms_prop_id, dpms_value);
- if (ret < 0) {
- TDM_ERR("set dpms failed: %m");
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-nexell_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
-{
- tdm_nexell_output_data *output_data = output;
- tdm_nexell_data *nexell_data;
- drmModeObjectPropertiesPtr props;
- int i;
-
- RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(dpms_value, TDM_ERROR_INVALID_PARAMETER);
-
- nexell_data = output_data->nexell_data;
- props = drmModeObjectGetProperties(nexell_data->drm_fd, output_data->connector_id,
- DRM_MODE_OBJECT_CONNECTOR);
- if (props == NULL) {
- TDM_ERR("get property failed: %m");
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- for (i = 0; i < props->count_props; i++)
- if (props->props[i] == output_data->dpms_prop_id) {
- *dpms_value = (uint)props->prop_values[i];
- break;
- }
-
- drmModeFreeObjectProperties(props);
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-nexell_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
-{
- tdm_nexell_output_data *output_data = output;
- tdm_error ret = TDM_ERROR_NONE;
-
- RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
-
- /* create or replace the target_window when the output mode is set */
- if (output_data->hwc_enable) {
- ret = nexell_hwc_target_window_set_info(output_data->hwc_data, mode->hdisplay, mode->vdisplay);
- if (ret != TDM_ERROR_NONE) {
- TDM_ERR("set info target hwc window failed (%d)", ret);
- return ret;
- }
- }
-
- output_data->current_mode = mode;
- output_data->mode_changed = 1;
-
- TDM_INFO("Set the output mode: %s, %d, %d, %d, %d, %d",
- mode->name, mode->hdisplay, mode->vdisplay, mode->vrefresh, mode->flags, mode->type);
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-nexell_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
-{
- tdm_nexell_output_data *output_data = output;
-
- RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
-
- *mode = output_data->current_mode;
-
- return TDM_ERROR_NONE;
-}
-
-tdm_hwc *
-nexell_output_get_hwc(tdm_output *output, tdm_error *error)
-{
- tdm_nexell_hwc_data *hwc_data = NULL;
- tdm_nexell_output_data *output_data = output;
- tdm_error ret = TDM_ERROR_NONE;
- int i;
-
- if (!output_data) {
- TDM_ERR("invalid params");
- if (error)
- *error = TDM_ERROR_INVALID_PARAMETER;
- return NULL;
- }
-
- if (output_data->hwc_data) {
- TDM_INFO("hwc_data already exists");
- if (error)
- *error = TDM_ERROR_NONE;
- return output_data->hwc_data;
- }
-
- hwc_data = calloc(1, sizeof(tdm_nexell_hwc_data));
- if (!hwc_data) {
- TDM_ERR("alloc failed");
- if (error)
- *error = TDM_ERROR_OUT_OF_MEMORY;
- return NULL;
- }
-
- for (i = 0; i < NUM_LAYERS; i++) {
- hwc_data->ui_buffer_queue[i].tqueue = NULL;
- hwc_data->ui_buffer_queue[i].ref_cnt = 0;
- }
-
- hwc_data->output_data = output_data;
-
- LIST_INITHEAD(&hwc_data->hwc_window_list);
-
- output_data->hwc_data = hwc_data;
-
- ret = nexell_hwc_initailize_target_window(output_data->hwc_data);
- if (ret != TDM_ERROR_NONE) {
- TDM_ERR("create target hwc window failed (%d)", ret);
- free(hwc_data);
- if (error)
- *error = ret;
- return NULL;
- }
-
- if (error)
- *error = TDM_ERROR_NONE;
-
- return hwc_data;
-}
-
-tdm_error
-nexell_output_set_status_handler(tdm_output *output,
- tdm_output_status_handler func,
- void *user_data)
-{
- tdm_nexell_output_data *output_data = output;
-
- RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
-
- output_data->status_func = func;
- output_data->status_user_data = user_data;
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-nexell_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps)
-{
- tdm_nexell_layer_data *layer_data = layer;
- tdm_nexell_data *nexell_data;
- drmModePlanePtr plane = NULL;
- drmModeObjectPropertiesPtr props = NULL;
- int i, format_count = 0;
- tdm_error ret;
-
- RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
-
- memset(caps, 0, sizeof(tdm_caps_layer));
-
- nexell_data = layer_data->nexell_data;
- plane = drmModeGetPlane(nexell_data->drm_fd, layer_data->plane_id);
- if (!plane) {
- TDM_ERR("get plane failed: %m");
- ret = TDM_ERROR_OPERATION_FAILED;
- goto failed_get;
- }
-
- caps->capabilities = layer_data->capabilities;
- caps->zpos = layer_data->zpos; /* if VIDEO layer, zpos is -1 */
-
- caps->format_count = plane->count_formats;
- caps->formats = calloc(1, sizeof(tbm_format) * caps->format_count);
- if (!caps->formats) {
- ret = TDM_ERROR_OUT_OF_MEMORY;
- TDM_ERR("alloc failed\n");
- goto failed_get;
- }
-
- for (i = 0; i < caps->format_count; i++) {
- /* TODO: kernel reports wrong formats */
- if (plane->formats[i] != DRM_FORMAT_XRGB8888 &&
- plane->formats[i] != DRM_FORMAT_ARGB8888 &&
- plane->formats[i] != DRM_FORMAT_YUV420) {
- TDM_WRN("plane(%d) zpos(%d) %c%c%c%c skipped",
- layer_data->plane_id, layer_data->zpos, FOURCC_STR(plane->formats[i]));
- continue;
- }
- caps->formats[format_count] = tdm_nexell_format_to_tbm_format(plane->formats[i]);
- format_count++;
- }
-
- caps->format_count = format_count;
-
- props = drmModeObjectGetProperties(nexell_data->drm_fd, layer_data->plane_id,
- DRM_MODE_OBJECT_PLANE);
- if (!props) {
- ret = TDM_ERROR_OPERATION_FAILED;
- TDM_ERR("get plane properties failed: %m\n");
- goto failed_get;
- }
-
- caps->props = calloc(1, sizeof(tdm_prop) * props->count_props);
- if (!caps->props) {
- ret = TDM_ERROR_OUT_OF_MEMORY;
- TDM_ERR("alloc failed\n");
- goto failed_get;
- }
-
- caps->prop_count = 0;
- for (i = 0; i < props->count_props; i++) {
- drmModePropertyPtr prop = drmModeGetProperty(nexell_data->drm_fd, props->props[i]);
- if (!prop)
- continue;
- if (!strncmp(prop->name, "type", TDM_NAME_LEN)) {
- drmModeFreeProperty(prop);
- continue;
- }
- if (!strncmp(prop->name, "zpos", TDM_NAME_LEN)) {
- drmModeFreeProperty(prop);
- continue;
- }
- snprintf(caps->props[caps->prop_count].name, TDM_NAME_LEN, "%s", prop->name);
- caps->props[caps->prop_count].id = props->props[i];
- caps->prop_count++;
- drmModeFreeProperty(prop);
- }
-
- drmModeFreeObjectProperties(props);
- drmModeFreePlane(plane);
-
- return TDM_ERROR_NONE;
-failed_get:
- drmModeFreeObjectProperties(props);
- drmModeFreePlane(plane);
- free(caps->formats);
- free(caps->props);
- memset(caps, 0, sizeof(tdm_caps_layer));
- return ret;
-}
-
-tdm_error
-nexell_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
-{
- tdm_nexell_layer_data *layer_data = layer;
- tdm_nexell_data *nexell_data;
- int ret;
-
- RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, TDM_ERROR_INVALID_PARAMETER);
-
- nexell_data = layer_data->nexell_data;
- ret = drmModeObjectSetProperty(nexell_data->drm_fd,
- layer_data->plane_id, DRM_MODE_OBJECT_PLANE,
- id, value.u32);
- if (ret < 0) {
- TDM_ERR("set property failed: %m");
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-nexell_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
-{
- tdm_nexell_layer_data *layer_data = layer;
- tdm_nexell_data *nexell_data;
- drmModeObjectPropertiesPtr props;
- int i;
-
- RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(value, TDM_ERROR_INVALID_PARAMETER);
-
- nexell_data = layer_data->nexell_data;
- props = drmModeObjectGetProperties(nexell_data->drm_fd, layer_data->plane_id,
- DRM_MODE_OBJECT_PLANE);
- if (props == NULL) {
- TDM_ERR("get property failed: %m");
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- for (i = 0; i < props->count_props; i++)
- if (props->props[i] == id) {
- (*value).u32 = (uint)props->prop_values[i];
- break;
- }
-
- drmModeFreeObjectProperties(props);
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-nexell_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
-{
- tdm_nexell_layer_data *layer_data = layer;
-
- RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
-
- layer_data->info = *info;
- layer_data->info_changed = 1;
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-nexell_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
-{
- tdm_nexell_layer_data *layer_data = layer;
-
- RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
-
- *info = layer_data->info;
-
- return TDM_ERROR_NONE;
-}
-
-static tdm_nexell_display_buffer *
-_tdm_nexell_display_find_buffer(tdm_nexell_data *nexell_data, tbm_surface_h buffer)
-{
- tdm_nexell_display_buffer *display_buffer = NULL;
-
- LIST_FOR_EACH_ENTRY(display_buffer, &nexell_data->buffer_list, link) {
- if (display_buffer->buffer == buffer)
- return display_buffer;
- }
-
- return NULL;
-}
-
-static void
-_tdm_nexell_display_cb_destroy_buffer(tbm_surface_h buffer, void *user_data)
-{
- tdm_nexell_data *nexell_data;
- tdm_nexell_display_buffer *display_buffer;
- tdm_nexell_layer_data *layer_data = NULL;
- tdm_nexell_output_data *output_data = NULL;
- char buf[256] = {0,};
- char *ret_tmp;
-
- if (!user_data) {
- TDM_ERR("no user_data");
- return;
- }
- if (!buffer) {
- TDM_ERR("no buffer");
- return;
- }
-
- nexell_data = (tdm_nexell_data *) user_data;
-
- display_buffer = _tdm_nexell_display_find_buffer(nexell_data, buffer);
- if (!display_buffer) {
- TDM_ERR("no display_buffer");
- return;
- }
-
- LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) {
- LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
- if (display_buffer == layer_data->display_buffer)
- layer_data->display_buffer = NULL;
- }
- }
-
- if (display_buffer->fb_id > 0) {
- if (drmModeRmFB(nexell_data->drm_fd, display_buffer->fb_id) < 0) {
- ret_tmp = strerror_r(errno, buf, sizeof(buf));
- TDM_ERR("rm fb failed: %d(%s,%s)\n", errno, buf, ret_tmp);
- }
- }
-
- TDM_DBG("destroy buffer:%p", display_buffer->buffer);
-
- LIST_DEL(&display_buffer->link);
- free(display_buffer);
-}
-
-static tdm_nexell_display_buffer *
-_tdm_nexell_display_create_buffer(tdm_nexell_data *nexell_data, tbm_surface_h buffer, tdm_error *err)
-{
- tdm_nexell_display_buffer *display_buffer = NULL;
- tdm_error res = TDM_ERROR_NONE;
- int count, i, ret;
-
- display_buffer = calloc(1, sizeof(tdm_nexell_display_buffer));
- if (!display_buffer) {
- TDM_ERR("alloc failed");
- if (err)
- *err = TDM_ERROR_OUT_OF_MEMORY;
- return NULL;
- }
-
- display_buffer->buffer = buffer;
-
- res = tdm_buffer_add_destroy_handler(buffer, _tdm_nexell_display_cb_destroy_buffer, nexell_data);
- if (res != TDM_ERROR_NONE) {
- TDM_ERR("add destroy handler fail");
- free(display_buffer);
- if (err)
- *err = res;
- return NULL;
- }
-
- display_buffer->width = tbm_surface_get_width(buffer);
- display_buffer->height = tbm_surface_get_height(buffer);
- display_buffer->format = tbm_surface_get_format(buffer);
- display_buffer->count = tbm_surface_internal_get_num_bos(buffer);
- count = tbm_surface_internal_get_num_planes(display_buffer->format);
- TDM_DBG(" display_buffer:%p %dx%d %c%c%c%c bo_num:%d plane_num:%d",
- buffer, display_buffer->width, display_buffer->height,
- FOURCC_STR(display_buffer->format), display_buffer->count, count);
-
- for (i = 0; i < count; i++) {
- int bo_idx = 0;
- tbm_bo bo = NULL;
-
- bo_idx = tbm_surface_internal_get_plane_bo_idx(buffer, i);
- bo = tbm_surface_internal_get_bo(buffer, bo_idx);
- display_buffer->handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
-
- tbm_surface_internal_get_plane_data(buffer, i, &display_buffer->size,
- &display_buffer->offsets[i],
- &display_buffer->pitches[i]);
- TDM_DBG("\tplane%d(size:%d offset:%d pitch:%d) bo%d(handle:%d)",
- i, display_buffer->size, display_buffer->offsets[i],
- display_buffer->pitches[i], bo_idx, display_buffer->handles[i]);
- }
-
- ret = drmModeAddFB2(nexell_data->drm_fd, display_buffer->width, display_buffer->height,
- display_buffer->format, display_buffer->handles, display_buffer->pitches,
- display_buffer->offsets, &display_buffer->fb_id, 0);
- if (ret < 0) {
- TDM_ERR("add fb failed: %m");
- free(display_buffer);
- if (err)
- *err = TDM_ERROR_OPERATION_FAILED;
- return NULL;
- }
-
- TDM_DBG("nexell_data->drm_fd : %d, display_buffer->fb_id:%u", nexell_data->drm_fd,
- display_buffer->fb_id);
-
- if (IS_RGB(display_buffer->format))
- display_buffer->width = display_buffer->pitches[0] >> 2;
- else
- display_buffer->width = display_buffer->pitches[0];
-
- LIST_ADDTAIL(&display_buffer->link, &nexell_data->buffer_list);
-
- if (err)
- *err = TDM_ERROR_NONE;
-
- return display_buffer;
-}
-
-void
-tdm_nexell_data_destroy_buffer_list(tdm_nexell_data *nexell_data)
-{
- tdm_nexell_display_buffer *b = NULL, *bb = NULL;
-
- LIST_FOR_EACH_ENTRY_SAFE(b, bb, &nexell_data->buffer_list, link) {
- tdm_buffer_remove_destroy_handler(b->buffer, _tdm_nexell_display_cb_destroy_buffer, nexell_data);
- _tdm_nexell_display_cb_destroy_buffer(b->buffer, nexell_data);
- }
-}
-
-tdm_error
-nexell_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
-{
- tdm_nexell_layer_data *layer_data = layer;
- tdm_nexell_data *nexell_data;
- tdm_nexell_display_buffer *display_buffer;
- tdm_error err = TDM_ERROR_NONE;
-
- RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(buffer, TDM_ERROR_INVALID_PARAMETER);
-
- nexell_data = layer_data->nexell_data;
- display_buffer = _tdm_nexell_display_find_buffer(nexell_data, buffer);
- if (!display_buffer) {
- display_buffer = _tdm_nexell_display_create_buffer(nexell_data, buffer, &err);
- RETURN_VAL_IF_FAIL(display_buffer != NULL, err);
- }
-
- if (layer_data->display_buffer != display_buffer) {
- if (layer_data->display_buffer)
- tbm_surface_internal_unref(layer_data->display_buffer->buffer);
-
- layer_data->display_buffer = display_buffer;
- tbm_surface_internal_ref(layer_data->display_buffer->buffer);
- layer_data->display_buffer_changed = 1;
- }
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-nexell_layer_unset_buffer(tdm_layer *layer)
-{
- tdm_nexell_layer_data *layer_data = layer;
-
- RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
-
- if (!(layer_data->capabilities & TDM_LAYER_CAPABILITY_PRIMARY) && layer_data->display_buffer) {
- tbm_surface_internal_unref(layer_data->display_buffer->buffer);
- layer_data->display_buffer = NULL;
- }
-
- layer_data->display_buffer_changed = 1;
-
- return TDM_ERROR_NONE;
-}
-
-tdm_nexell_layer_data *
-nexell_output_data_get_layer_data(tdm_nexell_output_data *output_data, int layer_zpos)
-{
- tdm_nexell_layer_data *l = NULL;
-
- RETURN_VAL_IF_FAIL(output_data, NULL);
-
- LIST_FOR_EACH_ENTRY(l, &output_data->layer_list, link) {
- if (l->zpos == layer_zpos)
- return l;
- }
-
- return NULL;
-}