summaryrefslogblamecommitdiffstats
path: root/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
blob: b89d3b5d0ba0bb1dbb79e74ff9fbd9dced737890 (plain) (tree)




















































































































































































































                                                                                                    
/*
 * Copyright 2015 Advanced Micro Devices, Inc.
 *
 * 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, sublicense,
 * 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 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 NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
 *
 * Authors: AMD
 *
 */

/* DC interface (public) */
#include "dm_services.h"
#include "dc.h"

/* DC core (private) */
#include "core_dc.h"
#include "transform.h"

/*******************************************************************************
 * Private structures
 ******************************************************************************/
struct surface {
	struct core_surface protected;
	enum dc_irq_source irq_source;
	int ref_count;
};

struct gamma {
	struct core_gamma protected;
	int ref_count;
};

#define DC_SURFACE_TO_SURFACE(dc_surface) container_of(dc_surface, struct surface, protected.public)
#define CORE_SURFACE_TO_SURFACE(core_surface) container_of(core_surface, struct surface, protected)

#define DC_GAMMA_TO_GAMMA(dc_gamma) \
	container_of(dc_gamma, struct gamma, protected.public)
#define CORE_GAMMA_TO_GAMMA(core_gamma) \
	container_of(core_gamma, struct gamma, protected)

/*******************************************************************************
 * Private functions
 ******************************************************************************/
static bool construct(struct dc_context *ctx, struct surface *surface)
{
	surface->protected.ctx = ctx;
	return true;
}

static void destruct(struct surface *surface)
{

}

/*******************************************************************************
 * Public functions
 ******************************************************************************/
void enable_surface_flip_reporting(struct dc_surface *dc_surface,
		uint32_t controller_id)
{
	struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface);
	surface->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1;
	/*register_flip_interrupt(surface);*/
}

struct dc_surface *dc_create_surface(const struct dc *dc)
{
	struct core_dc *core_dc = DC_TO_CORE(dc);

	struct surface *surface = dm_alloc(sizeof(*surface));

	if (NULL == surface)
		goto alloc_fail;

	if (false == construct(core_dc->ctx, surface))
		goto construct_fail;

	dc_surface_retain(&surface->protected.public);

	return &surface->protected.public;

construct_fail:
	dm_free(surface);

alloc_fail:
	return NULL;
}

const struct dc_surface_status *dc_surface_get_status(
		const struct dc_surface *dc_surface)
{
	struct dc_surface_status *surface_status;
	struct core_surface *core_surface;
	struct core_dc *core_dc;
	int i;

	if (dc_surface == NULL)
		return NULL;

	core_surface = DC_SURFACE_TO_CORE(dc_surface);

	if (core_surface == NULL || core_surface->ctx == NULL)
		return NULL;

	surface_status = &core_surface->status;

	if (core_surface->ctx == NULL || core_surface->ctx->dc == NULL)
		return NULL;

	core_dc = DC_TO_CORE(core_surface->ctx->dc);


	if (core_dc->current_context == NULL)
		return NULL;

	for (i = 0; i < core_dc->current_context->res_ctx.pool->pipe_count;
			i++) {
		struct pipe_ctx *pipe_ctx =
				&core_dc->current_context->res_ctx.pipe_ctx[i];

		if (pipe_ctx->surface !=
				DC_SURFACE_TO_CORE(dc_surface))
			continue;

		core_dc->hwss.update_pending_status(pipe_ctx);
	}

	return surface_status;
}

void dc_surface_retain(const struct dc_surface *dc_surface)
{
	struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface);

	++surface->ref_count;
}

void dc_surface_release(const struct dc_surface *dc_surface)
{
	struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface);

	--surface->ref_count;

	if (surface->ref_count == 0) {
		destruct(surface);
		dm_free(surface);
	}
}

static bool construct_gamma(struct gamma *gamma)
{
	return true;
}

static void destruct_gamma(struct gamma *gamma)
{

}

void dc_gamma_retain(const struct dc_gamma *dc_gamma)
{
	struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma);

	++gamma->ref_count;
}

void dc_gamma_release(const struct dc_gamma *dc_gamma)
{
	struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma);
	--gamma->ref_count;

	if (gamma->ref_count == 0) {
		destruct_gamma(gamma);
		dm_free(gamma);
	}
}

struct dc_gamma *dc_create_gamma()
{
	struct gamma *gamma = dm_alloc(sizeof(*gamma));

	if (gamma == NULL)
		goto alloc_fail;

	if (false == construct_gamma(gamma))
		goto construct_fail;

	dc_gamma_retain(&gamma->protected.public);

	return &gamma->protected.public;

construct_fail:
	dm_free(gamma);

alloc_fail:
	return NULL;
}