Пример #1
0
int mdfld_dsi_dsr_update_panel_fb(struct mdfld_dsi_config *dsi_config)
{
	struct mdfld_dsi_dsr *dsr;
	struct mdfld_dsi_pkg_sender *sender;
	int err = 0;

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

	dsr = dsi_config->dsr;

	if (!IS_ANN(dev)) {
		/*if no dsr attached, return 0*/
		if (!dsr)
			return 0;
	}

	PSB_DEBUG_ENTRY("\n");

	if (dsi_config->type == MDFLD_DSI_ENCODER_DPI)
		return 0;
	mutex_lock(&dsi_config->context_lock);

	if (!dsi_config->dsi_hw_context.panel_on) {
		PSB_DEBUG_ENTRY(
		"if screen off, update fb is not allowed\n");
		err = -EINVAL;
		goto update_fb_out;
	}

	/*no pending fb updates, go ahead to send out write_mem_start*/
	PSB_DEBUG_ENTRY("send out write_mem_start\n");
	sender = mdfld_dsi_get_pkg_sender(dsi_config);
	if (!sender) {
		DRM_ERROR("No sender\n");
		err = -EINVAL;
		goto update_fb_out;
	}

	err = mdfld_dsi_send_dcs(sender, write_mem_start,
				NULL, 0, CMD_DATA_SRC_PIPE,
				MDFLD_DSI_SEND_PACKAGE);
	if (err) {
		DRM_ERROR("Failed to send write_mem_start");
		err = -EINVAL;
		goto update_fb_out;
	}

	/*clear free count*/
	dsr->free_count = 0;

update_fb_out:
	mutex_unlock(&dsi_config->context_lock);
	return err;
}
/*
 * _sysfs_support_fbc_show() - Return 1 if FBC/FBDC supported, else 0.
 * @kdev - Pointer to struct device
 * @attr - pointer to struct device_attribute
 * @buf - Pointer to output buffer to receive character string.
 * The buffer length is PAGE_SIZE bytes.
 */
static ssize_t _sysfs_support_fbc_show(struct device *kdev,
	struct device_attribute *attr, char *buf)
{
	const int buflen = PAGE_SIZE;
	int support_fbc;

	/* Supported for Anniedale, but not for ANN A0 and ANN B0. */
	if (!IS_ANN() || IS_ANN_A0() || IS_ANN_B0())
		support_fbc = 0;
	else
		support_fbc = 1;

	return scnprintf(buf, buflen, "%d\n", support_fbc);
}
Пример #3
0
static
int jdi_cmd_drv_ic_init(struct mdfld_dsi_config *dsi_config)
{
	struct mdfld_dsi_pkg_sender *sender
		= mdfld_dsi_get_pkg_sender(dsi_config);
	int err = 0;

	PSB_DEBUG_ENTRY("\n");

	if (!sender) {
		DRM_ERROR("Cannot get sender\n");
		return -EINVAL;
	}
	err = mdfld_dsi_send_mcs_short_hs(sender,
			exit_sleep_mode, 0, 0,
			MDFLD_DSI_SEND_PACKAGE);
	if (err) {
		DRM_ERROR("%s: %d: Exit Sleep Mode\n",
		__func__, __LINE__);
		goto ic_init_err;
	}

	msleep(120);
	err = mdfld_dsi_send_mcs_short_hs(sender,
			write_display_brightness, 0x0, 1,
			MDFLD_DSI_SEND_PACKAGE);
	if (err) {
		DRM_ERROR("%s: %d: Set Brightness\n",
		__func__, __LINE__);
		goto ic_init_err;
	}

	err = mdfld_dsi_send_mcs_short_hs(sender,
			write_ctrl_display, 0x24, 1,
			MDFLD_DSI_SEND_PACKAGE);
	if (err) {
		DRM_ERROR("%s: %d: Write Control Display\n",
		__func__, __LINE__);
		goto ic_init_err;
	}

	err = mdfld_dsi_send_mcs_short_hs(sender,
			write_ctrl_cabc, STILL_IMAGE, 1,
			MDFLD_DSI_SEND_PACKAGE);
	if (err) {
		DRM_ERROR("%s: %d: Write Control CABC\n",
		__func__, __LINE__);
		goto ic_init_err;
	}

	if (!IS_ANN(dev)) {
		err = mdfld_dsi_send_mcs_short_hs(sender,
				write_cabc_min_bright, 51, 1,
				MDFLD_DSI_SEND_PACKAGE);
		if (err) {
			DRM_ERROR("%s: %d: Write CABC minimum brightness\n",
					__func__, __LINE__);
			goto ic_init_err;
		}
	}

	err = mdfld_dsi_send_gen_short_hs(sender,
			access_protect, 4, 2,
			MDFLD_DSI_SEND_PACKAGE);
	if (err) {
		DRM_ERROR("%s: %d: Manufacture command protect on\n",
				__func__, __LINE__);
		goto ic_init_err;
	}

	err = mdfld_dsi_send_gen_long_lp(sender,
			jdi_timing_control,
			21, MDFLD_DSI_SEND_PACKAGE);
	if (err) {
		DRM_ERROR("%s: %d: Set panel timing\n",
				__func__, __LINE__);
		goto ic_init_err;
	}
	msleep(20);

	err = mdfld_dsi_send_mcs_short_hs(sender,
			set_tear_on, 0x00, 1,
			MDFLD_DSI_SEND_PACKAGE);
	if (err) {
		DRM_ERROR("%s: %d: Set Tear On\n",
		__func__, __LINE__);
		goto ic_init_err;
	}

	err = mdfld_dsi_send_mcs_long_hs(sender,
			jdi_mcs_clumn_addr,
			5, MDFLD_DSI_SEND_PACKAGE);
	if (err) {
		DRM_ERROR("%s: %d: Set Clumn Address\n",
		__func__, __LINE__);
		goto ic_init_err;
	}

	err = mdfld_dsi_send_mcs_long_hs(sender,
			jdi_mcs_page_addr,
			5, MDFLD_DSI_SEND_PACKAGE);
	if (err) {
		DRM_ERROR("%s: %d: Set Page Address\n",
		__func__, __LINE__);
		goto ic_init_err;
	}

	return 0;

ic_init_err:
	err = -EIO;
	return err;
}
Пример #4
0
static
void jdi_cmd_controller_init(
		struct mdfld_dsi_config *dsi_config)
{

