/*
 * Copyright 2013 Ilia Mirkin
 *
 * 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 AUTHORS 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.
 *
 * Implementation based on the pre-KMS implementation in xf86-video-nouveau,
 * written by Arthur Huillet.
 */

#include <drm/drm_crtc.h>
#include <drm/drm_fourcc.h>

#include "nouveau_drv.h"

#include "nouveau_bo.h"
#include "nouveau_connector.h"
#include "nouveau_display.h"
#include "nouveau_gem.h"
#include "nvreg.h"
#include "disp.h"

struct nouveau_plane {
	struct drm_plane base;
	bool flip;
	struct nouveau_bo *cur;

	struct {
		struct drm_property *colorkey;
		struct drm_property *contrast;
		struct drm_property *brightness;
		struct drm_property *hue;
		struct drm_property *saturation;
	} props;

	int colorkey;
	int contrast;
	int brightness;
	int hue;
	int saturation;
	enum drm_color_encoding color_encoding;

	void (*set_params)(struct nouveau_plane *);
};

static uint32_t formats[] = {
	DRM_FORMAT_YUYV,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_NV12,
	DRM_FORMAT_NV21,
};

/* Sine can be approximated with
 * http://en.wikipedia.org/wiki/Bhaskara_I's_sine_approximation_formula
 * sin(x degrees) ~= 4 x (180 - x) / (40500 - x (180 - x) )
 * Note that this only works for the range [0, 180].
 * Also note that sin(x) == -sin(x - 180)
 */
static inline int
sin_mul(int degrees, int factor)
{
	if (degrees > 180) {
		degrees -= 180;
		factor *= -1;
	}
	return factor * 4 * degrees * (180 - degrees) /
		(40500 - degrees * (180 - degrees));
}

/* cos(x) = sin(x + 90) */
static inline int
cos_mul(int degrees, int factor)
{
	return sin_mul((degrees + 90) % 360, factor);
}

static int
verify_scaling(const struct drm_framebuffer *fb, uint8_t shift,
               uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h,
               uint32_t crtc_w, uint32_t crtc_h)
{
	if (crtc_w < (src_w >> shift) || crtc_h < (src_h >> shift)) {
		DRM_DEBUG_KMS("Unsuitable framebuffer scaling: %dx%d -> %dx%d\n",
			      src_w, src_h, crtc_w, crtc_h);
		return -ERANGE;
	}

	if (src_x != 0 || src_y != 0) {
		DRM_DEBUG_KMS("Unsuitable framebuffer offset: %d,%d\n",
                              src_x, src_y);
		return -ERANGE;
	}

	return 0;
}

static int
nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
		  struct drm_framebuffer *fb, int crtc_x, int crtc_y,
		  unsigned int crtc_w, unsigned int crtc_h,
		  uint32_t src_x, uint32_t src_y,
		  uint32_t src_w, uint32_t src_h,
		  struct drm_modeset_acquire_ctx *ctx)
{
	struct nouveau_drm *drm = nouveau_drm(plane->dev);
	struct nvif_object *dev = &drm->client.device.object;
	struct nouveau_plane *nv_plane =
		container_of(plane, struct nouveau_plane, base);
	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
	struct nouveau_bo *cur = nv_plane->cur;
	struct nouveau_bo *nvbo;
	bool flip = nv_plane->flip;
	int soff = NV_PCRTC0_SIZE * nv_crtc->index;
	int soff2 = NV_PCRTC0_SIZE * !nv_crtc->index;
	unsigned shift = drm->client.device.info.chipset >= 0x30 ? 1 : 3;
	unsigned format = 0;
	int ret;

	/* Source parameters given in 16.16 fixed point, ignore fractional. */
	src_x >>= 16;
	src_y >>= 16;
	src_w >>= 16;
	src_h >>= 16;

	ret = verify_scaling(fb, shift, 0, 0, src_w, src_h, crtc_w, crtc_h);
	if (ret)
		return ret;

