Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 66264ba8 authored by Alex Deucher's avatar Alex Deucher
Browse files

drm/amdgpu: simplify encoder and connector setup (v2)



No need to emulate all of the stuff for real hw.

v2: warning fix

Reviewed-By: default avatarEmily Deng <Emily.Deng@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 9405e47d
Loading
Loading
Loading
Loading
+0 −93
Original line number Diff line number Diff line
@@ -1517,88 +1517,6 @@ static const struct drm_connector_funcs amdgpu_connector_edp_funcs = {
	.force = amdgpu_connector_dvi_force,
};

static struct drm_encoder *
amdgpu_connector_virtual_encoder(struct drm_connector *connector)
{
	int enc_id = connector->encoder_ids[0];
	struct drm_encoder *encoder;
	int i;
	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
		if (connector->encoder_ids[i] == 0)
			break;

		encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
		if (!encoder)
			continue;

		if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
			return encoder;
	}

	/* pick the first one */
	if (enc_id)
		return drm_encoder_find(connector->dev, enc_id);
	return NULL;
}

static int amdgpu_connector_virtual_get_modes(struct drm_connector *connector)
{
	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);

	if (encoder) {
		amdgpu_connector_add_common_modes(encoder, connector);
	}

	return 0;
}

static int amdgpu_connector_virtual_mode_valid(struct drm_connector *connector,
					   struct drm_display_mode *mode)
{
	return MODE_OK;
}

static int
amdgpu_connector_virtual_dpms(struct drm_connector *connector, int mode)
{
	return 0;
}

static enum drm_connector_status

amdgpu_connector_virtual_detect(struct drm_connector *connector, bool force)
{
	return connector_status_connected;
}

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

static void amdgpu_connector_virtual_force(struct drm_connector *connector)
{
	return;
}

static const struct drm_connector_helper_funcs amdgpu_connector_virtual_helper_funcs = {
	.get_modes = amdgpu_connector_virtual_get_modes,
	.mode_valid = amdgpu_connector_virtual_mode_valid,
	.best_encoder = amdgpu_connector_virtual_encoder,
};

static const struct drm_connector_funcs amdgpu_connector_virtual_funcs = {
	.dpms = amdgpu_connector_virtual_dpms,
	.detect = amdgpu_connector_virtual_detect,
	.fill_modes = drm_helper_probe_single_connector_modes,
	.set_property = amdgpu_connector_virtual_set_property,
	.destroy = amdgpu_connector_destroy,
	.force = amdgpu_connector_virtual_force,
};

void
amdgpu_connector_add(struct amdgpu_device *adev,
		      uint32_t connector_id,
@@ -1983,17 +1901,6 @@ amdgpu_connector_add(struct amdgpu_device *adev,
			connector->interlace_allowed = false;
			connector->doublescan_allowed = false;
			break;
		case DRM_MODE_CONNECTOR_VIRTUAL:
			amdgpu_dig_connector = kzalloc(sizeof(struct amdgpu_connector_atom_dig), GFP_KERNEL);
			if (!amdgpu_dig_connector)
				goto failed;
			amdgpu_connector->con_priv = amdgpu_dig_connector;
			drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_virtual_funcs, connector_type);
			drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_virtual_helper_funcs);
			subpixel_order = SubPixelHorizontalRGB;
			connector->interlace_allowed = false;
			connector->doublescan_allowed = false;
			break;
		}
	}

+144 −87
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@

static void dce_virtual_set_display_funcs(struct amdgpu_device *adev);
static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev);
static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
					      int index);

/**
 * dce_virtual_vblank_wait - vblank wait asic callback.
@@ -274,24 +276,6 @@ static bool dce_virtual_crtc_mode_fixup(struct drm_crtc *crtc,
				     const struct drm_display_mode *mode,
				     struct drm_display_mode *adjusted_mode)
{
	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
	struct drm_device *dev = crtc->dev;
	struct drm_encoder *encoder;

	/* assign the encoder to the amdgpu crtc to avoid repeated lookups later */
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
		if (encoder->crtc == crtc) {
			amdgpu_crtc->encoder = encoder;
			amdgpu_crtc->connector = amdgpu_get_connector_for_encoder(encoder);
			break;
		}
	}
	if ((amdgpu_crtc->encoder == NULL) || (amdgpu_crtc->connector == NULL)) {
		amdgpu_crtc->encoder = NULL;
		amdgpu_crtc->connector = NULL;
		return false;
	}

	return true;
}

