/*
 * Copyright © 2010 Intel Corporation
 *
 * 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:
 * jim liu <jim.liu@intel.com>
 * Jackie Li<yaodong.li@intel.com>
 */

#include "mdfld_dsi_output.h"
#include "mdfld_dsi_dbi.h"
#include "mdfld_dsi_dpi.h"
#include "mdfld_output.h"
#include <asm/intel_scu_ipc.h>
#include "mdfld_dsi_pkg_sender.h"
#include <linux/pm_runtime.h>

#define MDFLD_DSI_BRIGHTNESS_MAX_LEVEL 100

static int CABC_control = 1;
static int LABC_control = 1;

module_param (CABC_control, int, 0644);
module_param (LABC_control, int, 0644);

/**
 * make these MCS command global 
 * we don't need 'movl' everytime we send them.
 * FIXME: these datas were provided by OEM, we should get them from GCT.
 **/
static u32 mdfld_dbi_mcs_hysteresis[] = {
	0x42000f57, 0x8c006400, 0xff00bf00, 0xffffffff,
	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
	0x38000aff, 0x82005000, 0xff00ab00, 0xffffffff,
	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
	0x000000ff,
};

static u32 mdfld_dbi_mcs_display_profile[] = {
	0x50281450, 0x0000c882, 0x00000000, 0x00000000,
	0x00000000,
};

static u32 mdfld_dbi_mcs_kbbc_profile[] = {
	0x00ffcc60, 0x00000000, 0x00000000, 0x00000000,
}; 
	
static u32 mdfld_dbi_mcs_gamma_profile[] = {
	0x81111158, 0x88888888, 0x88888888,
}; 

/*
 * write hysteresis values.
 */
static void mdfld_dsi_write_hysteresis (struct mdfld_dsi_config *dsi_config,
                                                                int pipe)
{
	struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);

	if(!sender) {
	        WARN_ON(1);
		return;
	}
	mdfld_dsi_send_mcs_long_hs(sender,
				   mdfld_dbi_mcs_hysteresis,
				   17,
				   MDFLD_DSI_SEND_PACKAGE);
}

/*
 * write display profile values.
 */
static void mdfld_dsi_write_display_profile(struct mdfld_dsi_config *dsi_config, int pipe)
{
	struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);

	if(!sender) {
	        WARN_ON(1);
		return;
        }
	mdfld_dsi_send_mcs_long_hs(sender,
				   mdfld_dbi_mcs_display_profile,
				   5,
				   MDFLD_DSI_SEND_PACKAGE);
}

/*
 * write KBBC profile values.
 */
static void mdfld_dsi_write_kbbc_profile (struct mdfld_dsi_config * dsi_config, int pipe)
{
	struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);

	if(!sender) {
	        WARN_ON(1);
		return;
        }
	mdfld_dsi_send_mcs_long_hs(sender,
				   mdfld_dbi_mcs_kbbc_profile,
				   4,
				   MDFLD_DSI_SEND_PACKAGE);
}

/*
 * write gamma setting.
 */
static void mdfld_dsi_write_gamma_setting (struct mdfld_dsi_config *dsi_config, int pipe)
{
	struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);

	if(!sender) {
	        WARN_ON(1);
		return;
	}
	mdfld_dsi_send_mcs_long_hs(sender,
				   mdfld_dbi_mcs_gamma_profile,
				   3,
				   MDFLD_DSI_SEND_PACKAGE);
}

/*
 * Check and see if the generic control or data buffer is empty and ready.
 */
void mdfld_dsi_gen_fifo_ready (struct drm_device *dev, u32 gen_fifo_stat_reg, u32 fifo_stat)
{
	u32 GEN_BF_time_out_count = 0;
	
	/* Check MIPI Adatper command registers */
	for (GEN_BF_time_out_count = 0; GEN_BF_time_out_count < GEN_FB_TIME_OUT; GEN_BF_time_out_count++)
	{
		if ((REG_READ(gen_fifo_stat_reg) & fifo_stat) == fifo_stat)
			break;
		udelay (100);
	}

	if (GEN_BF_time_out_count == GEN_FB_TIME_OUT)
		dev_err(dev->dev,
        "mdfld_dsi_gen_fifo_ready, Timeout. gen_fifo_stat_reg = 0x%x. \n",
                                                gen_fifo_stat_reg);
}

/*
 * Manage the DSI MIPI keyboard and display brightness.
 * FIXME: this is exported to OSPM code. should work out an specific 
 * display interface to OSPM. 
 */
void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, int pipe)
{
	struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
	struct drm_device *dev = sender->dev;
	struct drm_psb_private *dev_priv = dev->dev_private;
	u32 gen_ctrl_val;
	
	if(!sender) {
	        WARN_ON(1);
	        return;
	}
	/* Set default display backlight value to 85% (0xd8)*/
	mdfld_dsi_send_mcs_short_hs(sender,
				    write_display_brightness,
				    0xd8,
				    1,
				    MDFLD_DSI_SEND_PACKAGE);

	/* Set minimum brightness setting of CABC function to 20% (0x33)*/
	mdfld_dsi_send_mcs_short_hs(sender,
				    write_cabc_min_bright,
				    0x33,
				    1,
				    MDFLD_DSI_SEND_PACKAGE);

	mdfld_dsi_write_hysteresis(dsi_config, pipe);
	mdfld_dsi_write_display_profile (dsi_config, pipe);
	mdfld_dsi_write_kbbc_profile (dsi_config, pipe);
	mdfld_dsi_write_gamma_setting (dsi_config, pipe);

	/* Enable backlight or/and LABC */
	gen_ctrl_val = BRIGHT_CNTL_BLOCK_ON | DISPLAY_DIMMING_ON| BACKLIGHT_ON;
	if (LABC_control == 1 || CABC_control == 1)
		gen_ctrl_val |= DISPLAY_DIMMING_ON| DISPLAY_BRIGHTNESS_AUTO | GAMMA_AUTO;

	if (LABC_control == 1)
		gen_ctrl_val |= AMBIENT_LIGHT_SENSE_ON;

	dev_priv->mipi_ctrl_display = gen_ctrl_val;

	mdfld_dsi_send_mcs_short_hs(sender,
				    write_ctrl_display,
				    (u8)gen_ctrl_val,
				    1,
				    MDFLD_DSI_SEND_PACKAGE);

	if (CABC_control == 0)
		return;
	mdfld_dsi_send_mcs_short_hs(sender,
				    write_ctrl_cabc,
				    UI_IMAGE,
				    1,
				    MDFLD_DSI_SEND_PACKAGE);
}

/*
 * Manage the mipi display brightness.
 * TODO: refine this interface later
 */
void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, int level)
{
	struct mdfld_dsi_pkg_sender *sender;
	struct drm_psb_private *dev_priv;
	struct mdfld_dsi_config *dsi_config;
	u32 gen_ctrl_val;
	int p_type;	
	
	if (!dev || (pipe != 0 && pipe != 2)) {
		dev_err(dev->dev, "Invalid parameter\n");
		return;
	}

	p_type = mdfld_get_panel_type(dev, 0);

	dev_priv = dev->dev_private;

	if(pipe)
		dsi_config = dev_priv->dsi_configs[1];
	else
		dsi_config = dev_priv->dsi_configs[0];

	sender = mdfld_dsi_get_pkg_sender(dsi_config);

	if(!sender) {
	        WARN_ON(1);
		return;
	}

	gen_ctrl_val = ((level * 0xff) / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL) & 0xff;

	dev_dbg(dev->dev,
                "pipe = %d, gen_ctrl_val = %d.  \n", pipe, gen_ctrl_val);
	
	if(p_type == TMD_VID || p_type == TMD_CMD){
		/* Set display backlight value */
		mdfld_dsi_send_mcs_short_hs(sender, 
					tmd_write_display_brightness, 
					(u8)gen_ctrl_val, 
	                                 1, 
	                        	MDFLD_DSI_SEND_PACKAGE);		
	} else {			
		/* Set display backlight value */
		mdfld_dsi_send_mcs_short_hs(sender,
				    write_display_brightness,
				    (u8)gen_ctrl_val,
                                    1,
                                    MDFLD_DSI_SEND_PACKAGE);


		/* Enable backlight control */
		if (level == 0)
			gen_ctrl_val = 0;
		else 
			gen_ctrl_val = dev_priv->mipi_ctrl_display;

		mdfld_dsi_send_mcs_short_hs(sender,
                                    write_ctrl_display,
                                   (u8)gen_ctrl_val,
                                   1,
                                   MDFLD_DSI_SEND_PACKAGE);
	}
}