	nvbo = nouveau_gem_object(fb->obj[0]);
	ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM, false);
	if (ret)
		return ret;

	nv_plane->cur = nvbo;

	nvif_mask(dev, NV_PCRTC_ENGINE_CTRL + soff, NV_CRTC_FSEL_OVERLAY, NV_CRTC_FSEL_OVERLAY);
	nvif_mask(dev, NV_PCRTC_ENGINE_CTRL + soff2, NV_CRTC_FSEL_OVERLAY, 0);

	nvif_wr32(dev, NV_PVIDEO_BASE(flip), 0);
	nvif_wr32(dev, NV_PVIDEO_OFFSET_BUFF(flip), nvbo->bo.offset);
	nvif_wr32(dev, NV_PVIDEO_SIZE_IN(flip), src_h << 16 | src_w);
	nvif_wr32(dev, NV_PVIDEO_POINT_IN(flip), src_y << 16 | src_x);
	nvif_wr32(dev, NV_PVIDEO_DS_DX(flip), (src_w << 20) / crtc_w);
	nvif_wr32(dev, NV_PVIDEO_DT_DY(flip), (src_h << 20) / crtc_h);
	nvif_wr32(dev, NV_PVIDEO_POINT_OUT(flip), crtc_y << 16 | crtc_x);
	nvif_wr32(dev, NV_PVIDEO_SIZE_OUT(flip), crtc_h << 16 | crtc_w);

	if (fb->format->format == DRM_FORMAT_YUYV ||
	    fb->format->format == DRM_FORMAT_NV12)
		format |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
	if (fb->format->format == DRM_FORMAT_NV12 ||
	    fb->format->format == DRM_FORMAT_NV21)
		format |= NV_PVIDEO_FORMAT_PLANAR;
	if (nv_plane->color_encoding == DRM_COLOR_YCBCR_BT709)
		format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
	if (nv_plane->colorkey & (1 << 24))
		format |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY;

	if (format & NV_PVIDEO_FORMAT_PLANAR) {
		nvif_wr32(dev, NV_PVIDEO_UVPLANE_BASE(flip), 0);
		nvif_wr32(dev, NV_PVIDEO_UVPLANE_OFFSET_BUFF(flip),
			nvbo->bo.offset + fb->offsets[1]);
	}
	nvif_wr32(dev, NV_PVIDEO_FORMAT(flip), format | fb->pitches[0]);
	nvif_wr32(dev, NV_PVIDEO_STOP, 0);
	/* TODO: wait for vblank? */
	nvif_wr32(dev, NV_PVIDEO_BUFFER, flip ? 0x10 : 0x1);
	nv_plane->flip = !flip;

	if (cur)
		nouveau_bo_unpin(cur);

	return 0;
}

static int
nv10_disable_plane(struct drm_plane *plane,
		   struct drm_modeset_acquire_ctx *ctx)
{
	struct nvif_object *dev = &nouveau_drm(plane->dev)->client.device.object;
	struct nouveau_plane *nv_plane =
		container_of(plane, struct nouveau_plane, base);

	nvif_wr32(dev, NV_PVIDEO_STOP, 1);
	if (nv_plane->cur) {
		nouveau_bo_unpin(nv_plane->cur);
		nv_plane->cur = NULL;
	}

	return 0;
}

static void
nv_destroy_plane(struct drm_plane *plane)
{
	drm_plane_force_disable(plane);
	drm_plane_cleanup(plane);
	kfree(plane);
}

static void
nv10_set_params(struct nouveau_plane *plane)
{
	struct nvif_object *dev = &nouveau_drm(plane->base.dev)->client.device.object;
	u32 luma = (plane->brightness - 512) << 16 | plane->contrast;
	u32 chroma = ((sin_mul(plane->hue, plane->saturation) & 0xffff) << 16) |
		(cos_mul(plane->hue, plane->saturation) & 0xffff);
	u32 format = 0;

	nvif_wr32(dev, NV_PVIDEO_LUMINANCE(0), luma);
	nvif_wr32(dev, NV_PVIDEO_LUMINANCE(1), luma);
	nvif_wr32(dev, NV_PVIDEO_CHROMINANCE(0), chroma);
	nvif_wr32(dev, NV_PVIDEO_CHROMINANCE(1), chroma);
	nvif_wr32(dev, NV_PVIDEO_COLOR_KEY, plane->colorkey & 0xffffff);

	if (plane->cur) {
		if (plane->color_encoding == DRM_COLOR_YCBCR_BT709)
			format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
		if (plane->colorkey & (1 << 24))
			format |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY;
		nvif_mask(dev, NV_PVIDEO_FORMAT(plane->flip),
			NV_PVIDEO_FORMAT_MATRIX_ITURBT709 |
			NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY,
			format);
	}
}

static int
nv_set_property(struct drm_plane *plane,
		struct drm_property *property,
		uint64_t value)
{
	struct nouveau_plane *nv_plane =
		container_of(plane, struct nouveau_plane, base);

	if (property == nv_plane->props.colorkey)
		nv_plane->colorkey = value;
	else if (property == nv_plane->props.contrast)
		nv_plane->contrast = value;
	else if (property == nv_plane->props.brightness)
		nv_plane->brightness = value;
	else if (property == nv_plane->props.hue)
		nv_plane->hue = value;
	else if (property == nv_plane->props.saturation)
		nv_plane->saturation = value;
	else if (property == nv_plane->base.color_encoding_property)
		nv_plane->color_encoding = value;
	else
		return -EINVAL;

	if (nv_plane->set_params)
		nv_plane->set_params(nv_plane);
	return 0;
}

