/*
 * Copyright (C) 2012-2018 Rob Clark <robclark@freedesktop.org>
 *
 * 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 (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 NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS 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:
 *    Rob Clark <robclark@freedesktop.org>
 */

#include "util/slab.h"

#include "msm_priv.h"

static int query_param(struct fd_pipe *pipe, uint32_t param,
		uint64_t *value)
{
	struct msm_pipe *msm_pipe = to_msm_pipe(pipe);
	struct drm_msm_param req = {
			.pipe = msm_pipe->pipe,
			.param = param,
	};
	int ret;

	ret = drmCommandWriteRead(pipe->dev->fd, DRM_MSM_GET_PARAM,
			&req, sizeof(req));
	if (ret)
		return ret;

	*value = req.value;

	return 0;
}

static int query_queue_param(struct fd_pipe *pipe, uint32_t param,
		uint64_t *value)
{
	struct msm_pipe *msm_pipe = to_msm_pipe(pipe);
	struct drm_msm_submitqueue_query req = {
			.data = VOID2U64(value),
			.id = msm_pipe->queue_id,
			.param = param,
			.len = sizeof(*value),
	};
	int ret;

	ret = drmCommandWriteRead(pipe->dev->fd, DRM_MSM_SUBMITQUEUE_QUERY,
			&req, sizeof(req));
	if (ret)
		return ret;

	return 0;
}

static int msm_pipe_get_param(struct fd_pipe *pipe,
		enum fd_param_id param, uint64_t *value)
{
	struct msm_pipe *msm_pipe = to_msm_pipe(pipe);
	switch(param) {
	case FD_DEVICE_ID: // XXX probably get rid of this..
	case FD_GPU_ID:
		*value = msm_pipe->gpu_id;
		return 0;
	case FD_GMEM_SIZE:
		*value = msm_pipe->gmem;
		return 0;
	case FD_GMEM_BASE:
		*value = msm_pipe->gmem_base;
		return 0;
	case FD_CHIP_ID:
		*value = msm_pipe->chip_id;
		return 0;
	case FD_MAX_FREQ:
		return query_param(pipe, MSM_PARAM_MAX_FREQ, value);
	case FD_TIMESTAMP:
		return query_param(pipe, MSM_PARAM_TIMESTAMP, value);
	case FD_NR_RINGS:
		return query_param(pipe, MSM_PARAM_NR_RINGS, value);
	case FD_PP_PGTABLE:
		return query_param(pipe, MSM_PARAM_PP_PGTABLE, value);
	case FD_CTX_FAULTS:
		return query_queue_param(pipe, MSM_SUBMITQUEUE_PARAM_FAULTS, value);
	case FD_GLOBAL_FAULTS:
		return query_param(pipe, MSM_PARAM_FAULTS, value);
	default:
		ERROR_MSG("invalid param id: %d", param);
		return -1;
	}
}

static int msm_pipe_wait(struct fd_pipe *pipe, uint32_t timestamp,
		uint64_t timeout)
{
	struct fd_device *dev = pipe->dev;
	struct drm_msm_wait_fence req = {
			.fence = timestamp,
			.queueid = to_msm_pipe(pipe)->queue_id,
	};
	int ret;

	get_abs_timeout(&req.timeout, timeout);

	ret = drmCommandWrite(dev->fd, DRM_MSM_WAIT_FENCE, &req, sizeof(req));
	if (ret) {
		ERROR_MSG("wait-fence failed! %d (%s)", ret, strerror(errno));
		return ret;
	}

	return 0;
}

static int open_submitqueue(struct fd_pipe *pipe, uint32_t prio)
{
	struct drm_msm_submitqueue req = {
		.flags = 0,
		.prio = prio,
	};
	uint64_t nr_rings = 1;
	int ret;

	if (fd_device_version(pipe->dev) < FD_VERSION_SUBMIT_QUEUES) {
		to_msm_pipe(pipe)->queue_id = 0;
		return 0;
	}

	msm_pipe_get_param(pipe, FD_NR_RINGS, &nr_rings);

	req.prio = MIN2(req.prio, MAX2(nr_rings, 1) - 1);

	ret = drmCommandWriteRead(pipe->dev->fd, DRM_MSM_SUBMITQUEUE_NEW,
			&req, sizeof(req));
	if (ret) {
		ERROR_MSG("could not create submitqueue! %d (%s)", ret, strerror(errno));
		return ret;
	}

	to_msm_pipe(pipe)->queue_id = req.id;
	return 0;
}