/*
 * shut down DSI controller
 */ 
void mdfld_dsi_controller_shutdown(struct mdfld_dsi_config * dsi_config, int pipe)
{
	struct drm_device * dev;
	u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
	int retry = 100;
	
	if (!dsi_config) {
	        WARN_ON(1);
		return;
	}
	
	dev = dsi_config->dev;
	
	if (!gma_power_begin(dev, true)) {
		dev_err(dev->dev, "hw begin failed\n");
		return;
	}
		
	if(!(REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) &  DSI_DEVICE_READY)) 
		goto shutdown_out;
	
	/* Send shut down package, clean packet send bit first */
	if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
		REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), 
				(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) | DSI_INTR_STATE_SPL_PKG_SENT));
	}
	
	/*send shut down package in HS*/
	REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_SHUTDOWN);
	
	
	/*
	 * make sure shut down is sent.
	 * FIXME: add max retry counter
	 */
	while(!(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT)) {
		retry--;
		
		if(!retry) {
			dev_err(dev->dev, "timeout\n");
			break;
		}
	}
	
	/*sleep 1 ms to ensure shutdown finished*/
	msleep(100);
	
	/*un-ready device*/
	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset),
			   (REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & ~DSI_DEVICE_READY));

shutdown_out:			   
	gma_power_end(dev);
}

void mdfld_dsi_controller_startup(struct mdfld_dsi_config * dsi_config, int pipe)
{
	struct drm_device * dev;
	u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
	int retry = 100;
	
	
	if (!dsi_config) {
		WARN_ON(1);
		return;
	}
	
	dev = dsi_config->dev;
	dev_dbg(dev->dev, "starting up DSI controller on pipe %d...\n", pipe);
	
	if (!gma_power_begin(dev, true)) {
		dev_err(dev->dev, "hw begin failed\n");
		return;
	}
	
	if((REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & DSI_DEVICE_READY)) 
		goto startup_out;
	
	/*if config DPI, turn on DPI interface*/
	if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
		if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
			REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT);
		}
		
		REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_TURN_ON);
		
		/*
		 * make sure shut down is sent.
		 * FIXME: add max retry counter
		 */
		while(!(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT)) {
			retry--;
			if(!retry) {
				dev_err(dev->dev, "timeout\n");
				break;
			}
		}
		
		msleep(100);
	}
	
	/*set device ready*/
	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset),
			   (REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) | DSI_DEVICE_READY));

startup_out:	
	gma_power_end(dev);
}


static int mdfld_dsi_get_panel_status(struct mdfld_dsi_config *dsi_config,
					u8 dcs,
					u32 *data,
					u8 transmission)
{
	struct mdfld_dsi_pkg_sender *sender
		= mdfld_dsi_get_pkg_sender(dsi_config);

	if (!sender || !data) {
		DRM_ERROR("Invalid parameter\n");
		return -EINVAL;
	}

	if (transmission == MDFLD_DSI_HS_TRANSMISSION)
		return mdfld_dsi_read_mcs_hs(sender, dcs, data, 1);
	else if (transmission == MDFLD_DSI_LP_TRANSMISSION)
		return mdfld_dsi_read_mcs_lp(sender, dcs, data, 1);
	else
		return -EINVAL;
}

int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config,
				u32 *mode,
				u8 transmission)
{
	if (!dsi_config || !mode) {
		DRM_ERROR("Invalid parameter\n");
		return -EINVAL;
	}

	return mdfld_dsi_get_panel_status(dsi_config, 0x0a, mode, transmission);
}

int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config,
					u32 *result,
					u8 transmission)
{
	if (!dsi_config || !result) {
		DRM_ERROR("Invalid parameter\n");
		return -EINVAL;
	}

	return mdfld_dsi_get_panel_status(dsi_config, 0x0f, result,
					  transmission);
}

/*
 * NOTE: this function was used by OSPM.
 * TODO: will be removed later, should work out display interfaces for OSPM
 */
void mdfld_dsi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe)
{
	if(!dsi_config || ((pipe != 0) && (pipe != 2))) {
	        WARN_ON(1);
		return;
	}

	if(dsi_config->type)
		mdfld_dsi_dpi_controller_init(dsi_config, pipe);
	else
		mdfld_dsi_controller_dbi_init(dsi_config, pipe);
}

static void mdfld_dsi_connector_save(struct drm_connector * connector)
{
}

static void mdfld_dsi_connector_restore(struct drm_connector * connector)
{
}

static enum drm_connector_status mdfld_dsi_connector_detect(struct drm_connector * connector, bool force)
{
	struct psb_intel_output *psb_output
					= to_psb_intel_output(connector);
	struct mdfld_dsi_connector *dsi_connector
	                                = MDFLD_DSI_CONNECTOR(psb_output);
	return dsi_connector->status;
}

static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
					struct drm_property *property,
					uint64_t value)
{
	struct drm_encoder *encoder = connector->encoder;

	if (!strcmp(property->name, "scaling mode") && encoder) {
		struct psb_intel_crtc * psb_crtc = to_psb_intel_crtc(encoder->crtc);
		bool bTransitionFromToCentered;
		uint64_t curValue;

		if (!psb_crtc)
			goto set_prop_error;

		switch (value) {
		case DRM_MODE_SCALE_FULLSCREEN:
			break;
		case DRM_MODE_SCALE_NO_SCALE:
			break;
		case DRM_MODE_SCALE_ASPECT:
			break;
		default:
			goto set_prop_error;
		}

		if (drm_connector_property_get_value(connector, property, &curValue))
			goto set_prop_error;

		if (curValue == value)
			goto set_prop_done;

		if (drm_connector_property_set_value(connector, property, value))
			goto set_prop_error;

		bTransitionFromToCentered = (curValue == DRM_MODE_SCALE_NO_SCALE) ||
			(value == DRM_MODE_SCALE_NO_SCALE);

		if (psb_crtc->saved_mode.hdisplay != 0 &&
		    psb_crtc->saved_mode.vdisplay != 0) {
			if (bTransitionFromToCentered) {
				if (!drm_crtc_helper_set_mode(encoder->crtc, &psb_crtc->saved_mode,
					    encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb))
					goto set_prop_error;
			} else {
				struct drm_encoder_helper_funcs *pEncHFuncs  = encoder->helper_private;
				pEncHFuncs->mode_set(encoder, &psb_crtc->saved_mode,
						     &psb_crtc->saved_adjusted_mode);
			}
		}
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
	} else if (!strcmp(property->name, "backlight") && encoder) {
		struct drm_psb_private *dev_priv = encoder->dev->dev_private;
		struct backlight_device *psb_bd = dev_priv->backlight_device;
		dev_dbg(encoder->dev->dev, "backlight level = %d\n", (int)value);
		if (drm_connector_property_set_value(connector, property, value))
			goto set_prop_error;
		else {
			dev_dbg(encoder->dev->dev,
			                "set brightness to %d", (int)value);
			if (psb_bd) {
				psb_bd->props.brightness = value;
				backlight_update_status(psb_bd);
			}
		}
#endif
	}
set_prop_done:
    return 0;
set_prop_error:
    return -1;
}

static void mdfld_dsi_connector_destroy(struct drm_connector *connector)
{
	struct psb_intel_output * psb_output = to_psb_intel_output(connector);
	struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
	struct mdfld_dsi_pkg_sender * sender;
	
	if(!dsi_connector)
	        return;
	
	drm_sysfs_connector_remove(connector);
	drm_connector_cleanup(connector);
	
	sender = dsi_connector->pkg_sender;

	mdfld_dsi_pkg_sender_destroy(sender);

	kfree(dsi_connector);
}

static int mdfld_dsi_connector_get_modes(struct drm_connector * connector)
{
	struct psb_intel_output * psb_output = to_psb_intel_output(connector);
	struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
	struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
	struct drm_display_mode * fixed_mode = dsi_config->fixed_mode;
	struct drm_display_mode * dup_mode = NULL;
	struct drm_device * dev = connector->dev;
	
	connector->display_info.min_vfreq = 0;
	connector->display_info.max_vfreq = 200;
	connector->display_info.min_hfreq = 0;
	connector->display_info.max_hfreq = 200;

	if(fixed_mode) {
		dev_dbg(dev->dev, "fixed_mode %dx%d\n",
		        fixed_mode->hdisplay, fixed_mode->vdisplay);
		
		dup_mode = drm_mode_duplicate(dev, fixed_mode);
		drm_mode_probed_add(connector, dup_mode);
		return 1;
	}
	dev_err(dev->dev, "Didn't get any modes!\n");
	return 0;
}

static int mdfld_dsi_connector_mode_valid(struct drm_connector * connector, struct drm_display_mode * mode)
{
	struct psb_intel_output * psb_output = to_psb_intel_output(connector);
	struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
	struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
	struct drm_display_mode * fixed_mode = dsi_config->fixed_mode;

	dev_dbg(connector->dev->dev, "mode %p, fixed mode %p\n",
	                                                mode, fixed_mode);

	if(mode->flags & DRM_MODE_FLAG_DBLSCAN) 
		return MODE_NO_DBLESCAN;

	if(mode->flags & DRM_MODE_FLAG_INTERLACE)
		return MODE_NO_INTERLACE;

	/**
	 * FIXME: current DC has no fitting unit, reject any mode setting request
	 * will figure out a way to do up-scaling(pannel fitting) later.  
	 **/
	if(fixed_mode) {
		if(mode->hdisplay != fixed_mode->hdisplay)
			return MODE_PANEL;

		if(mode->vdisplay != fixed_mode->vdisplay)
			return MODE_PANEL;
	}
	dev_dbg(connector->dev->dev, "mode ok\n");

	return MODE_OK;
}

static void mdfld_dsi_connector_dpms(struct drm_connector *connector, int mode)
{
#ifdef CONFIG_PM_RUNTIME
	struct drm_device * dev = connector->dev;
	struct drm_psb_private * dev_priv = dev->dev_private;
	bool panel_on, panel_on2;
#endif
	/* First, execute DPMS */
	drm_helper_connector_dpms(connector, mode);

#ifdef CONFIG_PM_RUNTIME
	if(mdfld_panel_dpi(dev)) {
		/* DPI panel */
		panel_on = dev_priv->dpi_panel_on;
		panel_on2 = dev_priv->dpi_panel_on2;
	} else {
		/* DBI panel */
		panel_on = dev_priv->dbi_panel_on;
		panel_on2 = dev_priv->dbi_panel_on2;
	}

	/* Then check all display panels + monitors status */
	/* Make sure that the Display (B) sub-system status isn't i3 when
	 * R/W the DC register, otherwise "Fabric error" issue would occur
	 * during S0i3 state. */
	if(!panel_on && !panel_on2 && !(REG_READ(HDMIB_CONTROL)
	                                        & HDMIB_PORT_EN)) {
		/* Request rpm idle */
		if(dev_priv->rpm_enabled)
			pm_request_idle(&dev->pdev->dev);
	}
	/*
	 * if rpm wasn't enabled yet, try to allow it
	 * FIXME: won't enable rpm for DPI since DPI
	 * CRTC setting is a little messy now.
	 * Enable it later!
	 */
#if 0
	if(!dev_priv->rpm_enabled && !mdfld_panel_dpi(dev))
		ospm_runtime_pm_allow(dev);
#endif
#endif
}