static const struct drm_plane_funcs nv10_plane_funcs = {
	.update_plane = nv10_update_plane,
	.disable_plane = nv10_disable_plane,
	.set_property = nv_set_property,
	.destroy = nv_destroy_plane,
};

static void
nv10_overlay_init(struct drm_device *device)
{
	struct nouveau_drm *drm = nouveau_drm(device);
	struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL);
	unsigned int num_formats = ARRAY_SIZE(formats);
	int ret;

	if (!plane)
		return;

	switch (drm->client.device.info.chipset) {
	case 0x10:
	case 0x11:
	case 0x15:
	case 0x1a:
	case 0x20:
		num_formats = 2;
		break;
	}

	ret = drm_plane_init(device, &plane->base, 3 /* both crtc's */,
			     &nv10_plane_funcs,
			     formats, num_formats, false);
	if (ret)
		goto err;

	/* Set up the plane properties */
	plane->props.colorkey = drm_property_create_range(
			device, 0, "colorkey", 0, 0x01ffffff);
	plane->props.contrast = drm_property_create_range(
			device, 0, "contrast", 0, 8192 - 1);
	plane->props.brightness = drm_property_create_range(
			device, 0, "brightness", 0, 1024);
	plane->props.hue = drm_property_create_range(
			device, 0, "hue", 0, 359);
	plane->props.saturation = drm_property_create_range(
			device, 0, "saturation", 0, 8192 - 1);
	if (!plane->props.colorkey ||
	    !plane->props.contrast ||
	    !plane->props.brightness ||
	    !plane->props.hue ||
	    !plane->props.saturation)
		goto cleanup;

	plane->colorkey = 0;
	drm_object_attach_property(&plane->base.base,
				   plane->props.colorkey, plane->colorkey);

	plane->contrast = 0x1000;
	drm_object_attach_property(&plane->base.base,
				   plane->props.contrast, plane->contrast);

	plane->brightness = 512;
	drm_object_attach_property(&plane->base.base,
				   plane->props.brightness, plane->brightness);

	plane->hue = 0;
	drm_object_attach_property(&plane->base.base,
				   plane->props.hue, plane->hue);

	plane->saturation = 0x1000;
	drm_object_attach_property(&plane->base.base,
				   plane->props.saturation, plane->saturation);

	plane->color_encoding = DRM_COLOR_YCBCR_BT601;
	drm_plane_create_color_properties(&plane->base,
					  BIT(DRM_COLOR_YCBCR_BT601) |
					  BIT(DRM_COLOR_YCBCR_BT709),
					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
					  DRM_COLOR_YCBCR_BT601,
					  DRM_COLOR_YCBCR_LIMITED_RANGE);

	plane->set_params = nv10_set_params;
	nv10_set_params(plane);
	drm_plane_force_disable(&plane->base);
	return;
cleanup:
	drm_plane_cleanup(&plane->base);
err:
	kfree(plane);
	NV_ERROR(drm, "Failed to create plane\n");
}

static int
nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
		  struct drm_framebuffer *fb, int crtc_x, int crtc_y,
		  unsigned int crtc_w, unsigned int crtc_h,
		  uint32_t src_x, uint32_t src_y,
		  uint32_t src_w, uint32_t src_h,
		  struct drm_modeset_acquire_ctx *ctx)
{
	struct nvif_object *dev = &nouveau_drm(plane->dev)->client.device.object;
	struct nouveau_plane *nv_plane =
		container_of(plane, struct nouveau_plane, base);
	struct nouveau_bo *cur = nv_plane->cur;
	struct nouveau_bo *nvbo;
	uint32_t overlay = 1;
	int brightness = (nv_plane->brightness - 512) * 62 / 512;
	int ret, i;

	/* Source parameters given in 16.16 fixed point, ignore fractional. */
	src_x >>= 16;
	src_y >>= 16;
	src_w >>= 16;
	src_h >>= 16;

	ret = verify_scaling(fb, 0, src_x, src_y, src_w, src_h, crtc_w, crtc_h);
	if (ret)
		return ret;

	nvbo = nouveau_gem_object(fb->obj[0]);
	ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM, false);
	if (ret)
		return ret;

	nv_plane->cur = nvbo;

	nvif_wr32(dev, NV_PVIDEO_OE_STATE, 0);
	nvif_wr32(dev, NV_PVIDEO_SU_STATE, 0);
	nvif_wr32(dev, NV_PVIDEO_RM_STATE, 0);

	for (i = 0; i < 2; i++) {
		nvif_wr32(dev, NV_PVIDEO_BUFF0_START_ADDRESS + 4 * i,
			  nvbo->bo.offset);
		nvif_wr32(dev, NV_PVIDEO_BUFF0_PITCH_LENGTH + 4 * i,
			  fb->pitches[0]);
		nvif_wr32(dev, NV_PVIDEO_BUFF0_OFFSET + 4 * i, 0);
	}
	nvif_wr32(dev, NV_PVIDEO_WINDOW_START, crtc_y << 16 | crtc_x);
	nvif_wr32(dev, NV_PVIDEO_WINDOW_SIZE, crtc_h << 16 | crtc_w);
	nvif_wr32(dev, NV_PVIDEO_STEP_SIZE,
		(uint32_t)(((src_h - 1) << 11) / (crtc_h - 1)) << 16 | (uint32_t)(((src_w - 1) << 11) / (crtc_w - 1)));

	/* It should be possible to convert hue/contrast to this */
	nvif_wr32(dev, NV_PVIDEO_RED_CSC_OFFSET, 0x69 - brightness);
	nvif_wr32(dev, NV_PVIDEO_GREEN_CSC_OFFSET, 0x3e + brightness);
	nvif_wr32(dev, NV_PVIDEO_BLUE_CSC_OFFSET, 0x89 - brightness);
	nvif_wr32(dev, NV_PVIDEO_CSC_ADJUST, 0);

	nvif_wr32(dev, NV_PVIDEO_CONTROL_Y, 0x001); /* (BLUR_ON, LINE_HALF) */
	nvif_wr32(dev, NV_PVIDEO_CONTROL_X, 0x111); /* (WEIGHT_HEAVY, SHARPENING_ON, SMOOTHING_ON) */

	nvif_wr32(dev, NV_PVIDEO_FIFO_BURST_LENGTH, 0x03);
	nvif_wr32(dev, NV_PVIDEO_FIFO_THRES_SIZE, 0x38);

	nvif_wr32(dev, NV_PVIDEO_KEY, nv_plane->colorkey);

	if (nv_plane->colorkey & (1 << 24))
		overlay |= 0x10;
	if (fb->format->format == DRM_FORMAT_YUYV)
		overlay |= 0x100;

	nvif_wr32(dev, NV_PVIDEO_OVERLAY, overlay);

	nvif_wr32(dev, NV_PVIDEO_SU_STATE, nvif_rd32(dev, NV_PVIDEO_SU_STATE) ^ (1 << 16));

	if (cur)
		nouveau_bo_unpin(cur);

	return 0;
}

static int
nv04_disable_plane(struct drm_plane *plane,
		   struct drm_modeset_acquire_ctx *ctx)
{
	struct nvif_object *dev = &nouveau_drm(plane->dev)->client.device.object;
	struct nouveau_plane *nv_plane =
		container_of(plane, struct nouveau_plane, base);

	nvif_mask(dev, NV_PVIDEO_OVERLAY, 1, 0);
	nvif_wr32(dev, NV_PVIDEO_OE_STATE, 0);
	nvif_wr32(dev, NV_PVIDEO_SU_STATE, 0);
	nvif_wr32(dev, NV_PVIDEO_RM_STATE, 0);
	if (nv_plane->cur) {
		nouveau_bo_unpin(nv_plane->cur);
		nv_plane->cur = NULL;
	}

	return 0;
}

static const struct drm_plane_funcs nv04_plane_funcs = {
	.update_plane = nv04_update_plane,
	.disable_plane = nv04_disable_plane,
	.set_property = nv_set_property,
	.destroy = nv_destroy_plane,
};

static void
nv04_overlay_init(struct drm_device *device)
{
	struct nouveau_drm *drm = nouveau_drm(device);
	struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL);
	int ret;

	if (!plane)
		return;

	ret = drm_plane_init(device, &plane->base, 1 /* single crtc */,
			     &nv04_plane_funcs,
			     formats, 2, false);
	if (ret)
		goto err;

	/* Set up the plane properties */
	plane->props.colorkey = drm_property_create_range(
			device, 0, "colorkey", 0, 0x01ffffff);
	plane->props.brightness = drm_property_create_range(
			device, 0, "brightness", 0, 1024);
	if (!plane->props.colorkey ||
	    !plane->props.brightness)
		goto cleanup;

	plane->colorkey = 0;
	drm_object_attach_property(&plane->base.base,
				   plane->props.colorkey, plane->colorkey);

	plane->brightness = 512;
	drm_object_attach_property(&plane->base.base,
				   plane->props.brightness, plane->brightness);

	drm_plane_force_disable(&plane->base);
	return;
cleanup:
	drm_plane_cleanup(&plane->base);
err:
	kfree(plane);
	NV_ERROR(drm, "Failed to create plane\n");
}

void
nouveau_overlay_init(struct drm_device *device)
{
	struct nvif_device *dev = &nouveau_drm(device)->client.device;
	if (dev->info.chipset < 0x10)
		nv04_overlay_init(device);
	else if (dev->info.chipset <= 0x40)
		nv10_overlay_init(device);
}