	struct mdfld_dsi_hw_context *hw_ctx =
				&dsi_config->dsi_hw_context;
#ifdef ENABLE_CSC_GAMMA /*FIXME*/
	struct drm_device *dev = dsi_config->dev;

	struct csc_setting csc = {
			.pipe = 0,
			.type = CSC_REG_SETTING,
			.enable_state = true,
			.data_len = CSC_REG_COUNT,
			.data.csc_reg_data = {
			0xFFB0424, 0xFDF, 0x4320FF1,
			0xFDC, 0xFF50FF5, 0x415}
		 };
	struct gamma_setting gamma = {
		.pipe = 0,
		.type = GAMMA_REG_SETTING,
		.enable_state = true,
		.data_len = GAMMA_10_BIT_TABLE_COUNT,
		.gamma_tableX100 = {
			0x000000, 0x030303, 0x050505, 0x070707,
			0x090909, 0x0C0C0C, 0x0E0E0E, 0x101010,
			0x121212, 0x141414, 0x171717, 0x191919,
			0x1B1B1B, 0x1D1D1D, 0x1F1F1F, 0x212121,
			0x232323, 0x252525, 0x282828, 0x2A2A2A,
			0x2C2C2C, 0x2E2E2E, 0x303030, 0x323232,
			0x343434, 0x363636, 0x383838, 0x3A3A3A,
			0x3C3C3C, 0x3E3E3E, 0x404040, 0x424242,
			0x444444, 0x464646, 0x484848, 0x4A4A4A,
			0x4C4C4C, 0x4E4E4E, 0x505050, 0x525252,
			0x545454, 0x565656, 0x585858, 0x5A5A5A,
			0x5C5C5C, 0x5E5E5E, 0x606060, 0x626262,
			0x646464, 0x666666, 0x686868, 0x6A6A6A,
			0x6C6C6C, 0x6E6E6E, 0x707070, 0x727272,
			0x747474, 0x767676, 0x787878, 0x7A7A7A,
			0x7C7C7C, 0x7E7E7E, 0x808080, 0x828282,
			0x848484, 0x868686, 0x888888, 0x8A8A8A,
			0x8C8C8C, 0x8E8E8E, 0x909090, 0x929292,
			0x949494, 0x969696, 0x989898, 0x999999,
			0x9B9B9B, 0x9D9D9D, 0x9F9F9F, 0xA1A1A1,
			0xA3A3A3, 0xA5A5A5, 0xA7A7A7, 0xA9A9A9,
			0xABABAB, 0xADADAD, 0xAFAFAF, 0xB1B1B1,
			0xB3B3B3, 0xB5B5B5, 0xB6B6B6, 0xB8B8B8,
			0xBABABA, 0xBCBCBC, 0xBEBEBE, 0xC0C0C0,
			0xC2C2C2, 0xC4C4C4, 0xC6C6C6, 0xC8C8C8,
			0xCACACA, 0xCCCCCC, 0xCECECE, 0xCFCFCF,
			0xD1D1D1, 0xD3D3D3, 0xD5D5D5, 0xD7D7D7,
			0xD9D9D9, 0xDBDBDB, 0xDDDDDD, 0xDFDFDF,
			0xE1E1E1, 0xE3E3E3, 0xE4E4E4, 0xE6E6E6,
			0xE8E8E8, 0xEAEAEA, 0xECECEC, 0xEEEEEE,
			0xF0F0F0, 0xF2F2F2, 0xF4F4F4, 0xF6F6F6,
			0xF7F7F7, 0xF9F9F9, 0xFBFBFB, 0xFDFDFD}
	 };
#endif

	PSB_DEBUG_ENTRY("\n");

	/*reconfig lane configuration*/
	dsi_config->lane_count = 3;
	dsi_config->lane_config = MDFLD_DSI_DATA_LANE_4_0;
	/* FIXME: enable CSC and GAMMA */
	/*dsi_config->enable_gamma_csc = ENABLE_GAMMA | ENABLE_CSC;*/
	/* This is for 400 mhz.  Set it to 0 for 800mhz */
	hw_ctx->cck_div = 1;
	hw_ctx->pll_bypass_mode = 0;

