(__after)->next->prev = (__item); \
(__after)->next = (__item);
+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 void
_tdm_vc4_display_buffer_destroy(void *user_data)
{
for (i = 0; i < output_data->count_drm_modes; i++) {
drmModeModeInfoPtr vc4_mode = &output_data->vc4_modes[i];
+
if ((vc4_mode->hdisplay == output_data->current_mode->hdisplay) &&
(vc4_mode->vdisplay == output_data->current_mode->vdisplay) &&
(vc4_mode->vrefresh == output_data->current_mode->vrefresh) &&
return TDM_ERROR_NONE;
}
+#if 0
static tdm_error
-_tdm_vc4_display_get_properties(int drm_fd, uint32_t connector_id, uint32_t crtc_id,
- uint32_t plane_id, struct display_properties_ids *ids)
-{
- drmModeObjectPropertiesPtr properties = NULL;
- drmModePropertyPtr property = NULL;
- int i, j;
- tdm_error ret = TDM_ERROR_NONE;
- struct {
- uint32_t object_type;
- uint32_t object_id;
- char *name;
- uint32_t *value;
- } glue[] = {
- { DRM_MODE_OBJECT_CONNECTOR, connector_id, "CRTC_ID", &ids->connector_crtc_id },
- { DRM_MODE_OBJECT_CRTC, crtc_id, "MODE_ID", &ids->crtc_mode_id },
- { DRM_MODE_OBJECT_CRTC, crtc_id, "ACTIVE", &ids->crtc_active },
- { DRM_MODE_OBJECT_PLANE, plane_id, "FB_ID", &ids->plane_fb_id },
- { DRM_MODE_OBJECT_PLANE, plane_id, "CRTC_ID", &ids->plane_crtc_id },
- { DRM_MODE_OBJECT_PLANE, plane_id, "SRC_X", &ids->plane_src_x },
- { DRM_MODE_OBJECT_PLANE, plane_id, "SRC_Y", &ids->plane_src_y },
- { DRM_MODE_OBJECT_PLANE, plane_id, "SRC_W", &ids->plane_src_w },
- { DRM_MODE_OBJECT_PLANE, plane_id, "SRC_H", &ids->plane_src_h },
- { DRM_MODE_OBJECT_PLANE, plane_id, "CRTC_X", &ids->plane_crtc_x },
- { DRM_MODE_OBJECT_PLANE, plane_id, "CRTC_Y", &ids->plane_crtc_y },
- { DRM_MODE_OBJECT_PLANE, plane_id, "CRTC_W", &ids->plane_crtc_w },
- { DRM_MODE_OBJECT_PLANE, plane_id, "CRTC_H", &ids->plane_crtc_h },
- };
-
- for (i = 0; i < ARRAY_SIZE(glue); i++) {
- properties = drmModeObjectGetProperties(drm_fd,
- glue[i].object_id,
- glue[i].object_type);
-
- if (properties == NULL) {
- ret = TDM_ERROR_OPERATION_FAILED;
- goto finish;
- }
-
- for (j = 0; j < properties->count_props; j++) {
- property = drmModeGetProperty(drm_fd, properties->props[j]);
- if (property == NULL) {
- continue;
- }
-
- if (strcmp(property->name, glue[i].name) == 0) {
- *glue[i].value = property->prop_id;
- drmModeFreeProperty(property);
- break;
- }
- drmModeFreeProperty(property);
- }
-
- if (j == properties->count_props) {
- ret = TDM_ERROR_OPERATION_FAILED;
- goto finish;
- }
-
- drmModeFreeObjectProperties(properties);
- properties = NULL;
- }
-
-finish:
- if (properties != NULL)
- drmModeFreeObjectProperties(properties);
-
- return ret;
-}
-
-static tdm_error
-_tdm_vc4_display_get_plane_id(int drm_fd, uint32_t crtc_id, uint32_t *id)
-{
- drmModeResPtr ressources = NULL;
- drmModePlaneResPtr plane_resources;
- uint32_t crtc_index = 0;
- uint32_t plane_id = 0;
- uint32_t found_primary = 0;
- int i, j;
- tdm_error ret = TDM_ERROR_NONE;
-
- if (id) *id = 0;
-
- ressources = drmModeGetResources(drm_fd);
- if (ressources == NULL) {
- ret = TDM_ERROR_OPERATION_FAILED;
- goto finish;
- }
-
- for (i = 0; i < ressources->count_crtcs; i++) {
- if (ressources->crtcs[i] == crtc_id) {
- crtc_index = i;
- break;
- }
- }
-
- if (i == ressources->count_crtcs) {
- ret = TDM_ERROR_OPERATION_FAILED;
- goto free_resource;
- }
-
- plane_resources = drmModeGetPlaneResources(drm_fd);
- if (!plane_resources) {
- ret = TDM_ERROR_OPERATION_FAILED;
- goto free_resource;
- }
-
- for (i = 0; (i < plane_resources->count_planes) && !found_primary; i++) {
- plane_id = plane_resources->planes[i];
- drmModePlanePtr plane = drmModeGetPlane(drm_fd, plane_id);
- if (!plane) {
- continue;
- }
-
- if (plane->possible_crtcs & (1 << crtc_index)) {
- drmModeObjectPropertiesPtr props =
- drmModeObjectGetProperties(drm_fd, plane_id, DRM_MODE_OBJECT_PLANE);
- if (!props) {
- ret = TDM_ERROR_OPERATION_FAILED;
- goto free_resource;
- }
-
- for (j = 0; j < props->count_props; j++) {
- drmModePropertyPtr p = drmModeGetProperty(drm_fd, props->props[j]);
-
- if (!p)
- continue;
-
- if ((strcmp(p->name, "type") == 0) &&
- (props->prop_values[j] == DRM_PLANE_TYPE_PRIMARY)) {
- found_primary = 1;
- }
-
- drmModeFreeProperty(p);
- }
-
- drmModeFreeObjectProperties(props);
- }
-
- drmModeFreePlane(plane);
- }
-
- if (found_primary) {
- if (id)
- *id = plane_id;
- } else {
- ret = TDM_ERROR_OPERATION_FAILED;
- }
-
- drmModeFreePlaneResources(plane_resources);
-free_resource:
- drmModeFreeResources(ressources);
-finish:
- return ret;
-}
-
-static tdm_error
-_tdm_vc4_display_commit_layer(tdm_vc4_layer_data *layer_data, void *event_data)
+_tdm_vc4_display_commit_layer(tdm_vc4_layer_data *layer_data)
{
tdm_vc4_data *vc4_data = layer_data->vc4_data;
tdm_vc4_output_data *output_data = layer_data->output_data;
uint32_t fx, fy, fw, fh;
- drmModeAtomicReqPtr request;
- uint32_t flags = 0;
- tdm_error ret = TDM_ERROR_NONE;
+ int crtc_w;
if (!layer_data->display_buffer_changed && !layer_data->info_changed)
return TDM_ERROR_NONE;
if (_tdm_vc4_display_set_crtc(vc4_data, output_data, 1) != TDM_ERROR_NONE)
return TDM_ERROR_OPERATION_FAILED;
- drmSetClientCap(vc4_data->drm_fd, DRM_CLIENT_CAP_ATOMIC, 1);
- drmSetClientCap(vc4_data->drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
+ output_data->crtc_enabled = 1;
+ }
+
+ if (output_data->current_mode)
+ crtc_w = output_data->current_mode->hdisplay;
+ else {
+ drmModeCrtcPtr crtc = drmModeGetCrtc(vc4_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);
+ }
- ret = _tdm_vc4_display_get_plane_id(vc4_data->drm_fd, output_data->crtc_id, &output_data->output_plane);
- if (ret != TDM_ERROR_NONE) return ret;
+ layer_data->display_buffer_changed = 0;
+ layer_data->info_changed = 0;
- ret = _tdm_vc4_display_get_properties(vc4_data->drm_fd, output_data->connector_id,
- output_data->crtc_id, output_data->output_plane, &output_data->props);
- if (ret != TDM_ERROR_NONE) return ret;
+ if (!layer_data->display_buffer) {
+ if (drmModeSetPlane(vc4_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);
- output_data->crtc_enabled = 1;
+ return TDM_ERROR_NONE;
}
- flags = DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK;
- request = drmModeAtomicAlloc();
-
/* 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;
- drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_fb_id, layer_data->display_buffer->fb_id);
- drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_crtc_id, output_data->crtc_id);
- drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_src_x, fx);
- drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_src_y, fy);
- drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_src_w, fw);
- drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_src_h, fh);
- drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_crtc_x, layer_data->info.src_config.pos.x);
- drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_crtc_y, layer_data->info.src_config.pos.y);
- drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_crtc_w, layer_data->info.src_config.pos.w);
- drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_crtc_h, layer_data->info.src_config.pos.h);
-
- layer_data->display_buffer_changed = 0;
- layer_data->info_changed = 0;
+ if (drmModeSetPlane(vc4_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;
+ }
- drmModeAtomicCommit(vc4_data->drm_fd, request, flags, event_data);
+ 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);
return TDM_ERROR_NONE;
}
+#endif
static void
_tdm_vc4_display_cb_event(int fd, unsigned int sequence,
}
static tdm_error
+_vc4_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_vc4_display_create_layer_list(tdm_vc4_data *vc4_data)
{
tdm_vc4_output_data *output_data = NULL;
layer_data, layer_data->plane_id, layer_data->output_data->crtc_id,
layer_data->zpos, layer_data->capabilities);
+ /* get the atomic prop ids*/
+ if (vc4_data->has_atomic) {
+ ret = _vc4_output_get_atomic_prop_id(vc4_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)
+ goto failed_atomic_prop_id;
+ ret = _vc4_output_get_atomic_prop_id(vc4_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)
+ goto failed_atomic_prop_id;
+ ret = _vc4_output_get_atomic_prop_id(vc4_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)
+ goto failed_atomic_prop_id;
+ ret = _vc4_output_get_atomic_prop_id(vc4_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)
+ goto failed_atomic_prop_id;
+ ret = _vc4_output_get_atomic_prop_id(vc4_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)
+ goto failed_atomic_prop_id;
+ ret = _vc4_output_get_atomic_prop_id(vc4_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)
+ goto failed_atomic_prop_id;
+ ret = _vc4_output_get_atomic_prop_id(vc4_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)
+ goto failed_atomic_prop_id;
+ ret = _vc4_output_get_atomic_prop_id(vc4_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)
+ goto failed_atomic_prop_id;
+ ret = _vc4_output_get_atomic_prop_id(vc4_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)
+ goto failed_atomic_prop_id;
+ ret = _vc4_output_get_atomic_prop_id(vc4_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)
+ goto failed_atomic_prop_id;
+ }
+
LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
}
return TDM_ERROR_NONE;
+failed_atomic_prop_id:
failed:
if (planes) {
for (i = 0; i < vc4_data->plane_res->count_planes; i++)
drmModeFreeEncoder(encoder);
drmModeFreeConnector(connector);
+ /* get the atomic prop ids*/
+ if (vc4_data->has_atomic) {
+ ret = _vc4_output_get_atomic_prop_id(vc4_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_atomic_prop_id;
+
+ ret = _vc4_output_get_atomic_prop_id(vc4_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_atomic_prop_id;
+
+ ret = _vc4_output_get_atomic_prop_id(vc4_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_atomic_prop_id;
+ }
+
TDM_DBG("output count: %d", vc4_data->mode_res->count_connectors);
return TDM_ERROR_NONE;
+failed_atomic_prop_id:
failed_create:
tdm_vc4_display_destroy_output_list(vc4_data);
return ret;
return TDM_ERROR_NONE;
}
+static tdm_error
+_vc4_layer_add_atomic_properties(tdm_vc4_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
+_vc4_layer_make_atomic_request(tdm_vc4_layer_data *layer_data, drmModeAtomicReqPtr request)
+{
+ tdm_vc4_data *vc4_data = layer_data->vc4_data;
+ tdm_vc4_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;
+ tdm_error ret = TDM_ERROR_NONE;
+
+ 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(vc4_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("MakeAtomicRequest: drm_fd(%d) plane_id(%u) crtc_id(%u) off",
+ vc4_data->drm_fd, layer_data->plane_id, output_data->crtc_id);
+
+ ret = _vc4_layer_add_atomic_properties(layer_data, request, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ if (ret != TDM_ERROR_NONE) {
+ TDM_ERR("_vc4_layer_add_atomic_properties failed.");
+ return ret;
+ }
+
+ return TDM_ERROR_NONE;
+ }
+
+ /* 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_INFO("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)",
+ vc4_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);
+
+ ret = _vc4_layer_add_atomic_properties(layer_data, request,
+ layer_data->display_buffer->fb_id, output_data->crtc_id,
+ fx, fy, fw, fh,
+ 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);
+ if (ret != TDM_ERROR_NONE) {
+ TDM_ERR("MakeAtomicRequest failed: 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",
+ vc4_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 ret;
+ }
+
+ return TDM_ERROR_NONE;
+}
+
tdm_error
vc4_output_commit(tdm_output *output, int sync, void *user_data)
{
tdm_vc4_output_data *output_data = output;
tdm_vc4_layer_data *layer_data = NULL;
+ tdm_vc4_event_data *event_data;
+ drmModeAtomicReqPtr request;
+ uint32_t flags = 0;
tdm_error ret;
RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
- tdm_vc4_event_data *event_data = calloc(1, sizeof(tdm_vc4_event_data));
- RETURN_VAL_IF_FAIL(event_data, TDM_ERROR_OUT_OF_MEMORY);
+ if (!output_data->crtc_enabled || output_data->mode_changed) {
+ ret = _tdm_vc4_display_set_crtc(output_data->vc4_data, output_data, 1);
+ if (ret != TDM_ERROR_NONE) {
+ TDM_ERR("fail to set crtc.");
+ return TDM_ERROR_OPERATION_FAILED;
+ }
- event_data->type = TDM_DRM_EVENT_TYPE_COMMIT;
- event_data->output_data = output_data;
- event_data->user_data = user_data;
+ output_data->crtc_enabled = 1;
+#if 0//TODO: do set crtc with atomic pageflip
+ flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
+ drmModeModeInfoPtr mode;
+ uint32_t blob_id;
+
+ mode = _tdm_vc4_display_get_mode(output_data);
+ if (!mode) {
+ TDM_ERR("fail to find the drm mode.");
+ return TDM_ERROR_OPERATION_FAILED;
+ }
+
+ if (drmModeCreatePropertyBlob(output_data->vc4_data->drm_fd, mode, sizeof(*mode), &blob_id) != 0) {
+ TDM_ERR("fail to create the Mode PropertyBlob.");
+ return TDM_ERROR_OPERATION_FAILED;
+ }
+
+ drmModeAtomicAddProperty(request, output_data->output_plane, output_data->props.plane_fb_id,
+ layer_data->display_buffer->fb_id);
+
+ output_data->crtc_enabled = 1;
+#endif
+ }
+
+ 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 = _tdm_vc4_display_commit_layer(layer_data, event_data);
+ ret = _vc4_layer_make_atomic_request(layer_data, request);
if (ret != TDM_ERROR_NONE) {
- free(event_data);
+ TDM_ERR("_vc4_layer_make_atomic_request failed.");
+ drmModeAtomicFree(request);
return ret;
}
}
+ event_data = calloc(1, sizeof(tdm_vc4_event_data));
+ if (!event_data) {
+ TDM_ERR("fail to alloc event_data.");
+ drmModeAtomicFree(request);
+ return TDM_ERROR_OUT_OF_MEMORY;
+ }
+
+ event_data->type = TDM_DRM_EVENT_TYPE_COMMIT;
+ event_data->output_data = output_data;
+ event_data->user_data = user_data;
+
+ if (drmModeAtomicCommit(output_data->vc4_data->drm_fd, request, flags, event_data) < 0) {
+ TDM_ERR("drmModeAtomicCommit failed.");
+ drmModeAtomicFree(request);
+ return TDM_ERROR_OPERATION_FAILED;
+ }
+
+ drmModeAtomicFree(request);
+
#if 0
tdm_vc4_data *vc4_data;
- int do_waitvblank = 0;
vc4_data = output_data->vc4_data;
+ int do_waitvblank = 0;
+
+ event_data = calloc(1, sizeof(tdm_vc4_event_data));
+ if (!event_data) {
+ TDM_ERR("fail to alloc event_data.");
+ drmModeAtomicFree(request);
+ return TDM_ERROR_OUT_OF_MEMORY;
+ }
+
+ event_data->type = TDM_DRM_EVENT_TYPE_COMMIT;
+ event_data->output_data = output_data;
+ event_data->user_data = user_data;
+
+ LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
+ ret = _tdm_vc4_display_commit_layer(layer_data);
+ if (ret != TDM_ERROR_NONE) {
+ free(event_data);
+ return ret;
+ }
+ }
if (do_waitvblank == 1) {
event_data = calloc(1, sizeof(tdm_vc4_event_data));