/** * drm_atomic_set_mode_for_crtc - set mode for CRTC * @state: the CRTC whose incoming state to update * @mode: kernel-internal mode to use for the CRTC, or NULL to disable * * Set a mode (originating from the kernel) on the desired CRTC state. Does * not change any other state properties, including enable, active, or * mode_changed. * * RETURNS: * Zero on success, error code on failure. Cannot return -EDEADLK. */ int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state, struct drm_display_mode *mode) { struct drm_mode_modeinfo umode; /* Early return for no change. */ if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0) return 0; if (state->mode_blob) drm_property_unreference_blob(state->mode_blob); state->mode_blob = NULL; if (mode) { drm_mode_convert_to_umode(&umode, mode); state->mode_blob = drm_property_create_blob(state->crtc->dev, sizeof(umode), &umode); if (IS_ERR(state->mode_blob)) return PTR_ERR(state->mode_blob); drm_mode_copy(&state->mode, mode); state->enable = true; DRM_DEBUG_ATOMIC("Set [MODE:%s] for CRTC state %p\n", mode->name, state); } else { memset(&state->mode, 0, sizeof(state->mode)); state->enable = false; DRM_DEBUG_ATOMIC("Set [NOMODE] for CRTC state %p\n", state); } return 0; }
static int create_in_format_blob(struct drm_device *dev, struct drm_plane *plane) { const struct drm_mode_config *config = &dev->mode_config; struct drm_property_blob *blob; struct drm_format_modifier *mod; size_t blob_size, formats_size, modifiers_size; struct drm_format_modifier_blob *blob_data; unsigned int i, j; formats_size = sizeof(__u32) * plane->format_count; if (WARN_ON(!formats_size)) { /* 0 formats are never expected */ return 0; } modifiers_size = sizeof(struct drm_format_modifier) * plane->modifier_count; blob_size = sizeof(struct drm_format_modifier_blob); /* Modifiers offset is a pointer to a struct with a 64 bit field so it * should be naturally aligned to 8B. */ BUILD_BUG_ON(sizeof(struct drm_format_modifier_blob) % 8); blob_size += ALIGN(formats_size, 8); blob_size += modifiers_size; blob = drm_property_create_blob(dev, blob_size, NULL); if (IS_ERR(blob)) return -1; blob_data = blob->data; blob_data->version = FORMAT_BLOB_CURRENT; blob_data->count_formats = plane->format_count; blob_data->formats_offset = sizeof(struct drm_format_modifier_blob); blob_data->count_modifiers = plane->modifier_count; blob_data->modifiers_offset = ALIGN(blob_data->formats_offset + formats_size, 8); memcpy(formats_ptr(blob_data), plane->format_types, formats_size); /* If we can't determine support, just bail */ if (!plane->funcs->format_mod_supported) goto done; mod = modifiers_ptr(blob_data); for (i = 0; i < plane->modifier_count; i++) { for (j = 0; j < plane->format_count; j++) { if (plane->funcs->format_mod_supported(plane, plane->format_types[j], plane->modifiers[i])) { mod->formats |= 1ULL << j; } } mod->modifier = plane->modifiers[i]; mod->offset = 0; mod->pad = 0; mod++; } done: drm_object_attach_property(&plane->base, config->modifiers_property, blob->base.id); return 0; }
/** * drm_writeback_connector_init - Initialize a writeback connector and its properties * @dev: DRM device * @wb_connector: Writeback connector to initialize * @con_funcs: Connector funcs vtable * @enc_helper_funcs: Encoder helper funcs vtable to be used by the internal encoder * @formats: Array of supported pixel formats for the writeback engine * @n_formats: Length of the formats array * * This function creates the writeback-connector-specific properties if they * have not been already created, initializes the connector as * type DRM_MODE_CONNECTOR_WRITEBACK, and correctly initializes the property * values. It will also create an internal encoder associated with the * drm_writeback_connector and set it to use the @enc_helper_funcs vtable for * the encoder helper. * * Drivers should always use this function instead of drm_connector_init() to * set up writeback connectors. * * Returns: 0 on success, or a negative error code */ int drm_writeback_connector_init(struct drm_device *dev, struct drm_writeback_connector *wb_connector, const struct drm_connector_funcs *con_funcs, const struct drm_encoder_helper_funcs *enc_helper_funcs, const u32 *formats, int n_formats) { struct drm_property_blob *blob; struct drm_connector *connector = &wb_connector->base; struct drm_mode_config *config = &dev->mode_config; int ret = create_writeback_properties(dev); if (ret != 0) return ret; blob = drm_property_create_blob(dev, n_formats * sizeof(*formats), formats); if (IS_ERR(blob)) return PTR_ERR(blob); drm_encoder_helper_add(&wb_connector->encoder, enc_helper_funcs); ret = drm_encoder_init(dev, &wb_connector->encoder, &drm_writeback_encoder_funcs, DRM_MODE_ENCODER_VIRTUAL, NULL); if (ret) goto fail; connector->interlace_allowed = 0; ret = drm_connector_init(dev, connector, con_funcs, DRM_MODE_CONNECTOR_WRITEBACK); if (ret) goto connector_fail; ret = drm_connector_attach_encoder(connector, &wb_connector->encoder); if (ret) goto attach_fail; INIT_LIST_HEAD(&wb_connector->job_queue); spin_lock_init(&wb_connector->job_lock); wb_connector->fence_context = dma_fence_context_alloc(1); spin_lock_init(&wb_connector->fence_lock); snprintf(wb_connector->timeline_name, sizeof(wb_connector->timeline_name), "CONNECTOR:%d-%s", connector->base.id, connector->name); drm_object_attach_property(&connector->base, config->writeback_out_fence_ptr_property, 0); drm_object_attach_property(&connector->base, config->writeback_fb_id_property, 0); drm_object_attach_property(&connector->base, config->writeback_pixel_formats_property, blob->base.id); wb_connector->pixel_formats_blob_ptr = blob; return 0; attach_fail: drm_connector_cleanup(connector); connector_fail: drm_encoder_cleanup(&wb_connector->encoder); fail: drm_property_blob_put(blob); return ret; }