/*
 * Copyright (C) 2012 Red Hat
 * based in parts on udlfb.c:
 * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it>
 * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com>
 * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License v2. See the file COPYING in the main directory of this archive for
 * more details.
 */

#include <drm/drmP.h>
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
#include <drm/drm_crtc_helper.h>
#include "udl_connector.h"
#include "udl_drv.h"

static bool udl_get_edid_block(struct udl_device *udl, int block_idx,
							   u8 *buff)
{
	int ret, i;
	u8 *read_buff;

	read_buff = kmalloc(2, GFP_KERNEL);
	if (!read_buff)
		return false;

	for (i = 0; i < EDID_LENGTH; i++) {
		int bval = (i + block_idx * EDID_LENGTH) << 8;
		ret = usb_control_msg(udl->udev,
				      usb_rcvctrlpipe(udl->udev, 0),
					  (0x02), (0x80 | (0x02 << 5)), bval,
					  0xA1, read_buff, 2, HZ);
		if (ret < 1) {
			DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret);
			kfree(read_buff);
			return false;
		}
		buff[i] = read_buff[1];
	}

	kfree(read_buff);
	return true;
}

static bool udl_get_edid(struct udl_device *udl, u8 **result_buff,
			 int *result_buff_size)
{
	int i, extensions;
	u8 *block_buff = NULL, *buff_ptr;

	block_buff = kmalloc(EDID_LENGTH, GFP_KERNEL);
	if (block_buff == NULL)
		return false;

	if (udl_get_edid_block(udl, 0, block_buff) &&
	    memchr_inv(block_buff, 0, EDID_LENGTH)) {
		extensions = ((struct edid *)block_buff)->extensions;
		if (extensions > 0) {
			/* we have to read all extensions one by one */
			*result_buff_size = EDID_LENGTH * (extensions + 1);
			*result_buff = kmalloc(*result_buff_size, GFP_KERNEL);
			buff_ptr = *result_buff;
			if (buff_ptr == NULL) {
				kfree(block_buff);
				return false;
			}
			memcpy(buff_ptr, block_buff, EDID_LENGTH);
			kfree(block_buff);
			buff_ptr += EDID_LENGTH;
			for (i = 1; i < extensions; ++i) {
				if (udl_get_edid_block(udl, i, buff_ptr)) {
					buff_ptr += EDID_LENGTH;
				} else {
					kfree(*result_buff);
					*result_buff = NULL;
					return false;
				}
			}
			return true;
		}
		/* we have only base edid block */
		*result_buff = block_buff;
		*result_buff_size = EDID_LENGTH;
		return true;
	}

	kfree(block_buff);

	return false;
}

static int udl_get_modes(struct drm_connector *connector)
{
	struct udl_drm_connector *udl_connector =
					container_of(connector,
					struct udl_drm_connector,
					connector);

	drm_connector_update_edid_property(connector, udl_connector->edid);
	if (udl_connector->edid)
		return drm_add_edid_modes(connector, udl_connector->edid);
	return 0;
}

static enum drm_mode_status udl_mode_valid(struct drm_connector *connector,
			  struct drm_display_mode *mode)
{
	struct udl_device *udl = connector->dev->dev_private;
	if (!udl->sku_pixel_limit)
		return 0;

	if (mode->vdisplay * mode->hdisplay > udl->sku_pixel_limit)
		return MODE_VIRTUAL_Y;

	return 0;
}

static enum drm_connector_status
udl_detect(struct drm_connector *connector, bool force)
{
	u8 *edid_buff = NULL;
	int edid_buff_size = 0;
	struct udl_device *udl = connector->dev->dev_private;
	struct udl_drm_connector *udl_connector =
					container_of(connector,
					struct udl_drm_connector,
					connector);

	/* cleanup previous edid */
	if (udl_connector->edid != NULL) {
		kfree(udl_connector->edid);
		udl_connector->edid = NULL;
	}


	if (!udl_get_edid(udl, &edid_buff, &edid_buff_size))
		return connector_status_disconnected;

	udl_connector->edid = (struct edid *)edid_buff;
	
	return connector_status_connected;
}

static struct drm_encoder*
udl_best_single_encoder(struct drm_connector *connector)
{
	int enc_id = connector->encoder_ids[0];
	return drm_encoder_find(connector->dev, NULL, enc_id);
}

static int udl_connector_set_property(struct drm_connector *connector,
				      struct drm_property *property,
				      uint64_t val)
{
	return 0;
}

static void udl_connector_destroy(struct drm_connector *connector)
{
	struct udl_drm_connector *udl_connector =
					container_of(connector,
					struct udl_drm_connector,
					connector);

	drm_connector_unregister(connector);
	drm_connector_cleanup(connector);
	kfree(udl_connector->edid);
	kfree(connector);
}

static const struct drm_connector_helper_funcs udl_connector_helper_funcs = {
	.get_modes = udl_get_modes,
	.mode_valid = udl_mode_valid,
	.best_encoder = udl_best_single_encoder,
};

static const struct drm_connector_funcs udl_connector_funcs = {
	.dpms = drm_helper_connector_dpms,
	.detect = udl_detect,
	.fill_modes = drm_helper_probe_single_connector_modes,
	.destroy = udl_connector_destroy,
	.set_property = udl_connector_set_property,
};

int udl_connector_init(struct drm_device *dev, struct drm_encoder *encoder)
{
	struct udl_drm_connector *udl_connector;
	struct drm_connector *connector;

	udl_connector = kzalloc(sizeof(struct udl_drm_connector), GFP_KERNEL);
	if (!udl_connector)
		return -ENOMEM;

	connector = &udl_connector->connector;
	drm_connector_init(dev, connector, &udl_connector_funcs,
			   DRM_MODE_CONNECTOR_DVII);
	drm_connector_helper_add(connector, &udl_connector_helper_funcs);

	drm_connector_register(connector);
	drm_connector_attach_encoder(connector, encoder);
	connector->polled = DRM_CONNECTOR_POLL_HPD |
		DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;

	return 0;
}
