static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux,
				       struct drm_dp_aux_msg *msg)
{
	struct analogix_dp_device *dp = to_dp(aux);

	return analogix_dp_transfer(dp, msg);
}
static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder)
{
	struct rockchip_dp_device *dp = to_dp(encoder);
	int ret;
	u32 val;

	ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder);
	if (ret < 0)
		return;

	if (ret)
		val = dp->data->lcdsel_lit;
	else
		val = dp->data->lcdsel_big;

	dev_dbg(dp->dev, "vop %s output to dp\n", (ret) ? "LIT" : "BIG");

	ret = clk_prepare_enable(dp->grfclk);
	if (ret < 0) {
		dev_err(dp->dev, "failed to enable grfclk %d\n", ret);
		return;
	}

	ret = regmap_write(dp->grf, dp->data->lcdsel_grf_reg, val);
	if (ret != 0)
		dev_err(dp->dev, "Could not write to GRF: %d\n", ret);

	clk_disable_unprepare(dp->grfclk);
}
static int
rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder,
				      struct drm_crtc_state *crtc_state,
				      struct drm_connector_state *conn_state)
{
	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
	struct rockchip_dp_device *dp = to_dp(encoder);
	int ret;

	/*
	 * The hardware IC designed that VOP must output the RGB10 video
	 * format to eDP controller, and if eDP panel only support RGB8,
	 * then eDP controller should cut down the video data, not via VOP
	 * controller, that's why we need to hardcode the VOP output mode
	 * to RGA10 here.
	 */

	s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
	s->output_type = DRM_MODE_CONNECTOR_eDP;
	if (dp->data->chip_type == RK3399_EDP) {
		/*
		 * For RK3399, VOP Lit must code the out mode to RGB888,
		 * VOP Big must code the out mode to RGB10.
		 */
		ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node,
							encoder);
		if (ret > 0)
			s->output_mode = ROCKCHIP_OUT_MODE_P888;
	}

	return 0;
}
Exemple #4
0
static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
				   struct drm_bridge *bridge,
				   struct drm_connector *connector)
{
	struct exynos_dp_device *dp = to_dp(plat_data);
	struct drm_encoder *encoder = &dp->encoder;
	int ret;

	drm_connector_register(connector);
	dp->connector = connector;

	/* Pre-empt DP connector creation if there's a bridge */
	if (dp->ptn_bridge) {
		bridge->next = dp->ptn_bridge;
		dp->ptn_bridge->encoder = encoder;
		ret = drm_bridge_attach(encoder->dev, dp->ptn_bridge);
		if (ret) {
			DRM_ERROR("Failed to attach bridge to drm\n");
			bridge->next = NULL;
			return ret;
		}
	}

	return 0;
}
static enum drm_connector_status
analogix_dp_detect(struct drm_connector *connector, bool force)
{
	struct analogix_dp_device *dp = to_dp(connector);
	enum drm_connector_status status = connector_status_disconnected;
	int ret;

	if (dp->plat_data->panel)
		return connector_status_connected;

	ret = analogix_dp_prepare_panel(dp, true, false);
	if (ret) {
		DRM_ERROR("Failed to prepare panel (%d)\n", ret);
		return connector_status_disconnected;
	}

	if (!analogix_dp_detect_hpd(dp))
		status = connector_status_connected;

	ret = analogix_dp_prepare_panel(dp, false, false);
	if (ret)
		DRM_ERROR("Failed to unprepare panel (%d)\n", ret);

	return status;
}
int analogix_dp_get_modes(struct drm_connector *connector)
{
	struct analogix_dp_device *dp = to_dp(connector);
	struct edid *edid = (struct edid *)dp->edid;
	int ret, num_modes = 0;

	ret = analogix_dp_prepare_panel(dp, true, false);
	if (ret) {
		DRM_ERROR("Failed to prepare panel (%d)\n", ret);
		return 0;
	}

	if (analogix_dp_handle_edid(dp) == 0) {
		drm_mode_connector_update_edid_property(&dp->connector, edid);
		num_modes += drm_add_edid_modes(&dp->connector, edid);
	}

	if (dp->plat_data->panel)
		num_modes += drm_panel_get_modes(dp->plat_data->panel);

	if (dp->plat_data->get_modes)
		num_modes += dp->plat_data->get_modes(dp->plat_data, connector);

	ret = analogix_dp_prepare_panel(dp, false, false);
	if (ret)
		DRM_ERROR("Failed to unprepare panel (%d)\n", ret);

	return num_modes;
}
static void xilinx_drm_dp_dpms(struct drm_encoder *encoder, int dpms)
{
	struct xilinx_drm_dp *dp = to_dp(encoder);
	void __iomem *iomem = dp->iomem;

	if (dp->dpms == dpms)
		return;

	dp->dpms = dpms;

	switch (dpms) {
	case DRM_MODE_DPMS_ON:
		xilinx_drm_writel(dp->iomem, XILINX_DP_TX_SW_RESET,
				  XILINX_DP_TX_SW_RESET_ALL);
		if (dp->aud_clk)
			xilinx_drm_writel(iomem, XILINX_DP_TX_AUDIO_CONTROL, 1);

		xilinx_drm_writel(iomem, XILINX_DP_TX_PHY_POWER_DOWN, 0);
		drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, DP_SET_POWER_D0);
		xilinx_drm_dp_train(dp);
		xilinx_drm_writel(iomem, XILINX_DP_TX_ENABLE_MAIN_STREAM, 1);

		return;
	default:
		xilinx_drm_writel(iomem, XILINX_DP_TX_ENABLE_MAIN_STREAM, 0);
		drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, DP_SET_POWER_D3);
		xilinx_drm_writel(iomem, XILINX_DP_TX_PHY_POWER_DOWN,
				  XILINX_DP_TX_PHY_POWER_DOWN_ALL);
		if (dp->aud_clk)
			xilinx_drm_writel(iomem, XILINX_DP_TX_AUDIO_CONTROL, 0);

		return;
	}
}
static enum drm_connector_status
xilinx_drm_dp_detect(struct drm_encoder *encoder,
		     struct drm_connector *connector)
{
	struct xilinx_drm_dp *dp = to_dp(encoder);
	struct xilinx_drm_dp_link_config *link_config = &dp->link_config;
	u32 state;
	int ret;

	state = xilinx_drm_readl(dp->iomem, XILINX_DP_TX_INTR_SIGNAL_STATE);
	if (state & XILINX_DP_TX_INTR_SIGNAL_STATE_HPD) {
		ret = xilinx_drm_dp_aux_read(dp, 0x0, dp->dpcd,
					     sizeof(dp->dpcd));
		if (ret)
			return connector_status_disconnected;

		link_config->max_rate = min_t(int,
					      drm_dp_max_link_rate(dp->dpcd),
					      dp->config.max_link_rate);
		link_config->max_lanes = min_t(u8,
					       drm_dp_max_lane_count(dp->dpcd),
					       dp->config.max_lanes);

		return connector_status_connected;
	}
static int exynos_dp_get_modes(struct analogix_dp_plat_data *plat_data)
{
	struct exynos_dp_device *dp = to_dp(plat_data);
	struct drm_connector *connector = &dp->connector;
	struct drm_display_mode *mode;
	int num_modes = 0;

	if (dp->plat_data.panel)
		return num_modes;

	mode = drm_mode_create(connector->dev);
	if (!mode) {
		DRM_ERROR("failed to create a new display mode.\n");
		return num_modes;
	}

	drm_display_mode_from_videomode(&dp->vm, mode);
	connector->display_info.width_mm = mode->width_mm;
	connector->display_info.height_mm = mode->height_mm;

	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
	drm_mode_set_name(mode);
	drm_mode_probed_add(connector, mode);

	return num_modes + 1;
}
static void xilinx_drm_dp_dpms(struct drm_encoder *encoder, int dpms)
{
	struct xilinx_drm_dp *dp = to_dp(encoder);
	void __iomem *iomem = dp->iomem;

	if (dp->dpms == dpms)
		return;

	dp->dpms = dpms;

	switch (dpms) {
	case DRM_MODE_DPMS_ON:
		xilinx_drm_writel(iomem, XILINX_DP_TX_PHY_POWER_DOWN, 0);
		xilinx_drm_dp_aux_write_byte(dp, DP_SET_POWER, DP_SET_POWER_D0);
		xilinx_drm_dp_train(dp);
		xilinx_drm_writel(iomem, XILINX_DP_TX_ENABLE_MAIN_STREAM, 1);
		return;
	default:
		xilinx_drm_writel(iomem, XILINX_DP_TX_ENABLE_MAIN_STREAM, 0);
		xilinx_drm_dp_aux_write_byte(dp, DP_SET_POWER, DP_SET_POWER_D3);
		xilinx_drm_writel(iomem, XILINX_DP_TX_PHY_POWER_DOWN,
				  XILINX_DP_TX_PHY_POWER_DOWN_ALL);
		return;
	}
}
static void xilinx_drm_dp_mode_set(struct drm_encoder *encoder,
				   struct drm_display_mode *mode,
				   struct drm_display_mode *adjusted_mode)
{
	struct xilinx_drm_dp *dp = to_dp(encoder);
	int bw = 0;
	unsigned int ret;

