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

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
...@@ -1517,88 +1517,6 @@ static const struct drm_connector_funcs amdgpu_connector_edp_funcs = { ...@@ -1517,88 +1517,6 @@ static const struct drm_connector_funcs amdgpu_connector_edp_funcs = {
.force = amdgpu_connector_dvi_force, .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 void
amdgpu_connector_add(struct amdgpu_device *adev, amdgpu_connector_add(struct amdgpu_device *adev,
uint32_t connector_id, uint32_t connector_id,
...@@ -1983,17 +1901,6 @@ amdgpu_connector_add(struct amdgpu_device *adev, ...@@ -1983,17 +1901,6 @@ amdgpu_connector_add(struct amdgpu_device *adev,
connector->interlace_allowed = false; connector->interlace_allowed = false;
connector->doublescan_allowed = false; connector->doublescan_allowed = false;
break; 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;
} }
} }
......
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
static void dce_virtual_set_display_funcs(struct amdgpu_device *adev); static void dce_virtual_set_display_funcs(struct amdgpu_device *adev);
static void dce_virtual_set_irq_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. * dce_virtual_vblank_wait - vblank wait asic callback.
...@@ -274,24 +276,6 @@ static bool dce_virtual_crtc_mode_fixup(struct drm_crtc *crtc, ...@@ -274,24 +276,6 @@ static bool dce_virtual_crtc_mode_fixup(struct drm_crtc *crtc,
const struct drm_display_mode *mode, const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_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; return true;
} }
...@@ -370,38 +354,120 @@ static int dce_virtual_early_init(void *handle) ...@@ -370,38 +354,120 @@ static int dce_virtual_early_init(void *handle)
return 0; 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; int enc_id = connector->encoder_ids[0];
struct amdgpu_router router; struct drm_encoder *encoder;
struct amdgpu_hpd hpd; 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;
/* look up gpio for ddc, hpd */ if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
ddc_bus.valid = false; return encoder;
hpd.hpd = AMDGPU_HPD_NONE; }
/* needed for aux chan transactions */
ddc_bus.hpd = hpd.hpd;
memset(&router, 0, sizeof(router)); /* pick the first one */
router.ddc_valid = false; if (enc_id)
router.cd_valid = false; return drm_encoder_find(connector->dev, enc_id);
amdgpu_display_add_connector(adev, return NULL;
0, }
ATOM_DEVICE_CRT1_SUPPORT,
DRM_MODE_CONNECTOR_VIRTUAL, &ddc_bus, static int dce_virtual_get_modes(struct drm_connector *connector)
CONNECTOR_OBJECT_ID_VIRTUAL, {
&hpd, struct drm_device *dev = connector->dev;
&router); 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}
};
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, return 0;
ATOM_DEVICE_CRT1_SUPPORT, }
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) static int dce_virtual_sw_init(void *handle)
{ {
int r, i; int r, i;
...@@ -430,16 +496,16 @@ static int dce_virtual_sw_init(void *handle) ...@@ -430,16 +496,16 @@ static int dce_virtual_sw_init(void *handle)
adev->ddev->mode_config.max_width = 16384; adev->ddev->mode_config.max_width = 16384;
adev->ddev->mode_config.max_height = 16384; adev->ddev->mode_config.max_height = 16384;
/* allocate crtcs */ /* allocate crtcs, encoders, connectors */
for (i = 0; i < adev->mode_info.num_crtc; i++) { for (i = 0; i < adev->mode_info.num_crtc; i++) {
r = dce_virtual_crtc_init(adev, i); r = dce_virtual_crtc_init(adev, i);
if (r) if (r)
return 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); drm_kms_helper_poll_init(adev->ddev);
adev->mode_info.mode_config_initialized = true; adev->mode_info.mode_config_initialized = true;
...@@ -536,8 +602,8 @@ static void dce_virtual_encoder_commit(struct drm_encoder *encoder) ...@@ -536,8 +602,8 @@ static void dce_virtual_encoder_commit(struct drm_encoder *encoder)
static void static void
dce_virtual_encoder_mode_set(struct drm_encoder *encoder, dce_virtual_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode) struct drm_display_mode *adjusted_mode)
{ {
return; return;
} }
...@@ -557,10 +623,6 @@ static bool dce_virtual_encoder_mode_fixup(struct drm_encoder *encoder, ...@@ -557,10 +623,6 @@ static bool dce_virtual_encoder_mode_fixup(struct drm_encoder *encoder,
const struct drm_display_mode *mode, const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode) struct drm_display_mode *adjusted_mode)
{ {
/* set the active encoder to connector routing */
amdgpu_encoder_set_active_device(encoder);
return true; return true;
} }
...@@ -586,45 +648,40 @@ static const struct drm_encoder_funcs dce_virtual_encoder_funcs = { ...@@ -586,45 +648,40 @@ static const struct drm_encoder_funcs dce_virtual_encoder_funcs = {
.destroy = dce_virtual_encoder_destroy, .destroy = dce_virtual_encoder_destroy,
}; };
static void dce_virtual_encoder_add(struct amdgpu_device *adev, static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
uint32_t encoder_enum, int index)
uint32_t supported_device,
u16 caps)
{ {
struct drm_device *dev = adev->ddev;
struct drm_encoder *encoder; 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 */ /* add a new connector */
amdgpu_encoder = kzalloc(sizeof(struct amdgpu_encoder), GFP_KERNEL); drm_connector_init(adev->ddev, connector, &dce_virtual_connector_funcs,
if (!amdgpu_encoder) DRM_MODE_CONNECTOR_VIRTUAL);
return; 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; /* link them */
encoder->possible_crtcs = 0x1; drm_mode_connector_attach_encoder(connector, encoder);
amdgpu_encoder->enc_priv = NULL;
amdgpu_encoder->encoder_enum = encoder_enum; return 0;
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);
} }
static const struct amdgpu_display_funcs dce_virtual_display_funcs = { static const struct amdgpu_display_funcs dce_virtual_display_funcs = {
...@@ -640,8 +697,8 @@ 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, .hpd_get_gpio_reg = &dce_virtual_hpd_get_gpio_reg,
.page_flip = &dce_virtual_page_flip, .page_flip = &dce_virtual_page_flip,
.page_flip_get_scanoutpos = &dce_virtual_crtc_get_scanoutpos, .page_flip_get_scanoutpos = &dce_virtual_crtc_get_scanoutpos,
.add_encoder = &dce_virtual_encoder_add, .add_encoder = NULL,
.add_connector = &amdgpu_connector_add, .add_connector = NULL,
.stop_mc_access = &dce_virtual_stop_mc_access, .stop_mc_access = &dce_virtual_stop_mc_access,
.resume_mc_access = &dce_virtual_resume_mc_access, .resume_mc_access = &dce_virtual_resume_mc_access,
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment