diff options
Diffstat (limited to 'src/libtdm-exynos/tdm_exynos_output.c')
-rw-r--r-- | src/libtdm-exynos/tdm_exynos_output.c | 1085 |
1 files changed, 0 insertions, 1085 deletions
diff --git a/src/libtdm-exynos/tdm_exynos_output.c b/src/libtdm-exynos/tdm_exynos_output.c deleted file mode 100644 index acf2a42..0000000 --- a/src/libtdm-exynos/tdm_exynos_output.c +++ /dev/null @@ -1,1085 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <drm_fourcc.h> -#include <tdm_helper.h> -#include "tdm_exynos.h" - -#define MIN_WIDTH 32 - -#define LIST_INSERT_AFTER(__after, __item) \ - (__item)->prev = (__after); \ - (__item)->next = (__after)->next; \ - (__after)->next->prev = (__item); \ - (__after)->next = (__item); - -static tdm_error -check_hw_restriction_crtc(unsigned int crtc_w, - unsigned int buf_w, unsigned int buf_h, - unsigned int src_x, unsigned int src_y, - unsigned int src_w, unsigned int src_h, - unsigned int dst_w, unsigned int dst_h, - unsigned int *new_x, unsigned int *new_y) -{ - int tmp; - int dx = 1, dy = 1; - int changed_x = 0; - int changed_y = 0; - - (void) crtc_w; - (void) dst_w; - (void) dst_h; - - *new_x = src_x; - *new_y = src_y; - - if (src_x + src_w > buf_w) { - tmp = src_x; - while (tmp + src_w != buf_w) - tmp -= dx; - - changed_x = 1; - *new_x = tmp; - } - - if (src_y + src_h > buf_h) { - tmp = src_y; - while (tmp + src_h != buf_h) - tmp -= dy; - - changed_y = 1; - *new_y = tmp; - } - - if (changed_x == 1 || changed_y == 1) - return TDM_ERROR_INVALID_PARAMETER; - return TDM_ERROR_NONE; -} - -static tdm_error -check_hw_restriction(unsigned int crtc_w, unsigned int crtc_h, unsigned int buf_w, - unsigned int src_x, unsigned int src_w, - unsigned int dst_x, unsigned int dst_y, unsigned int dst_w, - unsigned int *new_src_x, unsigned int *new_src_w, - unsigned int *new_dst_x, unsigned int *new_dst_w) -{ - int start, end, diff; - int virtual_screen; - - *new_src_x = src_x; - *new_src_w = src_w; - *new_dst_x = dst_x; - *new_dst_w = dst_w; - - if (buf_w < MIN_WIDTH || buf_w % 2) { - TDM_ERR("buf_w(%u) not 2's multiple or less than %u", buf_w, MIN_WIDTH); - return TDM_ERROR_BAD_REQUEST; - } - - if (dst_x > crtc_w || dst_y > crtc_h) { - TDM_ERR("dst_pos(%u,%u) is out of crtc(%ux%u)", dst_x, dst_y, crtc_w, crtc_h); - return TDM_ERROR_BAD_REQUEST; - } - - if (src_x > dst_x || ((dst_x - src_x) + buf_w) > crtc_w) - virtual_screen = 1; - else - virtual_screen = 0; - - start = dst_x; - end = ((dst_x + dst_w) > crtc_w) ? crtc_w : (dst_x + dst_w); - - /* check window minimun width */ - if ((end - start) < MIN_WIDTH) { - TDM_ERR("visible_w(%d) less than %u", end - start, MIN_WIDTH); - return TDM_ERROR_BAD_REQUEST; - } - - if (!virtual_screen) { - /* Pagewidth of window (= 8 byte align / bytes-per-pixel ) */ - if ((end - start) % 2) - end--; - } else { - /* You should align the sum of PAGEWIDTH_F and OFFSIZE_F double-word (8 byte) boundary. */ - if (end % 2) - end--; - } - - *new_dst_x = start; - *new_dst_w = end - start; - *new_src_w = *new_dst_w; - diff = start - dst_x; - *new_src_x += diff; - - RETURN_VAL_IF_FAIL(*new_src_w > 0, TDM_ERROR_BAD_REQUEST); - RETURN_VAL_IF_FAIL(*new_dst_w > 0, TDM_ERROR_BAD_REQUEST); - - if (src_x != *new_src_x || src_w != *new_src_w || dst_x != *new_dst_x || - dst_w != *new_dst_w) - TDM_DBG("=> buf_w(%d) src(%d,%d) dst(%d,%d), virt(%d) start(%d) end(%d)", - buf_w, *new_src_x, *new_src_w, *new_dst_x, *new_dst_w, virtual_screen, start, - end); - - return TDM_ERROR_NONE; -} - -static drmModeModeInfoPtr -_tdm_exynos_output_get_mode(tdm_exynos_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 (exynos_screen_prerotation_hint % 180) { - if ((drm_mode->hdisplay == output_data->current_mode->vdisplay) && - (drm_mode->vdisplay == output_data->current_mode->hdisplay) && - (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; - } else { - 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 tdm_error -_tdm_exynos_output_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_exynos_output_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 void -_tdm_exynos_output_transform_layer_info(int width, int height, tdm_info_layer *info) -{ - tdm_pos dst_pos; - - switch (exynos_screen_prerotation_hint) { - case 90: - dst_pos.x = info->dst_pos.y; - dst_pos.y = width - info->dst_pos.x - info->dst_pos.w; - dst_pos.w = info->dst_pos.h; - dst_pos.h = info->dst_pos.w; - break; - case 180: - dst_pos.x = width - info->dst_pos.x - info->dst_pos.w; - dst_pos.y = height - info->dst_pos.y - info->dst_pos.h; - dst_pos.w = info->dst_pos.w; - dst_pos.h = info->dst_pos.h; - break; - case 270: - dst_pos.x = height - info->dst_pos.y - info->dst_pos.h; - dst_pos.y = info->dst_pos.x; - dst_pos.w = info->dst_pos.h; - dst_pos.h = info->dst_pos.w; - break; - default: - return; - } - - info->dst_pos = dst_pos; -} - -static tdm_error -_tdm_exynos_output_commit_primary_layer(tdm_exynos_layer_data *layer_data, - void *user_data, int *do_waitvblank) -{ - tdm_exynos_data *exynos_data = layer_data->exynos_data; - tdm_exynos_output_data *output_data = layer_data->output_data; - unsigned int new_x = -1, new_y = -1; - uint32_t fx, fy; - int crtc_w, crtc_h; - - if (output_data->mode_changed && layer_data->display_buffer_changed) { - tdm_info_layer layer_info = layer_data->info; - drmModeModeInfoPtr mode; - - if (!layer_data->display_buffer) { - TDM_ERR("primary layer should have a buffer for modestting"); - return TDM_ERROR_BAD_REQUEST; - } - - if (output_data->current_mode) { - crtc_w = output_data->current_mode->hdisplay; - crtc_h = output_data->current_mode->vdisplay; - } else { - drmModeCrtcPtr crtc = drmModeGetCrtc(exynos_data->drm_fd, output_data->crtc_id); - if (!crtc) { - TDM_ERR("getting crtc failed"); - return TDM_ERROR_OPERATION_FAILED; - } - crtc_w = crtc->width; - crtc_h = crtc->height; - if (crtc_w == 0) { - TDM_ERR("getting crtc width failed"); - drmModeFreeCrtc(crtc); - return TDM_ERROR_OPERATION_FAILED; - } - drmModeFreeCrtc(crtc); - } - - output_data->mode_changed = 0; - layer_data->display_buffer_changed = 0; - layer_data->info_changed = 0; - - mode = _tdm_exynos_output_get_mode(output_data); - if (!mode) { - TDM_ERR("couldn't find proper mode"); - return TDM_ERROR_BAD_REQUEST; - } - - _tdm_exynos_output_transform_layer_info(crtc_w, crtc_h, &layer_info); - - if (check_hw_restriction_crtc(crtc_w, - layer_info.src_config.size.h, layer_info.src_config.size.v, - 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.w, layer_info.dst_pos.h, - &new_x, &new_y) != TDM_ERROR_NONE) - TDM_WRN("not going to set crtc(%u)", output_data->crtc_id); - - if (layer_info.src_config.pos.x != new_x) - TDM_DBG("src_x changed: %u => %u", layer_info.src_config.pos.x, - new_x); - if (layer_info.src_config.pos.y != new_y) - TDM_DBG("src_y changed: %u => %u", layer_info.src_config.pos.y, - new_y); - - fx = (unsigned int)new_x; - fy = (unsigned int)new_y; - - TDM_DBG("SetCrtc: drm_fd(%d) crtc_id(%u) fb_id(%u) mode(%ux%u, %uhz) pos(%u %u)", - exynos_data->drm_fd, output_data->crtc_id, layer_data->display_buffer->fb_id, - mode->hdisplay, mode->vdisplay, mode->vrefresh, fx, fy); - - if (drmModeSetCrtc(exynos_data->drm_fd, output_data->crtc_id, - layer_data->display_buffer->fb_id, fx, fy, - &output_data->connector_id, 1, mode)) { - TDM_ERR("set crtc failed: %m"); - return TDM_ERROR_OPERATION_FAILED; - } - - tdm_exynos_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) { - tbm_surface_info_s info; - int ret; - tdm_exynos_event_data *event_data = calloc(1, sizeof(tdm_exynos_event_data)); - - if (!event_data) { - TDM_ERR("alloc failed"); - return TDM_ERROR_OUT_OF_MEMORY; - } - event_data->type = TDM_EXYNOS_EVENT_TYPE_PAGEFLIP; - event_data->output_data = output_data; - event_data->user_data = user_data; - event_data->hwc_mode = exynos_data->hwc_mode; - - TDM_DBG("PageFlip: drm_fd(%d) crtc_id(%u) fb_id(%u)", - exynos_data->drm_fd, output_data->crtc_id, - layer_data->display_buffer->fb_id); - - ret = tbm_surface_map(layer_data->display_buffer->buffer, TBM_SURF_OPTION_READ, &info); - if (ret == TBM_SURFACE_ERROR_NONE) - tbm_surface_unmap(layer_data->display_buffer->buffer); - - if (drmModePageFlip(exynos_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_exynos_output_commit_layer(tdm_exynos_layer_data *layer_data) -{ - tdm_exynos_data *exynos_data = layer_data->exynos_data; - tdm_exynos_output_data *output_data = layer_data->output_data; - unsigned int new_src_x, new_src_w; - unsigned int new_dst_x, new_dst_w; - uint32_t fx, fy, fw, fh; - int crtc_w, crtc_h; - tdm_info_layer layer_info = layer_data->info; - - 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; - crtc_h = output_data->current_mode->vdisplay; - } else { - drmModeCrtcPtr crtc = drmModeGetCrtc(exynos_data->drm_fd, output_data->crtc_id); - if (!crtc) { - TDM_ERR("getting crtc failed"); - return TDM_ERROR_OPERATION_FAILED; - } - crtc_w = crtc->width; - crtc_h = crtc->height; - if (crtc_w == 0) { - TDM_ERR("getting crtc width failed"); - drmModeFreeCrtc(crtc); - return TDM_ERROR_OPERATION_FAILED; - } - drmModeFreeCrtc(crtc); - } - - layer_data->display_buffer_changed = 0; - layer_data->info_changed = 0; - - if (!layer_data->display_buffer) { - TDM_DBG("SetPlane: drm_fd(%d) plane_id(%u) crtc_id(%u) off", - exynos_data->drm_fd, layer_data->plane_id, output_data->crtc_id); - - if (drmModeSetPlane(exynos_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(%u) filed: %m", layer_data->plane_id); - - return TDM_ERROR_NONE; - } - - _tdm_exynos_output_transform_layer_info(crtc_w, crtc_h, &layer_info); - - /* check hw restriction*/ - if (check_hw_restriction(crtc_w, crtc_h, layer_data->display_buffer->width, - layer_info.src_config.pos.x, - layer_info.src_config.pos.w, - layer_info.dst_pos.x, - layer_info.dst_pos.y, - layer_info.dst_pos.w, - &new_src_x, &new_src_w, &new_dst_x, &new_dst_w) != TDM_ERROR_NONE) { - TDM_WRN("not going to set plane(%u)", layer_data->plane_id); - return TDM_ERROR_NONE; - } - - if (layer_info.src_config.pos.x != new_src_x) - TDM_DBG("src_x changed: %u => %u", layer_info.src_config.pos.x, new_src_x); - if (layer_info.src_config.pos.w != new_src_w) - TDM_DBG("src_w changed: %u => %u", layer_info.src_config.pos.w, new_src_w); - if (layer_info.dst_pos.x != new_dst_x) - TDM_DBG("dst_x changed: %u => %u", layer_info.dst_pos.x, new_dst_x); - if (layer_info.dst_pos.w != new_dst_w) - TDM_DBG("dst_w changed: %u => %u", layer_info.dst_pos.w, new_dst_w); - - /* Source values are 16.16 fixed point */ - fx = ((unsigned int)new_src_x) << 16; - fy = ((unsigned int)layer_info.src_config.pos.y) << 16; - fw = ((unsigned int)new_src_w) << 16; - fh = ((unsigned int)layer_info.src_config.pos.h) << 16; - - TDM_DBG("SetPlane: drm_fd(%d) plane_id(%u) zpos(%d) crtc_id(%u) fb_id(%u) src(%u,%u %ux%u) dst(%u,%u %ux%u)", - exynos_data->drm_fd, layer_data->plane_id, layer_data->zpos, - output_data->crtc_id, layer_data->display_buffer->fb_id, - new_src_x, layer_info.src_config.pos.y, - new_src_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); - - if (drmModeSetPlane(exynos_data->drm_fd, layer_data->plane_id, - output_data->crtc_id, layer_data->display_buffer->fb_id, 0, - new_dst_x, layer_info.dst_pos.y, - new_dst_w, layer_info.dst_pos.h, - fx, fy, fw, fh) < 0) { - TDM_ERR("SetPlane: drm_fd(%d) plane_id(%u) zpos(%d) crtc_id(%u) fb_id(%u) src(%u,%u %ux%u) dst(%u,%u %ux%u) failed: %m", - exynos_data->drm_fd, layer_data->plane_id, layer_data->zpos, - output_data->crtc_id, layer_data->display_buffer->fb_id, - new_src_x, layer_info.src_config.pos.y, - new_src_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); - return TDM_ERROR_OPERATION_FAILED; - } - - return TDM_ERROR_NONE; -} - -void -tdm_exynos_output_cb_event(int fd, unsigned int sequence, - unsigned int tv_sec, unsigned int tv_usec, - void *user_data) -{ - tdm_exynos_event_data *event_data = user_data; - tdm_exynos_output_data *output_data; - tdm_exynos_hwc_data *hwc_data; - - if (!event_data) { - TDM_ERR("no event data"); - return; - } - - output_data = event_data->output_data; - hwc_data = output_data->hwc_data; - - switch (event_data->type) { - case TDM_EXYNOS_EVENT_TYPE_PAGEFLIP: - case TDM_EXYNOS_EVENT_TYPE_COMMIT: - if (event_data->hwc_mode && hwc_data) { - 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; - case TDM_EXYNOS_EVENT_TYPE_WAIT: - if (output_data->vblank_func) - output_data->vblank_func(output_data, sequence, tv_sec, tv_usec, - event_data->user_data); - break; - default: - break; - } - - free(event_data); -} - -tdm_error -tdm_exynos_output_update_status(tdm_exynos_output_data *output_data, - tdm_output_conn_status status) -{ - tdm_exynos_layer_data *layer_data = NULL; - - RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); - - if (output_data->status == status) - return TDM_ERROR_NONE; - - output_data->status = status; - - LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) { - if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) { - if (layer_data->display_buffer) - layer_data->display_buffer_force_unset = 1; - } else - layer_data->display_buffer_force_unset = 0; - } - - if (output_data->status_func) - output_data->status_func(output_data, status, - output_data->status_user_data); - - return TDM_ERROR_NONE; -} - -tdm_error -exynos_output_get_capability(tdm_output *output, tdm_caps_output *caps) -{ - tdm_exynos_output_data *output_data = output; - tdm_exynos_data *exynos_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)); - - exynos_data = output_data->exynos_data; - - snprintf(caps->maker, TDM_NAME_LEN, "unknown"); - snprintf(caps->model, TDM_NAME_LEN, "unknown"); - snprintf(caps->name, TDM_NAME_LEN, "unknown"); - - caps->type = output_data->connector_type; - caps->type_id = output_data->connector_type_id; - - connector = drmModeGetConnector(exynos_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_exynos_display_to_tdm_mode(&output_data->drm_modes[i], - &output_data->output_modes[i]); - caps->modes[i] = output_data->output_modes[i]; - } - - if (connector->connection == DRM_MODE_CONNECTED) - output_data->status = TDM_OUTPUT_CONN_STATUS_CONNECTED; - else - output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; - caps->status = output_data->status; - - if (exynos_screen_prerotation_hint % 180) { - caps->mmWidth = connector->mmHeight; - caps->mmHeight = connector->mmWidth; - caps->min_w = exynos_data->mode_res->min_height; - caps->min_h = exynos_data->mode_res->min_width; - caps->max_w = exynos_data->mode_res->max_height; - caps->max_h = exynos_data->mode_res->max_width; - } else { - caps->mmWidth = connector->mmWidth; - caps->mmHeight = connector->mmHeight; - caps->min_w = exynos_data->mode_res->min_width; - caps->min_h = exynos_data->mode_res->min_height; - caps->max_w = exynos_data->mode_res->max_width; - caps->max_h = exynos_data->mode_res->max_height; - } - - caps->subpixel = connector->subpixel; - caps->preferred_align = -1; - - caps->cursor_min_w = 32; - caps->cursor_min_h = 32; - caps->cursor_max_w = -1; - caps->cursor_max_h = -1; - caps->cursor_preferred_align = -1; - - crtc = drmModeGetCrtc(exynos_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(exynos_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(exynos_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 ** -exynos_output_get_layers(tdm_output *output, int *count, tdm_error *error) -{ - tdm_exynos_output_data *output_data = output; - tdm_exynos_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); - - if (output_data->hwc_enable) { - *count = 0; - ret = TDM_ERROR_NONE; - goto failed_get; - } - - *count = 0; - LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) - (*count)++; - - if (*count == 0) { - ret = TDM_ERROR_NONE; - goto failed_get; - } - - /* will be freed in frontend */ - layers = calloc(*count, sizeof(tdm_exynos_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 -exynos_output_set_property(tdm_output *output, unsigned int id, tdm_value value) -{ - tdm_exynos_output_data *output_data = output; - tdm_exynos_data *exynos_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); - - exynos_data = output_data->exynos_data; - ret = drmModeObjectSetProperty(exynos_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 -exynos_output_get_property(tdm_output *output, unsigned int id, - tdm_value *value) -{ - tdm_exynos_output_data *output_data = output; - tdm_exynos_data *exynos_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); - - exynos_data = output_data->exynos_data; - props = drmModeObjectGetProperties(exynos_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 -exynos_output_wait_vblank(tdm_output *output, int interval, int sync, - void *user_data) -{ - tdm_exynos_output_data *output_data = output; - tdm_exynos_data *exynos_data; - tdm_exynos_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_exynos_event_data)); - if (!event_data) { - TDM_ERR("alloc failed"); - return TDM_ERROR_OUT_OF_MEMORY; - } - - exynos_data = output_data->exynos_data; - - ret = _tdm_exynos_output_get_cur_msc(exynos_data->drm_fd, output_data->pipe, - &target_msc); - if (ret != TDM_ERROR_NONE) - goto failed_vblank; - - target_msc += interval; - - event_data->type = TDM_EXYNOS_EVENT_TYPE_WAIT; - event_data->output_data = output_data; - event_data->user_data = user_data; - - ret = _tdm_exynos_output_wait_vblank(exynos_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 -exynos_output_set_vblank_handler(tdm_output *output, - tdm_output_vblank_handler func) -{ - tdm_exynos_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; -} - -tdm_error -exynos_output_commit(tdm_output *output, int sync, void *user_data) -{ - tdm_exynos_output_data *output_data = output; - tdm_exynos_data *exynos_data; - tdm_exynos_layer_data *layer_data = NULL; - tdm_error ret; - int do_waitvblank = 1; - - RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); - - exynos_data = output_data->exynos_data; - - LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) { - if (layer_data == output_data->primary_layer) { - if (!layer_data->display_buffer || - (output_data->current_mode->hdisplay == layer_data->info.src_config.pos.w && - output_data->current_mode->vdisplay == layer_data->info.src_config.pos.h)) { - ret = _tdm_exynos_output_commit_primary_layer(layer_data, user_data, - &do_waitvblank); - } else - ret = _tdm_exynos_output_commit_layer(layer_data); - - if (ret != TDM_ERROR_NONE) - return ret; - } else { - ret = _tdm_exynos_output_commit_layer(layer_data); - if (ret != TDM_ERROR_NONE) - return ret; - } - } - - if (do_waitvblank == 1) { - tdm_exynos_event_data *event_data = calloc(1, sizeof(tdm_exynos_event_data)); - uint target_msc; - - if (!event_data) { - TDM_ERR("alloc failed"); - return TDM_ERROR_OUT_OF_MEMORY; - } - - ret = _tdm_exynos_output_get_cur_msc(exynos_data->drm_fd, output_data->pipe, - &target_msc); - if (ret != TDM_ERROR_NONE) { - free(event_data); - return ret; - } - - target_msc++; - - event_data->type = TDM_EXYNOS_EVENT_TYPE_COMMIT; - event_data->output_data = output_data; - event_data->user_data = user_data; - event_data->hwc_mode = exynos_data->hwc_mode; - - ret = _tdm_exynos_output_wait_vblank(exynos_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 -exynos_output_set_commit_handler(tdm_output *output, - tdm_output_commit_handler func) -{ - tdm_exynos_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 -exynos_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value) -{ - tdm_exynos_output_data *output_data = output; - tdm_exynos_data *exynos_data; - int ret; - - RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); - - exynos_data = output_data->exynos_data; - ret = drmModeObjectSetProperty(exynos_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 -exynos_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value) -{ - tdm_exynos_output_data *output_data = output; - tdm_exynos_data *exynos_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); - - exynos_data = output_data->exynos_data; - props = drmModeObjectGetProperties(exynos_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 -exynos_output_set_mode(tdm_output *output, const tdm_output_mode *mode) -{ - tdm_exynos_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 = exynos_hwc_initailize_target_window(output_data->hwc_data, mode->hdisplay, mode->vdisplay); - if (ret != TDM_ERROR_NONE) { - TDM_ERR("create target hwc window failed (%d)", ret); - return ret; - } - } - - output_data->current_mode = mode; - output_data->mode_changed = 1; - - return TDM_ERROR_NONE; -} - -tdm_error -exynos_output_get_mode(tdm_output *output, const tdm_output_mode **mode) -{ - tdm_exynos_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_capture* -exynos_output_create_capture(tdm_output *output, tdm_error *error) -{ - tdm_exynos_output_data *output_data = output; - tdm_exynos_data *exynos_data; - - RETURN_VAL_IF_FAIL(output_data, NULL); - - exynos_data = output_data->exynos_data; - - if (exynos_data->use_ippv2) - return tdm_exynos_capture_create_output(exynos_data, output, error); - else - return tdm_exynos_capture_legacy_create_output(exynos_data, output, error); -} - -tdm_error -exynos_output_set_status_handler(tdm_output *output, - tdm_output_status_handler func, - void *user_data) -{ - tdm_exynos_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_hwc * -exynos_output_get_hwc(tdm_output *output, tdm_error *error) -{ - tdm_exynos_hwc_data *hwc_data = NULL; - tdm_exynos_output_data *output_data = output; - - 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_exynos_hwc_data)); - if (!hwc_data) { - TDM_ERR("alloc failed"); - if (error) - *error = TDM_ERROR_OUT_OF_MEMORY; - return NULL; - } - hwc_data->output_data = output_data; - - LIST_INITHEAD(&hwc_data->hwc_window_list); - - output_data->hwc_data = hwc_data; - - if (error) - *error = TDM_ERROR_NONE; - - return hwc_data; -} |