	do {
		bw = xilinx_drm_dp_mode_configure(dp, adjusted_mode->clock, bw);
		if (bw < 0)
			return;

		xilinx_drm_dp_mode_set_stream(dp, adjusted_mode);
		xilinx_drm_dp_mode_set_transfer_unit(dp, adjusted_mode);

		xilinx_drm_writel(dp->iomem, XILINX_DP_TX_PHY_POWER_DOWN, 0);
		ret = xilinx_drm_dp_train(dp);
		xilinx_drm_writel(dp->iomem, XILINX_DP_TX_PHY_POWER_DOWN,
				  XILINX_DP_TX_PHY_POWER_DOWN_ALL);
		if (!ret)
			return;
	} while (bw >= DP_LINK_BW_1_62);

	DRM_ERROR("failed to train the DP link\n");
}
static struct drm_encoder *
analogix_dp_best_encoder(struct drm_connector *connector)
{
	struct analogix_dp_device *dp = to_dp(connector);

	return dp->encoder;
}
static int analogix_dp_get_modes(struct drm_connector *connector)
{
	struct analogix_dp_device *dp = to_dp(connector);
	struct edid *edid;
	int ret, num_modes = 0;

	if (dp->plat_data->panel) {
		num_modes += drm_panel_get_modes(dp->plat_data->panel);
	} else {
		ret = analogix_dp_prepare_panel(dp, true, false);
		if (ret) {
			DRM_ERROR("Failed to prepare panel (%d)\n", ret);
			return 0;
		}

		edid = drm_get_edid(connector, &dp->aux.ddc);
		if (edid) {
			drm_mode_connector_update_edid_property(&dp->connector,
								edid);
			num_modes += drm_add_edid_modes(&dp->connector, edid);
			kfree(edid);
		}

		ret = analogix_dp_prepare_panel(dp, false, false);
		if (ret)
			DRM_ERROR("Failed to unprepare panel (%d)\n", ret);
	}

	if (dp->plat_data->get_modes)
		num_modes += dp->plat_data->get_modes(dp->plat_data, connector);

	return num_modes;
}
static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data)
{
	struct rockchip_dp_device *dp = to_dp(plat_data);

	clk_disable_unprepare(dp->pclk);

	return 0;
}
static void xilinx_drm_dp_mode_set(struct drm_encoder *encoder,
				   struct drm_display_mode *mode,
				   struct drm_display_mode *adjusted_mode)
{
	struct xilinx_drm_dp *dp = to_dp(encoder);

	xilinx_drm_dp_mode_configure(dp, adjusted_mode->clock);
	xilinx_drm_dp_mode_set_stream(dp, adjusted_mode);
	xilinx_drm_dp_mode_set_transfer_unit(dp, adjusted_mode);
}
Exemple #16
0
int exynos_dp_crtc_clock_enable(struct analogix_dp_plat_data *plat_data,
				bool enable)
{
	struct exynos_dp_device *dp = to_dp(plat_data);
	struct drm_encoder *encoder = &dp->encoder;

	if (!encoder->crtc)
		return -EPERM;

	exynos_drm_pipe_clk_enable(to_exynos_crtc(encoder->crtc), enable);

	return 0;
}
int exynos_dp_crtc_clock_enable(struct analogix_dp_plat_data *plat_data,
				bool enable)
{
	struct exynos_dp_device *dp = to_dp(plat_data);
	struct drm_encoder *encoder = &dp->encoder;
	struct exynos_drm_crtc *crtc;

	if (!encoder)
		return -1;

	crtc = to_exynos_crtc(encoder->crtc);
	if (crtc && crtc->ops && crtc->ops->clock_enable)
		crtc->ops->clock_enable(crtc, enable);

	return 0;
}
static int xilinx_drm_dp_mode_valid(struct drm_encoder *encoder,
				    struct drm_display_mode *mode)
{
	struct xilinx_drm_dp *dp = to_dp(encoder);
	u8 max_lanes = dp->link_config.max_lanes;
	u8 bpp = dp->config.bpp;
	int max_rate = dp->link_config.max_rate;
	int rate;