static struct drm_encoder *mdfld_dsi_connector_best_encoder(
                                        struct drm_connector *connector) 
{
	struct psb_intel_output * psb_output = to_psb_intel_output(connector);
	struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
	struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
	struct mdfld_dsi_encoder * encoder = NULL;
	
	if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) 
		encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DBI];
	else if (dsi_config->type == MDFLD_DSI_ENCODER_DPI) 
		encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DPI];
	
	dev_dbg(connector->dev->dev, "get encoder %p\n", encoder);
	
	if(!encoder) {
		dev_err(connector->dev->dev,
                        "Invalid encoder for type %d\n", dsi_config->type);
		return NULL;
	}
	dsi_config->encoder = encoder;	
	return &encoder->base;	
}

/* DSI connector funcs */
static const struct drm_connector_funcs mdfld_dsi_connector_funcs = {
	.dpms = /*drm_helper_connector_dpms*/mdfld_dsi_connector_dpms,
	.save = mdfld_dsi_connector_save,
	.restore = mdfld_dsi_connector_restore,
	.detect = mdfld_dsi_connector_detect,
	.fill_modes = drm_helper_probe_single_connector_modes,
	.set_property = mdfld_dsi_connector_set_property,
	.destroy = mdfld_dsi_connector_destroy,
};

/* DSI connector helper funcs */
static const struct drm_connector_helper_funcs mdfld_dsi_connector_helper_funcs = {
	.get_modes = mdfld_dsi_connector_get_modes,
	.mode_valid = mdfld_dsi_connector_mode_valid,
	.best_encoder = mdfld_dsi_connector_best_encoder,
};

static int mdfld_dsi_get_default_config(struct drm_device * dev, 
										struct mdfld_dsi_config * config, int pipe)
{
	if(!dev || !config) {
	        WARN_ON(1);
		return -EINVAL;
	}
	
	config->bpp = 24;
	config->type = mdfld_panel_dpi(dev);
	config->lane_count = 2;
	config->channel_num = 0;
	/*NOTE: video mode is ignored when type is MDFLD_DSI_ENCODER_DBI*/
	if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
		config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE;
	} else {
		config->video_mode = MDFLD_DSI_VIDEO_BURST_MODE;
	}
	
	return 0;
}

/*
 * Returns the panel fixed mode from configuration. 
 */
