struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
						   struct drm_encoder *encoder)
{
	struct exynos_drm_connector *exynos_connector;
	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
	struct drm_connector *connector;
	int type;
	int err;

	DRM_DEBUG_KMS("%s\n", __FILE__);

	exynos_connector = kzalloc(sizeof(*exynos_connector), GFP_KERNEL);
	if (!exynos_connector) {
		DRM_ERROR("failed to allocate connector\n");
		return NULL;
	}

	connector = &exynos_connector->drm_connector;

	switch (manager->display_ops->type) {
	case EXYNOS_DISPLAY_TYPE_HDMI:
		type = DRM_MODE_CONNECTOR_HDMIA;
		connector->interlace_allowed = true;
		connector->polled = DRM_CONNECTOR_POLL_HPD;
		break;
	case EXYNOS_DISPLAY_TYPE_VIDI:
		type = DRM_MODE_CONNECTOR_VIRTUAL;
		connector->polled = DRM_CONNECTOR_POLL_HPD;
		break;
	default:
		type = DRM_MODE_CONNECTOR_Unknown;
		break;
	}

	drm_connector_init(dev, connector, &exynos_connector_funcs, type);
	drm_connector_helper_add(connector, &exynos_connector_helper_funcs);

	err = drm_sysfs_connector_add(connector);
	if (err)
		goto err_connector;

	exynos_connector->encoder_id = encoder->base.id;
	exynos_connector->manager = manager;
	connector->encoder = encoder;

	err = drm_mode_connector_attach_encoder(connector, encoder);
	if (err) {
		DRM_ERROR("failed to attach a connector to a encoder\n");
		goto err_sysfs;
	}

	DRM_DEBUG_KMS("connector has been created\n");

	return connector;

err_sysfs:
	drm_sysfs_connector_remove(connector);
err_connector:
	drm_connector_cleanup(connector);
	kfree(exynos_connector);
	return NULL;
}
示例#2
0
static int omap_modeset_init(struct drm_device *dev)
{
	struct omap_drm_private *priv = dev->dev_private;
	struct omap_dss_device *dssdev = NULL;
	int num_ovls = dss_feat_get_num_ovls();
	int num_mgrs = dss_feat_get_num_mgrs();
	int num_crtcs;
	int i, id = 0;

	drm_mode_config_init(dev);

	omap_drm_irq_install(dev);

	/*
	 * We usually don't want to create a CRTC for each manager, at least
	 * not until we have a way to expose private planes to userspace.
	 * Otherwise there would not be enough video pipes left for drm planes.
	 * We use the num_crtc argument to limit the number of crtcs we create.
	 */
	num_crtcs = min3(num_crtc, num_mgrs, num_ovls);

	dssdev = NULL;

	for_each_dss_dev(dssdev) {
		struct drm_connector *connector;
		struct drm_encoder *encoder;
		enum omap_channel channel;
		struct omap_overlay_manager *mgr;

		if (!omapdss_device_is_connected(dssdev))
			continue;

		encoder = omap_encoder_init(dev, dssdev);

		if (!encoder) {
			dev_err(dev->dev, "could not create encoder: %s\n",
					dssdev->name);
			return -ENOMEM;
		}

		connector = omap_connector_init(dev,
				get_connector_type(dssdev), dssdev, encoder);

		if (!connector) {
			dev_err(dev->dev, "could not create connector: %s\n",
					dssdev->name);
			return -ENOMEM;
		}

		BUG_ON(priv->num_encoders >= ARRAY_SIZE(priv->encoders));
		BUG_ON(priv->num_connectors >= ARRAY_SIZE(priv->connectors));

		priv->encoders[priv->num_encoders++] = encoder;
		priv->connectors[priv->num_connectors++] = connector;

		drm_mode_connector_attach_encoder(connector, encoder);

		/*
		 * if we have reached the limit of the crtcs we are allowed to
		 * create, let's not try to look for a crtc for this
		 * panel/encoder and onwards, we will, of course, populate the
		 * the possible_crtcs field for all the encoders with the final
		 * set of crtcs we create
		 */
		if (id == num_crtcs)
			continue;

		/*
		 * get the recommended DISPC channel for this encoder. For now,
		 * we only try to get create a crtc out of the recommended, the
		 * other possible channels to which the encoder can connect are
		 * not considered.
		 */

		mgr = omapdss_find_mgr_from_display(dssdev);
		channel = mgr->id;
		/*
		 * if this channel hasn't already been taken by a previously
		 * allocated crtc, we create a new crtc for it
		 */
		if (!channel_used(dev, channel)) {
			struct drm_plane *plane;
			struct drm_crtc *crtc;

			plane = omap_plane_init(dev, id, true);
			crtc = omap_crtc_init(dev, plane, channel, id);

			BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs));
			priv->crtcs[id] = crtc;
			priv->num_crtcs++;

			priv->planes[id] = plane;
			priv->num_planes++;

			id++;
		}
	}

	/*
	 * we have allocated crtcs according to the need of the panels/encoders,
	 * adding more crtcs here if needed
	 */
	for (; id < num_crtcs; id++) {

		/* find a free manager for this crtc */
		for (i = 0; i < num_mgrs; i++) {
			if (!channel_used(dev, i)) {
				struct drm_plane *plane;
				struct drm_crtc *crtc;

				plane = omap_plane_init(dev, id, true);
				crtc = omap_crtc_init(dev, plane, i, id);

				BUG_ON(priv->num_crtcs >=
					ARRAY_SIZE(priv->crtcs));

				priv->crtcs[id] = crtc;
				priv->num_crtcs++;

				priv->planes[id] = plane;
				priv->num_planes++;

				break;
			} else {
				continue;
			}
		}

		if (i == num_mgrs) {
			/* this shouldn't really happen */
			dev_err(dev->dev, "no managers left for crtc\n");
			return -ENOMEM;
		}
	}

	/*
	 * Create normal planes for the remaining overlays:
	 */
	for (; id < num_ovls; id++) {
		struct drm_plane *plane = omap_plane_init(dev, id, false);

		BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes));
		priv->planes[priv->num_planes++] = plane;
	}

	for (i = 0; i < priv->num_encoders; i++) {
		struct drm_encoder *encoder = priv->encoders[i];
		struct omap_dss_device *dssdev =
					omap_encoder_get_dssdev(encoder);
		struct omap_dss_device *output;

		output = omapdss_find_output_from_display(dssdev);

		/* figure out which crtc's we can connect the encoder to: */
		encoder->possible_crtcs = 0;
		for (id = 0; id < priv->num_crtcs; id++) {
			struct drm_crtc *crtc = priv->crtcs[id];
			enum omap_channel crtc_channel;
			enum omap_dss_output_id supported_outputs;

			crtc_channel = omap_crtc_channel(crtc);
			supported_outputs =
				dss_feat_get_supported_outputs(crtc_channel);

			if (supported_outputs & output->id)
				encoder->possible_crtcs |= (1 << id);
		}

		omap_dss_put_device(output);
	}

	DBG("registered %d planes, %d crtcs, %d encoders and %d connectors\n",
		priv->num_planes, priv->num_crtcs, priv->num_encoders,
		priv->num_connectors);

	dev->mode_config.min_width = 32;
	dev->mode_config.min_height = 32;

	/* note: eventually will need some cpu_is_omapXYZ() type stuff here
	 * to fill in these limits properly on different OMAP generations..
	 */
	dev->mode_config.max_width = 2048;
	dev->mode_config.max_height = 2048;

	dev->mode_config.funcs = &omap_mode_config_funcs;

	return 0;
}
示例#3
0
/*
 * Init DSI DPI encoder. 
 * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
 * return pointer of newly allocated DPI encoder, NULL on error
 */
struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
		struct mdfld_dsi_connector *dsi_connector,
		struct panel_funcs *p_funcs)
{
	struct drm_psb_private *dev_priv = dev->dev_private;
	struct mdfld_dsi_dpi_output *dpi_output = NULL;
	struct mdfld_dsi_config *dsi_config;
	struct drm_connector *connector = NULL;
	struct drm_encoder *encoder = NULL;
	struct drm_display_mode *fixed_mode = NULL;
	int pipe;
	int ret;

	PSB_DEBUG_ENTRY("[DISPLAY] %s\n", __func__);

	if (!dsi_connector || !p_funcs) {
		DRM_ERROR("Invalid parameters\n");
		return NULL;
	}
	dsi_config = mdfld_dsi_get_config(dsi_connector);
	pipe = dsi_connector->pipe;

	/*detect panel connection stauts*/
	if (p_funcs->detect) {
		ret = p_funcs->detect(dsi_config);
		if (ret) {
			DRM_INFO("Detecting Panel %d, Not connected\n", pipe);
			dsi_connector->status = connector_status_disconnected;
		} else {
			PSB_DEBUG_ENTRY("Panel %d is connected\n", pipe);
			dsi_connector->status = connector_status_connected;
		}

		if (dsi_connector->status == connector_status_disconnected &&
				pipe == 0) {
			DRM_ERROR("Primary panel disconnected\n");
			return NULL;
		}
	} else {
		/*use the default config*/
		if (pipe == 0)
			dsi_connector->status = connector_status_connected;
		else
			dsi_connector->status = connector_status_disconnected;
	}
	/*init DSI controller*/
	if (p_funcs->dsi_controller_init)
		p_funcs->dsi_controller_init(dsi_config);
	/**
	 * TODO: can we keep these code out of display driver as
	 * it will make display driver hard to be maintained
	 */
	if (dsi_connector->status == connector_status_connected) {
		if (pipe == 0)
			dev_priv->panel_desc |= DISPLAY_A;
		if (pipe == 2)
			dev_priv->panel_desc |= DISPLAY_C;
	}

	dpi_output = kzalloc(sizeof(struct mdfld_dsi_dpi_output), GFP_KERNEL);
	if (!dpi_output) {
		DRM_ERROR("No memory\n");
		return NULL;
	}

	dpi_output->dev = dev;
	dpi_output->p_funcs = p_funcs;
	dpi_output->first_boot = 1;
	/*get fixed mode*/
	fixed_mode = dsi_config->fixed_mode;

	/*create drm encoder object*/
	connector = &dsi_connector->base.base;
	encoder = &dpi_output->base.base;
	drm_encoder_init(dev,
			encoder,
			&dsi_dpi_generic_encoder_funcs,
			DRM_MODE_ENCODER_DSI);
	drm_encoder_helper_add(encoder,
			&dsi_dpi_generic_encoder_helper_funcs);

	/*attach to given connector*/
	drm_mode_connector_attach_encoder(connector, encoder);
	connector->encoder = encoder;

	/*set possible crtcs and clones*/
	if (dsi_connector->pipe) {
		encoder->possible_crtcs = (1 << 2);
		encoder->possible_clones = (1 << 1);
	} else {
		encoder->possible_crtcs = (1 << 0);
		encoder->possible_clones = (1 << 0);
	}

	dev_priv->dsr_fb_update = 0;
	dev_priv->b_dsr_enable = false;
	dev_priv->exit_idle = NULL;
#if defined(CONFIG_MDFLD_DSI_DPU) || defined(CONFIG_MDFLD_DSI_DSR)
	dev_priv->b_dsr_enable_config = true;
#endif /*CONFIG_MDFLD_DSI_DSR*/

	PSB_DEBUG_ENTRY("successfully\n");

	return &dpi_output->base;
}
/*
 * Init DSI DPI encoder.
 * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
 * return pointer of newly allocated DPI encoder, NULL on error
 */
struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
				struct mdfld_dsi_connector *dsi_connector,
				const struct panel_funcs *p_funcs)
{
	struct mdfld_dsi_dpi_output *dpi_output = NULL;
	struct mdfld_dsi_config *dsi_config;
	struct drm_connector *connector = NULL;
	struct drm_encoder *encoder = NULL;
	int pipe;
	u32 data;
	int ret;

	pipe = dsi_connector->pipe;

	if (mdfld_get_panel_type(dev, pipe) != TC35876X) {
		dsi_config = mdfld_dsi_get_config(dsi_connector);

		/* panel hard-reset */
		if (p_funcs->reset) {
			ret = p_funcs->reset(pipe);
			if (ret) {
				DRM_ERROR("Panel %d hard-reset failed\n", pipe);
				return NULL;
			}
		}

		/* panel drvIC init */
		if (p_funcs->drv_ic_init)
			p_funcs->drv_ic_init(dsi_config, pipe);

		/* panel power mode detect */
		ret = mdfld_dsi_get_power_mode(dsi_config, &data, false);
		if (ret) {
			DRM_ERROR("Panel %d get power mode failed\n", pipe);
			dsi_connector->status = connector_status_disconnected;
		} else {
			DRM_INFO("pipe %d power mode 0x%x\n", pipe, data);
			dsi_connector->status = connector_status_connected;
		}
	}

	dpi_output = kzalloc(sizeof(struct mdfld_dsi_dpi_output), GFP_KERNEL);
	if (!dpi_output) {
		DRM_ERROR("No memory\n");
		return NULL;
	}

	if (dsi_connector->pipe)
		dpi_output->panel_on = 0;
	else
		dpi_output->panel_on = 0;

	dpi_output->dev = dev;
	if (mdfld_get_panel_type(dev, pipe) != TC35876X)
		dpi_output->p_funcs = p_funcs;
	dpi_output->first_boot = 1;

	/*get fixed mode*/
	dsi_config = mdfld_dsi_get_config(dsi_connector);

	/*create drm encoder object*/
	connector = &dsi_connector->base.base;
	encoder = &dpi_output->base.base.base;
	drm_encoder_init(dev,
			encoder,
			p_funcs->encoder_funcs,
			DRM_MODE_ENCODER_LVDS);
	drm_encoder_helper_add(encoder,
				p_funcs->encoder_helper_funcs);

	/*attach to given connector*/
	drm_mode_connector_attach_encoder(connector, encoder);

	/*set possible crtcs and clones*/
	if (dsi_connector->pipe) {
		encoder->possible_crtcs = (1 << 2);
		encoder->possible_clones = (1 << 1);
	} else {
		encoder->possible_crtcs = (1 << 0);
		encoder->possible_clones = (1 << 0);
	}

	dsi_connector->base.encoder = &dpi_output->base.base;

	return &dpi_output->base;
}
示例#5
0
struct drm_connector *sde_connector_init(struct drm_device *dev,
		struct drm_encoder *encoder,
		struct drm_panel *panel,
		void *display,
		const struct sde_connector_ops *ops,
		int connector_poll,
		int connector_type)
{
	struct msm_drm_private *priv;
	struct sde_kms *sde_kms;
	struct sde_kms_info *info;
	struct sde_connector *c_conn = NULL;
	int rc;

	if (!dev || !dev->dev_private || !encoder) {
		SDE_ERROR("invalid argument(s), dev %pK, enc %pK\n",
				dev, encoder);
		return ERR_PTR(-EINVAL);
	}

	priv = dev->dev_private;
	if (!priv->kms) {
		SDE_ERROR("invalid kms reference\n");
		return ERR_PTR(-EINVAL);
	}

	c_conn = kzalloc(sizeof(*c_conn), GFP_KERNEL);
	if (!c_conn) {
		SDE_ERROR("failed to alloc sde connector\n");
		return ERR_PTR(-ENOMEM);
	}

	rc = drm_connector_init(dev,
			&c_conn->base,
			&sde_connector_ops,
			connector_type);
	if (rc)
		goto error_free_conn;

	c_conn->connector_type = connector_type;
	c_conn->encoder = encoder;
	c_conn->panel = panel;
	c_conn->display = display;

	/* cache mmu_id's for later */
	sde_kms = to_sde_kms(priv->kms);
	if (sde_kms->vbif[VBIF_NRT]) {
		c_conn->mmu_id[SDE_IOMMU_DOMAIN_UNSECURE] =
			sde_kms->mmu_id[MSM_SMMU_DOMAIN_NRT_UNSECURE];
		c_conn->mmu_id[SDE_IOMMU_DOMAIN_SECURE] =
			sde_kms->mmu_id[MSM_SMMU_DOMAIN_NRT_SECURE];
	} else {
		c_conn->mmu_id[SDE_IOMMU_DOMAIN_UNSECURE] =
			sde_kms->mmu_id[MSM_SMMU_DOMAIN_UNSECURE];
		c_conn->mmu_id[SDE_IOMMU_DOMAIN_SECURE] =
			sde_kms->mmu_id[MSM_SMMU_DOMAIN_SECURE];
	}

	if (ops)
		c_conn->ops = *ops;

	c_conn->base.helper_private = &sde_connector_helper_ops;
	c_conn->base.polled = connector_poll;
	c_conn->base.interlace_allowed = 0;
	c_conn->base.doublescan_allowed = 0;

	snprintf(c_conn->name,
			SDE_CONNECTOR_NAME_SIZE,
			"conn%u",
			c_conn->base.base.id);

	/*
	 * Initialize retire fence support. Set fence offset to 0 for virtual
	 * connectors so that the fence signals at the end of the current commit
	 * and 1 for others so that the fence signals after one additional
	 * commit.
	 */
	rc = sde_fence_init(dev, &c_conn->retire_fence, c_conn->name,
			connector_type == DRM_MODE_CONNECTOR_VIRTUAL ? 0 : 1);
	if (rc) {
		SDE_ERROR("failed to init fence, %d\n", rc);
		goto error_cleanup_conn;
	}

	rc = drm_connector_register(&c_conn->base);
	if (rc) {
		SDE_ERROR("failed to register drm connector, %d\n", rc);
		goto error_cleanup_fence;
	}

	rc = drm_mode_connector_attach_encoder(&c_conn->base, encoder);
	if (rc) {
		SDE_ERROR("failed to attach encoder to connector, %d\n", rc);
		goto error_unregister_conn;
	}

	/* create properties */
	msm_property_init(&c_conn->property_info, &c_conn->base.base, dev,
			priv->conn_property, c_conn->property_data,
			CONNECTOR_PROP_COUNT, CONNECTOR_PROP_BLOBCOUNT,
			sizeof(struct sde_connector_state));

	if (c_conn->ops.post_init) {
		info = kmalloc(sizeof(*info), GFP_KERNEL);
		if (!info) {
			SDE_ERROR("failed to allocate info buffer\n");
			rc = -ENOMEM;
			goto error_unregister_conn;
		}

		sde_kms_info_reset(info);
		rc = c_conn->ops.post_init(&c_conn->base, info, display);
		if (rc) {
			SDE_ERROR("post-init failed, %d\n", rc);
			kfree(info);
			goto error_unregister_conn;
		}

		msm_property_install_blob(&c_conn->property_info,
				"capabilities",
				DRM_MODE_PROP_IMMUTABLE,
				CONNECTOR_PROP_SDE_INFO);

		msm_property_set_blob(&c_conn->property_info,
				&c_conn->blob_caps,
				SDE_KMS_INFO_DATA(info),
				SDE_KMS_INFO_DATALEN(info),
				CONNECTOR_PROP_SDE_INFO);
		kfree(info);
	}

	msm_property_install_range(&c_conn->property_info, "RETIRE_FENCE",
			0x0, 0, INR_OPEN_MAX, 0, CONNECTOR_PROP_RETIRE_FENCE);

	/* enum/bitmask properties */
	msm_property_install_enum(&c_conn->property_info, "topology_name",
			DRM_MODE_PROP_IMMUTABLE, 0, e_topology_name,
			ARRAY_SIZE(e_topology_name),
			CONNECTOR_PROP_TOPOLOGY_NAME, 0);
	msm_property_install_enum(&c_conn->property_info, "topology_control",
			0, 1, e_topology_control,
			ARRAY_SIZE(e_topology_control),
			CONNECTOR_PROP_TOPOLOGY_CONTROL, 0);

	rc = msm_property_install_get_status(&c_conn->property_info);
	if (rc) {
		SDE_ERROR("failed to create one or more properties\n");
		goto error_destroy_property;
	}

	SDE_DEBUG("connector %d attach encoder %d\n",
			c_conn->base.base.id, encoder->base.id);

	priv->connectors[priv->num_connectors++] = &c_conn->base;

	return &c_conn->base;

error_destroy_property:
	if (c_conn->blob_caps)
		drm_property_unreference_blob(c_conn->blob_caps);
	msm_property_destroy(&c_conn->property_info);
error_unregister_conn:
	drm_connector_unregister(&c_conn->base);
error_cleanup_fence:
	sde_fence_deinit(&c_conn->retire_fence);
error_cleanup_conn:
	drm_connector_cleanup(&c_conn->base);
error_free_conn:
	kfree(c_conn);

	return ERR_PTR(rc);
}
示例#6
0
void cdv_intel_crt_init(struct drm_device *dev,
			struct psb_intel_mode_device *mode_dev)
{

	struct psb_intel_output *psb_intel_output;
	struct drm_connector *connector;
	struct drm_encoder *encoder;

	u32 i2c_reg;

	psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL);
	if (!psb_intel_output)
		return;

	psb_intel_output->mode_dev = mode_dev;
	connector = &psb_intel_output->base;
	drm_connector_init(dev, connector,
		&cdv_intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);

	encoder = &psb_intel_output->enc;
	drm_encoder_init(dev, encoder,
		&cdv_intel_crt_enc_funcs, DRM_MODE_ENCODER_DAC);

	drm_mode_connector_attach_encoder(&psb_intel_output->base,
					  &psb_intel_output->enc);

	/* Set up the DDC bus. */
	i2c_reg = GPIOA;
	/* Remove the following code for CDV */
	/*
	if (dev_priv->crt_ddc_bus != 0)
		i2c_reg = dev_priv->crt_ddc_bus;
	}*/
	psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
						i2c_reg, "CRTDDC_A");
	if (!psb_intel_output->ddc_bus) {
		dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
			   "failed.\n");
		goto failed_ddc;
	}

	psb_intel_output->type = INTEL_OUTPUT_ANALOG;
	/*
	psb_intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT);
	psb_intel_output->crtc_mask = (1 << 0) | (1 << 1);
	*/
	connector->interlace_allowed = 0;
	connector->doublescan_allowed = 0;

	drm_encoder_helper_add(encoder, &cdv_intel_crt_helper_funcs);
	drm_connector_helper_add(connector,
					&cdv_intel_crt_connector_helper_funcs);

	drm_sysfs_connector_add(connector);

	return;
failed_ddc:
	drm_encoder_cleanup(&psb_intel_output->enc);
	drm_connector_cleanup(&psb_intel_output->base);
	kfree(psb_intel_output);
	return;
}
示例#7
0
/*
 * Init DSI DBI encoder.
 * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
 * return pointer of newly allocated DBI encoder, NULL on error
 */
struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev,
				struct mdfld_dsi_connector *dsi_connector,
				struct panel_funcs *p_funcs)
{
	struct drm_psb_private *dev_priv = dev->dev_private;
	struct mdfld_dsi_dbi_output *dbi_output = NULL;
	struct mdfld_dsi_config *dsi_config;
	struct drm_connector *connector = NULL;
	struct drm_encoder *encoder = NULL;
	struct drm_display_mode *fixed_mode = NULL;
	struct psb_gtt *pg = dev_priv ? (&dev_priv->gtt) : NULL;
	struct mdfld_dbi_dpu_info *dpu_info = dev_priv ? (dev_priv->dbi_dpu_info) : NULL;
	struct mdfld_dbi_dsr_info *dsr_info = dev_priv ? (dev_priv->dbi_dsr_info) : NULL;
	u32 data = 0;
	int pipe;
	int ret;

	if (!pg || !dsi_connector || !p_funcs) {
		WARN_ON(1);
		return NULL;
	}

	dsi_config = mdfld_dsi_get_config(dsi_connector);
	pipe = dsi_connector->pipe;

	/*panel hard-reset*/
	if (p_funcs->reset) {
		ret = p_funcs->reset(pipe);
		if (ret) {
			DRM_ERROR("Panel %d hard-reset failed\n", pipe);
			return NULL;
		}
	}
	/* Panel drvIC init */
	if (p_funcs->drv_ic_init)
		p_funcs->drv_ic_init(dsi_config, pipe);

	/* Panel power mode detect */
	ret = mdfld_dsi_get_power_mode(dsi_config,
				       &data,
				       MDFLD_DSI_HS_TRANSMISSION);
	if (ret) {
		DRM_ERROR("Panel %d get power mode failed\n", pipe);
		dsi_connector->status = connector_status_disconnected;
	} else {
		DRM_INFO("pipe %d power mode 0x%x\n", pipe, data);
		dsi_connector->status = connector_status_connected;
	}

	/*TODO: get panel info from DDB*/

	dbi_output = kzalloc(sizeof(struct mdfld_dsi_dbi_output), GFP_KERNEL);
	if (!dbi_output) {
		dev_err(dev->dev, "No memory\n");
		return NULL;
	}

	if (dsi_connector->pipe == 0) {
		dbi_output->channel_num = 0;
		dev_priv->dbi_output = dbi_output;
	} else if (dsi_connector->pipe == 2) {
		dbi_output->channel_num = 1;
		dev_priv->dbi_output2 = dbi_output;
	} else {
		dev_err(dev->dev, "only support 2 DSI outputs\n");
		goto out_err1;
	}

	dbi_output->dev = dev;
	dbi_output->p_funcs = p_funcs;
	fixed_mode = dsi_config->fixed_mode;
	dbi_output->panel_fixed_mode = fixed_mode;

	/* Create drm encoder object */
	connector = &dsi_connector->base.base;
	encoder = &dbi_output->base.base;
	drm_encoder_init(dev,
			encoder,
			p_funcs->encoder_funcs,
			DRM_MODE_ENCODER_MIPI);
	drm_encoder_helper_add(encoder, p_funcs->encoder_helper_funcs);

	/* Attach to given connector */
	drm_mode_connector_attach_encoder(connector, encoder);

	/* Set possible CRTCs and clones */
	if (dsi_connector->pipe) {
		encoder->possible_crtcs = (1 << 2);
		encoder->possible_clones = (1 << 1);
	} else {
		encoder->possible_crtcs = (1 << 0);
		encoder->possible_clones = (1 << 0);
	}

	dev_priv->dsr_fb_update = 0;
	dev_priv->dsr_enable = false;
	dev_priv->exit_idle = mdfld_dsi_dbi_exit_dsr;

	dbi_output->first_boot = true;
	dbi_output->mode_flags = MODE_SETTING_IN_ENCODER;

	/* Add this output to dpu_info if in DPU mode */
	if (dpu_info && dsi_connector->status == connector_status_connected) {
		if (dsi_connector->pipe == 0)
			dpu_info->dbi_outputs[0] = dbi_output;
		else
			dpu_info->dbi_outputs[1] = dbi_output;

		dpu_info->dbi_output_num++;
	} else if (dsi_connector->status == connector_status_connected) {
		/* Add this output to dsr_info if not */
		if (dsi_connector->pipe == 0)
			dsr_info->dbi_outputs[0] = dbi_output;
		else
			dsr_info->dbi_outputs[1] = dbi_output;

		dsr_info->dbi_output_num++;
	}
	return &dbi_output->base;
out_err1:
	kfree(dbi_output);
	return NULL;
}
示例#8
0
static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
{
	struct vmw_screen_object_unit *sou;
	struct drm_device *dev = dev_priv->dev;
	struct drm_connector *connector;
	struct drm_encoder *encoder;
	struct drm_plane *primary, *cursor;
	struct drm_crtc *crtc;
	int ret;

	sou = kzalloc(sizeof(*sou), GFP_KERNEL);
	if (!sou)
		return -ENOMEM;

	sou->base.unit = unit;
	crtc = &sou->base.crtc;
	encoder = &sou->base.encoder;
	connector = &sou->base.connector;
	primary = &sou->base.primary;
	cursor = &sou->base.cursor;

	sou->base.active_implicit = false;
	sou->base.pref_active = (unit == 0);
	sou->base.pref_width = dev_priv->initial_width;
	sou->base.pref_height = dev_priv->initial_height;
	sou->base.pref_mode = NULL;

	/*
	 * Remove this after enabling atomic because property values can
	 * only exist in a state object
	 */
	sou->base.is_implicit = false;

	/* Initialize primary plane */
	vmw_du_plane_reset(primary);

	ret = drm_universal_plane_init(dev, &sou->base.primary,
				       0, &vmw_sou_plane_funcs,
				       vmw_primary_plane_formats,
				       ARRAY_SIZE(vmw_primary_plane_formats),
				       DRM_PLANE_TYPE_PRIMARY, NULL);
	if (ret) {
		DRM_ERROR("Failed to initialize primary plane");
		goto err_free;
	}

	drm_plane_helper_add(primary, &vmw_sou_primary_plane_helper_funcs);

	/* Initialize cursor plane */
	vmw_du_plane_reset(cursor);

	ret = drm_universal_plane_init(dev, &sou->base.cursor,
			0, &vmw_sou_cursor_funcs,
			vmw_cursor_plane_formats,
			ARRAY_SIZE(vmw_cursor_plane_formats),
			DRM_PLANE_TYPE_CURSOR, NULL);
	if (ret) {
		DRM_ERROR("Failed to initialize cursor plane");
		drm_plane_cleanup(&sou->base.primary);
		goto err_free;
	}

	drm_plane_helper_add(cursor, &vmw_sou_cursor_plane_helper_funcs);

	vmw_du_connector_reset(connector);
	ret = drm_connector_init(dev, connector, &vmw_sou_connector_funcs,
				 DRM_MODE_CONNECTOR_VIRTUAL);
	if (ret) {
		DRM_ERROR("Failed to initialize connector\n");
		goto err_free;
	}

	drm_connector_helper_add(connector, &vmw_sou_connector_helper_funcs);
	connector->status = vmw_du_connector_detect(connector, true);
	vmw_connector_state_to_vcs(connector->state)->is_implicit = false;


	ret = drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs,
			       DRM_MODE_ENCODER_VIRTUAL, NULL);
	if (ret) {
		DRM_ERROR("Failed to initialize encoder\n");
		goto err_free_connector;
	}

	(void) drm_mode_connector_attach_encoder(connector, encoder);
	encoder->possible_crtcs = (1 << unit);
	encoder->possible_clones = 0;

	ret = drm_connector_register(connector);
	if (ret) {
		DRM_ERROR("Failed to register connector\n");
		goto err_free_encoder;
	}


	vmw_du_crtc_reset(crtc);
	ret = drm_crtc_init_with_planes(dev, crtc, &sou->base.primary,
					&sou->base.cursor,
					&vmw_screen_object_crtc_funcs, NULL);
	if (ret) {
		DRM_ERROR("Failed to initialize CRTC\n");
		goto err_free_unregister;
	}

	drm_crtc_helper_add(crtc, &vmw_sou_crtc_helper_funcs);

	drm_mode_crtc_set_gamma_size(crtc, 256);

	drm_object_attach_property(&connector->base,
				   dev_priv->hotplug_mode_update_property, 1);
	drm_object_attach_property(&connector->base,
				   dev->mode_config.suggested_x_property, 0);
	drm_object_attach_property(&connector->base,
				   dev->mode_config.suggested_y_property, 0);
	if (dev_priv->implicit_placement_property)
		drm_object_attach_property
			(&connector->base,
			 dev_priv->implicit_placement_property,
			 sou->base.is_implicit);

	return 0;