@@ -370,38 +354,120 @@ static int dce_virtual_early_init(void *handle)
	return 0;
}

static bool dce_virtual_get_connector_info(struct amdgpu_device *adev)
static struct drm_encoder *
dce_virtual_encoder(struct drm_connector *connector)
{
	struct amdgpu_i2c_bus_rec ddc_bus;
	struct amdgpu_router router;
	struct amdgpu_hpd hpd;
	int enc_id = connector->encoder_ids[0];
	struct drm_encoder *encoder;
	int i;

	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
		if (connector->encoder_ids[i] == 0)
			break;

	/* look up gpio for ddc, hpd */
	ddc_bus.valid = false;
	hpd.hpd = AMDGPU_HPD_NONE;
	/* needed for aux chan transactions */
	ddc_bus.hpd = hpd.hpd;
		encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
		if (!encoder)
			continue;

		if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
			return encoder;
	}

	/* pick the first one */
	if (enc_id)
		return drm_encoder_find(connector->dev, enc_id);
	return NULL;
}

static int dce_virtual_get_modes(struct drm_connector *connector)
{
	struct drm_device *dev = connector->dev;
	struct drm_display_mode *mode = NULL;
	unsigned i;
	static const struct mode_size {
		int w;
		int h;
	} common_modes[17] = {
		{ 640,  480},
		{ 720,  480},
		{ 800,  600},
		{ 848,  480},
		{1024,  768},
		{1152,  768},
		{1280,  720},
		{1280,  800},
		{1280,  854},
		{1280,  960},
		{1280, 1024},
		{1440,  900},
		{1400, 1050},
		{1680, 1050},
		{1600, 1200},
		{1920, 1080},
		{1920, 1200}
	};

	memset(&router, 0, sizeof(router));
	router.ddc_valid = false;
	router.cd_valid = false;
	amdgpu_display_add_connector(adev,
				      0,
				      ATOM_DEVICE_CRT1_SUPPORT,
				      DRM_MODE_CONNECTOR_VIRTUAL, &ddc_bus,
				      CONNECTOR_OBJECT_ID_VIRTUAL,
				      &hpd,
				      &router);
	for (i = 0; i < 17; i++) {
		mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
		drm_mode_probed_add(connector, mode);
	}

	amdgpu_display_add_encoder(adev, ENCODER_VIRTUAL_ENUM_VIRTUAL,
							ATOM_DEVICE_CRT1_SUPPORT,
							0);
	return 0;
}

	amdgpu_link_encoder_connector(adev->ddev);
static int dce_virtual_mode_valid(struct drm_connector *connector,
				  struct drm_display_mode *mode)
{
	return MODE_OK;
}

	return true;
static int
dce_virtual_dpms(struct drm_connector *connector, int mode)
{
	return 0;
}

static enum drm_connector_status
dce_virtual_detect(struct drm_connector *connector, bool force)
{
	return connector_status_connected;
}

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

static void dce_virtual_destroy(struct drm_connector *connector)
{
	drm_connector_unregister(connector);
	drm_connector_cleanup(connector);
	kfree(connector);
}

static void dce_virtual_force(struct drm_connector *connector)
{
	return;
}

static const struct drm_connector_helper_funcs dce_virtual_connector_helper_funcs = {
	.get_modes = dce_virtual_get_modes,
	.mode_valid = dce_virtual_mode_valid,
	.best_encoder = dce_virtual_encoder,
};

static const struct drm_connector_funcs dce_virtual_connector_funcs = {
	.dpms = dce_virtual_dpms,
	.detect = dce_virtual_detect,
	.fill_modes = drm_helper_probe_single_connector_modes,
	.set_property = dce_virtual_set_property,
	.destroy = dce_virtual_destroy,
	.force = dce_virtual_force,
};

static int dce_virtual_sw_init(void *handle)
{
	int r, i;
@@ -430,16 +496,16 @@ static int dce_virtual_sw_init(void *handle)
	adev->ddev->mode_config.max_width = 16384;
	adev->ddev->mode_config.max_height = 16384;

	/* allocate crtcs */
	/* allocate crtcs, encoders, connectors */
	for (i = 0; i < adev->mode_info.num_crtc; i++) {
		r = dce_virtual_crtc_init(adev, i);
		if (r)
			return r;
		r = dce_virtual_connector_encoder_init(adev, i);
		if (r)
			return r;
	}

	dce_virtual_get_connector_info(adev);
	amdgpu_print_display_setup(adev->ddev);

	drm_kms_helper_poll_init(adev->ddev);

	adev->mode_info.mode_config_initialized = true;
@@ -557,10 +623,6 @@ static bool dce_virtual_encoder_mode_fixup(struct drm_encoder *encoder,
				    const struct drm_display_mode *mode,
				    struct drm_display_mode *adjusted_mode)
{

	/* set the active encoder to connector routing */
	amdgpu_encoder_set_active_device(encoder);

	return true;
}

@@ -586,45 +648,40 @@ static const struct drm_encoder_funcs dce_virtual_encoder_funcs = {
	.destroy = dce_virtual_encoder_destroy,
};

static void dce_virtual_encoder_add(struct amdgpu_device *adev,
				 uint32_t encoder_enum,
				 uint32_t supported_device,
				 u16 caps)
static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
					      int index)
{
	struct drm_device *dev = adev->ddev;
	struct drm_encoder *encoder;
	struct amdgpu_encoder *amdgpu_encoder;
	struct drm_connector *connector;

	/* see if we already added it */
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
		amdgpu_encoder = to_amdgpu_encoder(encoder);
		if (amdgpu_encoder->encoder_enum == encoder_enum) {
			amdgpu_encoder->devices |= supported_device;
			return;
		}
	/* add a new encoder */
	encoder = kzalloc(sizeof(struct drm_encoder), GFP_KERNEL);
	if (!encoder)
		return -ENOMEM;
	encoder->possible_crtcs = 1 << index;
	drm_encoder_init(adev->ddev, encoder, &dce_virtual_encoder_funcs,
			 DRM_MODE_ENCODER_VIRTUAL, NULL);
	drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs);

	connector = kzalloc(sizeof(struct drm_connector), GFP_KERNEL);
	if (!connector) {
		kfree(encoder);
		return -ENOMEM;
	}

	/* add a new one */
	amdgpu_encoder = kzalloc(sizeof(struct amdgpu_encoder), GFP_KERNEL);
	if (!amdgpu_encoder)
		return;
	/* add a new connector */
	drm_connector_init(adev->ddev, connector, &dce_virtual_connector_funcs,
			   DRM_MODE_CONNECTOR_VIRTUAL);
	drm_connector_helper_add(connector, &dce_virtual_connector_helper_funcs);
	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
	connector->interlace_allowed = false;
	connector->doublescan_allowed = false;
	drm_connector_register(connector);

	encoder = &amdgpu_encoder->base;
	encoder->possible_crtcs = 0x1;
	amdgpu_encoder->enc_priv = NULL;
	amdgpu_encoder->encoder_enum = encoder_enum;
	amdgpu_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
	amdgpu_encoder->devices = supported_device;
	amdgpu_encoder->rmx_type = RMX_OFF;
	amdgpu_encoder->underscan_type = UNDERSCAN_OFF;
	amdgpu_encoder->is_ext_encoder = false;
	amdgpu_encoder->caps = caps;

	drm_encoder_init(dev, encoder, &dce_virtual_encoder_funcs,
					 DRM_MODE_ENCODER_VIRTUAL, NULL);
	drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs);
	DRM_INFO("[FM]encoder: %d is VIRTUAL\n", amdgpu_encoder->encoder_id);
	/* link them */
	drm_mode_connector_attach_encoder(connector, encoder);

	return 0;
}

static const struct amdgpu_display_funcs dce_virtual_display_funcs = {
@@ -640,8 +697,8 @@ static const struct amdgpu_display_funcs dce_virtual_display_funcs = {
	.hpd_get_gpio_reg = &dce_virtual_hpd_get_gpio_reg,
	.page_flip = &dce_virtual_page_flip,
	.page_flip_get_scanoutpos = &dce_virtual_crtc_get_scanoutpos,
	.add_encoder = &dce_virtual_encoder_add,
	.add_connector = &amdgpu_connector_add,
	.add_encoder = NULL,
	.add_connector = NULL,
	.stop_mc_access = &dce_virtual_stop_mc_access,
	.resume_mc_access = &dce_virtual_resume_mc_access,
};