struct drm_display_mode *
mdfld_dsi_get_configuration_mode(struct mdfld_dsi_config * dsi_config, int pipe)
{
	struct drm_device *dev = dsi_config->dev;
	struct drm_display_mode *mode;
	struct drm_psb_private *dev_priv = dev->dev_private;
	struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
	bool use_gct = false;

	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
	if (!mode) {
	        dev_err(dev->dev, "Out of memory for mode\n");
		return NULL;
        }
	if (use_gct) {
		dev_dbg(dev->dev, "gct find MIPI panel.\n");

		mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
		mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
		mode->hsync_start = mode->hdisplay + \
				((ti->hsync_offset_hi << 8) | \
				ti->hsync_offset_lo);
		mode->hsync_end = mode->hsync_start + \
				((ti->hsync_pulse_width_hi << 8) | \
				ti->hsync_pulse_width_lo);
		mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
								ti->hblank_lo);
		mode->vsync_start = \
			mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
						ti->vsync_offset_lo);
		mode->vsync_end = \
			mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
						ti->vsync_pulse_width_lo);
		mode->vtotal = mode->vdisplay + \
				((ti->vblank_hi << 8) | ti->vblank_lo);
		mode->clock = ti->pixel_clock * 10;
	} else {
		if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) { 
			if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
				mode->hdisplay = 480;
				mode->vdisplay = 854;
				mode->hsync_start = 487;
				mode->hsync_end = 490;
				mode->htotal = 499;
				mode->vsync_start = 861;
				mode->vsync_end = 865;
				mode->vtotal = 873;
				mode->clock = 33264;
			} else {
				mode->hdisplay = 864;
				mode->vdisplay = 480;
				mode->hsync_start = 873;
				mode->hsync_end = 876;
				mode->htotal = 887;
				mode->vsync_start = 487;
				mode->vsync_end = 490;
				mode->vtotal = 499;
				mode->clock = 33264;
			}
		} else if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
			mode->hdisplay = 864;
			mode->vdisplay = 480;
			mode->hsync_start = 872;
			mode->hsync_end = 876;
			mode->htotal = 884;
			mode->vsync_start = 482;
			mode->vsync_end = 494;
			mode->vtotal = 486;
			mode->clock = 25777;
			
		}
	}

	drm_mode_set_name(mode);
	drm_mode_set_crtcinfo(mode, 0);
	
	mode->type |= DRM_MODE_TYPE_PREFERRED;

	return mode;
}

int mdfld_dsi_panel_reset(int pipe)
{
	unsigned gpio;
	int ret = 0;

	switch (pipe) {
	case 0:
		gpio = 128;
		break;
	case 2:
		gpio = 34;
		break;
	default:
		DRM_ERROR("Invalid output\n");
		return -EINVAL;
	}

	ret = gpio_request(gpio, "gfx");
	if (ret) {
		DRM_ERROR("gpio_rqueset failed\n");
		return ret;
	}

	ret = gpio_direction_output(gpio, 1);
	if (ret) {
		DRM_ERROR("gpio_direction_output failed\n");
		goto gpio_error;
	}

	gpio_get_value(128);

gpio_error:
	if (gpio_is_valid(gpio))
		gpio_free(gpio);

	return ret;
}

/*
 * MIPI output init
 * @dev drm device
 * @pipe pipe number. 0 or 2
 * @config 
 * 
 * Do the initialization of a MIPI output, including create DRM mode objects
 * initialization of DSI output on @pipe 
 */
void mdfld_dsi_output_init(struct drm_device *dev,
			   int pipe, 
			   struct mdfld_dsi_config *config,
			   struct panel_funcs* p_cmd_funcs,
			   struct panel_funcs* p_vid_funcs)
{
	struct mdfld_dsi_config * dsi_config;
	struct mdfld_dsi_connector * dsi_connector;
	struct psb_intel_output * psb_output;
	struct drm_connector * connector;
	struct mdfld_dsi_encoder * encoder;
	struct drm_psb_private * dev_priv = dev->dev_private;
	struct panel_info dsi_panel_info;
	u32 width_mm, height_mm;

	dev_dbg(dev->dev, "init DSI output on pipe %d\n", pipe);
	
	if(!dev || ((pipe != 0) && (pipe != 2))) {
	        WARN_ON(1);
		return;
	}
	
	/*create a new connetor*/
	dsi_connector = kzalloc(sizeof(struct mdfld_dsi_connector), GFP_KERNEL);
	if(!dsi_connector) {
		DRM_ERROR("No memory");
		return;
	}
	
	dsi_connector->pipe =  pipe;
	
	/*set DSI config*/
	if(config) { 
		dsi_config = config;
	} else {
		dsi_config = kzalloc(sizeof(struct mdfld_dsi_config), GFP_KERNEL);
		if(!dsi_config) {
			dev_err(dev->dev,
			        "cannot allocate memory for DSI config\n");
			goto dsi_init_err0;
		}
		
		mdfld_dsi_get_default_config(dev, dsi_config, pipe);
	}
	