	if (IS_ANN(dev)) {
		hw_ctx->mipi_control = 0x18;
		hw_ctx->intr_en = 0xFFFFFFFF;
		hw_ctx->hs_tx_timeout = 0xFFFFFF;
		hw_ctx->lp_rx_timeout = 0xFFFFFF;
		hw_ctx->device_reset_timer = 0xff;
		hw_ctx->turn_around_timeout = 0xffff;
		hw_ctx->high_low_switch_count = 0x20;
		hw_ctx->clk_lane_switch_time_cnt = 0x21000e;
		hw_ctx->lp_byteclk = 0x4;
		hw_ctx->dphy_param = 0x1b104315;
		hw_ctx->eot_disable = 0x1;
		hw_ctx->init_count = 0x7d0;
		hw_ctx->dbi_bw_ctrl = 1390;
		hw_ctx->hs_ls_dbi_enable = 0x0;
		hw_ctx->dsi_func_prg = ((DBI_DATA_WIDTH_OPT2 << 13) |
				dsi_config->lane_count);
		hw_ctx->mipi = SEL_FLOPPED_HSTX	| PASS_FROM_SPHY_TO_AFE |
			BANDGAP_CHICKEN_BIT | TE_TRIGGER_GPIO_PIN;
	} else {
		hw_ctx->mipi_control = 0x0;
		hw_ctx->intr_en = 0xFFFFFFFF;
		hw_ctx->hs_tx_timeout = 0xFFFFFF;
		hw_ctx->lp_rx_timeout = 0xFFFFFF;
		hw_ctx->device_reset_timer = 0xffff;
		hw_ctx->turn_around_timeout = 0x1a;
		hw_ctx->high_low_switch_count = 0x21;
		hw_ctx->clk_lane_switch_time_cnt = 0x21000f;
		hw_ctx->lp_byteclk = 0x5;
		hw_ctx->dphy_param = 0x25155b1e;
		hw_ctx->eot_disable = 0x3;
		hw_ctx->init_count = 0xf0;
		hw_ctx->dbi_bw_ctrl = 1390;
		hw_ctx->hs_ls_dbi_enable = 0x0;
		hw_ctx->dsi_func_prg = ((DBI_DATA_WIDTH_OPT2 << 13) |
				dsi_config->lane_count);
		hw_ctx->mipi = PASS_FROM_SPHY_TO_AFE |
			BANDGAP_CHICKEN_BIT |
			TE_TRIGGER_GPIO_PIN;
	}
	hw_ctx->video_mode_format = 0xf;

#ifdef ENABLE_CSC_GAMMA /*FIXME*/
	if (dsi_config->enable_gamma_csc & ENABLE_CSC) {
		/* setting the tuned csc setting */
		drm_psb_enable_color_conversion = 1;
		mdfld_intel_crtc_set_color_conversion(dev, &csc);
	}

	if (dsi_config->enable_gamma_csc & ENABLE_GAMMA) {
		/* setting the tuned gamma setting */
		drm_psb_enable_gamma = 1;
		mdfld_intel_crtc_set_gamma(dev, &gamma);
	}
#endif

}
static
int jdi_cmd_panel_connection_detect(
	struct mdfld_dsi_config *dsi_config)
{
	int status;
	int pipe = dsi_config->pipe;

	PSB_DEBUG_ENTRY("\n");

	if (pipe == 0) {
		status = MDFLD_DSI_PANEL_CONNECTED;
	} else {
		DRM_INFO("%s: do NOT support dual panel\n",
		__func__);
		status = MDFLD_DSI_PANEL_DISCONNECTED;
	}

	return status;
}

static
int jdi_cmd_power_on(
	struct mdfld_dsi_config *dsi_config)
{

	struct mdfld_dsi_pkg_sender *sender =
		mdfld_dsi_get_pkg_sender(dsi_config);
	int err = 0;

	PSB_DEBUG_ENTRY("\n");

	if (!sender) {
		DRM_ERROR("Failed to get DSI packet sender\n");
		return -EINVAL;
	}

	err = mdfld_dsi_send_mcs_short_hs(sender,
			set_address_mode, 0x0, 1,
			MDFLD_DSI_SEND_PACKAGE);
	if (err) {
		DRM_ERROR("%s: %d: Set Address Mode\n",
		__func__, __LINE__);
		goto power_err;
	}
	usleep_range(20000, 20100);

	err = mdfld_dsi_send_mcs_short_hs(sender,
			set_pixel_format, 0x77, 1,
			MDFLD_DSI_SEND_PACKAGE);
	if (err) {
		DRM_ERROR("%s: %d: Set Pixel format\n",
		__func__, __LINE__);
		goto power_err;
	}

	/*turn on display*/
	err = mdfld_dsi_send_dcs(sender,
		 set_display_on,
		 NULL,
		 0,
		 CMD_DATA_SRC_SYSTEM_MEM,
		 MDFLD_DSI_SEND_PACKAGE);
	if (err) {
		DRM_ERROR("faild to set_display_on mode\n");
		goto power_err;
	}
	usleep_range(20000, 20100);

power_err:
	return err;
}

static void __vpro2_power_ctrl(bool on)
{
	u8 addr, value;
	addr = 0xad;
	if (intel_scu_ipc_ioread8(addr, &value))
		DRM_ERROR("%s: %d: failed to read vPro2\n",
		__func__, __LINE__);

	/* Control vPROG2 power rail with 2.85v. */
	if (on)
		value |= 0x1;
	else
		value &= ~0x1;

	if (intel_scu_ipc_iowrite8(addr, value))
		DRM_ERROR("%s: %d: failed to write vPro2\n",
				__func__, __LINE__);
}
bool enable_DSIPLL(struct drm_device *dev)
{
	DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private;
	struct mdfld_dsi_config *dsi_config = NULL;
	struct mdfld_dsi_hw_context *ctx = NULL;
	u32 guit_val = 0x0;
	u32 retry;

	if (!dev_priv)
		goto err_out;
	dsi_config = dev_priv->dsi_configs[0];
	if (!dsi_config)
		goto err_out;
	ctx = &dsi_config->dsi_hw_context;

	if (IS_ANN(dev)) {
		int dspfreq;

		if ((get_panel_type(dev, 0) == JDI_7x12_CMD) ||
			(get_panel_type(dev, 0) == JDI_7x12_VID))
			dspfreq = DISPLAY_FREQ_FOR_200;
		else
			dspfreq = DISPLAY_FREQ_FOR_333;

		intel_mid_msgbus_write32(CCK_PORT,
			FUSE_OVERRIDE_FREQ_CNTRL_REG5,
			CKESC_GATE_EN | CKDP1X_GATE_EN | DISPLAY_FRE_EN
			| dspfreq);
	}

	/* Prepare DSI  PLL register before enabling */
	intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_DIV_REG, 0);
	guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG);
	guit_val &= ~(DPLL_VCO_ENABLE | _DSI_LDO_EN
			|_CLK_EN_MASK | _DSI_MUX_SEL_CCK_DSI0 | _DSI_MUX_SEL_CCK_DSI1);
	intel_mid_msgbus_write32(CCK_PORT,
					DSI_PLL_CTRL_REG, guit_val);
	udelay(1);
	/* Program PLL */

	/*first set up the dpll and fp variables
	 * dpll - will contain the following information
	 *      - the clock source - DSI vs HFH vs LFH PLL
	 * 	- what clocks should be running DSI0, DSI1
	 *      - and the divisor.
	 *
	 */

	intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_DIV_REG, ctx->fp);
	guit_val &= ~_P1_POST_DIV_MASK;	/*clear the divisor bit*/
	/* the ctx->dpll contains the divisor that we need to use as well as which clocks
	 * need to start up */
	guit_val |= ctx->dpll;
	guit_val &= ~_DSI_LDO_EN;	/* We want to clear the LDO enable when programming*/
	guit_val |=  DPLL_VCO_ENABLE;	/* Enable the DSI PLL */

	/* For the CD clock (clock used by Display controller), we need to set
	 * the DSI_CCK_PLL_SELECT bit (bit 11). This should already be set. But
	 * setting it just in case
	 */
	if (dev_priv->bUseHFPLL)
		guit_val |= _DSI_CCK_PLL_SELECT;

	intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_CTRL_REG, guit_val);

	/* Wait for DSI PLL lock */
	retry = 10000;
	guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG);
	while (((guit_val & _DSI_PLL_LOCK) != _DSI_PLL_LOCK) && (--retry)) {
		udelay(3);
		guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG);
		if (!retry%1000)
			DRM_ERROR("DSI PLL taking too long to lock"
				"- retry count=%d\n", 10000-retry);
	}
	if (retry == 0) {
		DRM_ERROR("DSI PLL fails to lock\n");
		return false;
	}

	return true;