err_free_unregister:
	drm_connector_unregister(connector);
err_free_encoder:
	drm_encoder_cleanup(encoder);
err_free_connector:
	drm_connector_cleanup(connector);
err_free:
	kfree(sou);
	return ret;
}
示例#9
0
/*
 * Init DSI DPI encoder. 
 * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
 * return pointer of newly allocated DPI encoder, NULL on error
 */ 
struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev, 
				struct mdfld_dsi_connector *dsi_connector,
				struct panel_funcs *p_funcs)
{
	struct mdfld_dsi_dpi_output *dpi_output = NULL;
	struct mdfld_dsi_config *dsi_config;
	struct drm_connector *connector = NULL;
	struct drm_encoder *encoder = NULL;
	struct drm_display_mode *fixed_mode = NULL;
	int pipe;
	u32 data;
	int ret;

	if (!dsi_connector || !p_funcs) {
		WARN_ON(1);
		return NULL;
	}

	dsi_config = mdfld_dsi_get_config(dsi_connector);
	pipe = dsi_connector->pipe;

	/* Panel hard-reset */
	if (p_funcs->reset) {
		ret = p_funcs->reset(pipe);
		if (ret) {
			DRM_ERROR("Panel %d hard-reset failed\n", pipe);
			return NULL;
		}
	}

	/* Panel drvIC init */
	if (p_funcs->drv_ic_init)
		p_funcs->drv_ic_init(dsi_config, pipe);

	/* Panel power mode detect */
	ret = mdfld_dsi_get_power_mode(dsi_config,
					&data,
					MDFLD_DSI_LP_TRANSMISSION);
	if (ret) {
		DRM_ERROR("Panel %d get power mode failed\n", pipe);
		dsi_connector->status = connector_status_disconnected;
	} else {
		DRM_INFO("pipe %d power mode 0x%x\n", pipe, data);
		dsi_connector->status = connector_status_connected;
	}

	dpi_output = kzalloc(sizeof(struct mdfld_dsi_dpi_output), GFP_KERNEL);
	if(!dpi_output) {
		dev_err(dev->dev, "No memory for dsi_dpi_output\n");
		return NULL;
	}

	if(dsi_connector->pipe) 
		dpi_output->panel_on = 0;
	else
		dpi_output->panel_on = 0;
	
	dpi_output->dev = dev;
	dpi_output->p_funcs = p_funcs;
	dpi_output->first_boot = 1;
	
	/* Get fixed mode */
	dsi_config = mdfld_dsi_get_config(dsi_connector);
	fixed_mode = dsi_config->fixed_mode;
	
	/* Create drm encoder object */
	connector = &dsi_connector->base.base;
	encoder = &dpi_output->base.base;
	/*
	 * On existing hardware this will be a panel of some form,
	 * if future devices also have HDMI bridges this will need
	 * revisiting
	 */
	drm_encoder_init(dev,
			encoder,
			p_funcs->encoder_funcs,
			DRM_MODE_ENCODER_LVDS);
	drm_encoder_helper_add(encoder,
				p_funcs->encoder_helper_funcs);
	
	/* Attach to given connector */
	drm_mode_connector_attach_encoder(connector, encoder);
	
	/* Set possible crtcs and clones */
	if(dsi_connector->pipe) {
		encoder->possible_crtcs = (1 << 2);
		encoder->possible_clones = (1 << 1);
	} else {
		encoder->possible_crtcs = (1 << 0);
		encoder->possible_clones = (1 << 0);
	}
	return &dpi_output->base;
}
示例#10
0
/*
 * Init DSI DBI encoder.
 * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
 * return pointer of newly allocated DBI encoder, NULL on error
 */
struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev,
        struct mdfld_dsi_connector *dsi_connector,
        struct panel_funcs *p_funcs)
{
    struct drm_psb_private *dev_priv =
        (struct drm_psb_private *)dev->dev_private;
    struct mdfld_dsi_dbi_output *dbi_output = NULL;
    struct mdfld_dsi_config *dsi_config;
    struct drm_connector *connector = NULL;
    struct drm_encoder *encoder = NULL;
    struct drm_display_mode *fixed_mode = NULL;
    struct psb_gtt *pg = dev_priv ? (dev_priv->pg) : NULL;

#ifdef CONFIG_MDFLD_DSI_DPU
    struct mdfld_dbi_dpu_info *dpu_info =
        dev_priv ? (dev_priv->dbi_dpu_info) : NULL;
#else
    struct mdfld_dbi_dsr_info *dsr_info =
        dev_priv ? (dev_priv->dbi_dsr_info) : NULL;
#endif
    int pipe;
    int ret;

    PSB_DEBUG_ENTRY("\n");

    if (!pg || !dsi_connector || !p_funcs) {
        DRM_ERROR("Invalid parameters\n");
        return NULL;
    }

    dsi_config = mdfld_dsi_get_config(dsi_connector);
    pipe = dsi_connector->pipe;

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

    /*detect panel connection stauts*/
    if (p_funcs->detect) {
        ret = p_funcs->detect(dsi_config);
        if (ret) {
            DRM_INFO("Fail to detect Panel on pipe %d\n", pipe);
            dsi_connector->status =
                connector_status_disconnected;
        } else {
            DRM_INFO("Panel on pipe %d is connected\n", pipe);
            dsi_connector->status =
                connector_status_connected;
        }
    } else {
        /*use the default config*/
        if (pipe == 0)
            dsi_connector->status =
                connector_status_connected;
        else
            dsi_connector->status =
                connector_status_disconnected;
    }

    /*init DSI controller*/
    if (p_funcs->dsi_controller_init)
        p_funcs->dsi_controller_init(dsi_config);

    if (dsi_connector->status == connector_status_connected) {
        if (pipe == 0)
            dev_priv->panel_desc |= DISPLAY_A;
        if (pipe == 2)
            dev_priv->panel_desc |= DISPLAY_C;
    }

    /* TODO: get panel info from DDB */
    dbi_output = kzalloc(sizeof(struct mdfld_dsi_dbi_output), GFP_KERNEL);
    if (!dbi_output) {
        DRM_ERROR("No memory\n");
        return NULL;
    }

    if (dsi_connector->pipe == 0) {
        dbi_output->channel_num = 0;
        dev_priv->dbi_output = dbi_output;
    } else if (dsi_connector->pipe == 2) {
        dbi_output->channel_num = 1;
        dev_priv->dbi_output2 = dbi_output;
    } else {
        DRM_ERROR("only support 2 DSI outputs\n");
        goto out_err1;
    }

    dbi_output->dev = dev;
    dbi_output->p_funcs = p_funcs;

    /*get fixed mode*/
    fixed_mode = dsi_config->fixed_mode;