	dsi_connector->private = dsi_config;
	
	dsi_config->changed = 1;
	dsi_config->dev = dev;
	
	/* Init fixed mode basing on DSI config type */
	if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
		dsi_config->fixed_mode = p_cmd_funcs->get_config_mode(dev);
		if(p_cmd_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
			goto dsi_init_err0;
	} else if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
		dsi_config->fixed_mode = p_vid_funcs->get_config_mode(dev);
		if(p_vid_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
			goto dsi_init_err0;
	}

	width_mm = dsi_panel_info.width_mm;
	height_mm = dsi_panel_info.height_mm;

	dsi_config->mode = dsi_config->fixed_mode;
	dsi_config->connector = dsi_connector;
	
	if(!dsi_config->fixed_mode) {
		dev_err(dev->dev, "No pannel fixed mode was found\n");
		goto dsi_init_err0;
	}
	
	if(pipe && dev_priv->dsi_configs[0]) {
		dsi_config->dvr_ic_inited = 0;
		dev_priv->dsi_configs[1] = dsi_config;
	} else if(pipe == 0) {
		dsi_config->dvr_ic_inited = 1;
		dev_priv->dsi_configs[0] = dsi_config;
	} else {
		dev_err(dev->dev, "Trying to init MIPI1 before MIPI0\n");
		goto dsi_init_err0;
	}

	/*init drm connector object*/
	psb_output = &dsi_connector->base;
	
	psb_output->type = (pipe == 0) ? INTEL_OUTPUT_MIPI : INTEL_OUTPUT_MIPI2;

	connector = &psb_output->base;
	/* Revisit type if MIPI/HDMI bridges ever appear on Medfield */
	drm_connector_init(dev, connector, &mdfld_dsi_connector_funcs,
						DRM_MODE_CONNECTOR_LVDS);
	drm_connector_helper_add(connector, &mdfld_dsi_connector_helper_funcs);
	
	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
	connector->display_info.width_mm = width_mm;
	connector->display_info.height_mm = height_mm;
	connector->interlace_allowed = false;
	connector->doublescan_allowed = false;
	
	/* Attach properties */
	drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN);
	drm_connector_attach_property(connector, dev_priv->backlight_property, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);

	/* Init DSI package sender on this output */
	if (mdfld_dsi_pkg_sender_init(dsi_connector, pipe)) {
		DRM_ERROR("Package Sender initialization failed on pipe %d\n", pipe);
		goto dsi_init_err0;
	}

	/* Init DBI & DPI encoders */
	if (p_cmd_funcs) {
		encoder = mdfld_dsi_dbi_init(dev, dsi_connector, p_cmd_funcs);
		if(!encoder) {
			dev_err(dev->dev, "Create DBI encoder failed\n");
			goto dsi_init_err1;
		}
		encoder->private = dsi_config;
		dsi_config->encoders[MDFLD_DSI_ENCODER_DBI] = encoder;
	}
	
	if(p_vid_funcs) {
		encoder = mdfld_dsi_dpi_init(dev, dsi_connector, p_vid_funcs);
		if(!encoder) {
			dev_err(dev->dev, "Create DPI encoder failed\n");
			goto dsi_init_err1;
		}
		encoder->private = dsi_config;
		dsi_config->encoders[MDFLD_DSI_ENCODER_DPI] = encoder;
	}
	
	drm_sysfs_connector_add(connector);
	return;
	
	/*TODO: add code to destroy outputs on error*/
dsi_init_err1:
	/*destroy sender*/
	mdfld_dsi_pkg_sender_destroy(dsi_connector->pkg_sender);

	drm_connector_cleanup(connector);
	kfree(dsi_config->fixed_mode);
	kfree(dsi_config);
dsi_init_err0:
	kfree(dsi_connector);
}