err_out:
	return false;

}
Пример #6
0
/**
 * Setup Display Controller to turn on/off a video mode panel.
 * Most of the video mode MIPI panel should follow the power on/off
 * sequence in this function.
 * NOTE: do NOT modify this function for new panel Enabling. Register
 * new panel function callbacks to make this function available for a
 * new video mode panel
 */
static int __mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on)
{
	struct mdfld_dsi_encoder *dsi_encoder;
	struct mdfld_dsi_connector *dsi_connector;
	struct mdfld_dsi_dpi_output *dpi_output;
	struct mdfld_dsi_config *dsi_config;
	struct panel_funcs *p_funcs;
	int pipe;
	struct drm_device *dev;
	struct drm_psb_private *dev_priv;

	if (!encoder) {
		DRM_ERROR("Invalid encoder\n");
		return -EINVAL;
	}

	dsi_encoder = MDFLD_DSI_ENCODER(encoder);
	dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
	dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
	p_funcs = dpi_output->p_funcs;
	pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
	dsi_connector = mdfld_dsi_encoder_get_connector(dsi_encoder);
	if (!dsi_connector) {
		DRM_ERROR("dsi_connector is NULL\n");
		return -EINVAL;
	}

	dev = dsi_config->dev;
	dev_priv = dev->dev_private;

	if (dsi_connector->status != connector_status_connected)
		return 0;

	mutex_lock(&dsi_config->context_lock);

	if (dpi_output->first_boot && on) {
		if (dsi_config->dsi_hw_context.panel_on) {
			if (IS_ANN(dev))
				ann_dc_setup(dsi_config);

			psb_enable_vblank(dev, dsi_config->pipe);

			/* don't need ISLAND c for non dual-dsi panel */
			if (!is_dual_dsi(dev))
				power_island_put(OSPM_DISPLAY_C);

			DRM_INFO("skip panle power setting for first boot! "
				 "panel is already powered on\n");
			goto fun_exit;
		}
		if (android_hdmi_is_connected(dev))
			otm_hdmi_power_islands_off();
		/* power down islands turned on by firmware */
		power_island_put(OSPM_DISPLAY_A | OSPM_DISPLAY_C |
				 OSPM_DISPLAY_MIO);
	}

	switch (on) {
	case true:
		/* panel is already on */
		if (dsi_config->dsi_hw_context.panel_on)
			goto fun_exit;
		if (__dpi_panel_power_on(dsi_config, p_funcs, dpi_output->first_boot)) {
			DRM_ERROR("Faild to turn on panel\n");
			goto set_power_err;
		}
		dsi_config->dsi_hw_context.panel_on = 1;

		/* for every dpi panel power on, clear the dpi underrun count */
		dev_priv->pipea_dpi_underrun_count = 0;
		dev_priv->pipec_dpi_underrun_count = 0;

		break;
	case false:
		if (!dsi_config->dsi_hw_context.panel_on &&
			!dpi_output->first_boot)
			goto fun_exit;
		if (__dpi_panel_power_off(dsi_config, p_funcs)) {
			DRM_ERROR("Faild to turn off panel\n");
			goto set_power_err;
		}
		dsi_config->dsi_hw_context.panel_on = 0;
		break;
	default:
		break;
	}

fun_exit:
	mutex_unlock(&dsi_config->context_lock);
	PSB_DEBUG_ENTRY("successfully\n");
	return 0;
set_power_err:
	mutex_unlock(&dsi_config->context_lock);
	PSB_DEBUG_ENTRY("unsuccessfully!!!!\n");
	return -EAGAIN;
}
Пример #7
0
/**
 * Power on sequence for video mode MIPI panel.
 * NOTE: do NOT modify this function
 */
static int __dpi_panel_power_on(struct mdfld_dsi_config *dsi_config,
		struct panel_funcs *p_funcs, bool first_boot)
{
	u32 val = 0;
	struct mdfld_dsi_hw_registers *regs;
	struct mdfld_dsi_hw_context *ctx;
	struct drm_psb_private *dev_priv;
	struct drm_device *dev;
	int retry, reset_count = 10;
	int i;
	int err = 0;
	u32 power_island = 0;
	int offset = 0;

