mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-06 00:39:48 +00:00
drm/amdgpu: simplify encoder and connector setup (v2)
No need to emulate all of the stuff for real hw. v2: warning fix Reviewed-By: Emily Deng <Emily.Deng@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
9405e47dba
commit
66264ba804
2 changed files with 143 additions and 179 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
/* 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;
|
||||
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
|
||||
if (connector->encoder_ids[i] == 0)
|
||||
break;
|
||||
|
||||
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);
|
||||
encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
|
||||
if (!encoder)
|
||||
continue;
|
||||
|
||||
amdgpu_display_add_encoder(adev, ENCODER_VIRTUAL_ENUM_VIRTUAL,
|
||||
ATOM_DEVICE_CRT1_SUPPORT,
|
||||
0);
|
||||
|
||||
amdgpu_link_encoder_connector(adev->ddev);
|
||||
|
||||
return true;
|
||||
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}
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dce_virtual_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
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 one */
|
||||
amdgpu_encoder = kzalloc(sizeof(struct amdgpu_encoder), GFP_KERNEL);
|
||||
if (!amdgpu_encoder)
|
||||
return;
|
||||
|
||||
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,
|
||||
/* 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);
|
||||
DRM_INFO("[FM]encoder: %d is VIRTUAL\n", amdgpu_encoder->encoder_id);
|
||||
|
||||
connector = kzalloc(sizeof(struct drm_connector), GFP_KERNEL);
|
||||
if (!connector) {
|
||||
kfree(encoder);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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,
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue