|
@@ -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;
|
|
|
+
|
|
|
+ encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
|
|
|
+ if (!encoder)
|
|
|
+ continue;
|
|
|
|
|
|
- /* 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;
|
|
|
+ if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
|
|
|
+ return encoder;
|
|
|
+ }
|
|
|
|
|
|
- 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);
|
|
|
+ /* 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}
|
|
|
+ };
|
|
|
+
|
|
|
+ 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;
|
|
@@ -536,8 +602,8 @@ static void dce_virtual_encoder_commit(struct drm_encoder *encoder)
|
|
|
|
|
|
static void
|
|
|
dce_virtual_encoder_mode_set(struct drm_encoder *encoder,
|
|
|
- struct drm_display_mode *mode,
|
|
|
- struct drm_display_mode *adjusted_mode)
|
|
|
+ struct drm_display_mode *mode,
|
|
|
+ struct drm_display_mode *adjusted_mode)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
@@ -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;
|
|
|
-
|
|
|
- /* 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;
|
|
|
- }
|
|
|
+ struct drm_connector *connector;
|
|
|
|
|
|
+ /* 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,
|
|
|
};
|