	PSB_DEBUG_ENTRY("\n");

	if (!dsi_config)
		return -EINVAL;

	regs = &dsi_config->regs;
	ctx = &dsi_config->dsi_hw_context;
	dev = dsi_config->dev;
	dev_priv = dev->dev_private;
	power_island = pipe_to_island(dsi_config->pipe);
	if (power_island & (OSPM_DISPLAY_A | OSPM_DISPLAY_C))
		power_island |= OSPM_DISPLAY_MIO;
	if (is_dual_dsi(dev))
		power_island |= OSPM_DISPLAY_C;

	if (!power_island_get(power_island))
		return -EAGAIN;
	if (android_hdmi_is_connected(dev) && first_boot)
			otm_hdmi_power_islands_on();

reset_recovery:
	--reset_count;
	/*HW-Reset*/
	if (p_funcs && p_funcs->reset)
		p_funcs->reset(dsi_config);

	/*
	 * Wait for DSI PLL locked on pipe, and only need to poll status of pipe
	 * A as both MIPI pipes share the same DSI PLL.
	 */
	if (dsi_config->pipe == 0) {
		retry = 20000;
		while (!(REG_READ(regs->pipeconf_reg) & PIPECONF_DSIPLL_LOCK) &&
				--retry)
			udelay(150);
		if (!retry) {
			DRM_ERROR("PLL failed to lock on pipe\n");
			err = -EAGAIN;
			goto power_on_err;
		}
	}

	if (IS_ANN(dev)) {
		/* FIXME: reset the DC registers for ANN A0 */
		ann_dc_setup(dsi_config);
	}

	__dpi_set_properties(dsi_config, PORT_A);

	/* update 0x650c[0] = 1 to fixed arbitration pattern
	 * it is found display TLB request be blocked by display plane
	 * memory requests, never goes out. This causes display controller
	 * uses stale TLB data to do memory translation, getting wrong
	 * memory address for data, and causing the flickering issue.
	 */
	REG_WRITE(GCI_CTRL, REG_READ(GCI_CTRL) | 1);

	/*Setup pipe timing*/
	REG_WRITE(regs->htotal_reg, ctx->htotal);
	REG_WRITE(regs->hblank_reg, ctx->hblank);
	REG_WRITE(regs->hsync_reg, ctx->hsync);
	REG_WRITE(regs->vtotal_reg, ctx->vtotal);
	REG_WRITE(regs->vblank_reg, ctx->vblank);
	REG_WRITE(regs->vsync_reg, ctx->vsync);
	REG_WRITE(regs->pipesrc_reg, ctx->pipesrc);

	REG_WRITE(regs->dsppos_reg, ctx->dsppos);
	REG_WRITE(regs->dspstride_reg, ctx->dspstride);

	/*Setup plane*/
	REG_WRITE(regs->dspsize_reg, ctx->dspsize);
	REG_WRITE(regs->dspsurf_reg, ctx->dspsurf);
	REG_WRITE(regs->dsplinoff_reg, ctx->dsplinoff);
	REG_WRITE(regs->vgacntr_reg, ctx->vgacntr);

	/*restore color_coef (chrome) */
	for (i = 0; i < 6; i++)
		REG_WRITE(regs->color_coef_reg + (i<<2), csc_setting_save[i]);

	/* restore palette (gamma) */
	for (i = 0; i < 256; i++)
		REG_WRITE(regs->palette_reg + (i<<2), gamma_setting_save[i]);

	/* restore dpst setting */
	if (dev_priv->psb_dpst_state) {
		dpstmgr_reg_restore_locked(dev, dsi_config);
		psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
	}

	if (__dpi_config_port(dsi_config, p_funcs, PORT_A) != 0) {
		if (!reset_count) {
				err = -EAGAIN;
				goto power_on_err;
			}
			DRM_ERROR("Failed to init dsi controller, reset it!\n");
			goto reset_recovery;
	}
	if (is_dual_dsi(dev)) {
		__dpi_set_properties(dsi_config, PORT_C);
		__dpi_config_port(dsi_config, p_funcs, PORT_C);
	}

	/**
	 * Different panel may have different ways to have
	 * drvIC initialized. Support it!
	 */
	if (p_funcs && p_funcs->drv_ic_init) {
		if (p_funcs->drv_ic_init(dsi_config)) {
			if (!reset_count) {
				err = -EAGAIN;
				goto power_on_err;
			}

			DRM_ERROR("Failed to init dsi controller, reset it!\n");
			goto reset_recovery;
		}
	}

	/*Enable MIPI Port A*/
	offset = 0x0;
	REG_WRITE(regs->mipi_reg + offset, (ctx->mipi | BIT31));
	REG_WRITE(regs->dpi_control_reg + offset, BIT1);
	if (is_dual_dsi(dev)) {
		/*Enable MIPI Port C*/
		offset = 0x1000;
		REG_WRITE(regs->mipi_reg + offset, (ctx->mipi | BIT31));
		offset = 0x800;
		REG_WRITE(regs->dpi_control_reg + offset, BIT1);
	}
	/**
	 * Different panel may have different ways to have
	 * panel turned on. Support it!
	 */
	if (p_funcs && p_funcs->power_on)
		if (p_funcs->power_on(dsi_config)) {
			DRM_ERROR("Failed to power on panel\n");
			err = -EAGAIN;
			goto power_on_err;
		}

	if (IS_ANN(dev)) {
		REG_WRITE(regs->ddl1_reg, ctx->ddl1);
		REG_WRITE(regs->ddl2_reg, ctx->ddl2);
		REG_WRITE(regs->ddl3_reg, ctx->ddl3);
		REG_WRITE(regs->ddl4_reg, ctx->ddl4);

		REG_WRITE(DSPARB2, ctx->dsparb2);
		REG_WRITE(DSPARB, ctx->dsparb);
	}