static void close_submitqueue(struct fd_pipe *pipe, uint32_t queue_id)
{
	if (fd_device_version(pipe->dev) < FD_VERSION_SUBMIT_QUEUES)
		return;

	drmCommandWrite(pipe->dev->fd, DRM_MSM_SUBMITQUEUE_CLOSE,
			&queue_id, sizeof(queue_id));
}

static void msm_pipe_destroy(struct fd_pipe *pipe)
{
	struct msm_pipe *msm_pipe = to_msm_pipe(pipe);
	close_submitqueue(pipe, msm_pipe->queue_id);
	msm_pipe_sp_ringpool_init(msm_pipe);
	free(msm_pipe);
}

static const struct fd_pipe_funcs sp_funcs = {
		.ringbuffer_new_object = msm_ringbuffer_sp_new_object,
		.submit_new = msm_submit_sp_new,
		.get_param = msm_pipe_get_param,
		.wait = msm_pipe_wait,
		.destroy = msm_pipe_destroy,
};

static const struct fd_pipe_funcs legacy_funcs = {
		.ringbuffer_new_object = msm_ringbuffer_new_object,
		.submit_new = msm_submit_new,
		.get_param = msm_pipe_get_param,
		.wait = msm_pipe_wait,
		.destroy = msm_pipe_destroy,
};

static uint64_t get_param(struct fd_pipe *pipe, uint32_t param)
{
	uint64_t value;
	int ret = query_param(pipe, param, &value);
	if (ret) {
		ERROR_MSG("get-param failed! %d (%s)", ret, strerror(errno));
		return 0;
	}
	return value;
}

struct fd_pipe * msm_pipe_new(struct fd_device *dev,
		enum fd_pipe_id id, uint32_t prio)
{
	static const uint32_t pipe_id[] = {
			[FD_PIPE_3D] = MSM_PIPE_3D0,
			[FD_PIPE_2D] = MSM_PIPE_2D0,
	};
	struct msm_pipe *msm_pipe = NULL;
	struct fd_pipe *pipe = NULL;

	msm_pipe = calloc(1, sizeof(*msm_pipe));
	if (!msm_pipe) {
		ERROR_MSG("allocation failed");
		goto fail;
	}

	pipe = &msm_pipe->base;

	if (fd_device_version(dev) >= FD_VERSION_SOFTPIN) {
		pipe->funcs = &sp_funcs;
	} else {
		pipe->funcs = &legacy_funcs;
	}

	/* initialize before get_param(): */
	pipe->dev = dev;
	msm_pipe->pipe = pipe_id[id];

	/* these params should be supported since the first version of drm/msm: */
	msm_pipe->gpu_id = get_param(pipe, MSM_PARAM_GPU_ID);
	msm_pipe->gmem   = get_param(pipe, MSM_PARAM_GMEM_SIZE);
	msm_pipe->chip_id = get_param(pipe, MSM_PARAM_CHIP_ID);

	if (fd_device_version(pipe->dev) >= FD_VERSION_GMEM_BASE)
		msm_pipe->gmem_base = get_param(pipe, MSM_PARAM_GMEM_BASE);

	if (! msm_pipe->gpu_id)
		goto fail;

	INFO_MSG("Pipe Info:");
	INFO_MSG(" GPU-id:          %d", msm_pipe->gpu_id);
	INFO_MSG(" Chip-id:         0x%08x", msm_pipe->chip_id);
	INFO_MSG(" GMEM size:       0x%08x", msm_pipe->gmem);

	if (open_submitqueue(pipe, prio))
		goto fail;

	msm_pipe_sp_ringpool_init(msm_pipe);

	return pipe;
fail:
	if (pipe)
		fd_pipe_del(pipe);
	return NULL;
}