	if (mode->clock > XILINX_DP_MAX_CLOCK)
		return MODE_CLOCK_HIGH;

	rate = xilinx_drm_dp_max_rate(max_rate, max_lanes, bpp);
	if (mode->clock > rate)
		return MODE_CLOCK_HIGH;

	return MODE_OK;
}
static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data)
{
	struct rockchip_dp_device *dp = to_dp(plat_data);
	int ret;

	ret = clk_prepare_enable(dp->pclk);
	if (ret < 0) {
		dev_err(dp->dev, "failed to enable pclk %d\n", ret);
		return ret;
	}

	ret = rockchip_dp_pre_init(dp);
	if (ret < 0) {
		dev_err(dp->dev, "failed to dp pre init %d\n", ret);
		return ret;
	}

	return 0;
}
Exemple #20
0
static void xilinx_drm_dp_dpms(struct drm_encoder *encoder, int dpms)
{
	struct xilinx_drm_dp *dp = to_dp(encoder);
	void __iomem *iomem = dp->iomem;
	unsigned int i;
	int ret;

	if (dp->dpms == dpms)
		return;

	dp->dpms = dpms;

	switch (dpms) {
	case DRM_MODE_DPMS_ON:
		if (dp->aud_clk)
			xilinx_drm_writel(iomem, XILINX_DP_TX_AUDIO_CONTROL, 1);

		xilinx_drm_writel(iomem, XILINX_DP_TX_PHY_POWER_DOWN, 0);
		for (i = 0; i < 3; i++) {
			ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER,
						 DP_SET_POWER_D0);
			if (ret == 1)
				break;
			usleep_range(300, 500);
		}
		xilinx_drm_dp_train(dp);
		xilinx_drm_writel(dp->iomem, XILINX_DP_TX_SW_RESET,
				  XILINX_DP_TX_SW_RESET_ALL);
		xilinx_drm_writel(iomem, XILINX_DP_TX_ENABLE_MAIN_STREAM, 1);

		return;
	default:
		xilinx_drm_writel(iomem, XILINX_DP_TX_ENABLE_MAIN_STREAM, 0);
		drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, DP_SET_POWER_D3);
		xilinx_drm_writel(iomem, XILINX_DP_TX_PHY_POWER_DOWN,
				  XILINX_DP_TX_PHY_POWER_DOWN_ALL);
		if (dp->aud_clk)
			xilinx_drm_writel(iomem, XILINX_DP_TX_AUDIO_CONTROL, 0);

		return;
	}
}
static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder)
{
	struct rockchip_dp_device *dp = to_dp(encoder);
	int ret;
	u32 val;

	ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder);
	if (ret < 0)
		return;

	if (ret)
		val = GRF_EDP_SEL_VOP_LIT | (GRF_EDP_LCD_SEL_MASK << 16);
	else
		val = GRF_EDP_SEL_VOP_BIG | (GRF_EDP_LCD_SEL_MASK << 16);

	dev_dbg(dp->dev, "vop %s output to dp\n", (ret) ? "LIT" : "BIG");

	ret = regmap_write(dp->grf, GRF_SOC_CON6, val);
	if (ret != 0) {
		dev_err(dp->dev, "Could not write to GRF: %d\n", ret);
		return;
	}
}
Exemple #22
0
static bool xilinx_drm_dp_mode_fixup(struct drm_encoder *encoder,
				     const struct drm_display_mode *mode,
				     struct drm_display_mode *adjusted_mode)
{
	struct xilinx_drm_dp *dp = to_dp(encoder);
	int diff = mode->htotal - mode->hsync_end;

	/*
	 * ZynqMP DP requires horizontal backporch to be greater than 12.
	 * This limitation may conflict with the sink device.
	 */
	if (dp->dp_sub && diff < XILINX_DP_SUB_TX_MIN_H_BACKPORCH) {
		int vrefresh = (adjusted_mode->clock * 1000) /
			       (adjusted_mode->vtotal * adjusted_mode->htotal);

		diff = XILINX_DP_SUB_TX_MIN_H_BACKPORCH - diff;
		adjusted_mode->htotal += diff;
		adjusted_mode->clock = adjusted_mode->vtotal *
				       adjusted_mode->htotal * vrefresh / 1000;
	}

	return true;
}