	/*Enable pipe*/
	val = ctx->pipeconf;
	val &= ~0x000c0000;
	/**
	 * Frame Start occurs on third HBLANK
	 * after the start of VBLANK
	 */
	val |= BIT31 | BIT28;
	REG_WRITE(regs->pipeconf_reg, val);
	/*Wait for pipe enabling,when timing generator
	  is wroking */
	if (REG_READ(regs->mipi_reg) & BIT31) {
		retry = 10000;
		while (--retry && !(REG_READ(regs->pipeconf_reg) & BIT30))
			udelay(3);

		if (!retry) {
			DRM_ERROR("Failed to enable pipe\n");
			err = -EAGAIN;
			goto power_on_err;
		}
	}
	/*enable plane*/
	val = ctx->dspcntr | BIT31;
	REG_WRITE(regs->dspcntr_reg, val);

	if (p_funcs && p_funcs->set_brightness) {
		if (p_funcs->set_brightness(dsi_config,
				ctx->lastbrightnesslevel))
			DRM_ERROR("Failed to set panel brightness\n");
	} else {
		DRM_ERROR("Failed to set panel brightness\n");
	}
	if (p_funcs && p_funcs->drv_set_panel_mode)
		p_funcs->drv_set_panel_mode(dsi_config);

	psb_enable_vblank(dev, dsi_config->pipe);
	return err;

power_on_err:
	power_island_put(power_island);
	return err;
}
Пример #8
0
static
void intel_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output)
{
    struct mdfld_dsi_pkg_sender *sender;
    struct drm_device *dev = dbi_output->dev;
    struct drm_crtc *crtc = dbi_output->base.base.crtc;
    struct psb_intel_crtc *psb_crtc =
        (crtc) ? to_psb_intel_crtc(crtc) : NULL;
    int pipe = dbi_output->channel_num ? 2 : 0;
    u32 dpll_reg = MRST_DPLL_A;
    u32 dspcntr_reg = DSPACNTR;
    u32 pipeconf_reg = PIPEACONF;
    u32 dsplinoff_reg = DSPALINOFF;
    u32 dspsurf_reg = DSPASURF;

    sender = mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
    if (!sender) {
        DRM_ERROR("pkg sender is NULL\n");
        return;
    }

    /* if mode setting on-going, back off */

    if (!IS_ANN(dev)) {
        if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
                (psb_crtc && (psb_crtc->mode_flags & MODE_SETTING_ON_GOING)) ||
                !(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE))
            return;
    }

    if (pipe == 2) {
        dspcntr_reg = DSPCCNTR;
        pipeconf_reg = PIPECCONF;
        dsplinoff_reg = DSPCLINOFF;
        dspsurf_reg = DSPCSURF;
    }

    /* check DBI FIFO status */
    if (is_panel_vid_or_cmd(dev) == MDFLD_DSI_ENCODER_DBI) {
        if (!(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) ||
                !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE))
            return;
    } else if (!(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) ||
               !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) ||
               !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE))
        return;

    if (!IS_ANN(dev)) {
        /* refresh plane changes */

        REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg));
        REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg));
        REG_READ(dspsurf_reg);
    }

    mdfld_dsi_send_dcs(sender,
                       write_mem_start,
                       NULL,
                       0,
                       CMD_DATA_SRC_PIPE,
                       MDFLD_DSI_SEND_PACKAGE);
    dbi_output->dsr_fb_update_done = true;
    mdfld_dsi_cmds_kick_out(sender);
}
Пример #9
0
/**
 * Power on sequence for command mode MIPI panel.
 * NOTE: do NOT modify this function
 */
static int __dbi_panel_power_on(struct mdfld_dsi_config *dsi_config,
                                struct panel_funcs *p_funcs)
{
    struct mdfld_dsi_hw_registers *regs;
    struct mdfld_dsi_hw_context *ctx;
    struct drm_psb_private *dev_priv;
    struct drm_device *dev;
    int reset_count = 10;
    int err = 0;
    struct mdfld_dsi_pkg_sender *sender
        = mdfld_dsi_get_pkg_sender(dsi_config);
    struct mdfld_dbi_dsr_info *dsr_info;
    struct mdfld_dsi_dbi_output **dbi_outputs;
    struct mdfld_dsi_dbi_output *dbi_output;

    if (!sender) {
        DRM_ERROR("pkg sender is NULL\n");
        return -EINVAL;
    }

    PSB_DEBUG_ENTRY("\n");

    if (!dsi_config)
        return -EINVAL;

    regs = &dsi_config->regs;
    ctx = &dsi_config->dsi_hw_context;
    dev = dsi_config->dev;
    dev_priv = dev->dev_private;

    mdfld_dsi_dsr_forbid_locked(dsi_config);
reset_recovery:
    --reset_count;
    err = 0;
    /*after entering dstb mode, need reset*/
    if (p_funcs && p_funcs->exit_deep_standby)
        p_funcs->exit_deep_standby(dsi_config);

    if (__dbi_power_on(dsi_config)) {
        DRM_ERROR("Failed to init display controller!\n");
        err = -EAGAIN;
        goto power_on_err;
    }

    /**
     * Different panel may have different ways to have
     * drvIC initialized. Support it!
     */
    if (p_funcs && p_funcs->drv_ic_init) {
        if (p_funcs->drv_ic_init(dsi_config)) {
            DRM_ERROR("Failed to init dsi controller!\n");
            err = -EAGAIN;
            goto power_on_err;
        }
    }
    /* Issue "write_mem_start" DSI command during power on. */
    dsr_info = dev_priv->dbi_dsr_info;
    dbi_outputs = dsr_info->dbi_outputs;
    dbi_output = dsi_config->pipe ? dbi_outputs[1] : dbi_outputs[0];

    if (!IS_ANN(dev))
        intel_dsi_dbi_update_fb(dbi_output);

    /**
     * Different panel may have different ways to have
     * panel turned on. Support it!
     */
    if (p_funcs && p_funcs->power_on)
        if (p_funcs->power_on(dsi_config)) {
            DRM_ERROR("Failed to power on panel\n");
            err = -EAGAIN;
            goto power_on_err;
        }
    if (p_funcs && p_funcs->set_brightness)
        if (p_funcs->set_brightness(dsi_config,
                                    ctx->lastbrightnesslevel))
            DRM_ERROR("Failed to set panel brightness\n");

    if (p_funcs && p_funcs->drv_set_panel_mode)
        p_funcs->drv_set_panel_mode(dsi_config);

    /*wait for all FIFOs empty*/
    mdfld_dsi_wait_for_fifos_empty(sender);
    if (is_dual_dsi(dev)) {
        sender->work_for_slave_panel = true;
        mdfld_dsi_wait_for_fifos_empty(sender);
        sender->work_for_slave_panel = false;
    }

    if (IS_ANN(dev))
        intel_dsi_dbi_update_fb(dbi_output);

power_on_err:
    if (err && reset_count) {
        DRM_ERROR("Failed to init panel, try  reset it again!\n");
        goto reset_recovery;
    }
    mdfld_dsi_dsr_allow_locked(dsi_config);
    return err;
}
Пример #10
0
/* dbi interface power on*/
int __dbi_power_on(struct mdfld_dsi_config *dsi_config)
{
    u32 val = 0;
    struct mdfld_dsi_hw_registers *regs;
    struct mdfld_dsi_hw_context *ctx;
    struct drm_psb_private *dev_priv;
    struct drm_device *dev;
    int retry;
    int err = 0;
    u32 power_island = 0;
    u32 sprite_reg_offset = 0;
    int i = 0;
    int offset = 0;

    PSB_DEBUG_ENTRY("\n");

    if (!dsi_config)
        return -EINVAL;

    regs = &dsi_config->regs;
    ctx = &dsi_config->dsi_hw_context;
    dev = dsi_config->dev;
    dev_priv = dev->dev_private;

    power_island = pipe_to_island(dsi_config->pipe);

    if (power_island & (OSPM_DISPLAY_A | OSPM_DISPLAY_C))
        power_island |= OSPM_DISPLAY_MIO;

    if (is_dual_dsi(dev))
        power_island |= OSPM_DISPLAY_C;

    if (!power_island_get(power_island))
        return -EAGAIN;

    /*
     * Wait for DSI PLL locked on pipe, and only need to poll status of pipe
     * A as both MIPI pipes share the same DSI PLL.
     */
    if (dsi_config->pipe == 0) {
        retry = 20000;
        while (!(REG_READ(regs->pipeconf_reg) & PIPECONF_DSIPLL_LOCK) &&
                --retry)
            udelay(150);
        if (!retry) {
            DRM_ERROR("PLL failed to lock on pipe\n");
            err = -EAGAIN;
            goto power_on_err;
        }
    }

    if (IS_ANN(dev)) {
        /* FIXME: reset the DC registers for ANN A0 */
        power_island_get(OSPM_DISPLAY_B | OSPM_DISPLAY_C);

        REG_WRITE(DSPCLK_GATE_D, 0x0);
        REG_WRITE(RAMCLK_GATE_D, 0xc0000 | (1 << 11)); // FIXME: delay 1us for RDB done signal
        REG_WRITE(PFIT_CONTROL, 0x20000000);
        REG_WRITE(DSPIEDCFGSHDW, 0x0);
        REG_WRITE(DSPARB2, 0x000A0200);
        REG_WRITE(DSPARB, 0x18040080);
        REG_WRITE(DSPFW1, 0x0F0F3F3F);
        REG_WRITE(DSPFW2, 0x5F2F0F3F);
        REG_WRITE(DSPFW3, 0x0);
        REG_WRITE(DSPFW4, 0x07071F1F);
        REG_WRITE(DSPFW5, 0x2F17071F);
        REG_WRITE(DSPFW6, 0x00001F3F);
        REG_WRITE(DSPFW7, 0x1F3F1F3F);
        REG_WRITE(DSPSRCTRL, 0x00080100);
        REG_WRITE(DSPCHICKENBIT, 0x20);
        REG_WRITE(FBDC_CHICKEN, 0x0C0C0C0C);
        REG_WRITE(CURACNTR, 0x0);
        REG_WRITE(CURBCNTR, 0x0);
        REG_WRITE(CURCCNTR, 0x0);
        REG_WRITE(IEP_OVA_CTRL, 0x0);
        REG_WRITE(IEP_OVA_CTRL, 0x0);
        REG_WRITE(DSPACNTR, 0x0);
        REG_WRITE(DSPBCNTR, 0x0);
        REG_WRITE(DSPCCNTR, 0x0);
        REG_WRITE(DSPDCNTR, 0x0);
        REG_WRITE(DSPECNTR, 0x0);
        REG_WRITE(DSPFCNTR, 0x0);

        power_island_put(OSPM_DISPLAY_B | OSPM_DISPLAY_C);
    }

    /*exit ULPS*/
    if (__dbi_exit_ulps_locked(dsi_config, 0)) {
        DRM_ERROR("Failed to exit ULPS\n");
        goto power_on_err;
    }
    /*update MIPI port config*/
    REG_WRITE(regs->mipi_reg, ctx->mipi |
              REG_READ(regs->mipi_reg));

    /*unready dsi adapter for re-programming*/
    REG_WRITE(regs->device_ready_reg,
              REG_READ(regs->device_ready_reg) & ~(DSI_DEVICE_READY));

    if (is_dual_dsi(dev)) {
        if (__dbi_exit_ulps_locked(dsi_config, 0x800)) {
            DRM_ERROR("Failed to exit ULPS\n");
            goto power_on_err;
        }
        offset = 0x1000;
        REG_WRITE(regs->mipi_reg + offset, ctx->mipi |
                  REG_READ(regs->mipi_reg + offset));
        /*unready dsi adapter for re-programming*/
        offset = 0x800;
        REG_WRITE(regs->device_ready_reg + offset,
                  REG_READ(regs->device_ready_reg + offset) & ~(DSI_DEVICE_READY));
    }

    /*
     * According to MIPI D-PHY spec, if clock stop feature is enabled (EOT
     * Disable), un-ready MIPI adapter needs to wait for 20 cycles from HS
     * to LP mode. Per calculation 1us is enough.
     */
    if (ctx->eot_disable & CLOCK_STOP)
        udelay(1);

    __dbi_set_properties(dsi_config, PORT_A);

    /* update 0x650c[0] = 1 to fixed arbitration pattern
     * it is found display TLB request be blocked by display plane
     * memory requests, never goes out. This causes display controller
     * uses stale TLB data to do memory translation, getting wrong
     * memory address for data, and causing the flickering issue.
     */
    REG_WRITE(GCI_CTRL, REG_READ(GCI_CTRL) | 1);

    /*Setup pipe timing*/
    REG_WRITE(regs->htotal_reg, ctx->htotal);
    REG_WRITE(regs->hblank_reg, ctx->hblank);
    REG_WRITE(regs->hsync_reg, ctx->hsync);
    REG_WRITE(regs->vtotal_reg, ctx->vtotal);
    REG_WRITE(regs->vblank_reg, ctx->vblank);
    REG_WRITE(regs->vsync_reg, ctx->vsync);
    REG_WRITE(regs->pipesrc_reg, ctx->pipesrc);
    REG_WRITE(regs->dsppos_reg, ctx->dsppos);
    REG_WRITE(regs->dspstride_reg, ctx->dspstride);

    /*restore color_coef (chrome) */
    for (i = 0; i < 6; i++)
        REG_WRITE(regs->color_coef_reg + (i<<2), csc_setting_save[i]);

    /* restore palette (gamma) */
    for (i = 0; i < 256; i++)
        REG_WRITE(regs->palette_reg + (i<<2), gamma_setting_save[i]);

    /* restore dpst setting */
    if (dev_priv->psb_dpst_state) {
        dpstmgr_reg_restore_locked(dev, dsi_config);
        psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
    }

    /*Setup plane*/
    REG_WRITE(regs->dspsize_reg, ctx->dspsize);
    REG_WRITE(regs->dspsurf_reg, ctx->dspsurf);
    REG_WRITE(regs->dsplinoff_reg, ctx->dsplinoff);
    REG_WRITE(regs->vgacntr_reg, ctx->vgacntr);

    if (is_dual_dsi(dev))
        __dbi_set_properties(dsi_config, PORT_C);

    /*enable plane*/
    val = ctx->dspcntr | BIT31;
    REG_WRITE(regs->dspcntr_reg, val);

    if (ctx->sprite_dspcntr & BIT31) {
        if (dsi_config->pipe == 0)
            sprite_reg_offset = 0x3000;
        else if (dsi_config->pipe == 2)
            sprite_reg_offset = 0x1000;

        /* Set up Sprite Plane */
        REG_WRITE(regs->dspsize_reg + sprite_reg_offset,
                  ctx->sprite_dspsize);
        REG_WRITE(regs->dspsurf_reg + sprite_reg_offset,
                  ctx->sprite_dspsurf);
        REG_WRITE(regs->dsplinoff_reg + sprite_reg_offset,
                  ctx->sprite_dsplinoff);
        REG_WRITE(regs->dsppos_reg + sprite_reg_offset,
                  ctx->sprite_dsppos);
        REG_WRITE(regs->dspstride_reg + sprite_reg_offset,
                  ctx->sprite_dspstride);

        /* enable plane */
        REG_WRITE(regs->dspcntr_reg + sprite_reg_offset,
                  ctx->sprite_dspcntr);
    }

    /* Set up Overlay Plane */
    if (ctx->ovaadd)
        PSB_WVDC32(ctx->ovaadd, OV_OVADD);

    if (ctx->ovcadd)
        PSB_WVDC32(ctx->ovcadd, OVC_OVADD);

    /*ready dsi adapter*/
    REG_WRITE(regs->device_ready_reg,
              REG_READ(regs->device_ready_reg) | DSI_DEVICE_READY);
    mdelay(1);
    if (is_dual_dsi(dev)) {
        REG_WRITE(regs->device_ready_reg + offset,
                  REG_READ(regs->device_ready_reg + offset) | DSI_DEVICE_READY);
    }

    if (IS_ANN(dev)) {
        REG_WRITE(regs->ddl1_reg, ctx->ddl1);
        REG_WRITE(regs->ddl2_reg, ctx->ddl2);
        REG_WRITE(regs->ddl3_reg, ctx->ddl3);
        REG_WRITE(regs->ddl4_reg, ctx->ddl4);

        REG_WRITE(DSPARB2, ctx->dsparb2);
        REG_WRITE(DSPARB, ctx->dsparb);
    }

    /*Enable pipe*/
    val = ctx->pipeconf;
    val &= ~0x000c0000;
    val |= BIT31 | PIPEACONF_DSR;
    REG_WRITE(regs->pipeconf_reg, val);

    /*Wait for pipe enabling,when timing generator is working */
    retry = 10000;
    while (--retry && !(REG_READ(regs->pipeconf_reg) & BIT30))
        udelay(3);

    if (!retry) {
        DRM_ERROR("Failed to enable pipe\n");
        err = -EAGAIN;
        goto power_on_err;
    }

    /*
     * Enable TE to trigger "write_mem_start" issuing
     * in non-normal boot modes.
     */
    mdfld_enable_te(dev, dsi_config->pipe);
    return err;

power_on_err:
    power_island_put(power_island);
    return err;
}