    dbi_output->panel_fixed_mode = fixed_mode;

    /*create drm encoder object*/
    connector = &dsi_connector->base.base;
    encoder = &dbi_output->base.base;
    drm_encoder_init(dev,
                     encoder,
                     &dsi_dbi_generic_encoder_funcs,
                     DRM_MODE_ENCODER_DSI);
    drm_encoder_helper_add(encoder,
                           &dsi_dbi_generic_encoder_helper_funcs);

    /*attach to given connector*/
    drm_mode_connector_attach_encoder(connector, encoder);
    connector->encoder = encoder;

    /*set possible crtcs and clones*/
    if (dsi_connector->pipe) {
        encoder->possible_crtcs = (1 << 2);
        encoder->possible_clones = (1 << 1);
    } else {
        encoder->possible_crtcs = (1 << 0);
        encoder->possible_clones = (1 << 0);
    }

    dev_priv->dsr_fb_update = 0;
    dev_priv->b_dsr_enable = false;
    dev_priv->exit_idle = mdfld_dsi_dbi_exit_dsr;
    dev_priv->b_async_flip_enable = false;

#if defined(CONFIG_MDFLD_DSI_DPU) || defined(CONFIG_MDFLD_DSI_DSR)
    dev_priv->b_dsr_enable_config = true;
#endif /*CONFIG_MDFLD_DSI_DSR*/

    dbi_output->first_boot = true;
    dbi_output->mode_flags = MODE_SETTING_IN_ENCODER;

#ifdef CONFIG_MDFLD_DSI_DPU
    /*add this output to dpu_info*/

    if (dsi_connector->status == connector_status_connected) {
        if (dsi_connector->pipe == 0)
            dpu_info->dbi_outputs[0] = dbi_output;
        else
            dpu_info->dbi_outputs[1] = dbi_output;

        dpu_info->dbi_output_num++;
    }

#else /*CONFIG_MDFLD_DSI_DPU*/
    if (dsi_connector->status == connector_status_connected) {
        /*add this output to dsr_info*/
        if (dsi_connector->pipe == 0)
            dsr_info->dbi_outputs[0] = dbi_output;
        else
            dsr_info->dbi_outputs[1] = dbi_output;

        dsr_info->dbi_output_num++;
    }
#endif

    PSB_DEBUG_ENTRY("successfully\n");

    return &dbi_output->base;

out_err1:
    kfree(dbi_output);

    return NULL;
}
/*
 * Init DSI DPI encoder.
 * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
 * return pointer of newly allocated DPI encoder, NULL on error
 */
struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
        struct mdfld_dsi_connector *dsi_connector)
{
    struct drm_psb_private *dev_priv = dev->dev_private;
    struct mdfld_dsi_dpi_output *dpi_output = NULL;
    struct mdfld_dsi_config *dsi_config;
    struct drm_connector *connector = NULL;
    struct drm_encoder *encoder = NULL;
    int pipe;

    PSB_DEBUG_ENTRY("\n");

    if (!dsi_connector) {
        DRM_ERROR("Invalid parameters\n");
        return NULL;
    }
    dsi_config = mdfld_dsi_get_config(dsi_connector);
    pipe = dsi_connector->pipe;
    dsi_connector->status = connector_status_connected;

    dpi_output = kzalloc(sizeof(struct mdfld_dsi_dpi_output), GFP_KERNEL);
    if (!dpi_output) {
        DRM_ERROR("No memory\n");
        return NULL;
    }

    dpi_output->dev = dev;
    dpi_output->first_boot = 1;

    if (pipe)
        dev_priv->dpi_output2 = dpi_output;
    else
        dev_priv->dpi_output = dpi_output;

    /*create drm encoder object*/
    connector = &dsi_connector->base.base;
    encoder = &dpi_output->base.base;
    drm_encoder_init(dev,
                     encoder,
                     &dsi_dpi_generic_encoder_funcs,
                     DRM_MODE_ENCODER_DSI);
    drm_encoder_helper_add(encoder,
                           &dsi_dpi_generic_encoder_helper_funcs);

    /*attach to given connector*/
    drm_mode_connector_attach_encoder(connector, encoder);
    connector->encoder = encoder;

    /*set possible crtcs and clones*/
    if(dsi_connector->pipe) {
        encoder->possible_crtcs = (1 << 2);
        encoder->possible_clones = (1 << 1);
    } else {
        encoder->possible_crtcs = (1 << 0);
        encoder->possible_clones = (1 << 0);
    }

    dev_priv->dsr_fb_update = 0;
    dev_priv->b_dsr_enable = false;
    dev_priv->exit_idle = mdfld_dsi_dpi_exit_idle;
#if defined(CONFIG_MDFLD_DSI_DPU) || defined(CONFIG_MDFLD_DSI_DSR)
    dev_priv->b_dsr_enable_config = true;
#endif /*CONFIG_MDFLD_DSI_DSR*/

    encoder_shutdown = encoder;

    PSB_DEBUG_ENTRY("successfully\n");

    return &dpi_output->base;
}
static int omap_modeset_init(struct drm_device *dev)
{
	const struct omap_gpu_platform_data *pdata = dev->dev->platform_data;
	struct omap_gpu_private *priv = dev->dev_private;
	struct omap_dss_device *dssdev = NULL;
	int i, j;
	unsigned int connected_connectors = 0;

	/* create encoders for each manager */
	int create_encoder(int i) {
		struct omap_overlay_manager *mgr = omap_dss_get_overlay_manager(i);
		struct drm_encoder *encoder = omap_encoder_init(dev, mgr);

		if (!encoder) {
			dev_err(dev->dev, "could not create encoder\n");
			return -ENOMEM;
		}

		priv->encoders[priv->num_encoders++] = encoder;

		return 0;
	}

	/* create connectors for each display device */
	int create_connector(struct omap_dss_device *dssdev) {
		static struct notifier_block *notifier;
		struct drm_connector *connector;

		if (!dssdev->driver) {
			dev_warn(dev->dev, "%s has no driver.. skipping it\n",
					dssdev->name);
			return 0;
		}

		if (!(dssdev->driver->get_timings || dssdev->driver->get_edid)) {
			dev_warn(dev->dev, "%s driver does not support "
					"get_timings or get_edid.. skipping it!\n",
					dssdev->name);
			return 0;
		}

		connector = omap_connector_init(dev,
				get_connector_type(dssdev->type), dssdev);

		if (!connector) {
			dev_err(dev->dev, "could not create connector\n");
			return -ENOMEM;
		}

		/* track what is already connected.. rather than looping thru all
		 * connectors twice later, first for connected then for remainder
		 * (which could be a race condition if connected status changes)
		 */
		if (omap_connector_detect (connector) == connector_status_connected) {
			connected_connectors |= (1 << priv->num_connectors);
		}

		priv->connectors[priv->num_connectors++] = connector;

		notifier = kzalloc(sizeof(struct notifier_block), GFP_KERNEL);
		notifier->notifier_call = omap_gpu_notifier;
		omap_dss_add_notify(dssdev, notifier);

		for (j = 0; j < priv->num_encoders; j++) {
			struct omap_overlay_manager *mgr =
					omap_encoder_get_manager(priv->encoders[j]);
			if (mgr->device == dssdev) {
				drm_mode_connector_attach_encoder(connector,
						priv->encoders[j]);
			}
		}

		return 0;
	}

	/* create up to max_overlays CRTCs mapping to overlays.. by default,
	 * connect the overlays to different managers/encoders, giving priority
	 * to encoders connected to connectors with a detected connection
	 */
	int create_crtc(int i) {
		struct omap_overlay *ovl = omap_dss_get_overlay(i);
		struct omap_overlay_manager *mgr = NULL;
		struct drm_crtc *crtc;

		if (ovl->manager) {
			DBG("disconnecting %s from %s", ovl->name, ovl->manager->name);
			ovl->unset_manager(ovl);
		}

		/* find next best connector... ones with detected connection first
		 */
		while (j < priv->num_connectors && !mgr) {
			if (connected_connectors & (1 << j)) {
				struct drm_encoder * encoder =
						omap_connector_attached_encoder (priv->connectors[j]);
				if (encoder) {
					mgr = omap_encoder_get_manager (encoder);
				}
			}
			j++;
		}

		/* if we couldn't find another connected connector, lets start looking
		 * at the unconnected connectors:
		 */
		while (j < 2 * priv->num_connectors && !mgr) {
			int idx = j - priv->num_connectors;
			if (!(connected_connectors & (1 << idx))) {
				struct drm_encoder * encoder =
						omap_connector_attached_encoder (priv->connectors[idx]);
				if (encoder) {
					mgr = omap_encoder_get_manager (encoder);
				}
			}
			j++;
		}

		if (mgr) {
			DBG("connecting %s to %s", ovl->name, mgr->name);
			ovl->set_manager(ovl, mgr);
		}

		crtc = omap_crtc_init(dev, ovl);

		if (!crtc) {
			dev_err(dev->dev, "could not create CRTC\n");
			return -ENOMEM;
		}

		priv->crtcs[priv->num_crtcs++] = crtc;

		return 0;
	}

	drm_mode_config_init(dev);

	if (pdata) {
		/* if platform data is provided by the board file, use it to control
		 * which overlays, managers, and devices we own.
		 */
		for (i = 0; i < pdata->mgr_cnt; i++) {
			if (create_encoder(pdata->mgr_ids[i])) {
				goto fail;
			}
		}

		for (i = 0; i < pdata->dev_cnt; i++) {
			int m(struct omap_dss_device *dssdev, void *data) {
				return ! strcmp(dssdev->name, data);
			}
			struct omap_dss_device *dssdev =
					omap_dss_find_device((void *)pdata->dev_names[i], m);
			if (!dssdev) {
				dev_warn(dev->dev, "no such dssdev: %s\n",
						pdata->dev_names[i]);
				continue;
			}
			if (create_connector(dssdev)) {
				goto fail;
			}
		}

		j = 0;
		for (i = 0; i < pdata->ovl_cnt; i++) {
			if (create_crtc(pdata->ovl_ids[i])) {
				goto fail;
			}
		}
	} else {
示例#13
0
void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_connector *connector;
	struct intel_output *intel_output;
	struct intel_hdmi_priv *hdmi_priv;

	if (!hdmi_is_present_in_vbt(dev, sdvox_reg)) {
		DRM_DEBUG_KMS("HDMI is not present. Ignored it \n");
		return;
	}
	intel_output = kcalloc(sizeof(struct intel_output) +
			       sizeof(struct intel_hdmi_priv), 1, GFP_KERNEL);
	if (!intel_output)
		return;
	hdmi_priv = (struct intel_hdmi_priv *)(intel_output + 1);

	connector = &intel_output->base;
	drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,
			   DRM_MODE_CONNECTOR_HDMIA);
	drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs);

	intel_output->type = INTEL_OUTPUT_HDMI;

	connector->interlace_allowed = 0;
	connector->doublescan_allowed = 0;
	intel_output->crtc_mask = (1 << 0) | (1 << 1);

	/* Set up the DDC bus. */
	if (sdvox_reg == SDVOB) {
		intel_output->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
		intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB");
		dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
	} else if (sdvox_reg == SDVOC) {
		intel_output->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
		intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC");
		dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
	} else if (sdvox_reg == HDMIB) {
		intel_output->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
		intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOE,
								"HDMIB");
		dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
	} else if (sdvox_reg == HDMIC) {
		intel_output->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
		intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOD,
								"HDMIC");
		dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
	} else if (sdvox_reg == HDMID) {
		intel_output->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
		intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOF,
								"HDMID");
		dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
	}
	if (!intel_output->ddc_bus)
		goto err_connector;

	hdmi_priv->sdvox_reg = sdvox_reg;
	intel_output->dev_priv = hdmi_priv;

	drm_encoder_init(dev, &intel_output->enc, &intel_hdmi_enc_funcs,
			 DRM_MODE_ENCODER_TMDS);
	drm_encoder_helper_add(&intel_output->enc, &intel_hdmi_helper_funcs);

	drm_mode_connector_attach_encoder(&intel_output->base,
					  &intel_output->enc);
	drm_sysfs_connector_add(connector);

	/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
	 * 0xd.  Failure to do so will result in spurious interrupts being
	 * generated on the port when a cable is not attached.
	 */
	if (IS_G4X(dev) && !IS_GM45(dev)) {
		u32 temp = I915_READ(PEG_BAND_GAP_DATA);
		I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
	}

	return;

err_connector:
	drm_connector_cleanup(connector);
	kfree(intel_output);

	return;
}
示例#14
0
struct lcd_link *jzdrm_lcd_register(struct drm_device *dev)
{
	struct platform_device *pdev = dev->platformdev;
	struct jzfb_platform_data *pdata = pdev->dev.platform_data;
	struct lcd_link *lcd_link;
	struct drm_encoder *encoder;
	struct drm_connector *connector;
	struct lcd_manager *subdev;
	int ret;

	lcd_link = kzalloc(sizeof(struct lcd_link), GFP_KERNEL);
	if (!lcd_link)
		return NULL;

	lcd_link->drm = dev;
	encoder = &lcd_link->encoder;
	connector = &lcd_link->connector;

#ifdef CONFIG_LCD_BYD_8991FTGF
	subdev = rgb_lcd_register(lcd_link);
#endif

#ifdef CONFIG_LCD_X163
	subdev = mipi_dsi_lcd_register(lcd_link);
#endif
	if (!subdev)
		return NULL;

	connector->funcs = subdev->jzdrm_connector_funcs;
	encoder->funcs = subdev->jzdrm_encoder_funcs;

	encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
	connector->connector_type = DRM_MODE_CONNECTOR_DisplayPort;
	encoder->possible_crtcs = 1;

	drm_encoder_helper_add(encoder,
			      subdev->jzdrm_encoder_helper_funcs);

	drm_encoder_init(dev, encoder,
			encoder->funcs,
			encoder->encoder_type);

	drm_connector_helper_add(connector,
			subdev->jzdrm_connector_helper_funcs);

	drm_connector_init(dev, connector,
			connector->funcs,
			connector->connector_type);

	connector->encoder = encoder;
	connector->dpms = subdev->dpms;

	ret = drm_sysfs_connector_add(connector);
	if (ret) {
		dev_err(dev->dev,
			"[CONNECTOR:%d] drm_connector_register failed: %d\n",
			connector->base.id, ret);
		return NULL;
	}

	drm_mode_connector_attach_encoder(connector, encoder);

	lcd_link->dpms = subdev->dpms;

	return lcd_link;
}
示例#15
0
static int
armada_drm_conn_slave_create(struct drm_connector *conn, const void *data)
{
	const struct armada_drm_slave_config *config = data;
	struct drm_encoder_slave *slave;
	struct i2c_adapter *adap;
	int ret;

	conn->interlace_allowed = config->interlace_allowed;
	conn->doublescan_allowed = config->doublescan_allowed;
	conn->polled = config->polled;

	drm_connector_helper_add(conn, &armada_drm_slave_helper_funcs);

	slave = kzalloc(sizeof(*slave), GFP_KERNEL);
	if (!slave)
		return -ENOMEM;

	slave->base.possible_crtcs = config->crtcs;

	adap = i2c_get_adapter(config->i2c_adapter_id);
	if (!adap) {
		kfree(slave);
		return -EPROBE_DEFER;
	}

	ret = drm_encoder_init(conn->dev, &slave->base,
			       &armada_drm_slave_encoder_funcs,
			       DRM_MODE_ENCODER_TMDS);
	if (ret) {
		DRM_ERROR("unable to init encoder\n");
		i2c_put_adapter(adap);
		kfree(slave);
		return ret;
	}

	ret = drm_i2c_encoder_init(conn->dev, slave, adap, &config->info);
	i2c_put_adapter(adap);
	if (ret) {
		DRM_ERROR("unable to init encoder slave\n");
		armada_drm_slave_destroy(&slave->base);
		return ret;
	}

	drm_encoder_helper_add(&slave->base, &drm_slave_encoder_helpers);

	ret = slave->slave_funcs->create_resources(&slave->base, conn);
	if (ret) {
		armada_drm_slave_destroy(&slave->base);
		return ret;
	}

	ret = drm_mode_connector_attach_encoder(conn, &slave->base);
	if (ret) {
		armada_drm_slave_destroy(&slave->base);
		return ret;
	}

	conn->encoder = &slave->base;

	return ret;
}
示例#16
0
文件: ptn3460.c 项目: 24hours/linux
int ptn3460_init(struct drm_device *dev, struct drm_encoder *encoder,
		struct i2c_client *client, struct device_node *node)
{
	int ret;
	struct drm_bridge *bridge;
	struct ptn3460_bridge *ptn_bridge;

	bridge = devm_kzalloc(dev->dev, sizeof(*bridge), GFP_KERNEL);
	if (!bridge) {
		DRM_ERROR("Failed to allocate drm bridge\n");
		return -ENOMEM;
	}

	ptn_bridge = devm_kzalloc(dev->dev, sizeof(*ptn_bridge), GFP_KERNEL);
	if (!ptn_bridge) {
		DRM_ERROR("Failed to allocate ptn bridge\n");
		return -ENOMEM;
	}

	ptn_bridge->client = client;
	ptn_bridge->encoder = encoder;
	ptn_bridge->bridge = bridge;
	ptn_bridge->gpio_pd_n = of_get_named_gpio(node, "powerdown-gpio", 0);
	if (gpio_is_valid(ptn_bridge->gpio_pd_n)) {
		ret = gpio_request_one(ptn_bridge->gpio_pd_n,
				GPIOF_OUT_INIT_HIGH, "PTN3460_PD_N");
		if (ret) {
			DRM_ERROR("Request powerdown-gpio failed (%d)\n", ret);
			return ret;
		}
	}

	ptn_bridge->gpio_rst_n = of_get_named_gpio(node, "reset-gpio", 0);
	if (gpio_is_valid(ptn_bridge->gpio_rst_n)) {
		/*
		 * Request the reset pin low to avoid the bridge being
		 * initialized prematurely
		 */
		ret = gpio_request_one(ptn_bridge->gpio_rst_n,
				GPIOF_OUT_INIT_LOW, "PTN3460_RST_N");
		if (ret) {
			DRM_ERROR("Request reset-gpio failed (%d)\n", ret);
			gpio_free(ptn_bridge->gpio_pd_n);
			return ret;
		}
	}

	ret = of_property_read_u32(node, "edid-emulation",
			&ptn_bridge->edid_emulation);
	if (ret) {
		DRM_ERROR("Can't read edid emulation value\n");
		goto err;
	}

	ret = drm_bridge_init(dev, bridge, &ptn3460_bridge_funcs);
	if (ret) {
		DRM_ERROR("Failed to initialize bridge with drm\n");
		goto err;
	}

	bridge->driver_private = ptn_bridge;
	encoder->bridge = bridge;

	ret = drm_connector_init(dev, &ptn_bridge->connector,
			&ptn3460_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
	if (ret) {
		DRM_ERROR("Failed to initialize connector with drm\n");
		goto err;
	}
	drm_connector_helper_add(&ptn_bridge->connector,
			&ptn3460_connector_helper_funcs);
	drm_sysfs_connector_add(&ptn_bridge->connector);
	drm_mode_connector_attach_encoder(&ptn_bridge->connector, encoder);

	return 0;

err:
	if (gpio_is_valid(ptn_bridge->gpio_pd_n))
		gpio_free(ptn_bridge->gpio_pd_n);
	if (gpio_is_valid(ptn_bridge->gpio_rst_n))
		gpio_free(ptn_bridge->gpio_rst_n);
	return ret;
}
示例#17
0
static int omap_modeset_init(struct drm_device *dev)
{
	struct omap_drm_private *priv = dev->dev_private;
	struct omap_dss_device *dssdev = NULL;
	int num_ovls = dss_feat_get_num_ovls();
	int id;

	drm_mode_config_init(dev);

	omap_drm_irq_install(dev);

	/*
	 * Create private planes and CRTCs for the last NUM_CRTCs overlay
	 * plus manager:
	 */
	for (id = 0; id < min(num_crtc, num_ovls); id++) {
		struct drm_plane *plane;
		struct drm_crtc *crtc;

		plane = omap_plane_init(dev, id, true);
		crtc = omap_crtc_init(dev, plane, pipe2chan(id), id);

		BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs));
		priv->crtcs[id] = crtc;
		priv->num_crtcs++;

		priv->planes[id] = plane;
		priv->num_planes++;
	}

	/*
	 * Create normal planes for the remaining overlays:
	 */
	for (; id < num_ovls; id++) {
		struct drm_plane *plane = omap_plane_init(dev, id, false);

		BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes));
		priv->planes[priv->num_planes++] = plane;
	}

	for_each_dss_dev(dssdev) {
		struct drm_connector *connector;
		struct drm_encoder *encoder;

		if (!dssdev->driver) {
			dev_warn(dev->dev, "%s has no driver.. skipping it\n",
					dssdev->name);
			return 0;
		}

		if (!(dssdev->driver->get_timings ||
					dssdev->driver->read_edid)) {
			dev_warn(dev->dev, "%s driver does not support "
				"get_timings or read_edid.. skipping it!\n",
				dssdev->name);
			return 0;
		}

		encoder = omap_encoder_init(dev, dssdev);

		if (!encoder) {
			dev_err(dev->dev, "could not create encoder: %s\n",
					dssdev->name);
			return -ENOMEM;
		}

		connector = omap_connector_init(dev,
				get_connector_type(dssdev), dssdev, encoder);

		if (!connector) {
			dev_err(dev->dev, "could not create connector: %s\n",
					dssdev->name);
			return -ENOMEM;
		}

		BUG_ON(priv->num_encoders >= ARRAY_SIZE(priv->encoders));
		BUG_ON(priv->num_connectors >= ARRAY_SIZE(priv->connectors));

		priv->encoders[priv->num_encoders++] = encoder;
		priv->connectors[priv->num_connectors++] = connector;

		drm_mode_connector_attach_encoder(connector, encoder);

		/* figure out which crtc's we can connect the encoder to: */
		encoder->possible_crtcs = 0;
		for (id = 0; id < priv->num_crtcs; id++) {
			enum omap_dss_output_id supported_outputs =
					dss_feat_get_supported_outputs(pipe2chan(id));
			if (supported_outputs & dssdev->output->id)
				encoder->possible_crtcs |= (1 << id);
		}
	}

	dev->mode_config.min_width = 32;
	dev->mode_config.min_height = 32;

	/* note: eventually will need some cpu_is_omapXYZ() type stuff here
	 * to fill in these limits properly on different OMAP generations..
	 */
	dev->mode_config.max_width = 2048;
	dev->mode_config.max_height = 2048;

	dev->mode_config.funcs = &omap_mode_config_funcs;

	return 0;
}