Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions drivers/gpu/drm/amd/amdgpu/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ amdgpu-$(CONFIG_VGA_SWITCHEROO) += amdgpu_atpx_handler.o
amdgpu-$(CONFIG_ACPI) += amdgpu_acpi.o
amdgpu-$(CONFIG_MMU_NOTIFIER) += amdgpu_mn.o

amdgpu-$(CONFIG_X86_PS4) += ps4_bridge.o
include $(FULL_AMD_PATH)/powerplay/Makefile

amdgpu-y += $(AMD_POWERPLAY_FILES)
Expand Down
44 changes: 44 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
Original file line number Diff line number Diff line change
Expand Up @@ -1507,6 +1507,30 @@ static const struct drm_connector_funcs amdgpu_connector_dp_funcs = {
.force = amdgpu_connector_dvi_force,
};

#ifdef CONFIG_X86_PS4
int mn86471a_get_modes(struct drm_connector *connector);
enum drm_connector_status mn86471a_detect(struct drm_connector *connector,
bool force);
int mn86471a_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode);

static const struct drm_connector_helper_funcs amdgpu_ps4_dp_connector_helper_funcs = {
.get_modes = mn86471a_get_modes,
.mode_valid = mn86471a_mode_valid,
.best_encoder = amdgpu_connector_dvi_encoder,
};

static const struct drm_connector_funcs amdgpu_ps4_dp_connector_funcs = {
.dpms = drm_helper_connector_dpms,
.detect = mn86471a_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
//.set_property = amdgpu_connector_set_property,
.destroy = amdgpu_connector_destroy,
.force = amdgpu_connector_dvi_force,
};
#endif


static const struct drm_connector_funcs amdgpu_connector_edp_funcs = {
.dpms = drm_helper_connector_dpms,
.detect = amdgpu_connector_dp_detect,
Expand Down Expand Up @@ -1536,6 +1560,7 @@ amdgpu_connector_add(struct amdgpu_device *adev,
uint32_t subpixel_order = SubPixelNone;
bool shared_ddc = false;
bool is_dp_bridge = false;
bool is_ps4_bridge = false;
bool has_aux = false;

if (connector_type == DRM_MODE_CONNECTOR_Unknown)
Expand Down Expand Up @@ -1580,6 +1605,17 @@ amdgpu_connector_add(struct amdgpu_device *adev,
if (!amdgpu_connector)
return;

/* Liverpool (PS4) has an DP bridge which needs a special driver, and
* a fake HDMI port that doesn't really exist. */
if (adev->asic_type == CHIP_LIVERPOOL) {
if (connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
connector_type = DRM_MODE_CONNECTOR_HDMIA;
is_dp_bridge = true;
} else {
return;
}
}

connector = &amdgpu_connector->base;

amdgpu_connector->connector_id = connector_id;
Expand Down Expand Up @@ -1630,10 +1666,18 @@ amdgpu_connector_add(struct amdgpu_device *adev,
case DRM_MODE_CONNECTOR_HDMIA:
case DRM_MODE_CONNECTOR_HDMIB:
case DRM_MODE_CONNECTOR_DisplayPort:
if (is_ps4_bridge) {
drm_connector_init(dev, &amdgpu_connector->base,
&amdgpu_connector_dp_funcs, connector_type);
drm_connector_helper_add(&amdgpu_connector->base,
&amdgpu_connector_dp_helper_funcs);
} else {
drm_connector_init(dev, &amdgpu_connector->base,
&amdgpu_ps4_dp_connector_funcs, connector_type);
drm_connector_helper_add(&amdgpu_connector->base,
&amdgpu_ps4_dp_connector_helper_funcs);
}

drm_object_attach_property(&amdgpu_connector->base.base,
adev->mode_info.underscan_property,
UNDERSCAN_OFF);
Expand Down
14 changes: 14 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@

#include "amdgpu_amdkfd.h"

#ifdef CONFIG_X86_PS4
#include <asm/ps4.h>
#endif

/*
* KMS wrapper.
* - 3.0.0 - initial driver
Expand Down Expand Up @@ -478,6 +482,16 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
ret = amdgpu_kick_out_firmware_fb(pdev);
if (ret)
return ret;

#ifdef CONFIG_X86_PS4
/* On the PS4 (Liverpool graphics) we have a hard dependency on the
* Aeolia driver to set up the HDMI encoder which is connected to it,
* so defer probe until it is ready. This test passes if this isn't
* a PS4 (returns -ENODEV).
*/
if (apcie_status() == 0)
return -EPROBE_DEFER;
#endif

return drm_get_pci_dev(pdev, ent, &kms_driver);
}
Expand Down
19 changes: 19 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_encoders.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,22 @@
#include "atom.h"
#include "atombios_encoders.h"

#ifdef CONFIG_X86_PS4
int mn86471a_bridge_register(struct drm_connector *connector,
struct drm_encoder *encoder);

static void amdgpu_maybe_add_bridge(struct drm_connector *connector,
struct drm_encoder *encoder)
{
struct drm_device *dev = connector->dev;
struct amdgpu_device *adev = dev->dev_private;

if (adev->asic_type == CHIP_LIVERPOOL) {
mn86471a_bridge_register(connector, encoder);
}
}
#endif

void
amdgpu_link_encoder_connector(struct drm_device *dev)
{
Expand All @@ -46,6 +62,9 @@ amdgpu_link_encoder_connector(struct drm_device *dev)
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
amdgpu_encoder = to_amdgpu_encoder(encoder);
if (amdgpu_encoder->devices & amdgpu_connector->devices) {
#ifdef CONFIG_X86_PS4
amdgpu_maybe_add_bridge(connector, encoder);
#endif
drm_mode_connector_attach_encoder(connector, encoder);
if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
amdgpu_atombios_encoder_init_backlight(amdgpu_encoder, connector);
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,8 @@ bool amdgpu_dig_monitor_is_duallink(struct drm_encoder *encoder,
u16 amdgpu_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder);
struct drm_encoder *amdgpu_get_external_encoder(struct drm_encoder *encoder);

extern int amdgpu_atombios_dp_get_dpcd(struct amdgpu_connector *amdgpu_connector);

bool amdgpu_ddc_probe(struct amdgpu_connector *amdgpu_connector, bool use_aux);

void amdgpu_encoder_set_active_device(struct drm_encoder *encoder);
Expand Down
5 changes: 4 additions & 1 deletion drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
Original file line number Diff line number Diff line change
Expand Up @@ -450,9 +450,12 @@ int amdgpu_atombios_encoder_get_encoder_mode(struct drm_encoder *encoder)
struct drm_connector *connector;
struct amdgpu_connector *amdgpu_connector;
struct amdgpu_connector_atom_dig *dig_connector;
struct drm_device *dev = encoder->dev;
struct amdgpu_device *adev = dev->dev_private;

/* dp bridges are always DP */
if (amdgpu_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)
if (amdgpu_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE ||
adev->asic_type == CHIP_LIVERPOOL)
return ATOM_ENCODER_MODE_DP;

/* DVO is always DVO */
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
Original file line number Diff line number Diff line change
Expand Up @@ -1229,6 +1229,8 @@ static void dce_v8_0_bandwidth_update(struct amdgpu_device *adev)
struct drm_display_mode *mode = NULL;
u32 num_heads = 0, lb_size;
int i;
// FIXME PS4: this stuff is broken
return;

amdgpu_update_display_priority(adev);

Expand Down
Loading