radeon drm-next patches
Subsystems (3)
cover radeon drm-next patches
From: Alex Deucher <[email protected]>
These are the radeon patches for 3.11. Some of these patches are huge so, it might be easier to review things here:
http://cgit.freedesktop.org/~agd5f/linux/log/?h=drm-next-3.11-wip
I'll send a formal pull in request in the next day or two.
Highlights of this series:
- DPM support (Dynamic Power Management) for r6xx-SI
- Support for CIK (Sea Islands): modesetting, 3D, compute, UVD
- ASPM support for R6xx-SI
Since this is the initial public DPM code, it's still disabled by default until we get more community testing. Pass dpm=1 to the radeon module to enable it.
Alex Deucher (164):
drm/radeon: fix AVI infoframe generation
drm/radeon: add backlight quirk for hybrid mac drm/radeon: add a reset work handler
drm/radeon: add CIK chip families
drm/radeon: add DCE8 macro for CIK
drm/radeon: adapt to PCI BAR changes on CIK drm/radeon: add gpu init support for CIK (v9) drm/radeon: Add support for CIK GPU reset (v2) drm/radeon: add support for MC/VM setup on CIK (v6) drm/radeon/cik: stop page faults from hanging the system (v2) drm/radeon: add initial ucode loading for CIK (v5) drm/radeon: add support mc ucode loading on CIK (v2) drm/radeon: Add CP init for CIK (v7)
drm/radeon: add IB and fence dispatch functions for CIK gfx (v7) drm/radeon: add ring and IB tests for CIK (v3) drm/radeon: implement async vm_flush for the CP (v7) drm/radeon: Add support for RLC init on CIK (v4) drm/radeon: add support for interrupts on CIK (v5) drm/radeon/cik: log and handle VM page fault interrupts drm/radeon/cik: add support for sDMA dma engines (v8) drm/radeon: implement async vm_flush for the sDMA (v6) drm/radeon/cik: add support for doing async VM pt updates (v5) drm/radeon/cik: fill in startup/shutdown callbacks (v4) drm/radeon: upstream ObjectID.h updates (v2) drm/radeon: upstream atombios.h updates (v2) drm/radeon: atombios power table updates (v2) drm/radeon: handle the integrated thermal controller on CI drm/radeon: update power state parsing for CI drm/radeon/dce8: add support for display watermark setup drm/radeon/cik: add hw cursor support (v2) drm/radeon/dce8: properly handle interlaced timing drm/radeon/dce8: crtc_set_base updates drm/radeon/atom: add DCE8 encoder support drm/radeon/atom: add support for new DVO tables drm/radeon: update DISPCLK programming for DCE8 drm/radeon: add support pll selection for DCE8 (v4) drm/radeon: Handle PPLL0 powerdown on DCE8
drm/radeon: use frac fb div on DCE8
drm/radeon: add SS override support for KB/KV drm/radeon: Update radeon_info_ioctl for CIK (v2) drm/radeon: add get_gpu_clock_counter() callback for cik drm/radeon: update CIK soft reset
drm/radeon: add indirect register accessors for SMC registers drm/radeon: add get_xclk() callback for CIK drm/radeon/cik: add pcie_port indirect register accessors drm/radeon: update radeon_atom_get_clock_dividers() for SI drm/radeon: update radeon_atom_get_clock_dividers for CIK drm/radeon/cik: add srbm_select function
drm/radeon: use callbacks for ring pointer handling drm/radeon: implement simple doorbell page allocator drm/radeon/cik: Add support for compute queues (v2) drm/radeon/cik: switch to type3 nop packet for compute rings drm/radeon: fix up ring functions for compute rings drm/radeon/cik: add support for compute interrupts drm/radeon/cik: add support for golden register init drm/radeon: add radeon_asic struct for CIK (v11) drm/radeon: add cik tile mode array query
drm/radeon: add current Bonaire PCI ids
drm/radeon: add current KB pci ids
drm/radeon/kms: add accessors for RCU indirect space drm/radeon/evergreen: add indirect register accessors for CG
registers
drm/radeon: make get_temperature functions a callback drm/radeon: add support for thermal sensor on tn drm/radeon/kms: move ucode defines to a separate header drm/radeon: properly set up the RLC on ON/LN/TN (v3) drm/radeon/kms: add atom helper functions for dpm (v3) drm/radeon/kms: add new asic struct for rv6xx (v3) drm/radeon/kms: add common dpm infrastructure drm/radeon/kms: fix up rs780/rs880 display watermark calc for dpm drm/radeon/kms: fix up 6xx/7xx display watermark calc for dpm drm/radeon/kms: fix up dce4/5 display watermark calc for dpm drm/radeon/kms: fix up dce6 display watermark calc for dpm drm/radeon/kms: add common r600 dpm functions drm/radeon/kms: add dpm support for rs780/rs880 drm/radeon/kms: add dpm support for rv6xx drm/radeon/kms: add dpm support for rv7xx (v2) drm/radeon/kms: add dpm support for evergreen (v2) drm/radeon/kms: add dpm support for btc (v2) drm/radeon/kms: add dpm support for sumo asics drm/radeon/kms: add dpm support for trinity asics drm/radeon/dpm: let atom control display phy powergating drm/radeon: add dpm UVD handling for r7xx asics drm/radeon: add dpm UVD handling for evergreen/btc asics drm/radeon: add dpm UVD handling for sumo asics drm/radeon: add dpm UVD handling for TN asics (v2) drm/radeon/kms: enable UVD as needed (v9) drm/radeon/dpm: add helpers for extended power tables (v2) drm/radeon/dpm: track whether we are on AC or battery drm/radeon/dpm: fixup dynamic state adjust for sumo drm/radeon/dpm: fixup dynamic state adjust for TN drm/radeon/dpm: fixup dynamic state adjust for btc (v2) drm/radeon/kms: add dpm support for cayman drm/radeon/cayman: update tdp limits in set_power_state drm/radeon/dpm/rs780: restructure code drm/radeon/dpm/rv6xx: restructure code drm/radeon/dpm/rv7xx: restructure code drm/radeon/dpm/evergreen: restructure code drm/radeon/dpm/btc: restructure code drm/radeon/dpm/cayman: restructure code drm/radeon/dpm/sumo: restructure code drm/radeon/dpm/tn: restructure code
drm/radeon/dpm: add new pre/post_set_power_state callbacks drm/radeon/dpm: add pre/post_set_power_state callbacks (6xx-eg) drm/radeon/dpm: add pre/post_set_power_state callback (sumo) drm/radeon/dpm: add pre/post_set_power_state callback (TN) drm/radeon/dpm: add pre/post_set_power_state callback (BTC) drm/radeon/dpm: add pre/post_set_power_state callback (cayman) drm/radeon/dpm: remove broken dyn state remnants drm/radeon: add missing UVD clock set in cayman dpm code drm/radeon/dpm: remove local sumo_get_xclk() drm/radeon: implement apci perf request drm/radeon/atom: add helper to calcuate mpll params drm/radeon: update radeon_atom_is_voltage_gpio() for SI drm/radeon: update radeon_atom_get_voltage_table() for SI drm/radeon: implement pcie gen2/3 support for SI drm/radeon: add accessors of pif_phy indirect register space drm/radeon: add support for ASPM on evergreen asics drm/radeon: add support for ASPM on SI asics (v2) drm/radeon: enable additional power gating features on trinity drm/radeon: update rlc programming sequence on SI drm/radeon: add atom get leakage vddc function drm/radeon: add indirect accessors for UVD CTX registers drm/radeon: initialize save/restore buffer for pg on verde drm/radeon: add clearstate init for verde power gating drm/radeon: implement clock and power gating for SI drm/radeon/dpm: add an enum for pcie gen selection drm/radeon/dpm: pull in phase shedding limits from atom drm/radeon/dpm: endian fixes for extended power tables drm/radeon/dpm: pull in ppm info from atom drm/radeon/dpm: save some display parameters for DPM drm/radeon: minor sid.h cleanup
drm: add some additional fixed point helpers (v2) drm/radeon/dpm/cayman: use new fixed point functions drm/radeon: fix some memory leaks in extended table parsing drm/radeon/dpm: validate voltages against dispclk requirements drm/radeon: update radeon_atombios_get_default_voltages for mvdd drm/radeon/dpm: add pcie gen helper function drm/radeon: fix typo in atom voltage table handling (6xx-ni) drm/radeon: fix typo in atom voltage table handling (si+) drm/radeon/atom: fix voltage table parsing drm/radeon/dpm/ni: properly catch errors in dpm setup drm/radeon/dpm/btc: properly catch errors in dpm setup drm/radeon/dpm/evergreen: properly catch errors in dpm setup drm/radeon/dpm/sumo: properly catch errors in dpm setup drm/radeon/dpm/trinity: properly catch errors in dpm setup drm/radeon/dpm/r7xx: properly catch errors in dpm setup drm/radeon/dpm/r6xx: properly catch errors in dpm setup drm/radeon/dpm/rs780: properly catch errors in dpm setup drm/radeon: add SI to r600_is_internal_thermal_sensor() drm/radeon: switch SI to use radeon_ucode.h drm/radeon/kms: add dpm support for SI (v3) drm/radeon/dpm: add dpm_enable failure output (7xx-ni) drm/radeon/dpm: add dpm_enable failure output (si) drm/radeon/dpm: add dpm_set_power_state failure output (7xx-ni) drm/radeon/dpm: add dpm_set_power_state failure output (si) drm/radeon/dpm: fix typo in setting uvd clock drm/radeon/si: fix typo in function name
drm/radeon: fix typo in cik_select_se_sh()
drm/radeon: fix typo in ni_print_power_state drm/radeon/dpm: add support for setting UVD clock on rs780 drm/radeon/dpm: add support for setting UVD clock on rv6xx drm/radeon/dpm: fix UVD clock setting on cayman drm/radeon/dpm: fix UVD clock setting on SI drm/radeon: fix endian issues in atombios dpm code
Christian König (1):
drm/radeon: add UVD support for CIK (v3)
drivers/gpu/drm/radeon/Makefile | 5 +- drivers/gpu/drm/radeon/ObjectID.h | 40 + drivers/gpu/drm/radeon/atombios.h | 547 ++- drivers/gpu/drm/radeon/atombios_crtc.c | 88 +- drivers/gpu/drm/radeon/atombios_encoders.c | 51 +- drivers/gpu/drm/radeon/btc_dpm.c | 2731 ++++++++++ drivers/gpu/drm/radeon/btc_dpm.h | 57 + drivers/gpu/drm/radeon/btcd.h | 181 + drivers/gpu/drm/radeon/cik.c | 6995 +++++++++++++++++++++++++ drivers/gpu/drm/radeon/cik_blit_shaders.c | 246 + drivers/gpu/drm/radeon/cik_blit_shaders.h | 32 + drivers/gpu/drm/radeon/cik_reg.h | 147 + drivers/gpu/drm/radeon/cikd.h | 1297 +++++ drivers/gpu/drm/radeon/clearstate_cayman.h | 1081 ++++ drivers/gpu/drm/radeon/clearstate_defs.h | 44 + drivers/gpu/drm/radeon/clearstate_evergreen.h | 1080 ++++ drivers/gpu/drm/radeon/clearstate_si.h | 941 ++++ drivers/gpu/drm/radeon/cypress_dpm.c | 2170 ++++++++ drivers/gpu/drm/radeon/cypress_dpm.h | 160 + drivers/gpu/drm/radeon/evergreen.c | 644 +++- drivers/gpu/drm/radeon/evergreen_hdmi.c | 11 +- drivers/gpu/drm/radeon/evergreen_reg.h | 12 + drivers/gpu/drm/radeon/evergreen_smc.h | 67 + drivers/gpu/drm/radeon/evergreend.h | 389 ++- drivers/gpu/drm/radeon/ni.c | 198 +- drivers/gpu/drm/radeon/ni_dpm.c | 4288 +++++++++++++++ drivers/gpu/drm/radeon/ni_dpm.h | 248 + drivers/gpu/drm/radeon/nid.h | 561 ++ drivers/gpu/drm/radeon/nislands_smc.h | 329 ++ drivers/gpu/drm/radeon/ppsmc.h | 110 + drivers/gpu/drm/radeon/r600.c | 147 +- drivers/gpu/drm/radeon/r600_dpm.c | 1024 ++++ drivers/gpu/drm/radeon/r600_dpm.h | 226 + drivers/gpu/drm/radeon/r600_hdmi.c | 11 +- drivers/gpu/drm/radeon/r600_reg.h | 6 + drivers/gpu/drm/radeon/r600d.h | 232 +- drivers/gpu/drm/radeon/radeon.h | 517 ++- drivers/gpu/drm/radeon/radeon_acpi.c | 145 + drivers/gpu/drm/radeon/radeon_asic.c | 524 ++- drivers/gpu/drm/radeon/radeon_asic.h | 166 + drivers/gpu/drm/radeon/radeon_atombios.c | 880 +++- drivers/gpu/drm/radeon/radeon_cs.c | 1 + drivers/gpu/drm/radeon/radeon_cursor.c | 10 +- drivers/gpu/drm/radeon/radeon_device.c | 106 +- drivers/gpu/drm/radeon/radeon_display.c | 21 +- drivers/gpu/drm/radeon/radeon_drv.c | 7 +- drivers/gpu/drm/radeon/radeon_family.h | 3 + drivers/gpu/drm/radeon/radeon_irq_kms.c | 20 + drivers/gpu/drm/radeon/radeon_kms.c | 41 +- drivers/gpu/drm/radeon/radeon_mode.h | 93 + drivers/gpu/drm/radeon/radeon_pm.c | 610 ++- drivers/gpu/drm/radeon/radeon_reg.h | 1 + drivers/gpu/drm/radeon/radeon_ring.c | 55 +- drivers/gpu/drm/radeon/radeon_ucode.h | 129 + drivers/gpu/drm/radeon/radeon_uvd.c | 32 +- drivers/gpu/drm/radeon/rs690.c | 291 +- drivers/gpu/drm/radeon/rs780_dpm.c | 963 ++++ drivers/gpu/drm/radeon/rs780_dpm.h | 109 + drivers/gpu/drm/radeon/rs780d.h | 168 + drivers/gpu/drm/radeon/rv515.c | 224 +- drivers/gpu/drm/radeon/rv6xx_dpm.c | 2059 ++++++++ drivers/gpu/drm/radeon/rv6xx_dpm.h | 95 + drivers/gpu/drm/radeon/rv6xxd.h | 246 + drivers/gpu/drm/radeon/rv730_dpm.c | 508 ++ drivers/gpu/drm/radeon/rv730d.h | 165 + drivers/gpu/drm/radeon/rv740_dpm.c | 416 ++ drivers/gpu/drm/radeon/rv740d.h | 117 + drivers/gpu/drm/radeon/rv770_dpm.c | 2446 +++++++++ drivers/gpu/drm/radeon/rv770_dpm.h | 287 + drivers/gpu/drm/radeon/rv770_smc.c | 621 +++ drivers/gpu/drm/radeon/rv770_smc.h | 209 + drivers/gpu/drm/radeon/rv770d.h | 279 +- drivers/gpu/drm/radeon/si.c | 1337 +++++- drivers/gpu/drm/radeon/si_dpm.c | 6369 ++++++++++++++++++++++ drivers/gpu/drm/radeon/si_dpm.h | 227 + drivers/gpu/drm/radeon/si_smc.c | 284 + drivers/gpu/drm/radeon/sid.h | 599 ++- drivers/gpu/drm/radeon/sislands_smc.h | 397 ++ drivers/gpu/drm/radeon/sumo_dpm.c | 1801 +++++++ drivers/gpu/drm/radeon/sumo_dpm.h | 220 + drivers/gpu/drm/radeon/sumo_smc.c | 222 + drivers/gpu/drm/radeon/sumod.h | 372 ++ drivers/gpu/drm/radeon/trinity_dpm.c | 1887 +++++++ drivers/gpu/drm/radeon/trinity_dpm.h | 131 + drivers/gpu/drm/radeon/trinity_smc.c | 115 + drivers/gpu/drm/radeon/trinityd.h | 228 + include/drm/drm_fixed.h | 96 + include/drm/drm_pciids.h | 24 + 88 files changed, 52708 insertions(+), 561 deletions(-) create mode 100644 drivers/gpu/drm/radeon/btc_dpm.c create mode 100644 drivers/gpu/drm/radeon/btc_dpm.h create mode 100644 drivers/gpu/drm/radeon/btcd.h create mode 100644 drivers/gpu/drm/radeon/cik.c create mode 100644 drivers/gpu/drm/radeon/cik_blit_shaders.c create mode 100644 drivers/gpu/drm/radeon/cik_blit_shaders.h create mode 100644 drivers/gpu/drm/radeon/cik_reg.h create mode 100644 drivers/gpu/drm/radeon/cikd.h create mode 100644 drivers/gpu/drm/radeon/clearstate_cayman.h create mode 100644 drivers/gpu/drm/radeon/clearstate_defs.h create mode 100644 drivers/gpu/drm/radeon/clearstate_evergreen.h create mode 100644 drivers/gpu/drm/radeon/clearstate_si.h create mode 100644 drivers/gpu/drm/radeon/cypress_dpm.c create mode 100644 drivers/gpu/drm/radeon/cypress_dpm.h create mode 100644 drivers/gpu/drm/radeon/evergreen_smc.h create mode 100644 drivers/gpu/drm/radeon/ni_dpm.c create mode 100644 drivers/gpu/drm/radeon/ni_dpm.h create mode 100644 drivers/gpu/drm/radeon/nislands_smc.h create mode 100644 drivers/gpu/drm/radeon/ppsmc.h create mode 100644 drivers/gpu/drm/radeon/r600_dpm.c create mode 100644 drivers/gpu/drm/radeon/r600_dpm.h create mode 100644 drivers/gpu/drm/radeon/radeon_ucode.h create mode 100644 drivers/gpu/drm/radeon/rs780_dpm.c create mode 100644 drivers/gpu/drm/radeon/rs780_dpm.h create mode 100644 drivers/gpu/drm/radeon/rs780d.h create mode 100644 drivers/gpu/drm/radeon/rv6xx_dpm.c create mode 100644 drivers/gpu/drm/radeon/rv6xx_dpm.h create mode 100644 drivers/gpu/drm/radeon/rv6xxd.h create mode 100644 drivers/gpu/drm/radeon/rv730_dpm.c create mode 100644 drivers/gpu/drm/radeon/rv730d.h create mode 100644 drivers/gpu/drm/radeon/rv740_dpm.c create mode 100644 drivers/gpu/drm/radeon/rv740d.h create mode 100644 drivers/gpu/drm/radeon/rv770_dpm.c create mode 100644 drivers/gpu/drm/radeon/rv770_dpm.h create mode 100644 drivers/gpu/drm/radeon/rv770_smc.c create mode 100644 drivers/gpu/drm/radeon/rv770_smc.h create mode 100644 drivers/gpu/drm/radeon/si_dpm.c create mode 100644 drivers/gpu/drm/radeon/si_dpm.h create mode 100644 drivers/gpu/drm/radeon/si_smc.c create mode 100644 drivers/gpu/drm/radeon/sislands_smc.h create mode 100644 drivers/gpu/drm/radeon/sumo_dpm.c create mode 100644 drivers/gpu/drm/radeon/sumo_dpm.h create mode 100644 drivers/gpu/drm/radeon/sumo_smc.c create mode 100644 drivers/gpu/drm/radeon/sumod.h create mode 100644 drivers/gpu/drm/radeon/trinity_dpm.c create mode 100644 drivers/gpu/drm/radeon/trinity_dpm.h create mode 100644 drivers/gpu/drm/radeon/trinity_smc.c create mode 100644 drivers/gpu/drm/radeon/trinityd.h
Signature · 6 lines
1.7.7.5 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 1/165 drm/radeon: fix AVI infoframe generation
From: Alex Deucher <[email protected]>
- remove adding 2 to checksum, this is incorrect.
This was incorrectly introduced in:92db7f6c860b8190571a9dc1fcbc16d003422fe8
http://lists.freedesktop.org/archives/dri-devel/2011-December/017717.html
However, the off by 2 was due to adding the version twice. From the examples in the URL above:
[Rafał Miłecki][RV620] fglrx:
0x7454: 00 A8 5E 79 R600_HDMI_VIDEOINFOFRAME_0 0x7458: 00 28 00 10 R600_HDMI_VIDEOINFOFRAME_1 0x745C: 00 48 00 28 R600_HDMI_VIDEOINFOFRAME_2 0x7460: 02 00 00 48 R600_HDMI_VIDEOINFOFRAME_3
===================
(0x82 + 0x2 + 0xD) + 0x1F8 = 0x289
-0x289 = 0x77
However, the payload sum is not 0x1f8, it's 0x1f6. 00 + A8 + 5E + 00 +
00 + 28 + 00 + 10 +
00 + 48 + 00 + 28 +
00 + 48 =0x1f6
Bits 25:24 of HDMI_VIDEOINFOFRAME_3 are the packet version, not part of the payload. So the total would be:
(0x82 + 0x2 + 0xD) + 0x1f6 = 0x287
-0x287 = 0x79
- properly emit the AVI infoframe version. This was not being emitted previous which is probably what caused the issue above.
This should fix blank screen when HDMI audio is enabled on certain monitors.
--- drivers/gpu/drm/radeon/evergreen_hdmi.c | 11 ++--------- drivers/gpu/drm/radeon/r600_hdmi.c | 11 ++--------- 2 files changed, 4 insertions(+), 18 deletions(-)
drivers/gpu/drm/radeon/evergreen_hdmi.c +2 -9
@@ -128,14 +128,7 @@ static void evergreen_hdmi_update_avi_infoframe(struct drm_encoder *encoder,struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;uint32_t offset = dig->afmt->offset;uint8_t *frame = buffer +3 ; - -/* Our header values (type, version, length) should be alright, Intel -* is using the same. Checksum function also seems to be OK, it works -* fine for audio infoframe. However calculated value is always lower -* by 2 in comparison to fglrx. It breaks displaying anything in case -* of TVs that strictly check the checksum. Hack it manually here to -* workaround this issue. */ - frame[0x0 ] +=2 ; +uint8_t *header = buffer;WREG32 (AFMT_AVI_INFO0 + offset, frame[0x0 ] | (frame[0x1 ] <<8 ) | (frame[0x2 ] <<16 ) | (frame[0x3 ] <<24 ));
@@ -144,7 +137,7 @@ static void evergreen_hdmi_update_avi_infoframe(struct drm_encoder *encoder,WREG32 (AFMT_AVI_INFO2 + offset, frame[0x8 ] | (frame[0x9 ] <<8 ) | (frame[0xA ] <<16 ) | (frame[0xB ] <<24 ));WREG32 (AFMT_AVI_INFO3 + offset, - frame[0xC ] | (frame[0xD ] <<8 )); + frame[0xC ] | (frame[0xD ] <<8 ) | (header[1 ] <<24 )); }static void evergreen_audio_set_dto (struct drm_encoder *encoder,u32 clock)
drivers/gpu/drm/radeon/r600_hdmi.c +2 -9
@@ -133,14 +133,7 @@ static void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder,struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;uint32_t offset = dig->afmt->offset;uint8_t *frame = buffer +3 ; - -/* Our header values (type, version, length) should be alright, Intel -* is using the same. Checksum function also seems to be OK, it works -* fine for audio infoframe. However calculated value is always lower -* by 2 in comparison to fglrx. It breaks displaying anything in case -* of TVs that strictly check the checksum. Hack it manually here to -* workaround this issue. */ - frame[0x0 ] +=2 ; +uint8_t *header = buffer;WREG32 (HDMI0_AVI_INFO0 + offset, frame[0x0 ] | (frame[0x1 ] <<8 ) | (frame[0x2 ] <<16 ) | (frame[0x3 ] <<24 ));
@@ -149,7 +142,7 @@ static void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder,WREG32 (HDMI0_AVI_INFO2 + offset, frame[0x8 ] | (frame[0x9 ] <<8 ) | (frame[0xA ] <<16 ) | (frame[0xB ] <<24 ));WREG32 (HDMI0_AVI_INFO3 + offset, - frame[0xC ] | (frame[0xD ] <<8 )); + frame[0xC ] | (frame[0xD ] <<8 ) | (header[1 ] <<24 )); }/*
Signature · 1 line
1.7.7.5
PATCH 2/165 drm/radeon: add backlight quirk for hybrid mac
In reply to [email protected]From: Alex Deucher <[email protected]>
Mac laptops with multiple GPUs apparently use the gmux driver for backlight control. Don't register a radeon backlight interface. We may need to add other pci ids for other hybrid mac laptops.
Fixes:
https://bugs.freedesktop.org/show_bug.cgi?id=65377
--- drivers/gpu/drm/radeon/atombios_encoders.c | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/atombios_encoders.c +7 -0
@@ -186,6 +186,13 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,u8 backlight_level;char bl_name[16 ]; +/* Mac laptops with multiple GPUs use the gmux driver for backlight +* so don't register a backlight device +*/ +if ((rdev->pdev->subsystem_vendor ==PCI_VENDOR_ID_APPLE ) && + (rdev->pdev->device ==0x6741 )) +return ; +if (!radeon_encoder->enc_priv)return ;
Signature · 1 line
1.7.7.5
PATCH 3/165 drm/radeon: add a reset work handler
In reply to [email protected]From: Alex Deucher <[email protected]>
New asics support non-privileged IBs. This allows us to skip IB checking in the driver since the hardware will check the command buffers for us. When using non-privileged IBs, if the CP encounters an illegal register in the command stream, it will halt and generate an interrupt. The CP needs to be reset to continue. For now just do a full GPU reset when this happens.
--- drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_irq_kms.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/radeon.h +1 -0
@@ -1691,6 +1691,7 @@ struct radeon_device {struct si_rlc rlc;struct work_struct hotplug_work;struct work_struct audio_work; +struct work_struct reset_work;int num_crtc;/* number of crtcs */ struct mutex dc_hw_i2c_mutex;/* display controller hw i2c mutex */ bool audio_enabled;
drivers/gpu/drm/radeon/radeon_irq_kms.c +18 -0
@@ -82,6 +82,23 @@ static void radeon_hotplug_work_func(struct work_struct *work) }/** +* radeon_irq_reset_work_func - execute gpu reset +* +* @work: work struct +* +* Execute scheduled gpu reset (cayman+). +* This function is called when the irq handler +* thinks we need a gpu reset. +*/ +static void radeon_irq_reset_work_func (struct work_struct *work) +{ + struct radeon_device *rdev = container_of(work, struct radeon_device, + reset_work); + +radeon_gpu_reset (rdev); +} + +/** * radeon_driver_irq_preinstall_kms - drm irq preinstall callback * * @dev: drm dev pointer
@@ -243,6 +260,7 @@ int radeon_irq_kms_init(struct radeon_device *rdev)INIT_WORK (&rdev->hotplug_work, radeon_hotplug_work_func);INIT_WORK (&rdev->audio_work, r600_audio_update_hdmi); +INIT_WORK (&rdev->reset_work, radeon_irq_reset_work_func);spin_lock_init (&rdev->irq.lock); r =drm_vblank_init (rdev->ddev, rdev->num_crtc);
Signature · 1 line
1.7.7.5
PATCH 4/165 drm/radeon: add CIK chip families
In reply to [email protected]From: Alex Deucher <[email protected]>
--- drivers/gpu/drm/radeon/radeon_device.c | 3 +++ drivers/gpu/drm/radeon/radeon_family.h | 3 +++ 2 files changed, 6 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/radeon_device.c +3 -0
@@ -95,6 +95,9 @@ static const char radeon_family_name[][16] = {"VERDE" ,"OLAND" ,"HAINAN" , +"BONAIRE" , +"KAVERI" , +"KABINI" , "LAST", };
drivers/gpu/drm/radeon/radeon_family.h +3 -0
@@ -93,6 +93,9 @@ enum radeon_family {CHIP_VERDE ,CHIP_OLAND ,CHIP_HAINAN , +CHIP_BONAIRE , +CHIP_KAVERI , +CHIP_KABINI , CHIP_LAST, };
Signature · 1 line
1.7.7.5
PATCH 5/165 drm/radeon: add DCE8 macro for CIK
In reply to [email protected]From: Alex Deucher <[email protected]>
--- drivers/gpu/drm/radeon/radeon.h | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/radeon.h +1 -0
@@ -1841,6 +1841,7 @@ void r100_pll_errata_after_index(struct radeon_device *rdev); (rdev->flags & RADEON_IS_IGP))#define ASIC_IS_DCE64 (rdev) ((rdev->family == CHIP_OLAND))#define ASIC_IS_NODCE (rdev) ((rdev->family == CHIP_HAINAN)) +#define ASIC_IS_DCE8 (rdev) ((rdev->family >= CHIP_BONAIRE))/* * BIOS helpers.
Signature · 1 line
1.7.7.5
PATCH 6/165 drm/radeon: adapt to PCI BAR changes on CIK
In reply to [email protected]From: Alex Deucher <[email protected]>
register BAR is now at PCI BAR 5.
--- drivers/gpu/drm/radeon/radeon_device.c | 9 +++++++-- 1 files changed, 7 insertions(+), 2 deletions(-)
drivers/gpu/drm/radeon/radeon_device.c +7 -2
@@ -1148,8 +1148,13 @@ int radeon_device_init(struct radeon_device *rdev,/* Registers mapping */ /* TODO: block userspace mapping of io register */ spin_lock_init (&rdev->mmio_idx_lock); - rdev->rmmio_base =pci_resource_start (rdev->pdev,2 ); - rdev->rmmio_size =pci_resource_len (rdev->pdev,2 ); +if (rdev->family >=CHIP_BONAIRE ) { + rdev->rmmio_base =pci_resource_start (rdev->pdev,5 ); + rdev->rmmio_size =pci_resource_len (rdev->pdev,5 ); + }else { + rdev->rmmio_base =pci_resource_start (rdev->pdev,2 ); + rdev->rmmio_size =pci_resource_len (rdev->pdev,2 ); + } rdev->rmmio =ioremap (rdev->rmmio_base, rdev->rmmio_size);if (rdev->rmmio ==NULL ) {return -ENOMEM ;
Signature · 1 line
1.7.7.5
PATCH 7/165 drm/radeon: add gpu init support for CIK (v9)
In reply to [email protected]From: Alex Deucher <[email protected]>
v2: tiling fixes
v3: more tiling fixes
v4: more tiling fixes
v5: additional register init
v6: rebase
v7: fix gb_addr_config for KV/KB
v8: drop wip KV bits for now, add missing config reg
v9: fix cu count on Bonaire
--- drivers/gpu/drm/radeon/Makefile | 2 +- drivers/gpu/drm/radeon/cik.c | 1192 +++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/cikd.h | 253 +++++++++ drivers/gpu/drm/radeon/radeon.h | 30 + 4 files changed, 1476 insertions(+), 1 deletions(-) create mode 100644 drivers/gpu/drm/radeon/cik.c create mode 100644 drivers/gpu/drm/radeon/cikd.h
drivers/gpu/drm/radeon/Makefile +1 -1
@@ -76,7 +76,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \ evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o \ evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \ atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \ - si_blit_shaders.o radeon_prime.o radeon_uvd.o + si_blit_shaders.o radeon_prime.o radeon_uvd.o cik.o radeon-$(CONFIG_COMPAT) += radeon_ioc32.o radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
drivers/gpu/drm/radeon/cik.c new file +1192 -0
1,192 lines not on this page · raw message
drivers/gpu/drm/radeon/cikd.h new file +253 -0
253 lines not on this page · raw message
drivers/gpu/drm/radeon/radeon.h +30 -0
@@ -1505,6 +1505,35 @@ struct si_asic {uint32_t tile_mode_array[32 ]; }; +struct cik_asic { +unsigned max_shader_engines; +unsigned max_tile_pipes; +unsigned max_cu_per_sh; +unsigned max_sh_per_se; +unsigned max_backends_per_se; +unsigned max_texture_channel_caches; +unsigned max_gprs; +unsigned max_gs_threads; +unsigned max_hw_contexts; +unsigned sc_prim_fifo_size_frontend; +unsigned sc_prim_fifo_size_backend; +unsigned sc_hiz_tile_fifo_size; +unsigned sc_earlyz_tile_fifo_size; + +unsigned num_tile_pipes; +unsigned num_backends_per_se; +unsigned backend_disable_mask_per_asic; +unsigned backend_map; +unsigned num_texture_channel_caches; +unsigned mem_max_burst_length_bytes; +unsigned mem_row_size_in_kb; +unsigned shader_engine_tile_size; +unsigned num_gpus; +unsigned multi_gpu_tile_size; + +unsigned tile_config; +}; +union radeon_asic_config {struct r300_asic r300;struct r100_asic r100;
@@ -1513,6 +1542,7 @@ union radeon_asic_config {struct evergreen_asic evergreen;struct cayman_asic cayman;struct si_asic si; +struct cik_asic cik; };/*
Signature · 1 line
1.7.7.5
PATCH 8/165 drm/radeon: Add support for CIK GPU reset (v2)
In reply to [email protected]From: Alex Deucher <[email protected]>
v2: split soft reset into compute and gfx. Still need to make reset more fine grained, but this should be a start.
--- drivers/gpu/drm/radeon/cik.c | 197 +++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/cikd.h | 80 +++++++++++++++++ 2 files changed, 277 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/cik.c +197 -0
@@ -27,9 +27,13 @@#include <linux/module.h> #include "drmP.h" #include "radeon.h" +#include "radeon_asic.h" #include "cikd.h" #include "atom.h" +extern void evergreen_mc_stop (struct radeon_device *rdev,struct evergreen_mc_save *save); +extern void evergreen_mc_resume (struct radeon_device *rdev,struct evergreen_mc_save *save); +/* * Core functions */
@@ -1190,3 +1194,196 @@ static void cik_gpu_init(struct radeon_device *rdev)udelay (50 ); } +/** +* cik_gpu_is_lockup - check if the 3D engine is locked up +* +* @rdev: radeon_device pointer +* @ring: radeon_ring structure holding ring information +* +* Check if the 3D engine is locked up (CIK). +* Returns true if the engine is locked, false if not. +*/ +bool cik_gpu_is_lockup (struct radeon_device *rdev,struct radeon_ring *ring) +{ +u32 srbm_status, srbm_status2; +u32 grbm_status, grbm_status2; +u32 grbm_status_se0, grbm_status_se1, grbm_status_se2, grbm_status_se3; + + srbm_status =RREG32 (SRBM_STATUS ); + srbm_status2 =RREG32 (SRBM_STATUS2 ); + grbm_status =RREG32 (GRBM_STATUS ); + grbm_status2 =RREG32 (GRBM_STATUS2 ); + grbm_status_se0 =RREG32 (GRBM_STATUS_SE0 ); + grbm_status_se1 =RREG32 (GRBM_STATUS_SE1 ); + grbm_status_se2 =RREG32 (GRBM_STATUS_SE2 ); + grbm_status_se3 =RREG32 (GRBM_STATUS_SE3 ); +if (!(grbm_status &GUI_ACTIVE )) { +radeon_ring_lockup_update (ring); +return false; + } +/* force CP activities */ +radeon_ring_force_activity (rdev, ring); +return radeon_ring_test_lockup (rdev, ring); +} + +/** +* cik_gfx_gpu_soft_reset - soft reset the 3D engine and CPG +* +* @rdev: radeon_device pointer +* +* Soft reset the GFX engine and CPG blocks (CIK). +* XXX: deal with reseting RLC and CPF +* Returns 0 for success. +*/ +static int cik_gfx_gpu_soft_reset (struct radeon_device *rdev) +{ +struct evergreen_mc_save save; +u32 grbm_reset =0 ; + +if (!(RREG32 (GRBM_STATUS ) &GUI_ACTIVE )) +return 0 ; + +dev_info (rdev->dev,"GPU GFX softreset \n" ); +dev_info (rdev->dev," GRBM_STATUS=0x%08X\n" , +RREG32 (GRBM_STATUS )); +dev_info (rdev->dev," GRBM_STATUS2=0x%08X\n" , +RREG32 (GRBM_STATUS2 )); +dev_info (rdev->dev," GRBM_STATUS_SE0=0x%08X\n" , +RREG32 (GRBM_STATUS_SE0 )); +dev_info (rdev->dev," GRBM_STATUS_SE1=0x%08X\n" , +RREG32 (GRBM_STATUS_SE1 )); +dev_info (rdev->dev," GRBM_STATUS_SE2=0x%08X\n" , +RREG32 (GRBM_STATUS_SE2 )); +dev_info (rdev->dev," GRBM_STATUS_SE3=0x%08X\n" , +RREG32 (GRBM_STATUS_SE3 )); +dev_info (rdev->dev," SRBM_STATUS=0x%08X\n" , +RREG32 (SRBM_STATUS )); +dev_info (rdev->dev," SRBM_STATUS2=0x%08X\n" , +RREG32 (SRBM_STATUS2 )); +evergreen_mc_stop (rdev, &save); +if (radeon_mc_wait_for_idle (rdev)) { +dev_warn (rdev->dev,"Wait for MC idle timedout !\n" ); + } +/* Disable CP parsing/prefetching */ +WREG32 (CP_ME_CNTL ,CP_ME_HALT |CP_PFP_HALT |CP_CE_HALT ); + +/* reset all the gfx block and all CPG blocks */ + grbm_reset =SOFT_RESET_CPG |SOFT_RESET_GFX ; + +dev_info (rdev->dev," GRBM_SOFT_RESET=0x%08X\n" , grbm_reset); +WREG32 (GRBM_SOFT_RESET , grbm_reset); + (void )RREG32 (GRBM_SOFT_RESET ); +udelay (50 ); +WREG32 (GRBM_SOFT_RESET ,0 ); + (void )RREG32 (GRBM_SOFT_RESET ); +/* Wait a little for things to settle down */ +udelay (50 ); +dev_info (rdev->dev," GRBM_STATUS=0x%08X\n" , +RREG32 (GRBM_STATUS )); +dev_info (rdev->dev," GRBM_STATUS2=0x%08X\n" , +RREG32 (GRBM_STATUS2 )); +dev_info (rdev->dev," GRBM_STATUS_SE0=0x%08X\n" , +RREG32 (GRBM_STATUS_SE0 )); +dev_info (rdev->dev," GRBM_STATUS_SE1=0x%08X\n" , +RREG32 (GRBM_STATUS_SE1 )); +dev_info (rdev->dev," GRBM_STATUS_SE2=0x%08X\n" , +RREG32 (GRBM_STATUS_SE2 )); +dev_info (rdev->dev," GRBM_STATUS_SE3=0x%08X\n" , +RREG32 (GRBM_STATUS_SE3 )); +dev_info (rdev->dev," SRBM_STATUS=0x%08X\n" , +RREG32 (SRBM_STATUS )); +dev_info (rdev->dev," SRBM_STATUS2=0x%08X\n" , +RREG32 (SRBM_STATUS2 )); +evergreen_mc_resume (rdev, &save); +return 0 ; +} + +/** +* cik_compute_gpu_soft_reset - soft reset CPC +* +* @rdev: radeon_device pointer +* +* Soft reset the CPC blocks (CIK). +* XXX: deal with reseting RLC and CPF +* Returns 0 for success. +*/ +static int cik_compute_gpu_soft_reset (struct radeon_device *rdev) +{ +struct evergreen_mc_save save; +u32 grbm_reset =0 ; + +dev_info (rdev->dev,"GPU compute softreset \n" ); +dev_info (rdev->dev," GRBM_STATUS=0x%08X\n" , +RREG32 (GRBM_STATUS )); +dev_info (rdev->dev," GRBM_STATUS2=0x%08X\n" , +RREG32 (GRBM_STATUS2 )); +dev_info (rdev->dev," GRBM_STATUS_SE0=0x%08X\n" , +RREG32 (GRBM_STATUS_SE0 )); +dev_info (rdev->dev," GRBM_STATUS_SE1=0x%08X\n" , +RREG32 (GRBM_STATUS_SE1 )); +dev_info (rdev->dev," GRBM_STATUS_SE2=0x%08X\n" , +RREG32 (GRBM_STATUS_SE2 )); +dev_info (rdev->dev," GRBM_STATUS_SE3=0x%08X\n" , +RREG32 (GRBM_STATUS_SE3 )); +dev_info (rdev->dev," SRBM_STATUS=0x%08X\n" , +RREG32 (SRBM_STATUS )); +dev_info (rdev->dev," SRBM_STATUS2=0x%08X\n" , +RREG32 (SRBM_STATUS2 )); +evergreen_mc_stop (rdev, &save); +if (radeon_mc_wait_for_idle (rdev)) { +dev_warn (rdev->dev,"Wait for MC idle timedout !\n" ); + } +/* Disable CP parsing/prefetching */ +WREG32 (CP_MEC_CNTL ,MEC_ME1_HALT |MEC_ME2_HALT ); + +/* reset all the CPC blocks */ + grbm_reset =SOFT_RESET_CPG ; + +dev_info (rdev->dev," GRBM_SOFT_RESET=0x%08X\n" , grbm_reset); +WREG32 (GRBM_SOFT_RESET , grbm_reset); + (void )RREG32 (GRBM_SOFT_RESET ); +udelay (50 ); +WREG32 (GRBM_SOFT_RESET ,0 ); + (void )RREG32 (GRBM_SOFT_RESET ); +/* Wait a little for things to settle down */ +udelay (50 ); +dev_info (rdev->dev," GRBM_STATUS=0x%08X\n" , +RREG32 (GRBM_STATUS )); +dev_info (rdev->dev," GRBM_STATUS2=0x%08X\n" , +RREG32 (GRBM_STATUS2 )); +dev_info (rdev->dev," GRBM_STATUS_SE0=0x%08X\n" , +RREG32 (GRBM_STATUS_SE0 )); +dev_info (rdev->dev," GRBM_STATUS_SE1=0x%08X\n" , +RREG32 (GRBM_STATUS_SE1 )); +dev_info (rdev->dev," GRBM_STATUS_SE2=0x%08X\n" , +RREG32 (GRBM_STATUS_SE2 )); +dev_info (rdev->dev," GRBM_STATUS_SE3=0x%08X\n" , +RREG32 (GRBM_STATUS_SE3 )); +dev_info (rdev->dev," SRBM_STATUS=0x%08X\n" , +RREG32 (SRBM_STATUS )); +dev_info (rdev->dev," SRBM_STATUS2=0x%08X\n" , +RREG32 (SRBM_STATUS2 )); +evergreen_mc_resume (rdev, &save); +return 0 ; +} + +/** +* cik_asic_reset - soft reset compute and gfx +* +* @rdev: radeon_device pointer +* +* Soft reset the CPC blocks (CIK). +* XXX: make this more fine grained and only reset +* what is necessary. +* Returns 0 for success. +*/ +int cik_asic_reset (struct radeon_device *rdev) +{ +int r; + + r =cik_compute_gpu_soft_reset (rdev); +if (r) +dev_info (rdev->dev,"Compute reset failed!\n" ); + +return cik_gfx_gpu_soft_reset (rdev); +}
drivers/gpu/drm/radeon/cikd.h +80 -0
92 lines not on this page · raw message
Signature · 1 line
1.7.7.5
PATCH 9/165 drm/radeon: add support for MC/VM setup on CIK (v6)
In reply to [email protected]From: Alex Deucher <[email protected]>
The vm callbacks are the same as the SI ones right now (same regs and bits). We could share the SI variants, and I may yet do that, but I figured I would add CIK specific ones for now in case we need to change anything.
V2: add documentation, minor fixes.
V3: integrate vram offset fixes for APUs
V4: enable 2 level VM PTs
V5: index SH_MEM_* regs properly
V6: add ib_parse()
--- drivers/gpu/drm/radeon/cik.c | 361 +++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/cikd.h | 125 ++++++++++++++ drivers/gpu/drm/radeon/si.c | 4 +- 3 files changed, 488 insertions(+), 2 deletions(-)
drivers/gpu/drm/radeon/cik.c +361 -0
@@ -33,6 +33,7 @@extern void evergreen_mc_stop (struct radeon_device *rdev,struct evergreen_mc_save *save);extern void evergreen_mc_resume (struct radeon_device *rdev,struct evergreen_mc_save *save); +extern void si_vram_gtt_location (struct radeon_device *rdev,struct radeon_mc *mc);/* * Core functions
@@ -1387,3 +1388,363 @@ int cik_asic_reset(struct radeon_device *rdev)return cik_gfx_gpu_soft_reset (rdev); } + +/* MC */ +/** +* cik_mc_program - program the GPU memory controller +* +* @rdev: radeon_device pointer +* +* Set the location of vram, gart, and AGP in the GPU's +* physical address space (CIK). +*/ +static void cik_mc_program (struct radeon_device *rdev) +{ +struct evergreen_mc_save save; +u32 tmp; +int i, j; + +/* Initialize HDP */ +for (i =0 , j =0 ; i <32 ; i++, j +=0x18 ) { +WREG32 ((0x2c14 + j),0x00000000 ); +WREG32 ((0x2c18 + j),0x00000000 ); +WREG32 ((0x2c1c + j),0x00000000 ); +WREG32 ((0x2c20 + j),0x00000000 ); +WREG32 ((0x2c24 + j),0x00000000 ); + } +WREG32 (HDP_REG_COHERENCY_FLUSH_CNTL ,0 ); + +evergreen_mc_stop (rdev, &save); +if (radeon_mc_wait_for_idle (rdev)) { +dev_warn (rdev->dev,"Wait for MC idle timedout !\n" ); + } +/* Lockout access through VGA aperture*/ +WREG32 (VGA_HDP_CONTROL ,VGA_MEMORY_DISABLE ); +/* Update configuration */ +WREG32 (MC_VM_SYSTEM_APERTURE_LOW_ADDR , + rdev->mc.vram_start >>12 ); +WREG32 (MC_VM_SYSTEM_APERTURE_HIGH_ADDR , + rdev->mc.vram_end >>12 ); +WREG32 (MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR , + rdev->vram_scratch.gpu_addr >>12 ); + tmp = ((rdev->mc.vram_end >>24 ) &0xFFFF ) <<16 ; + tmp |= ((rdev->mc.vram_start >>24 ) &0xFFFF ); +WREG32 (MC_VM_FB_LOCATION , tmp); +/* XXX double check these! */ +WREG32 (HDP_NONSURFACE_BASE , (rdev->mc.vram_start >>8 )); +WREG32 (HDP_NONSURFACE_INFO , (2 <<7 ) | (1 <<30 )); +WREG32 (HDP_NONSURFACE_SIZE ,0x3FFFFFFF ); +WREG32 (MC_VM_AGP_BASE ,0 ); +WREG32 (MC_VM_AGP_TOP ,0x0FFFFFFF ); +WREG32 (MC_VM_AGP_BOT ,0x0FFFFFFF ); +if (radeon_mc_wait_for_idle (rdev)) { +dev_warn (rdev->dev,"Wait for MC idle timedout !\n" ); + } +evergreen_mc_resume (rdev, &save); +/* we need to own VRAM, so turn off the VGA renderer here +* to stop it overwriting our objects */ +rv515_vga_render_disable (rdev); +} + +/** +* cik_mc_init - initialize the memory controller driver params +* +* @rdev: radeon_device pointer +* +* Look up the amount of vram, vram width, and decide how to place +* vram and gart within the GPU's physical address space (CIK). +* Returns 0 for success. +*/ +static int cik_mc_init (struct radeon_device *rdev) +{ +u32 tmp; +int chansize, numchan; + +/* Get VRAM informations */ + rdev->mc.vram_is_ddr = true; + tmp =RREG32 (MC_ARB_RAMCFG ); +if (tmp &CHANSIZE_MASK ) { + chansize =64 ; + }else { + chansize =32 ; + } + tmp =RREG32 (MC_SHARED_CHMAP ); +switch ((tmp &NOOFCHAN_MASK ) >>NOOFCHAN_SHIFT ) { +case 0 : +default : + numchan =1 ; +break ; +case 1 : + numchan =2 ; +break ; +case 2 : + numchan =4 ; +break ; +case 3 : + numchan =8 ; +break ; +case 4 : + numchan =3 ; +break ; +case 5 : + numchan =6 ; +break ; +case 6 : + numchan =10 ; +break ; +case 7 : + numchan =12 ; +break ; +case 8 : + numchan =16 ; +break ; + } + rdev->mc.vram_width = numchan * chansize; +/* Could aper size report 0 ? */ + rdev->mc.aper_base =pci_resource_start (rdev->pdev,0 ); + rdev->mc.aper_size =pci_resource_len (rdev->pdev,0 ); +/* size in MB on si */ + rdev->mc.mc_vram_size =RREG32 (CONFIG_MEMSIZE ) *1024 *1024 ; + rdev->mc.real_vram_size =RREG32 (CONFIG_MEMSIZE ) *1024 *1024 ; + rdev->mc.visible_vram_size = rdev->mc.aper_size; +si_vram_gtt_location (rdev, &rdev->mc); +radeon_update_bandwidth_info (rdev); + +return 0 ; +} + +/* +* GART +* VMID 0 is the physical GPU addresses as used by the kernel. +* VMIDs 1-15 are used for userspace clients and are handled +* by the radeon vm/hsa code. +*/ +/** +* cik_pcie_gart_tlb_flush - gart tlb flush callback +* +* @rdev: radeon_device pointer +* +* Flush the TLB for the VMID 0 page table (CIK). +*/ +void cik_pcie_gart_tlb_flush (struct radeon_device *rdev) +{ +/* flush hdp cache */ +WREG32 (HDP_MEM_COHERENCY_FLUSH_CNTL ,0 ); + +/* bits 0-15 are the VM contexts0-15 */ +WREG32 (VM_INVALIDATE_REQUEST ,0x1 ); +} + +/** +* cik_pcie_gart_enable - gart enable +* +* @rdev: radeon_device pointer +* +* This sets up the TLBs, programs the page tables for VMID0, +* sets up the hw for VMIDs 1-15 which are allocated on +* demand, and sets up the global locations for the LDS, GDS, +* and GPUVM for FSA64 clients (CIK). +* Returns 0 for success, errors for failure. +*/ +static int cik_pcie_gart_enable (struct radeon_device *rdev) +{ +int r, i; + +if (rdev->gart.robj ==NULL ) { +dev_err (rdev->dev,"No VRAM object for PCIE GART.\n" ); +return -EINVAL ; + } + r =radeon_gart_table_vram_pin (rdev); +if (r) +return r; +radeon_gart_restore (rdev); +/* Setup TLB control */ +WREG32 (MC_VM_MX_L1_TLB_CNTL , + (0xA <<7 ) | +ENABLE_L1_TLB | +SYSTEM_ACCESS_MODE_NOT_IN_SYS | +ENABLE_ADVANCED_DRIVER_MODEL | +SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU ); +/* Setup L2 cache */ +WREG32 (VM_L2_CNTL ,ENABLE_L2_CACHE | +ENABLE_L2_FRAGMENT_PROCESSING | +ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | +ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE | +EFFECTIVE_L2_QUEUE_SIZE (7 ) | +CONTEXT1_IDENTITY_ACCESS_MODE (1 )); +WREG32 (VM_L2_CNTL2 ,INVALIDATE_ALL_L1_TLBS |INVALIDATE_L2_CACHE ); +WREG32 (VM_L2_CNTL3 ,L2_CACHE_BIGK_ASSOCIATIVITY | +L2_CACHE_BIGK_FRAGMENT_SIZE (6 )); +/* setup context0 */ +WREG32 (VM_CONTEXT0_PAGE_TABLE_START_ADDR , rdev->mc.gtt_start >>12 ); +WREG32 (VM_CONTEXT0_PAGE_TABLE_END_ADDR , rdev->mc.gtt_end >>12 ); +WREG32 (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR , rdev->gart.table_addr >>12 ); +WREG32 (VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR , + (u32)(rdev->dummy_page.addr >>12 )); +WREG32 (VM_CONTEXT0_CNTL2 ,0 ); +WREG32 (VM_CONTEXT0_CNTL , (ENABLE_CONTEXT |PAGE_TABLE_DEPTH (0 ) | +RANGE_PROTECTION_FAULT_ENABLE_DEFAULT )); + +WREG32 (0x15D4 ,0 ); +WREG32 (0x15D8 ,0 ); +WREG32 (0x15DC ,0 ); + +/* empty context1-15 */ +/* FIXME start with 4G, once using 2 level pt switch to full +* vm size space +*/ +/* set vm size, must be a multiple of 4 */ +WREG32 (VM_CONTEXT1_PAGE_TABLE_START_ADDR ,0 ); +WREG32 (VM_CONTEXT1_PAGE_TABLE_END_ADDR , rdev->vm_manager.max_pfn); +for (i =1 ; i <16 ; i++) { +if (i <8 ) +WREG32 (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i <<2 ), + rdev->gart.table_addr >>12 ); +else +WREG32 (VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((i -8 ) <<2 ), + rdev->gart.table_addr >>12 ); + } + +/* enable context1-15 */ +WREG32 (VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR , + (u32)(rdev->dummy_page.addr >>12 )); +WREG32 (VM_CONTEXT1_CNTL2 ,0 ); +WREG32 (VM_CONTEXT1_CNTL ,ENABLE_CONTEXT |PAGE_TABLE_DEPTH (1 ) | +RANGE_PROTECTION_FAULT_ENABLE_DEFAULT ); + +/* TC cache setup ??? */ +WREG32 (TC_CFG_L1_LOAD_POLICY0 ,0 ); +WREG32 (TC_CFG_L1_LOAD_POLICY1 ,0 ); +WREG32 (TC_CFG_L1_STORE_POLICY ,0 ); + +WREG32 (TC_CFG_L2_LOAD_POLICY0 ,0 ); +WREG32 (TC_CFG_L2_LOAD_POLICY1 ,0 ); +WREG32 (TC_CFG_L2_STORE_POLICY0 ,0 ); +WREG32 (TC_CFG_L2_STORE_POLICY1 ,0 ); +WREG32 (TC_CFG_L2_ATOMIC_POLICY ,0 ); + +WREG32 (TC_CFG_L1_VOLATILE ,0 ); +WREG32 (TC_CFG_L2_VOLATILE ,0 ); + +if (rdev->family ==CHIP_KAVERI ) { +u32 tmp =RREG32 (CHUB_CONTROL ); + tmp &= ~BYPASS_VM ; +WREG32 (CHUB_CONTROL , tmp); + } + +/* XXX SH_MEM regs */ +/* where to put LDS, scratch, GPUVM in FSA64 space */ +for (i =0 ; i <16 ; i++) { +WREG32 (SRBM_GFX_CNTL ,VMID (i)); +WREG32 (SH_MEM_CONFIG ,0 ); +WREG32 (SH_MEM_APE1_BASE ,1 ); +WREG32 (SH_MEM_APE1_LIMIT ,0 ); +WREG32 (SH_MEM_BASES ,0 ); + } +WREG32 (SRBM_GFX_CNTL ,0 ); + +cik_pcie_gart_tlb_flush (rdev); +DRM_INFO ("PCIE GART of %uM enabled (table at 0x%016llX).\n" , + (unsigned )(rdev->mc.gtt_size >>20 ), + (unsigned long long )rdev->gart.table_addr); + rdev->gart.ready = true; +return 0 ; +} + +/** +* cik_pcie_gart_disable - gart disable +* +* @rdev: radeon_device pointer +* +* This disables all VM page table (CIK). +*/ +static void cik_pcie_gart_disable (struct radeon_device *rdev) +{ +/* Disable all tables */ +WREG32 (VM_CONTEXT0_CNTL ,0 ); +WREG32 (VM_CONTEXT1_CNTL ,0 ); +/* Setup TLB control */ +WREG32 (MC_VM_MX_L1_TLB_CNTL ,SYSTEM_ACCESS_MODE_NOT_IN_SYS | +SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU ); +/* Setup L2 cache */ +WREG32 (VM_L2_CNTL , +ENABLE_L2_FRAGMENT_PROCESSING | +ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | +ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE | +EFFECTIVE_L2_QUEUE_SIZE (7 ) | +CONTEXT1_IDENTITY_ACCESS_MODE (1 )); +WREG32 (VM_L2_CNTL2 ,0 ); +WREG32 (VM_L2_CNTL3 ,L2_CACHE_BIGK_ASSOCIATIVITY | +L2_CACHE_BIGK_FRAGMENT_SIZE (6 )); +radeon_gart_table_vram_unpin (rdev); +} + +/** +* cik_pcie_gart_fini - vm fini callback +* +* @rdev: radeon_device pointer +* +* Tears down the driver GART/VM setup (CIK). +*/ +static void cik_pcie_gart_fini (struct radeon_device *rdev) +{ +cik_pcie_gart_disable (rdev); +radeon_gart_table_vram_free (rdev); +radeon_gart_fini (rdev); +} + +/* vm parser */ +/** +* cik_ib_parse - vm ib_parse callback +* +* @rdev: radeon_device pointer +* @ib: indirect buffer pointer +* +* CIK uses hw IB checking so this is a nop (CIK). +*/ +int cik_ib_parse (struct radeon_device *rdev,struct radeon_ib *ib) +{ +return 0 ; +} + +/* +* vm +* VMID 0 is the physical GPU addresses as used by the kernel. +* VMIDs 1-15 are used for userspace clients and are handled +* by the radeon vm/hsa code. +*/ +/** +* cik_vm_init - cik vm init callback +* +* @rdev: radeon_device pointer +* +* Inits cik specific vm parameters (number of VMs, base of vram for +* VMIDs 1-15) (CIK). +* Returns 0 for success. +*/ +int cik_vm_init (struct radeon_device *rdev) +{ +/* number of VMs */ + rdev->vm_manager.nvm =16 ; +/* base offset of vram pages */ +if (rdev->flags &RADEON_IS_IGP ) { +u64 tmp =RREG32 (MC_VM_FB_OFFSET ); + tmp <<=22 ; + rdev->vm_manager.vram_base_offset = tmp; + }else + rdev->vm_manager.vram_base_offset =0 ; + +return 0 ; +} + +/** +* cik_vm_fini - cik vm fini callback +* +* @rdev: radeon_device pointer +* +* Tear down any asic specific VM setup (CIK). +*/ +void cik_vm_fini (struct radeon_device *rdev) +{ +} +
drivers/gpu/drm/radeon/cikd.h +125 -0
163 lines not on this page · raw message
drivers/gpu/drm/radeon/si.c +2 -2
@@ -3535,8 +3535,8 @@ static void si_mc_program(struct radeon_device *rdev) } } -static void si_vram_gtt_location (struct radeon_device *rdev, -struct radeon_mc *mc) +void si_vram_gtt_location (struct radeon_device *rdev, +struct radeon_mc *mc) {if (mc->mc_vram_size >0xFFC0000000ULL ) {/* leave room for at least 1024M GTT */
Signature · 1 line
1.7.7.5
PATCH 10/165 drm/radeon/cik: stop page faults from hanging the system (v2)
In reply to [email protected]From: Alex Deucher <[email protected]>
Redirect invalid memory accesses to the default page instead of locking up the memory controller.
v2: rebase on top of 2 level PTs
--- drivers/gpu/drm/radeon/cik.c | 15 +++++++++++++-- drivers/gpu/drm/radeon/cikd.h | 11 +++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-)
drivers/gpu/drm/radeon/cik.c +13 -2
@@ -1608,9 +1608,20 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev)/* enable context1-15 */ WREG32 (VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR , (u32)(rdev->dummy_page.addr >>12 )); -WREG32 (VM_CONTEXT1_CNTL2 ,0 ); +WREG32 (VM_CONTEXT1_CNTL2 ,4 );WREG32 (VM_CONTEXT1_CNTL ,ENABLE_CONTEXT |PAGE_TABLE_DEPTH (1 ) | -RANGE_PROTECTION_FAULT_ENABLE_DEFAULT ); +RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT | +RANGE_PROTECTION_FAULT_ENABLE_DEFAULT | +DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT | +DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT | +PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT | +PDE0_PROTECTION_FAULT_ENABLE_DEFAULT | +VALID_PROTECTION_FAULT_ENABLE_INTERRUPT | +VALID_PROTECTION_FAULT_ENABLE_DEFAULT | +READ_PROTECTION_FAULT_ENABLE_INTERRUPT | +READ_PROTECTION_FAULT_ENABLE_DEFAULT | +WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT | +WRITE_PROTECTION_FAULT_ENABLE_DEFAULT );/* TC cache setup ??? */ WREG32 (TC_CFG_L1_LOAD_POLICY0 ,0 );
drivers/gpu/drm/radeon/cikd.h +11 -0
@@ -68,7 +68,18 @@#define VM_CONTEXT0_CNTL 0x1410#define ENABLE_CONTEXT (1 << 0)#define PAGE_TABLE_DEPTH (x) (((x) & 3) << 1) +#define RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 3)#define RANGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 4) +#define DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 6) +#define DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 7) +#define PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 9) +#define PDE0_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 10) +#define VALID_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 12) +#define VALID_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 13) +#define READ_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 15) +#define READ_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 16) +#define WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 18) +#define WRITE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 19)#define VM_CONTEXT1_CNTL 0x1414#define VM_CONTEXT0_CNTL2 0x1430#define VM_CONTEXT1_CNTL2 0x1434
Signature · 1 line
1.7.7.5
PATCH 11/165 drm/radeon: add initial ucode loading for CIK (v5)
In reply to [email protected]From: Alex Deucher <[email protected]>
Currently the driver required 6 sets of ucode:
1. pfp - pre-fetch parser, part of the GFX CP
2. me - micro engine, part of the GFX CP
3. ce - constant engine, part of the GFX CP
4. rlc - interrupt, etc. controller
5. mc - memory controller (discrete cards only)
6. mec - compute engines, part of Compute CP
V2: add documentation
V3: update MC ucode
V4: rebase
V5: update mc ucode
--- drivers/gpu/drm/radeon/cik.c | 180 +++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon.h | 1 + 2 files changed, 181 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/cik.c +180 -0
@@ -31,10 +31,190 @@#include "cikd.h" #include "atom.h" +/* GFX */ +#define CIK_PFP_UCODE_SIZE 2144 +#define CIK_ME_UCODE_SIZE 2144 +#define CIK_CE_UCODE_SIZE 2144 +/* compute */ +#define CIK_MEC_UCODE_SIZE 4192 +/* interrupts */ +#define BONAIRE_RLC_UCODE_SIZE 2048 +#define KB_RLC_UCODE_SIZE 2560 +#define KV_RLC_UCODE_SIZE 2560 +/* gddr controller */ +#define CIK_MC_UCODE_SIZE 7866 + +MODULE_FIRMWARE ("radeon/BONAIRE_pfp.bin" ); +MODULE_FIRMWARE ("radeon/BONAIRE_me.bin" ); +MODULE_FIRMWARE ("radeon/BONAIRE_ce.bin" ); +MODULE_FIRMWARE ("radeon/BONAIRE_mec.bin" ); +MODULE_FIRMWARE ("radeon/BONAIRE_mc.bin" ); +MODULE_FIRMWARE ("radeon/BONAIRE_rlc.bin" ); +MODULE_FIRMWARE ("radeon/KAVERI_pfp.bin" ); +MODULE_FIRMWARE ("radeon/KAVERI_me.bin" ); +MODULE_FIRMWARE ("radeon/KAVERI_ce.bin" ); +MODULE_FIRMWARE ("radeon/KAVERI_mec.bin" ); +MODULE_FIRMWARE ("radeon/KAVERI_rlc.bin" ); +MODULE_FIRMWARE ("radeon/KABINI_pfp.bin" ); +MODULE_FIRMWARE ("radeon/KABINI_me.bin" ); +MODULE_FIRMWARE ("radeon/KABINI_ce.bin" ); +MODULE_FIRMWARE ("radeon/KABINI_mec.bin" ); +MODULE_FIRMWARE ("radeon/KABINI_rlc.bin" ); +extern void evergreen_mc_stop (struct radeon_device *rdev,struct evergreen_mc_save *save);extern void evergreen_mc_resume (struct radeon_device *rdev,struct evergreen_mc_save *save);extern void si_vram_gtt_location (struct radeon_device *rdev,struct radeon_mc *mc); +/** +* cik_init_microcode - load ucode images from disk +* +* @rdev: radeon_device pointer +* +* Use the firmware interface to load the ucode images into +* the driver (not loaded into hw). +* Returns 0 on success, error on failure. +*/ +static int cik_init_microcode (struct radeon_device *rdev) +{ +struct platform_device *pdev; +const char *chip_name; +size_t pfp_req_size, me_req_size, ce_req_size, + mec_req_size, rlc_req_size, mc_req_size; +char fw_name[30 ]; +int err; + +DRM_DEBUG ("\n" ); + + pdev =platform_device_register_simple ("radeon_cp" ,0 ,NULL ,0 ); + err =IS_ERR (pdev); +if (err) { +printk (KERN_ERR "radeon_cp: Failed to register firmware\n" ); +return -EINVAL ; + } + +switch (rdev->family) { +case CHIP_BONAIRE : + chip_name ="BONAIRE" ; + pfp_req_size =CIK_PFP_UCODE_SIZE *4 ; + me_req_size =CIK_ME_UCODE_SIZE *4 ; + ce_req_size =CIK_CE_UCODE_SIZE *4 ; + mec_req_size =CIK_MEC_UCODE_SIZE *4 ; + rlc_req_size =BONAIRE_RLC_UCODE_SIZE *4 ; + mc_req_size =CIK_MC_UCODE_SIZE *4 ; +break ; +case CHIP_KAVERI : + chip_name ="KAVERI" ; + pfp_req_size =CIK_PFP_UCODE_SIZE *4 ; + me_req_size =CIK_ME_UCODE_SIZE *4 ; + ce_req_size =CIK_CE_UCODE_SIZE *4 ; + mec_req_size =CIK_MEC_UCODE_SIZE *4 ; + rlc_req_size =KV_RLC_UCODE_SIZE *4 ; +break ; +case CHIP_KABINI : + chip_name ="KABINI" ; + pfp_req_size =CIK_PFP_UCODE_SIZE *4 ; + me_req_size =CIK_ME_UCODE_SIZE *4 ; + ce_req_size =CIK_CE_UCODE_SIZE *4 ; + mec_req_size =CIK_MEC_UCODE_SIZE *4 ; + rlc_req_size =KB_RLC_UCODE_SIZE *4 ; +break ; +default :BUG (); + } + +DRM_INFO ("Loading %s Microcode\n" , chip_name); + +snprintf (fw_name,sizeof (fw_name),"radeon/%s_pfp.bin" , chip_name); + err =request_firmware (&rdev->pfp_fw, fw_name, &pdev->dev); +if (err) + goto out; +if (rdev->pfp_fw->size != pfp_req_size) { +printk (KERN_ERR +"cik_cp: Bogus length %zu in firmware \"%s\"\n" , + rdev->pfp_fw->size, fw_name); + err = -EINVAL ; + goto out; + } + +snprintf (fw_name,sizeof (fw_name),"radeon/%s_me.bin" , chip_name); + err =request_firmware (&rdev->me_fw, fw_name, &pdev->dev); +if (err) + goto out; +if (rdev->me_fw->size != me_req_size) { +printk (KERN_ERR +"cik_cp: Bogus length %zu in firmware \"%s\"\n" , + rdev->me_fw->size, fw_name); + err = -EINVAL ; + } + +snprintf (fw_name,sizeof (fw_name),"radeon/%s_ce.bin" , chip_name); + err =request_firmware (&rdev->ce_fw, fw_name, &pdev->dev); +if (err) + goto out; +if (rdev->ce_fw->size != ce_req_size) { +printk (KERN_ERR +"cik_cp: Bogus length %zu in firmware \"%s\"\n" , + rdev->ce_fw->size, fw_name); + err = -EINVAL ; + } + +snprintf (fw_name,sizeof (fw_name),"radeon/%s_mec.bin" , chip_name); + err =request_firmware (&rdev->mec_fw, fw_name, &pdev->dev); +if (err) + goto out; +if (rdev->mec_fw->size != mec_req_size) { +printk (KERN_ERR +"cik_cp: Bogus length %zu in firmware \"%s\"\n" , + rdev->mec_fw->size, fw_name); + err = -EINVAL ; + } + +snprintf (fw_name,sizeof (fw_name),"radeon/%s_rlc.bin" , chip_name); + err =request_firmware (&rdev->rlc_fw, fw_name, &pdev->dev); +if (err) + goto out; +if (rdev->rlc_fw->size != rlc_req_size) { +printk (KERN_ERR +"cik_rlc: Bogus length %zu in firmware \"%s\"\n" , + rdev->rlc_fw->size, fw_name); + err = -EINVAL ; + } + +/* No MC ucode on APUs */ +if (!(rdev->flags &RADEON_IS_IGP )) { +snprintf (fw_name,sizeof (fw_name),"radeon/%s_mc.bin" , chip_name); + err =request_firmware (&rdev->mc_fw, fw_name, &pdev->dev); +if (err) + goto out; +if (rdev->mc_fw->size != mc_req_size) { +printk (KERN_ERR +"cik_mc: Bogus length %zu in firmware \"%s\"\n" , + rdev->mc_fw->size, fw_name); + err = -EINVAL ; + } + } + +out: +platform_device_unregister (pdev); + +if (err) { +if (err != -EINVAL ) +printk (KERN_ERR +"cik_cp: Failed to load firmware \"%s\"\n" , + fw_name); +release_firmware (rdev->pfp_fw); + rdev->pfp_fw =NULL ; +release_firmware (rdev->me_fw); + rdev->me_fw =NULL ; +release_firmware (rdev->ce_fw); + rdev->ce_fw =NULL ; +release_firmware (rdev->rlc_fw); + rdev->rlc_fw =NULL ; +release_firmware (rdev->mc_fw); + rdev->mc_fw =NULL ; + } +return err; +} +/* * Core functions */
drivers/gpu/drm/radeon/radeon.h +1 -0
@@ -1714,6 +1714,7 @@ struct radeon_device {const struct firmware *mc_fw;/* NI MC firmware */ const struct firmware *ce_fw;/* SI CE firmware */ const struct firmware *uvd_fw;/* UVD firmware */ +const struct firmware *mec_fw;/* CIK MEC firmware */ struct r600_blit r600_blit;struct r600_vram_scratch vram_scratch;int msi_enabled;/* msi enabled */
Signature · 1 line
1.7.7.5
PATCH 12/165 drm/radeon: add support mc ucode loading on CIK (v2)
In reply to [email protected]From: Alex Deucher <[email protected]>
Load the GDDR5 ucode and train the links.
v2: update ucode
--- drivers/gpu/drm/radeon/cik.c | 116 +++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/cikd.h | 16 ++++++ 2 files changed, 132 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/cik.c +116 -0
@@ -65,6 +65,122 @@ extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_saextern void evergreen_mc_resume (struct radeon_device *rdev,struct evergreen_mc_save *save);extern void si_vram_gtt_location (struct radeon_device *rdev,struct radeon_mc *mc); +#define BONAIRE_IO_MC_REGS_SIZE 36 + +static const u32 bonaire_io_mc_regs[BONAIRE_IO_MC_REGS_SIZE ][2 ] = +{ + {0x00000070 ,0x04400000 }, + {0x00000071 ,0x80c01803 }, + {0x00000072 ,0x00004004 }, + {0x00000073 ,0x00000100 }, + {0x00000074 ,0x00ff0000 }, + {0x00000075 ,0x34000000 }, + {0x00000076 ,0x08000014 }, + {0x00000077 ,0x00cc08ec }, + {0x00000078 ,0x00000400 }, + {0x00000079 ,0x00000000 }, + {0x0000007a ,0x04090000 }, + {0x0000007c ,0x00000000 }, + {0x0000007e ,0x4408a8e8 }, + {0x0000007f ,0x00000304 }, + {0x00000080 ,0x00000000 }, + {0x00000082 ,0x00000001 }, + {0x00000083 ,0x00000002 }, + {0x00000084 ,0xf3e4f400 }, + {0x00000085 ,0x052024e3 }, + {0x00000087 ,0x00000000 }, + {0x00000088 ,0x01000000 }, + {0x0000008a ,0x1c0a0000 }, + {0x0000008b ,0xff010000 }, + {0x0000008d ,0xffffefff }, + {0x0000008e ,0xfff3efff }, + {0x0000008f ,0xfff3efbf }, + {0x00000092 ,0xf7ffffff }, + {0x00000093 ,0xffffff7f }, + {0x00000095 ,0x00101101 }, + {0x00000096 ,0x00000fff }, + {0x00000097 ,0x00116fff }, + {0x00000098 ,0x60010000 }, + {0x00000099 ,0x10010000 }, + {0x0000009a ,0x00006000 }, + {0x0000009b ,0x00001000 }, + {0x0000009f ,0x00b48000 } +}; + +/* ucode loading */ +/** +* ci_mc_load_microcode - load MC ucode into the hw +* +* @rdev: radeon_device pointer +* +* Load the GDDR MC ucode into the hw (CIK). +* Returns 0 on success, error on failure. +*/ +static int ci_mc_load_microcode (struct radeon_device *rdev) +{ +const __be32 *fw_data; +u32 running, blackout =0 ; +u32 *io_mc_regs; +int i, ucode_size, regs_size; + +if (!rdev->mc_fw) +return -EINVAL ; + +switch (rdev->family) { +case CHIP_BONAIRE : +default : + io_mc_regs = (u32 *)&bonaire_io_mc_regs; + ucode_size =CIK_MC_UCODE_SIZE ; + regs_size =BONAIRE_IO_MC_REGS_SIZE ; +break ; + } + + running =RREG32 (MC_SEQ_SUP_CNTL ) &RUN_MASK ; + +if (running ==0 ) { +if (running) { + blackout =RREG32 (MC_SHARED_BLACKOUT_CNTL ); +WREG32 (MC_SHARED_BLACKOUT_CNTL , blackout |1 ); + } + +/* reset the engine and set to writable */ +WREG32 (MC_SEQ_SUP_CNTL ,0x00000008 ); +WREG32 (MC_SEQ_SUP_CNTL ,0x00000010 ); + +/* load mc io regs */ +for (i =0 ; i < regs_size; i++) { +WREG32 (MC_SEQ_IO_DEBUG_INDEX , io_mc_regs[(i <<1 )]); +WREG32 (MC_SEQ_IO_DEBUG_DATA , io_mc_regs[(i <<1 ) +1 ]); + } +/* load the MC ucode */ + fw_data = (const __be32 *)rdev->mc_fw->data; +for (i =0 ; i < ucode_size; i++) +WREG32 (MC_SEQ_SUP_PGM ,be32_to_cpup (fw_data++)); + +/* put the engine back into the active state */ +WREG32 (MC_SEQ_SUP_CNTL ,0x00000008 ); +WREG32 (MC_SEQ_SUP_CNTL ,0x00000004 ); +WREG32 (MC_SEQ_SUP_CNTL ,0x00000001 ); + +/* wait for training to complete */ +for (i =0 ; i < rdev->usec_timeout; i++) { +if (RREG32 (MC_SEQ_TRAIN_WAKEUP_CNTL ) &TRAIN_DONE_D0 ) +break ; +udelay (1 ); + } +for (i =0 ; i < rdev->usec_timeout; i++) { +if (RREG32 (MC_SEQ_TRAIN_WAKEUP_CNTL ) &TRAIN_DONE_D1 ) +break ; +udelay (1 ); + } + +if (running) +WREG32 (MC_SHARED_BLACKOUT_CNTL , blackout); + } + +return 0 ; +} +/** * cik_init_microcode - load ucode images from disk *
drivers/gpu/drm/radeon/cikd.h +16 -0
@@ -139,6 +139,8 @@#define ENABLE_ADVANCED_DRIVER_MODEL (1 << 6)#define MC_VM_FB_OFFSET 0x2068 +#define MC_SHARED_BLACKOUT_CNTL 0x20ac +#define MC_ARB_RAMCFG 0x2760#define NOOFBANK_SHIFT 0#define NOOFBANK_MASK 0x00000003
@@ -153,6 +155,20 @@#define NOOFGROUPS_SHIFT 12#define NOOFGROUPS_MASK 0x00001000 +#define MC_SEQ_SUP_CNTL 0x28c8 +#define RUN_MASK (1 << 0) +#define MC_SEQ_SUP_PGM 0x28cc + +#define MC_SEQ_TRAIN_WAKEUP_CNTL 0x28e8 +#define TRAIN_DONE_D0 (1 << 30) +#define TRAIN_DONE_D1 (1 << 31) + +#define MC_IO_PAD_CNTL_D0 0x29d0 +#define MEM_FALL_OUT_CMD (1 << 8) + +#define MC_SEQ_IO_DEBUG_INDEX 0x2a44 +#define MC_SEQ_IO_DEBUG_DATA 0x2a48 +#define HDP_HOST_PATH_CNTL 0x2C00#define HDP_NONSURFACE_BASE 0x2C04#define HDP_NONSURFACE_INFO 0x2C08
Signature · 1 line
1.7.7.5
PATCH 13/165 drm/radeon: Add CP init for CIK (v7)
In reply to [email protected]From: Alex Deucher <[email protected]>
Sets up the GFX ring and loads ucode for GFX and Compute.
Todo:
- handle compute queue setup.
v2: add documentation
v3: integrate with latest reset changes
v4: additional init fixes
v5: scratch reg write back no longer supported on CIK
v6: properly set CP_RB0_BASE_HI
v7: rebase
--- drivers/gpu/drm/radeon/Makefile | 2 +- drivers/gpu/drm/radeon/cik.c | 395 +++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/cik_blit_shaders.c | 246 ++++++++++++++++++ drivers/gpu/drm/radeon/cik_blit_shaders.h | 32 +++ drivers/gpu/drm/radeon/cikd.h | 222 ++++++++++++++++ drivers/gpu/drm/radeon/radeon_cs.c | 4 +- 6 files changed, 899 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/radeon/cik_blit_shaders.c create mode 100644 drivers/gpu/drm/radeon/cik_blit_shaders.h
drivers/gpu/drm/radeon/Makefile +1 -1
@@ -76,7 +76,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \ evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o \ evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \ atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \ - si_blit_shaders.o radeon_prime.o radeon_uvd.o cik.o + si_blit_shaders.o radeon_prime.o radeon_uvd.o cik.o cik_blit_shaders.o radeon-$(CONFIG_COMPAT) += radeon_ioc32.o radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
drivers/gpu/drm/radeon/cik.c +395 -0
407 lines not on this page · raw message
drivers/gpu/drm/radeon/cik_blit_shaders.c new file +246 -0
246 lines not on this page · raw message
drivers/gpu/drm/radeon/cik_blit_shaders.h new file +32 -0
@@ -0,0 +1,32 @@ +/* +* Copyright 2012 Advanced Micro Devices, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice (including the next +* paragraph) shall be included in all copies or substantial portions of the +* Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +* DEALINGS IN THE SOFTWARE. +* +*/ + +#ifndef CIK_BLIT_SHADERS_H +#define CIK_BLIT_SHADERS_H + +extern const u32 cik_default_state[]; + +extern const u32 cik_default_size; + +#endif
drivers/gpu/drm/radeon/cikd.h +222 -0
249 lines not on this page · raw message
drivers/gpu/drm/radeon/radeon_cs.c +3 -1
@@ -121,7 +121,9 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority p->ring =RADEON_RING_TYPE_GFX_INDEX ;break ;case RADEON_CS_RING_COMPUTE : -if (p->rdev->family >=CHIP_TAHITI ) { +if (p->rdev->family >=CHIP_BONAIRE ) + p->ring =RADEON_RING_TYPE_GFX_INDEX ; +else if (p->rdev->family >=CHIP_TAHITI ) {if (p->priority >0 ) p->ring =CAYMAN_RING_TYPE_CP1_INDEX ;else
Signature · 1 line
1.7.7.5
PATCH 14/165 drm/radeon: add IB and fence dispatch functions for CIK gfx (v7)
In reply to [email protected]From: Alex Deucher <[email protected]>
For gfx ring only. Compute is still todo.
v2: add documentation
v3: update to latest reset changes, integrate emit update patch.
v4: fix count on wait_reg_mem for HDP flush
v5: use old hdp flush method for fence
v6: set valid bit for IB
v7: cleanup for release
--- drivers/gpu/drm/radeon/cik.c | 134 +++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/cikd.h | 120 +++++++++++++++++++++++++++++++++++- 2 files changed, 251 insertions(+), 3 deletions(-)
drivers/gpu/drm/radeon/cik.c +134 -0
@@ -1493,6 +1493,140 @@ static void cik_gpu_init(struct radeon_device *rdev) }/* +* GPU scratch registers helpers function. +*/ +/** +* cik_scratch_init - setup driver info for CP scratch regs +* +* @rdev: radeon_device pointer +* +* Set up the number and offset of the CP scratch registers. +* NOTE: use of CP scratch registers is a legacy inferface and +* is not used by default on newer asics (r6xx+). On newer asics, +* memory buffers are used for fences rather than scratch regs. +*/ +static void cik_scratch_init (struct radeon_device *rdev) +{ +int i; + + rdev->scratch.num_reg =7 ; + rdev->scratch.reg_base =SCRATCH_REG0 ; +for (i =0 ; i < rdev->scratch.num_reg; i++) { + rdev->scratch.free[i] = true; + rdev->scratch.reg[i] = rdev->scratch.reg_base + (i *4 ); + } +} + +/** +* cik_fence_ring_emit - emit a fence on the gfx ring +* +* @rdev: radeon_device pointer +* @fence: radeon fence object +* +* Emits a fence sequnce number on the gfx ring and flushes +* GPU caches. +*/ +void cik_fence_ring_emit (struct radeon_device *rdev, +struct radeon_fence *fence) +{ +struct radeon_ring *ring = &rdev->ring[fence->ring]; +u64 addr = rdev->fence_drv[fence->ring].gpu_addr; + +/* EVENT_WRITE_EOP - flush caches, send int */ +radeon_ring_write (ring,PACKET3 (PACKET3_EVENT_WRITE_EOP ,4 )); +radeon_ring_write (ring, (EOP_TCL1_ACTION_EN | +EOP_TC_ACTION_EN | +EVENT_TYPE (CACHE_FLUSH_AND_INV_TS_EVENT ) | +EVENT_INDEX (5 ))); +radeon_ring_write (ring, addr &0xfffffffc ); +radeon_ring_write (ring, (upper_32_bits (addr) &0xffff ) |DATA_SEL (1 ) |INT_SEL (2 )); +radeon_ring_write (ring, fence->seq); +radeon_ring_write (ring,0 ); +/* HDP flush */ +/* We should be using the new WAIT_REG_MEM special op packet here +* but it causes the CP to hang +*/ +radeon_ring_write (ring,PACKET3 (PACKET3_WRITE_DATA ,3 )); +radeon_ring_write (ring, (WRITE_DATA_ENGINE_SEL (0 ) | +WRITE_DATA_DST_SEL (0 ))); +radeon_ring_write (ring,HDP_MEM_COHERENCY_FLUSH_CNTL >>2 ); +radeon_ring_write (ring,0 ); +radeon_ring_write (ring,0 ); +} + +void cik_semaphore_ring_emit (struct radeon_device *rdev, +struct radeon_ring *ring, +struct radeon_semaphore *semaphore, +bool emit_wait) +{ +uint64_t addr = semaphore->gpu_addr; +unsigned sel = emit_wait ?PACKET3_SEM_SEL_WAIT :PACKET3_SEM_SEL_SIGNAL ; + +radeon_ring_write (ring,PACKET3 (PACKET3_MEM_SEMAPHORE ,1 )); +radeon_ring_write (ring, addr &0xffffffff ); +radeon_ring_write (ring, (upper_32_bits (addr) &0xffff ) | sel); +} + +/* +* IB stuff +*/ +/** +* cik_ring_ib_execute - emit an IB (Indirect Buffer) on the gfx ring +* +* @rdev: radeon_device pointer +* @ib: radeon indirect buffer object +* +* Emits an DE (drawing engine) or CE (constant engine) IB +* on the gfx ring. IBs are usually generated by userspace +* acceleration drivers and submitted to the kernel for +* sheduling on the ring. This function schedules the IB +* on the gfx ring for execution by the GPU. +*/ +void cik_ring_ib_execute (struct radeon_device *rdev,struct radeon_ib *ib) +{ +struct radeon_ring *ring = &rdev->ring[ib->ring]; +u32 header, control =INDIRECT_BUFFER_VALID ; + +if (ib->is_const_ib) { +/* set switch buffer packet before const IB */ +radeon_ring_write (ring,PACKET3 (PACKET3_SWITCH_BUFFER ,0 )); +radeon_ring_write (ring,0 ); + + header =PACKET3 (PACKET3_INDIRECT_BUFFER_CONST ,2 ); + }else { +u32 next_rptr; +if (ring->rptr_save_reg) { + next_rptr = ring->wptr +3 +4 ; +radeon_ring_write (ring,PACKET3 (PACKET3_SET_UCONFIG_REG ,1 )); +radeon_ring_write (ring, ((ring->rptr_save_reg - +PACKET3_SET_UCONFIG_REG_START ) >>2 )); +radeon_ring_write (ring, next_rptr); + }else if (rdev->wb.enabled) { + next_rptr = ring->wptr +5 +4 ; +radeon_ring_write (ring,PACKET3 (PACKET3_WRITE_DATA ,3 )); +radeon_ring_write (ring,WRITE_DATA_DST_SEL (1 )); +radeon_ring_write (ring, ring->next_rptr_gpu_addr &0xfffffffc ); +radeon_ring_write (ring,upper_32_bits (ring->next_rptr_gpu_addr) &0xffffffff ); +radeon_ring_write (ring, next_rptr); + } + + header =PACKET3 (PACKET3_INDIRECT_BUFFER ,2 ); + } + + control |= ib->length_dw | + (ib->vm ? (ib->vm->id <<24 ) :0 ); + +radeon_ring_write (ring, header); +radeon_ring_write (ring, +#ifdef __BIG_ENDIAN + (2 <<0 ) | +#endif + (ib->gpu_addr &0xFFFFFFFC )); +radeon_ring_write (ring,upper_32_bits (ib->gpu_addr) &0xFFFF ); +radeon_ring_write (ring, control); +} + +/* * CP. * On CIK, gfx and compute now have independant command processors. *
drivers/gpu/drm/radeon/cikd.h +117 -3
170 lines not on this page · raw message
Signature · 1 line
1.7.7.5
PATCH 15/165 drm/radeon: add ring and IB tests for CIK (v3)
In reply to [email protected]From: Alex Deucher <[email protected]>
v2: add documenation
v3: update the latest ib changes
--- drivers/gpu/drm/radeon/cik.c | 114 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 114 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/cik.c +114 -0
@@ -1518,6 +1518,57 @@ static void cik_scratch_init(struct radeon_device *rdev) }/** +* cik_ring_test - basic gfx ring test +* +* @rdev: radeon_device pointer +* @ring: radeon_ring structure holding ring information +* +* Allocate a scratch register and write to it using the gfx ring (CIK). +* Provides a basic gfx ring test to verify that the ring is working. +* Used by cik_cp_gfx_resume(); +* Returns 0 on success, error on failure. +*/ +int cik_ring_test (struct radeon_device *rdev,struct radeon_ring *ring) +{ +uint32_t scratch; +uint32_t tmp =0 ; +unsigned i; +int r; + + r =radeon_scratch_get (rdev, &scratch); +if (r) { +DRM_ERROR ("radeon: cp failed to get scratch reg (%d).\n" , r); +return r; + } +WREG32 (scratch,0xCAFEDEAD ); + r =radeon_ring_lock (rdev, ring,3 ); +if (r) { +DRM_ERROR ("radeon: cp failed to lock ring %d (%d).\n" , ring->idx, r); +radeon_scratch_free (rdev, scratch); +return r; + } +radeon_ring_write (ring,PACKET3 (PACKET3_SET_UCONFIG_REG ,1 )); +radeon_ring_write (ring, ((scratch -PACKET3_SET_UCONFIG_REG_START ) >>2 )); +radeon_ring_write (ring,0xDEADBEEF ); +radeon_ring_unlock_commit (rdev, ring); +for (i =0 ; i < rdev->usec_timeout; i++) { + tmp =RREG32 (scratch); +if (tmp ==0xDEADBEEF ) +break ; +DRM_UDELAY (1 ); + } +if (i < rdev->usec_timeout) { +DRM_INFO ("ring test on %d succeeded in %d usecs\n" , ring->idx, i); + }else { +DRM_ERROR ("radeon: ring %d test failed (scratch(0x%04X)=0x%08X)\n" , + ring->idx, scratch, tmp); + r = -EINVAL ; + } +radeon_scratch_free (rdev, scratch); +return r; +} + +/** * cik_fence_ring_emit - emit a fence on the gfx ring * * @rdev: radeon_device pointer
@@ -1626,6 +1677,69 @@ void cik_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)radeon_ring_write (ring, control); } +/** +* cik_ib_test - basic gfx ring IB test +* +* @rdev: radeon_device pointer +* @ring: radeon_ring structure holding ring information +* +* Allocate an IB and execute it on the gfx ring (CIK). +* Provides a basic gfx ring test to verify that IBs are working. +* Returns 0 on success, error on failure. +*/ +int cik_ib_test (struct radeon_device *rdev,struct radeon_ring *ring) +{ +struct radeon_ib ib; +uint32_t scratch; +uint32_t tmp =0 ; +unsigned i; +int r; + + r =radeon_scratch_get (rdev, &scratch); +if (r) { +DRM_ERROR ("radeon: failed to get scratch reg (%d).\n" , r); +return r; + } +WREG32 (scratch,0xCAFEDEAD ); + r =radeon_ib_get (rdev, ring->idx, &ib,NULL ,256 ); +if (r) { +DRM_ERROR ("radeon: failed to get ib (%d).\n" , r); +return r; + } + ib.ptr[0 ] =PACKET3 (PACKET3_SET_UCONFIG_REG ,1 ); + ib.ptr[1 ] = ((scratch -PACKET3_SET_UCONFIG_REG_START ) >>2 ); + ib.ptr[2 ] =0xDEADBEEF ; + ib.length_dw =3 ; + r =radeon_ib_schedule (rdev, &ib,NULL ); +if (r) { +radeon_scratch_free (rdev, scratch); +radeon_ib_free (rdev, &ib); +DRM_ERROR ("radeon: failed to schedule ib (%d).\n" , r); +return r; + } + r =radeon_fence_wait (ib.fence, false); +if (r) { +DRM_ERROR ("radeon: fence wait failed (%d).\n" , r); +return r; + } +for (i =0 ; i < rdev->usec_timeout; i++) { + tmp =RREG32 (scratch); +if (tmp ==0xDEADBEEF ) +break ; +DRM_UDELAY (1 ); + } +if (i < rdev->usec_timeout) { +DRM_INFO ("ib test on ring %d succeeded in %u usecs\n" , ib.fence->ring, i); + }else { +DRM_ERROR ("radeon: ib test failed (scratch(0x%04X)=0x%08X)\n" , + scratch, tmp); + r = -EINVAL ; + } +radeon_scratch_free (rdev, scratch); +radeon_ib_free (rdev, &ib); +return r; +} +/* * CP. * On CIK, gfx and compute now have independant command processors.
Signature · 1 line
1.7.7.5
PATCH 16/165 drm/radeon: implement async vm_flush for the CP (v7)
In reply to [email protected]From: Alex Deucher <[email protected]>
Update the page table base address and flush the
VM TLB using the CP.
v2: update for 2 level PTs
v3: use new packet for invalidate
v4: update SH_MEM* regs when flushing the VM
v5: add pfp sync, go back to old style vm TLB invalidate
v6: fix hdp flush packet count
v7: use old style HDP flush
--- drivers/gpu/drm/radeon/cik.c | 79 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 79 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/cik.c +79 -0
@@ -2698,3 +2698,82 @@ void cik_vm_fini(struct radeon_device *rdev) { } +/** +* cik_vm_flush - cik vm flush using the CP +* +* @rdev: radeon_device pointer +* +* Update the page table base and flush the VM TLB +* using the CP (CIK). +*/ +void cik_vm_flush (struct radeon_device *rdev,int ridx,struct radeon_vm *vm) +{ +struct radeon_ring *ring = &rdev->ring[ridx]; + +if (vm ==NULL ) +return ; + +radeon_ring_write (ring,PACKET3 (PACKET3_WRITE_DATA ,3 )); +radeon_ring_write (ring, (WRITE_DATA_ENGINE_SEL (0 ) | +WRITE_DATA_DST_SEL (0 ))); +if (vm->id <8 ) { +radeon_ring_write (ring, + (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id <<2 )) >>2 ); + }else { +radeon_ring_write (ring, + (VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((vm->id -8 ) <<2 )) >>2 ); + } +radeon_ring_write (ring,0 ); +radeon_ring_write (ring, vm->pd_gpu_addr >>12 ); + +/* update SH_MEM_* regs */ +radeon_ring_write (ring,PACKET3 (PACKET3_WRITE_DATA ,3 )); +radeon_ring_write (ring, (WRITE_DATA_ENGINE_SEL (0 ) | +WRITE_DATA_DST_SEL (0 ))); +radeon_ring_write (ring,SRBM_GFX_CNTL >>2 ); +radeon_ring_write (ring,0 ); +radeon_ring_write (ring,VMID (vm->id)); + +radeon_ring_write (ring,PACKET3 (PACKET3_WRITE_DATA ,6 )); +radeon_ring_write (ring, (WRITE_DATA_ENGINE_SEL (0 ) | +WRITE_DATA_DST_SEL (0 ))); +radeon_ring_write (ring,SH_MEM_BASES >>2 ); +radeon_ring_write (ring,0 ); + +radeon_ring_write (ring,0 );/* SH_MEM_BASES */ +radeon_ring_write (ring,0 );/* SH_MEM_CONFIG */ +radeon_ring_write (ring,1 );/* SH_MEM_APE1_BASE */ +radeon_ring_write (ring,0 );/* SH_MEM_APE1_LIMIT */ + +radeon_ring_write (ring,PACKET3 (PACKET3_WRITE_DATA ,3 )); +radeon_ring_write (ring, (WRITE_DATA_ENGINE_SEL (0 ) | +WRITE_DATA_DST_SEL (0 ))); +radeon_ring_write (ring,SRBM_GFX_CNTL >>2 ); +radeon_ring_write (ring,0 ); +radeon_ring_write (ring,VMID (0 )); + +/* HDP flush */ +/* We should be using the WAIT_REG_MEM packet here like in +* cik_fence_ring_emit(), but it causes the CP to hang in this +* context... +*/ +radeon_ring_write (ring,PACKET3 (PACKET3_WRITE_DATA ,3 )); +radeon_ring_write (ring, (WRITE_DATA_ENGINE_SEL (0 ) | +WRITE_DATA_DST_SEL (0 ))); +radeon_ring_write (ring,HDP_MEM_COHERENCY_FLUSH_CNTL >>2 ); +radeon_ring_write (ring,0 ); +radeon_ring_write (ring,0 ); + +/* bits 0-15 are the VM contexts0-15 */ +radeon_ring_write (ring,PACKET3 (PACKET3_WRITE_DATA ,3 )); +radeon_ring_write (ring, (WRITE_DATA_ENGINE_SEL (0 ) | +WRITE_DATA_DST_SEL (0 ))); +radeon_ring_write (ring,VM_INVALIDATE_REQUEST >>2 ); +radeon_ring_write (ring,0 ); +radeon_ring_write (ring,1 << vm->id); + +/* sync PFP to ME, otherwise we might get invalid PFP reads */ +radeon_ring_write (ring,PACKET3 (PACKET3_PFP_SYNC_ME ,0 )); +radeon_ring_write (ring,0x0 ); +} +
Signature · 1 line
1.7.7.5
PATCH 17/165 drm/radeon: Add support for RLC init on CIK (v4)
In reply to [email protected]From: Alex Deucher <[email protected]>
RLC handles the interrupt controller and other tasks on the GPU.
v2: add documentation
v3: update programming sequence
v4: additional setup
--- drivers/gpu/drm/radeon/cik.c | 142 +++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/cikd.h | 47 ++++++++++++++ 2 files changed, 189 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/cik.c +142 -0
@@ -2777,3 +2777,145 @@ void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)radeon_ring_write (ring,0x0 ); } +/* +* RLC +* The RLC is a multi-purpose microengine that handles a +* variety of functions, the most important of which is +* the interrupt controller. +*/ +/** +* cik_rlc_stop - stop the RLC ME +* +* @rdev: radeon_device pointer +* +* Halt the RLC ME (MicroEngine) (CIK). +*/ +static void cik_rlc_stop (struct radeon_device *rdev) +{ +int i, j, k; +u32 mask, tmp; + + tmp =RREG32 (CP_INT_CNTL_RING0 ); + tmp &= ~(CNTX_BUSY_INT_ENABLE |CNTX_EMPTY_INT_ENABLE ); +WREG32 (CP_INT_CNTL_RING0 , tmp); + +RREG32 (CB_CGTT_SCLK_CTRL ); +RREG32 (CB_CGTT_SCLK_CTRL ); +RREG32 (CB_CGTT_SCLK_CTRL ); +RREG32 (CB_CGTT_SCLK_CTRL ); + + tmp =RREG32 (RLC_CGCG_CGLS_CTRL ) &0xfffffffc ; +WREG32 (RLC_CGCG_CGLS_CTRL , tmp); + +WREG32 (RLC_CNTL ,0 ); + +for (i =0 ; i < rdev->config.cik.max_shader_engines; i++) { +for (j =0 ; j < rdev->config.cik.max_sh_per_se; j++) { +cik_select_se_sh (rdev, i, j); +for (k =0 ; k < rdev->usec_timeout; k++) { +if (RREG32 (RLC_SERDES_CU_MASTER_BUSY ) ==0 ) +break ; +udelay (1 ); + } + } + } +cik_select_se_sh (rdev,0xffffffff ,0xffffffff ); + + mask =SE_MASTER_BUSY_MASK |GC_MASTER_BUSY |TC0_MASTER_BUSY |TC1_MASTER_BUSY ; +for (k =0 ; k < rdev->usec_timeout; k++) { +if ((RREG32 (RLC_SERDES_NONCU_MASTER_BUSY ) & mask) ==0 ) +break ; +udelay (1 ); + } +} + +/** +* cik_rlc_start - start the RLC ME +* +* @rdev: radeon_device pointer +* +* Unhalt the RLC ME (MicroEngine) (CIK). +*/ +static void cik_rlc_start (struct radeon_device *rdev) +{ +u32 tmp; + +WREG32 (RLC_CNTL ,RLC_ENABLE ); + + tmp =RREG32 (CP_INT_CNTL_RING0 ); + tmp |= (CNTX_BUSY_INT_ENABLE |CNTX_EMPTY_INT_ENABLE ); +WREG32 (CP_INT_CNTL_RING0 , tmp); + +udelay (50 ); +} + +/** +* cik_rlc_resume - setup the RLC hw +* +* @rdev: radeon_device pointer +* +* Initialize the RLC registers, load the ucode, +* and start the RLC (CIK). +* Returns 0 for success, -EINVAL if the ucode is not available. +*/ +static int cik_rlc_resume (struct radeon_device *rdev) +{ +u32 i, size; +u32 clear_state_info[3 ]; +const __be32 *fw_data; + +if (!rdev->rlc_fw) +return -EINVAL ; + +switch (rdev->family) { +case CHIP_BONAIRE : +default : + size =BONAIRE_RLC_UCODE_SIZE ; +break ; +case CHIP_KAVERI : + size =KV_RLC_UCODE_SIZE ; +break ; +case CHIP_KABINI : + size =KB_RLC_UCODE_SIZE ; +break ; + } + +cik_rlc_stop (rdev); + +WREG32 (GRBM_SOFT_RESET ,SOFT_RESET_RLC ); +RREG32 (GRBM_SOFT_RESET ); +udelay (50 ); +WREG32 (GRBM_SOFT_RESET ,0 ); +RREG32 (GRBM_SOFT_RESET ); +udelay (50 ); + +WREG32 (RLC_LB_CNTR_INIT ,0 ); +WREG32 (RLC_LB_CNTR_MAX ,0x00008000 ); + +cik_select_se_sh (rdev,0xffffffff ,0xffffffff ); +WREG32 (RLC_LB_INIT_CU_MASK ,0xffffffff ); +WREG32 (RLC_LB_PARAMS ,0x00600408 ); +WREG32 (RLC_LB_CNTL ,0x80000004 ); + +WREG32 (RLC_MC_CNTL ,0 ); +WREG32 (RLC_UCODE_CNTL ,0 ); + + fw_data = (const __be32 *)rdev->rlc_fw->data; +WREG32 (RLC_GPM_UCODE_ADDR ,0 ); +for (i =0 ; i < size; i++) +WREG32 (RLC_GPM_UCODE_DATA ,be32_to_cpup (fw_data++)); +WREG32 (RLC_GPM_UCODE_ADDR ,0 ); + +/* XXX */ + clear_state_info[0 ] =0 ;//upper_32_bits(rdev->rlc.save_restore_gpu_addr); + clear_state_info[1 ] =0 ;//rdev->rlc.save_restore_gpu_addr; + clear_state_info[2 ] =0 ;//cik_default_size; +WREG32 (RLC_GPM_SCRATCH_ADDR ,0x3d ); +for (i =0 ; i <3 ; i++) +WREG32 (RLC_GPM_SCRATCH_DATA , clear_state_info[i]); +WREG32 (RLC_DRIVER_DMA_STATUS ,0 ); + +cik_rlc_start (rdev); + +return 0 ; +}
drivers/gpu/drm/radeon/cikd.h +47 -0
63 lines not on this page · raw message
Signature · 1 line
1.7.7.5
PATCH 18/165 drm/radeon: add support for interrupts on CIK (v5)
In reply to [email protected]From: Alex Deucher <[email protected]>
Todo:
- handle interrupts for compute queues
v2: add documentation
v3: update to latest reset code
v4: update to latest illegal CP handling
v5: fix missing break in interrupt handler switch statement
--- drivers/gpu/drm/radeon/cik.c | 840 +++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/cikd.h | 170 ++++++++ drivers/gpu/drm/radeon/radeon.h | 11 + 3 files changed, 1021 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/cik.c +840 -0
@@ -62,6 +62,8 @@ MODULE_FIRMWARE("radeon/KABINI_ce.bin");MODULE_FIRMWARE ("radeon/KABINI_mec.bin" );MODULE_FIRMWARE ("radeon/KABINI_rlc.bin" ); +extern int r600_ih_ring_alloc (struct radeon_device *rdev); +extern void r600_ih_ring_fini (struct radeon_device *rdev);extern void evergreen_mc_stop (struct radeon_device *rdev,struct evergreen_mc_save *save);extern void evergreen_mc_resume (struct radeon_device *rdev,struct evergreen_mc_save *save);extern void si_vram_gtt_location (struct radeon_device *rdev,struct radeon_mc *mc);
@@ -2919,3 +2921,841 @@ static int cik_rlc_resume(struct radeon_device *rdev)return 0 ; } + +/* +* Interrupts +* Starting with r6xx, interrupts are handled via a ring buffer. +* Ring buffers are areas of GPU accessible memory that the GPU +* writes interrupt vectors into and the host reads vectors out of. +* There is a rptr (read pointer) that determines where the +* host is currently reading, and a wptr (write pointer) +* which determines where the GPU has written. When the +* pointers are equal, the ring is idle. When the GPU +* writes vectors to the ring buffer, it increments the +* wptr. When there is an interrupt, the host then starts +* fetching commands and processing them until the pointers are +* equal again at which point it updates the rptr. +*/ + +/** +* cik_enable_interrupts - Enable the interrupt ring buffer +* +* @rdev: radeon_device pointer +* +* Enable the interrupt ring buffer (CIK). +*/ +static void cik_enable_interrupts (struct radeon_device *rdev) +{ +u32 ih_cntl =RREG32 (IH_CNTL ); +u32 ih_rb_cntl =RREG32 (IH_RB_CNTL ); + + ih_cntl |=ENABLE_INTR ; + ih_rb_cntl |=IH_RB_ENABLE ; +WREG32 (IH_CNTL , ih_cntl); +WREG32 (IH_RB_CNTL , ih_rb_cntl); + rdev->ih.enabled = true; +} + +/** +* cik_disable_interrupts - Disable the interrupt ring buffer +* +* @rdev: radeon_device pointer +* +* Disable the interrupt ring buffer (CIK). +*/ +static void cik_disable_interrupts (struct radeon_device *rdev) +{ +u32 ih_rb_cntl =RREG32 (IH_RB_CNTL ); +u32 ih_cntl =RREG32 (IH_CNTL ); + + ih_rb_cntl &= ~IH_RB_ENABLE ; + ih_cntl &= ~ENABLE_INTR ; +WREG32 (IH_RB_CNTL , ih_rb_cntl); +WREG32 (IH_CNTL , ih_cntl); +/* set rptr, wptr to 0 */ +WREG32 (IH_RB_RPTR ,0 ); +WREG32 (IH_RB_WPTR ,0 ); + rdev->ih.enabled = false; + rdev->ih.rptr =0 ; +} + +/** +* cik_disable_interrupt_state - Disable all interrupt sources +* +* @rdev: radeon_device pointer +* +* Clear all interrupt enable bits used by the driver (CIK). +*/ +static void cik_disable_interrupt_state (struct radeon_device *rdev) +{ +u32 tmp; + +/* gfx ring */ +WREG32 (CP_INT_CNTL_RING0 ,CNTX_BUSY_INT_ENABLE |CNTX_EMPTY_INT_ENABLE ); +/* compute queues */ +WREG32 (CP_ME1_PIPE0_INT_CNTL ,0 ); +WREG32 (CP_ME1_PIPE1_INT_CNTL ,0 ); +WREG32 (CP_ME1_PIPE2_INT_CNTL ,0 ); +WREG32 (CP_ME1_PIPE3_INT_CNTL ,0 ); +WREG32 (CP_ME2_PIPE0_INT_CNTL ,0 ); +WREG32 (CP_ME2_PIPE1_INT_CNTL ,0 ); +WREG32 (CP_ME2_PIPE2_INT_CNTL ,0 ); +WREG32 (CP_ME2_PIPE3_INT_CNTL ,0 ); +/* grbm */ +WREG32 (GRBM_INT_CNTL ,0 ); +/* vline/vblank, etc. */ +WREG32 (LB_INTERRUPT_MASK +EVERGREEN_CRTC0_REGISTER_OFFSET ,0 ); +WREG32 (LB_INTERRUPT_MASK +EVERGREEN_CRTC1_REGISTER_OFFSET ,0 ); +if (rdev->num_crtc >=4 ) { +WREG32 (LB_INTERRUPT_MASK +EVERGREEN_CRTC2_REGISTER_OFFSET ,0 ); +WREG32 (LB_INTERRUPT_MASK +EVERGREEN_CRTC3_REGISTER_OFFSET ,0 ); + } +if (rdev->num_crtc >=6 ) { +WREG32 (LB_INTERRUPT_MASK +EVERGREEN_CRTC4_REGISTER_OFFSET ,0 ); +WREG32 (LB_INTERRUPT_MASK +EVERGREEN_CRTC5_REGISTER_OFFSET ,0 ); + } + +/* dac hotplug */ +WREG32 (DAC_AUTODETECT_INT_CONTROL ,0 ); + +/* digital hotplug */ + tmp =RREG32 (DC_HPD1_INT_CONTROL ) & DC_HPDx_INT_POLARITY; +WREG32 (DC_HPD1_INT_CONTROL , tmp); + tmp =RREG32 (DC_HPD2_INT_CONTROL ) & DC_HPDx_INT_POLARITY; +WREG32 (DC_HPD2_INT_CONTROL , tmp); + tmp =RREG32 (DC_HPD3_INT_CONTROL ) & DC_HPDx_INT_POLARITY; +WREG32 (DC_HPD3_INT_CONTROL , tmp); + tmp =RREG32 (DC_HPD4_INT_CONTROL ) & DC_HPDx_INT_POLARITY; +WREG32 (DC_HPD4_INT_CONTROL , tmp); + tmp =RREG32 (DC_HPD5_INT_CONTROL ) & DC_HPDx_INT_POLARITY; +WREG32 (DC_HPD5_INT_CONTROL , tmp); + tmp =RREG32 (DC_HPD6_INT_CONTROL ) & DC_HPDx_INT_POLARITY; +WREG32 (DC_HPD6_INT_CONTROL , tmp); + +} + +/** +* cik_irq_init - init and enable the interrupt ring +* +* @rdev: radeon_device pointer +* +* Allocate a ring buffer for the interrupt controller, +* enable the RLC, disable interrupts, enable the IH +* ring buffer and enable it (CIK). +* Called at device load and reume. +* Returns 0 for success, errors for failure. +*/ +static int cik_irq_init (struct radeon_device *rdev) +{ +int ret =0 ; +int rb_bufsz; +u32 interrupt_cntl, ih_cntl, ih_rb_cntl; + +/* allocate ring */ + ret =r600_ih_ring_alloc (rdev); +if (ret) +return ret; + +/* disable irqs */ +cik_disable_interrupts (rdev); + +/* init rlc */ + ret =cik_rlc_resume (rdev); +if (ret) { +r600_ih_ring_fini (rdev); +return ret; + } + +/* setup interrupt control */ +/* XXX this should actually be a bus address, not an MC address. same on older asics */ +WREG32 (INTERRUPT_CNTL2 , rdev->ih.gpu_addr >>8 ); + interrupt_cntl =RREG32 (INTERRUPT_CNTL ); +/* IH_DUMMY_RD_OVERRIDE=0 - dummy read disabled with msi, enabled without msi +* IH_DUMMY_RD_OVERRIDE=1 - dummy read controlled by IH_DUMMY_RD_EN +*/ + interrupt_cntl &= ~IH_DUMMY_RD_OVERRIDE ; +/* IH_REQ_NONSNOOP_EN=1 if ring is in non-cacheable memory, e.g., vram */ + interrupt_cntl &= ~IH_REQ_NONSNOOP_EN ; +WREG32 (INTERRUPT_CNTL , interrupt_cntl); + +WREG32 (IH_RB_BASE , rdev->ih.gpu_addr >>8 ); + rb_bufsz =drm_order (rdev->ih.ring_size /4 ); + + ih_rb_cntl = (IH_WPTR_OVERFLOW_ENABLE | +IH_WPTR_OVERFLOW_CLEAR | + (rb_bufsz <<1 )); + +if (rdev->wb.enabled) + ih_rb_cntl |=IH_WPTR_WRITEBACK_ENABLE ; + +/* set the writeback address whether it's enabled or not */ +WREG32 (IH_RB_WPTR_ADDR_LO , (rdev->wb.gpu_addr +R600_WB_IH_WPTR_OFFSET ) &0xFFFFFFFC ); +WREG32 (IH_RB_WPTR_ADDR_HI ,upper_32_bits (rdev->wb.gpu_addr +R600_WB_IH_WPTR_OFFSET ) &0xFF ); + +WREG32 (IH_RB_CNTL , ih_rb_cntl); + +/* set rptr, wptr to 0 */ +WREG32 (IH_RB_RPTR ,0 ); +WREG32 (IH_RB_WPTR ,0 ); + +/* Default settings for IH_CNTL (disabled at first) */ + ih_cntl =MC_WRREQ_CREDIT (0x10 ) |MC_WR_CLEAN_CNT (0x10 ) |MC_VMID (0 ); +/* RPTR_REARM only works if msi's are enabled */ +if (rdev->msi_enabled) + ih_cntl |=RPTR_REARM ; +WREG32 (IH_CNTL , ih_cntl); + +/* force the active interrupt state to all disabled */ +cik_disable_interrupt_state (rdev); + +pci_set_master (rdev->pdev); + +/* enable irqs */ +cik_enable_interrupts (rdev); + +return ret; +} + +/** +* cik_irq_set - enable/disable interrupt sources +* +* @rdev: radeon_device pointer +* +* Enable interrupt sources on the GPU (vblanks, hpd, +* etc.) (CIK). +* Returns 0 for success, errors for failure. +*/ +int cik_irq_set (struct radeon_device *rdev) +{ +u32 cp_int_cntl =CNTX_BUSY_INT_ENABLE |CNTX_EMPTY_INT_ENABLE | +PRIV_INSTR_INT_ENABLE |PRIV_REG_INT_ENABLE ; +u32 crtc1 =0 , crtc2 =0 , crtc3 =0 , crtc4 =0 , crtc5 =0 , crtc6 =0 ; +u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6; +u32 grbm_int_cntl =0 ; + +if (!rdev->irq.installed) { +WARN (1 ,"Can't enable IRQ/MSI because no handler is installed\n" ); +return -EINVAL ; + } +/* don't enable anything if the ih is disabled */ +if (!rdev->ih.enabled) { +cik_disable_interrupts (rdev); +/* force the active interrupt state to all disabled */ +cik_disable_interrupt_state (rdev); +return 0 ; + } + + hpd1 =RREG32 (DC_HPD1_INT_CONTROL ) & ~DC_HPDx_INT_EN; + hpd2 =RREG32 (DC_HPD2_INT_CONTROL ) & ~DC_HPDx_INT_EN; + hpd3 =RREG32 (DC_HPD3_INT_CONTROL ) & ~DC_HPDx_INT_EN; + hpd4 =RREG32 (DC_HPD4_INT_CONTROL ) & ~DC_HPDx_INT_EN; + hpd5 =RREG32 (DC_HPD5_INT_CONTROL ) & ~DC_HPDx_INT_EN; + hpd6 =RREG32 (DC_HPD6_INT_CONTROL ) & ~DC_HPDx_INT_EN; + +/* enable CP interrupts on all rings */ +if (atomic_read (&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX ])) { +DRM_DEBUG ("cik_irq_set: sw int gfx\n" ); + cp_int_cntl |=TIME_STAMP_INT_ENABLE ; + } +/* TODO: compute queues! */ +/* CP_ME[1-2]_PIPE[0-3]_INT_CNTL */ + +if (rdev->irq.crtc_vblank_int[0 ] || +atomic_read (&rdev->irq.pflip[0 ])) { +DRM_DEBUG ("cik_irq_set: vblank 0\n" ); + crtc1 |=VBLANK_INTERRUPT_MASK ; + } +if (rdev->irq.crtc_vblank_int[1 ] || +atomic_read (&rdev->irq.pflip[1 ])) { +DRM_DEBUG ("cik_irq_set: vblank 1\n" ); + crtc2 |=VBLANK_INTERRUPT_MASK ; + } +if (rdev->irq.crtc_vblank_int[2 ] || +atomic_read (&rdev->irq.pflip[2 ])) { +DRM_DEBUG ("cik_irq_set: vblank 2\n" ); + crtc3 |=VBLANK_INTERRUPT_MASK ; + } +if (rdev->irq.crtc_vblank_int[3 ] || +atomic_read (&rdev->irq.pflip[3 ])) { +DRM_DEBUG ("cik_irq_set: vblank 3\n" ); + crtc4 |=VBLANK_INTERRUPT_MASK ; + } +if (rdev->irq.crtc_vblank_int[4 ] || +atomic_read (&rdev->irq.pflip[4 ])) { +DRM_DEBUG ("cik_irq_set: vblank 4\n" ); + crtc5 |=VBLANK_INTERRUPT_MASK ; + } +if (rdev->irq.crtc_vblank_int[5 ] || +atomic_read (&rdev->irq.pflip[5 ])) { +DRM_DEBUG ("cik_irq_set: vblank 5\n" ); + crtc6 |=VBLANK_INTERRUPT_MASK ; + } +if (rdev->irq.hpd[0 ]) { +DRM_DEBUG ("cik_irq_set: hpd 1\n" ); + hpd1 |= DC_HPDx_INT_EN; + } +if (rdev->irq.hpd[1 ]) { +DRM_DEBUG ("cik_irq_set: hpd 2\n" ); + hpd2 |= DC_HPDx_INT_EN; + } +if (rdev->irq.hpd[2 ]) { +DRM_DEBUG ("cik_irq_set: hpd 3\n" ); + hpd3 |= DC_HPDx_INT_EN; + } +if (rdev->irq.hpd[3 ]) { +DRM_DEBUG ("cik_irq_set: hpd 4\n" ); + hpd4 |= DC_HPDx_INT_EN; + } +if (rdev->irq.hpd[4 ]) { +DRM_DEBUG ("cik_irq_set: hpd 5\n" ); + hpd5 |= DC_HPDx_INT_EN; + } +if (rdev->irq.hpd[5 ]) { +DRM_DEBUG ("cik_irq_set: hpd 6\n" ); + hpd6 |= DC_HPDx_INT_EN; + } + +WREG32 (CP_INT_CNTL_RING0 , cp_int_cntl); + +WREG32 (GRBM_INT_CNTL , grbm_int_cntl); + +WREG32 (LB_INTERRUPT_MASK +EVERGREEN_CRTC0_REGISTER_OFFSET , crtc1); +WREG32 (LB_INTERRUPT_MASK +EVERGREEN_CRTC1_REGISTER_OFFSET , crtc2); +if (rdev->num_crtc >=4 ) { +WREG32 (LB_INTERRUPT_MASK +EVERGREEN_CRTC2_REGISTER_OFFSET , crtc3); +WREG32 (LB_INTERRUPT_MASK +EVERGREEN_CRTC3_REGISTER_OFFSET , crtc4); + } +if (rdev->num_crtc >=6 ) { +WREG32 (LB_INTERRUPT_MASK +EVERGREEN_CRTC4_REGISTER_OFFSET , crtc5); +WREG32 (LB_INTERRUPT_MASK +EVERGREEN_CRTC5_REGISTER_OFFSET , crtc6); + } + +WREG32 (DC_HPD1_INT_CONTROL , hpd1); +WREG32 (DC_HPD2_INT_CONTROL , hpd2); +WREG32 (DC_HPD3_INT_CONTROL , hpd3); +WREG32 (DC_HPD4_INT_CONTROL , hpd4); +WREG32 (DC_HPD5_INT_CONTROL , hpd5); +WREG32 (DC_HPD6_INT_CONTROL , hpd6); + +return 0 ; +} + +/** +* cik_irq_ack - ack interrupt sources +* +* @rdev: radeon_device pointer +* +* Ack interrupt sources on the GPU (vblanks, hpd, +* etc.) (CIK). Certain interrupts sources are sw +* generated and do not require an explicit ack. +*/ +static inline void cik_irq_ack (struct radeon_device *rdev) +{ +u32 tmp; + + rdev->irq.stat_regs.cik.disp_int =RREG32 (DISP_INTERRUPT_STATUS ); + rdev->irq.stat_regs.cik.disp_int_cont =RREG32 (DISP_INTERRUPT_STATUS_CONTINUE ); + rdev->irq.stat_regs.cik.disp_int_cont2 =RREG32 (DISP_INTERRUPT_STATUS_CONTINUE2 ); + rdev->irq.stat_regs.cik.disp_int_cont3 =RREG32 (DISP_INTERRUPT_STATUS_CONTINUE3 ); + rdev->irq.stat_regs.cik.disp_int_cont4 =RREG32 (DISP_INTERRUPT_STATUS_CONTINUE4 ); + rdev->irq.stat_regs.cik.disp_int_cont5 =RREG32 (DISP_INTERRUPT_STATUS_CONTINUE5 ); + rdev->irq.stat_regs.cik.disp_int_cont6 =RREG32 (DISP_INTERRUPT_STATUS_CONTINUE6 ); + +if (rdev->irq.stat_regs.cik.disp_int &LB_D1_VBLANK_INTERRUPT ) +WREG32 (LB_VBLANK_STATUS +EVERGREEN_CRTC0_REGISTER_OFFSET ,VBLANK_ACK ); +if (rdev->irq.stat_regs.cik.disp_int &LB_D1_VLINE_INTERRUPT ) +WREG32 (LB_VLINE_STATUS +EVERGREEN_CRTC0_REGISTER_OFFSET ,VLINE_ACK ); +if (rdev->irq.stat_regs.cik.disp_int_cont &LB_D2_VBLANK_INTERRUPT ) +WREG32 (LB_VBLANK_STATUS +EVERGREEN_CRTC1_REGISTER_OFFSET ,VBLANK_ACK ); +if (rdev->irq.stat_regs.cik.disp_int_cont &LB_D2_VLINE_INTERRUPT ) +WREG32 (LB_VLINE_STATUS +EVERGREEN_CRTC1_REGISTER_OFFSET ,VLINE_ACK ); + +if (rdev->num_crtc >=4 ) { +if (rdev->irq.stat_regs.cik.disp_int_cont2 &LB_D3_VBLANK_INTERRUPT ) +WREG32 (LB_VBLANK_STATUS +EVERGREEN_CRTC2_REGISTER_OFFSET ,VBLANK_ACK ); +if (rdev->irq.stat_regs.cik.disp_int_cont2 &LB_D3_VLINE_INTERRUPT ) +WREG32 (LB_VLINE_STATUS +EVERGREEN_CRTC2_REGISTER_OFFSET ,VLINE_ACK ); +if (rdev->irq.stat_regs.cik.disp_int_cont3 &LB_D4_VBLANK_INTERRUPT ) +WREG32 (LB_VBLANK_STATUS +EVERGREEN_CRTC3_REGISTER_OFFSET ,VBLANK_ACK ); +if (rdev->irq.stat_regs.cik.disp_int_cont3 &LB_D4_VLINE_INTERRUPT ) +WREG32 (LB_VLINE_STATUS +EVERGREEN_CRTC3_REGISTER_OFFSET ,VLINE_ACK ); + } + +if (rdev->num_crtc >=6 ) { +if (rdev->irq.stat_regs.cik.disp_int_cont4 &LB_D5_VBLANK_INTERRUPT ) +WREG32 (LB_VBLANK_STATUS +EVERGREEN_CRTC4_REGISTER_OFFSET ,VBLANK_ACK ); +if (rdev->irq.stat_regs.cik.disp_int_cont4 &LB_D5_VLINE_INTERRUPT ) +WREG32 (LB_VLINE_STATUS +EVERGREEN_CRTC4_REGISTER_OFFSET ,VLINE_ACK ); +if (rdev->irq.stat_regs.cik.disp_int_cont5 &LB_D6_VBLANK_INTERRUPT ) +WREG32 (LB_VBLANK_STATUS +EVERGREEN_CRTC5_REGISTER_OFFSET ,VBLANK_ACK ); +if (rdev->irq.stat_regs.cik.disp_int_cont5 &LB_D6_VLINE_INTERRUPT ) +WREG32 (LB_VLINE_STATUS +EVERGREEN_CRTC5_REGISTER_OFFSET ,VLINE_ACK ); + } + +if (rdev->irq.stat_regs.cik.disp_int &DC_HPD1_INTERRUPT ) { + tmp =RREG32 (DC_HPD1_INT_CONTROL ); + tmp |= DC_HPDx_INT_ACK; +WREG32 (DC_HPD1_INT_CONTROL , tmp); + } +if (rdev->irq.stat_regs.cik.disp_int_cont &DC_HPD2_INTERRUPT ) { + tmp =RREG32 (DC_HPD2_INT_CONTROL ); + tmp |= DC_HPDx_INT_ACK; +WREG32 (DC_HPD2_INT_CONTROL , tmp); + } +if (rdev->irq.stat_regs.cik.disp_int_cont2 &DC_HPD3_INTERRUPT ) { + tmp =RREG32 (DC_HPD3_INT_CONTROL ); + tmp |= DC_HPDx_INT_ACK; +WREG32 (DC_HPD3_INT_CONTROL , tmp); + } +if (rdev->irq.stat_regs.cik.disp_int_cont3 &DC_HPD4_INTERRUPT ) { + tmp =RREG32 (DC_HPD4_INT_CONTROL ); + tmp |= DC_HPDx_INT_ACK; +WREG32 (DC_HPD4_INT_CONTROL , tmp); + } +if (rdev->irq.stat_regs.cik.disp_int_cont4 &DC_HPD5_INTERRUPT ) { + tmp =RREG32 (DC_HPD5_INT_CONTROL ); + tmp |= DC_HPDx_INT_ACK; +WREG32 (DC_HPD5_INT_CONTROL , tmp); + } +if (rdev->irq.stat_regs.cik.disp_int_cont5 &DC_HPD6_INTERRUPT ) { + tmp =RREG32 (DC_HPD5_INT_CONTROL ); + tmp |= DC_HPDx_INT_ACK; +WREG32 (DC_HPD6_INT_CONTROL , tmp); + } +} + +/** +* cik_irq_disable - disable interrupts +* +* @rdev: radeon_device pointer +* +* Disable interrupts on the hw (CIK). +*/ +static void cik_irq_disable (struct radeon_device *rdev) +{ +cik_disable_interrupts (rdev); +/* Wait and acknowledge irq */ +mdelay (1 ); +cik_irq_ack (rdev); +cik_disable_interrupt_state (rdev); +} + +/** +* cik_irq_disable - disable interrupts for suspend +* +* @rdev: radeon_device pointer +* +* Disable interrupts and stop the RLC (CIK). +* Used for suspend. +*/ +static void cik_irq_suspend (struct radeon_device *rdev) +{ +cik_irq_disable (rdev); +cik_rlc_stop (rdev); +} + +/** +* cik_irq_fini - tear down interrupt support +* +* @rdev: radeon_device pointer +* +* Disable interrupts on the hw and free the IH ring +* buffer (CIK). +* Used for driver unload. +*/ +static void cik_irq_fini (struct radeon_device *rdev) +{ +cik_irq_suspend (rdev); +r600_ih_ring_fini (rdev); +} + +/** +* cik_get_ih_wptr - get the IH ring buffer wptr +* +* @rdev: radeon_device pointer +* +* Get the IH ring buffer wptr from either the register +* or the writeback memory buffer (CIK). Also check for +* ring buffer overflow and deal with it. +* Used by cik_irq_process(). +* Returns the value of the wptr. +*/ +static inline u32 cik_get_ih_wptr (struct radeon_device *rdev) +{ +u32 wptr, tmp; + +if (rdev->wb.enabled) + wptr =le32_to_cpu (rdev->wb.wb[R600_WB_IH_WPTR_OFFSET /4 ]); +else + wptr =RREG32 (IH_RB_WPTR ); + +if (wptr &RB_OVERFLOW ) { +/* When a ring buffer overflow happen start parsing interrupt +* from the last not overwritten vector (wptr + 16). Hopefully +* this should allow us to catchup. +*/ +dev_warn (rdev->dev,"IH ring buffer overflow (0x%08X, %d, %d)\n" , + wptr, rdev->ih.rptr, (wptr +16 ) + rdev->ih.ptr_mask); + rdev->ih.rptr = (wptr +16 ) & rdev->ih.ptr_mask; + tmp =RREG32 (IH_RB_CNTL ); + tmp |=IH_WPTR_OVERFLOW_CLEAR ; +WREG32 (IH_RB_CNTL , tmp); + } +return (wptr & rdev->ih.ptr_mask); +} + +/* CIK IV Ring +* Each IV ring entry is 128 bits: +* [7:0] - interrupt source id +* [31:8] - reserved +* [59:32] - interrupt source data +* [63:60] - reserved +* [71:64] - RINGID: ME_ID [1:0], PIPE_ID[1:0], QUEUE_ID[2:0] +* QUEUE_ID - for compute, which of the 8 queues owned by the dispatcher +* - for gfx, hw shader state (0=PS...5=LS, 6=CS) +* ME_ID - 0 = gfx, 1 = first 4 CS pipes, 2 = second 4 CS pipes +* PIPE_ID - ME0 0=3D +* - ME1&2 compute dispatcher (4 pipes each) +* [79:72] - VMID +* [95:80] - PASID +* [127:96] - reserved +*/ +/** +* cik_irq_process - interrupt handler +* +* @rdev: radeon_device pointer +* +* Interrupt hander (CIK). Walk the IH ring, +* ack interrupts and schedule work to handle +* interrupt events. +* Returns irq process return code. +*/ +int cik_irq_process (struct radeon_device *rdev) +{ +u32 wptr; +u32 rptr; +u32 src_id, src_data, ring_id; +u8 me_id, pipe_id, queue_id; +u32 ring_index; +bool queue_hotplug = false; +bool queue_reset = false; + +if (!rdev->ih.enabled || rdev->shutdown) +return IRQ_NONE ; + + wptr =cik_get_ih_wptr (rdev); + +restart_ih: +/* is somebody else already processing irqs? */ +if (atomic_xchg (&rdev->ih.lock,1 )) +return IRQ_NONE ; + + rptr = rdev->ih.rptr; +DRM_DEBUG ("cik_irq_process start: rptr %d, wptr %d\n" , rptr, wptr); + +/* Order reading of wptr vs. reading of IH ring data */ +rmb (); + +/* display interrupts */ +cik_irq_ack (rdev); + +while (rptr != wptr) { +/* wptr/rptr are in bytes! */ + ring_index = rptr /4 ; + src_id =le32_to_cpu (rdev->ih.ring[ring_index]) &0xff ; + src_data =le32_to_cpu (rdev->ih.ring[ring_index +1 ]) &0xfffffff ; + ring_id =le32_to_cpu (rdev->ih.ring[ring_index +2 ]) &0xff ; +/* XXX check the bitfield order! */ + me_id = (ring_id &0x60 ) >>5 ; + pipe_id = (ring_id &0x18 ) >>3 ; + queue_id = (ring_id &0x7 ) >>0 ; + +switch (src_id) { +case 1 :/* D1 vblank/vline */ +switch (src_data) { +case 0 :/* D1 vblank */ +if (rdev->irq.stat_regs.cik.disp_int &LB_D1_VBLANK_INTERRUPT ) { +if (rdev->irq.crtc_vblank_int[0 ]) { +drm_handle_vblank (rdev->ddev,0 ); + rdev->pm.vblank_sync = true; +wake_up (&rdev->irq.vblank_queue); + } +if (atomic_read (&rdev->irq.pflip[0 ])) +radeon_crtc_handle_flip (rdev,0 ); + rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VBLANK_INTERRUPT ; +DRM_DEBUG ("IH: D1 vblank\n" ); + } +break ; +case 1 :/* D1 vline */ +if (rdev->irq.stat_regs.cik.disp_int &LB_D1_VLINE_INTERRUPT ) { + rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VLINE_INTERRUPT ; +DRM_DEBUG ("IH: D1 vline\n" ); + } +break ; +default : +DRM_DEBUG ("Unhandled interrupt: %d %d\n" , src_id, src_data); +break ; + } +break ; +case 2 :/* D2 vblank/vline */ +switch (src_data) { +case 0 :/* D2 vblank */ +if (rdev->irq.stat_regs.cik.disp_int_cont &LB_D2_VBLANK_INTERRUPT ) { +if (rdev->irq.crtc_vblank_int[1 ]) { +drm_handle_vblank (rdev->ddev,1 ); + rdev->pm.vblank_sync = true; +wake_up (&rdev->irq.vblank_queue); + } +if (atomic_read (&rdev->irq.pflip[1 ])) +radeon_crtc_handle_flip (rdev,1 ); + rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT ; +DRM_DEBUG ("IH: D2 vblank\n" ); + } +break ; +case 1 :/* D2 vline */ +if (rdev->irq.stat_regs.cik.disp_int_cont &LB_D2_VLINE_INTERRUPT ) { + rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT ; +DRM_DEBUG ("IH: D2 vline\n" ); + } +break ; +default : +DRM_DEBUG ("Unhandled interrupt: %d %d\n" , src_id, src_data); +break ; + } +break ; +case 3 :/* D3 vblank/vline */ +switch (src_data) { +case 0 :/* D3 vblank */ +if (rdev->irq.stat_regs.cik.disp_int_cont2 &LB_D3_VBLANK_INTERRUPT ) { +if (rdev->irq.crtc_vblank_int[2 ]) { +drm_handle_vblank (rdev->ddev,2 ); + rdev->pm.vblank_sync = true; +wake_up (&rdev->irq.vblank_queue); + } +if (atomic_read (&rdev->irq.pflip[2 ])) +radeon_crtc_handle_flip (rdev,2 ); + rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT ; +DRM_DEBUG ("IH: D3 vblank\n" ); + } +break ; +case 1 :/* D3 vline */ +if (rdev->irq.stat_regs.cik.disp_int_cont2 &LB_D3_VLINE_INTERRUPT ) { + rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT ; +DRM_DEBUG ("IH: D3 vline\n" ); + } +break ; +default : +DRM_DEBUG ("Unhandled interrupt: %d %d\n" , src_id, src_data); +break ; + } +break ; +case 4 :/* D4 vblank/vline */ +switch (src_data) { +case 0 :/* D4 vblank */ +if (rdev->irq.stat_regs.cik.disp_int_cont3 &LB_D4_VBLANK_INTERRUPT ) { +if (rdev->irq.crtc_vblank_int[3 ]) { +drm_handle_vblank (rdev->ddev,3 ); + rdev->pm.vblank_sync = true; +wake_up (&rdev->irq.vblank_queue); + } +if (atomic_read (&rdev->irq.pflip[3 ])) +radeon_crtc_handle_flip (rdev,3 ); + rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT ; +DRM_DEBUG ("IH: D4 vblank\n" ); + } +break ; +case 1 :/* D4 vline */ +if (rdev->irq.stat_regs.cik.disp_int_cont3 &LB_D4_VLINE_INTERRUPT ) { + rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT ; +DRM_DEBUG ("IH: D4 vline\n" ); + } +break ; +default : +DRM_DEBUG ("Unhandled interrupt: %d %d\n" , src_id, src_data); +break ; + } +break ; +case 5 :/* D5 vblank/vline */ +switch (src_data) { +case 0 :/* D5 vblank */ +if (rdev->irq.stat_regs.cik.disp_int_cont4 &LB_D5_VBLANK_INTERRUPT ) { +if (rdev->irq.crtc_vblank_int[4 ]) { +drm_handle_vblank (rdev->ddev,4 ); + rdev->pm.vblank_sync = true; +wake_up (&rdev->irq.vblank_queue); + } +if (atomic_read (&rdev->irq.pflip[4 ])) +radeon_crtc_handle_flip (rdev,4 ); + rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT ; +DRM_DEBUG ("IH: D5 vblank\n" ); + } +break ; +case 1 :/* D5 vline */ +if (rdev->irq.stat_regs.cik.disp_int_cont4 &LB_D5_VLINE_INTERRUPT ) { + rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT ; +DRM_DEBUG ("IH: D5 vline\n" ); + } +break ; +default : +DRM_DEBUG ("Unhandled interrupt: %d %d\n" , src_id, src_data); +break ; + } +break ; +case 6 :/* D6 vblank/vline */ +switch (src_data) { +case 0 :/* D6 vblank */ +if (rdev->irq.stat_regs.cik.disp_int_cont5 &LB_D6_VBLANK_INTERRUPT ) { +if (rdev->irq.crtc_vblank_int[5 ]) { +drm_handle_vblank (rdev->ddev,5 ); + rdev->pm.vblank_sync = true; +wake_up (&rdev->irq.vblank_queue); + } +if (atomic_read (&rdev->irq.pflip[5 ])) +radeon_crtc_handle_flip (rdev,5 ); + rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT ; +DRM_DEBUG ("IH: D6 vblank\n" ); + } +break ; +case 1 :/* D6 vline */ +if (rdev->irq.stat_regs.cik.disp_int_cont5 &LB_D6_VLINE_INTERRUPT ) { + rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT ; +DRM_DEBUG ("IH: D6 vline\n" ); + } +break ; +default : +DRM_DEBUG ("Unhandled interrupt: %d %d\n" , src_id, src_data); +break ; + } +break ; +case 42 :/* HPD hotplug */ +switch (src_data) { +case 0 : +if (rdev->irq.stat_regs.cik.disp_int &DC_HPD1_INTERRUPT ) { + rdev->irq.stat_regs.cik.disp_int &= ~DC_HPD1_INTERRUPT ; + queue_hotplug = true; +DRM_DEBUG ("IH: HPD1\n" ); + } +break ; +case 1 : +if (rdev->irq.stat_regs.cik.disp_int_cont &DC_HPD2_INTERRUPT ) { + rdev->irq.stat_regs.cik.disp_int_cont &= ~DC_HPD2_INTERRUPT ; + queue_hotplug = true; +DRM_DEBUG ("IH: HPD2\n" ); + } +break ; +case 2 : +if (rdev->irq.stat_regs.cik.disp_int_cont2 &DC_HPD3_INTERRUPT ) { + rdev->irq.stat_regs.cik.disp_int_cont2 &= ~DC_HPD3_INTERRUPT ; + queue_hotplug = true; +DRM_DEBUG ("IH: HPD3\n" ); + } +break ; +case 3 : +if (rdev->irq.stat_regs.cik.disp_int_cont3 &DC_HPD4_INTERRUPT ) { + rdev->irq.stat_regs.cik.disp_int_cont3 &= ~DC_HPD4_INTERRUPT ; + queue_hotplug = true; +DRM_DEBUG ("IH: HPD4\n" ); + } +break ; +case 4 : +if (rdev->irq.stat_regs.cik.disp_int_cont4 &DC_HPD5_INTERRUPT ) { + rdev->irq.stat_regs.cik.disp_int_cont4 &= ~DC_HPD5_INTERRUPT ; + queue_hotplug = true; +DRM_DEBUG ("IH: HPD5\n" ); + } +break ; +case 5 : +if (rdev->irq.stat_regs.cik.disp_int_cont5 &DC_HPD6_INTERRUPT ) { + rdev->irq.stat_regs.cik.disp_int_cont5 &= ~DC_HPD6_INTERRUPT ; + queue_hotplug = true; +DRM_DEBUG ("IH: HPD6\n" ); + } +break ; +default : +DRM_DEBUG ("Unhandled interrupt: %d %d\n" , src_id, src_data); +break ; + } +break ; +case 176 :/* GFX RB CP_INT */ +case 177 :/* GFX IB CP_INT */ +radeon_fence_process (rdev,RADEON_RING_TYPE_GFX_INDEX ); +break ; +case 181 :/* CP EOP event */ +DRM_DEBUG ("IH: CP EOP\n" ); +switch (me_id) { +case 0 : +radeon_fence_process (rdev,RADEON_RING_TYPE_GFX_INDEX ); +break ; +case 1 : +/* XXX compute */ +break ; +case 2 : +/* XXX compute */ +break ; + } +break ; +case 184 :/* CP Privileged reg access */ +DRM_ERROR ("Illegal register access in command stream\n" ); +/* XXX check the bitfield order! */ + me_id = (ring_id &0x60 ) >>5 ; + pipe_id = (ring_id &0x18 ) >>3 ; + queue_id = (ring_id &0x7 ) >>0 ; +switch (me_id) { +case 0 : +/* This results in a full GPU reset, but all we need to do is soft +* reset the CP for gfx +*/ + queue_reset = true; +break ; +case 1 : +/* XXX compute */ +break ; +case 2 : +/* XXX compute */ +break ; + } +break ; +case 185 :/* CP Privileged inst */ +DRM_ERROR ("Illegal instruction in command stream\n" ); +switch (me_id) { +case 0 : +/* This results in a full GPU reset, but all we need to do is soft +* reset the CP for gfx +*/ + queue_reset = true; +break ; +case 1 : +/* XXX compute */ +break ; +case 2 : +/* XXX compute */ +break ; + } +break ; +case 233 :/* GUI IDLE */ +DRM_DEBUG ("IH: GUI idle\n" ); +break ; +default : +DRM_DEBUG ("Unhandled interrupt: %d %d\n" , src_id, src_data); +break ; + } + +/* wptr/rptr are in bytes! */ + rptr +=16 ; + rptr &= rdev->ih.ptr_mask; + } +if (queue_hotplug) +schedule_work (&rdev->hotplug_work); +if (queue_reset) +schedule_work (&rdev->reset_work); + rdev->ih.rptr = rptr; +WREG32 (IH_RB_RPTR , rdev->ih.rptr); +atomic_set (&rdev->ih.lock,0 ); + +/* make sure wptr hasn't changed while processing */ + wptr =cik_get_ih_wptr (rdev); +if (wptr != rptr) + goto restart_ih; + +return IRQ_HANDLED ; +}
drivers/gpu/drm/radeon/cikd.h +170 -0
196 lines not on this page · raw message
drivers/gpu/drm/radeon/radeon.h +11 -0
@@ -600,10 +600,21 @@ struct evergreen_irq_stat_regs {u32 afmt_status6; }; +struct cik_irq_stat_regs { +u32 disp_int; +u32 disp_int_cont; +u32 disp_int_cont2; +u32 disp_int_cont3; +u32 disp_int_cont4; +u32 disp_int_cont5; +u32 disp_int_cont6; +}; +union radeon_irq_stat_regs {struct r500_irq_stat_regs r500;struct r600_irq_stat_regs r600;struct evergreen_irq_stat_regs evergreen; +struct cik_irq_stat_regs cik; };#define RADEON_MAX_HPD_PINS 6
Signature · 1 line
1.7.7.5
PATCH 19/165 drm/radeon/cik: log and handle VM page fault interrupts
In reply to [email protected]From: Alex Deucher <[email protected]>
--- drivers/gpu/drm/radeon/cik.c | 10 ++++++++++ drivers/gpu/drm/radeon/cikd.h | 4 ++++ 2 files changed, 14 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/cik.c +10 -0
@@ -3676,6 +3676,16 @@ restart_ih:break ; }break ; +case 146 : +case 147 : +dev_err (rdev->dev,"GPU fault detected: %d 0x%08x\n" , src_id, src_data); +dev_err (rdev->dev," VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n" , +RREG32 (VM_CONTEXT1_PROTECTION_FAULT_ADDR )); +dev_err (rdev->dev," VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n" , +RREG32 (VM_CONTEXT1_PROTECTION_FAULT_STATUS )); +/* reset addr and status */ +WREG32_P (VM_CONTEXT1_CNTL2 ,1 , ~1 ); +break ;case 176 :/* GFX RB CP_INT */ case 177 :/* GFX IB CP_INT */ radeon_fence_process (rdev,RADEON_RING_TYPE_GFX_INDEX );
drivers/gpu/drm/radeon/cikd.h +4 -0
@@ -95,6 +95,10 @@#define VM_INVALIDATE_REQUEST 0x1478#define VM_INVALIDATE_RESPONSE 0x147c +#define VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x14DC + +#define VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x14FC +#define VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR 0x1518#define VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR 0x151c
Signature · 1 line
1.7.7.5
PATCH 20/165 drm/radeon/cik: add support for sDMA dma engines (v8)
In reply to [email protected]From: Alex Deucher <[email protected]>
CIK has new asynchronous DMA engines called sDMA (system DMA). Each engine supports 1 ring buffer for kernel and gfx and 2 userspace queues for compute.
TODO: fill in the compute setup.
v2: update to the latest reset code
v3: remove ib_parse
v4: fix copy_dma()
v5: drop WIP compute sDMA queues
v6: rebase
v7: endian fixes for IB
v8: cleanup for release
--- drivers/gpu/drm/radeon/cik.c | 745 ++++++++++++++++++++++++++++++++++++++- drivers/gpu/drm/radeon/cikd.h | 130 +++++++ drivers/gpu/drm/radeon/radeon.h | 1 + 3 files changed, 870 insertions(+), 6 deletions(-)
drivers/gpu/drm/radeon/cik.c +739 -6
@@ -44,6 +44,9 @@#define KV_RLC_UCODE_SIZE 2560/* gddr controller */ #define CIK_MC_UCODE_SIZE 7866 +/* sdma */ +#define CIK_SDMA_UCODE_SIZE 1050 +#define CIK_SDMA_UCODE_VERSION 64MODULE_FIRMWARE ("radeon/BONAIRE_pfp.bin" );MODULE_FIRMWARE ("radeon/BONAIRE_me.bin" );
@@ -51,16 +54,19 @@ MODULE_FIRMWARE("radeon/BONAIRE_ce.bin");MODULE_FIRMWARE ("radeon/BONAIRE_mec.bin" );MODULE_FIRMWARE ("radeon/BONAIRE_mc.bin" );MODULE_FIRMWARE ("radeon/BONAIRE_rlc.bin" ); +MODULE_FIRMWARE ("radeon/BONAIRE_sdma.bin" );MODULE_FIRMWARE ("radeon/KAVERI_pfp.bin" );MODULE_FIRMWARE ("radeon/KAVERI_me.bin" );MODULE_FIRMWARE ("radeon/KAVERI_ce.bin" );MODULE_FIRMWARE ("radeon/KAVERI_mec.bin" );MODULE_FIRMWARE ("radeon/KAVERI_rlc.bin" ); +MODULE_FIRMWARE ("radeon/KAVERI_sdma.bin" );MODULE_FIRMWARE ("radeon/KABINI_pfp.bin" );MODULE_FIRMWARE ("radeon/KABINI_me.bin" );MODULE_FIRMWARE ("radeon/KABINI_ce.bin" );MODULE_FIRMWARE ("radeon/KABINI_mec.bin" );MODULE_FIRMWARE ("radeon/KABINI_rlc.bin" ); +MODULE_FIRMWARE ("radeon/KABINI_sdma.bin" );extern int r600_ih_ring_alloc (struct radeon_device *rdev);extern void r600_ih_ring_fini (struct radeon_device *rdev);
@@ -198,7 +204,8 @@ static int cik_init_microcode(struct radeon_device *rdev)struct platform_device *pdev;const char *chip_name;size_t pfp_req_size, me_req_size, ce_req_size, - mec_req_size, rlc_req_size, mc_req_size; + mec_req_size, rlc_req_size, mc_req_size, + sdma_req_size;char fw_name[30 ];int err;
@@ -220,6 +227,7 @@ static int cik_init_microcode(struct radeon_device *rdev) mec_req_size =CIK_MEC_UCODE_SIZE *4 ; rlc_req_size =BONAIRE_RLC_UCODE_SIZE *4 ; mc_req_size =CIK_MC_UCODE_SIZE *4 ; + sdma_req_size =CIK_SDMA_UCODE_SIZE *4 ;break ;case CHIP_KAVERI : chip_name ="KAVERI" ;
@@ -228,6 +236,7 @@ static int cik_init_microcode(struct radeon_device *rdev) ce_req_size =CIK_CE_UCODE_SIZE *4 ; mec_req_size =CIK_MEC_UCODE_SIZE *4 ; rlc_req_size =KV_RLC_UCODE_SIZE *4 ; + sdma_req_size =CIK_SDMA_UCODE_SIZE *4 ;break ;case CHIP_KABINI : chip_name ="KABINI" ;
@@ -236,6 +245,7 @@ static int cik_init_microcode(struct radeon_device *rdev) ce_req_size =CIK_CE_UCODE_SIZE *4 ; mec_req_size =CIK_MEC_UCODE_SIZE *4 ; rlc_req_size =KB_RLC_UCODE_SIZE *4 ; + sdma_req_size =CIK_SDMA_UCODE_SIZE *4 ;break ;default :BUG (); }
@@ -298,6 +308,17 @@ static int cik_init_microcode(struct radeon_device *rdev) err = -EINVAL ; } +snprintf (fw_name,sizeof (fw_name),"radeon/%s_sdma.bin" , chip_name); + err =request_firmware (&rdev->sdma_fw, fw_name, &pdev->dev); +if (err) + goto out; +if (rdev->sdma_fw->size != sdma_req_size) { +printk (KERN_ERR +"cik_sdma: Bogus length %zu in firmware \"%s\"\n" , + rdev->sdma_fw->size, fw_name); + err = -EINVAL ; + } +/* No MC ucode on APUs */ if (!(rdev->flags &RADEON_IS_IGP )) {snprintf (fw_name,sizeof (fw_name),"radeon/%s_mc.bin" , chip_name);
@@ -1425,6 +1446,8 @@ static void cik_gpu_init(struct radeon_device *rdev)WREG32 (GB_ADDR_CONFIG , gb_addr_config);WREG32 (HDP_ADDR_CONFIG , gb_addr_config);WREG32 (DMIF_ADDR_CALC , gb_addr_config); +WREG32 (SDMA0_TILING_CONFIG +SDMA0_REGISTER_OFFSET , gb_addr_config &0x70 ); +WREG32 (SDMA0_TILING_CONFIG +SDMA1_REGISTER_OFFSET , gb_addr_config &0x70 );cik_tiling_mode_table_init (rdev);
@@ -2136,6 +2159,578 @@ static int cik_cp_resume(struct radeon_device *rdev)return 0 ; } +/* +* sDMA - System DMA +* Starting with CIK, the GPU has new asynchronous +* DMA engines. These engines are used for compute +* and gfx. There are two DMA engines (SDMA0, SDMA1) +* and each one supports 1 ring buffer used for gfx +* and 2 queues used for compute. +* +* The programming model is very similar to the CP +* (ring buffer, IBs, etc.), but sDMA has it's own +* packet format that is different from the PM4 format +* used by the CP. sDMA supports copying data, writing +* embedded data, solid fills, and a number of other +* things. It also has support for tiling/detiling of +* buffers. +*/ +/** +* cik_sdma_ring_ib_execute - Schedule an IB on the DMA engine +* +* @rdev: radeon_device pointer +* @ib: IB object to schedule +* +* Schedule an IB in the DMA ring (CIK). +*/ +void cik_sdma_ring_ib_execute (struct radeon_device *rdev, +struct radeon_ib *ib) +{ +struct radeon_ring *ring = &rdev->ring[ib->ring]; +u32 extra_bits = (ib->vm ? ib->vm->id :0 ) &0xf ; + +if (rdev->wb.enabled) { +u32 next_rptr = ring->wptr +5 ; +while ((next_rptr &7 ) !=4 ) + next_rptr++; + next_rptr +=4 ; +radeon_ring_write (ring,SDMA_PACKET (SDMA_OPCODE_WRITE ,SDMA_WRITE_SUB_OPCODE_LINEAR ,0 )); +radeon_ring_write (ring, ring->next_rptr_gpu_addr &0xfffffffc ); +radeon_ring_write (ring,upper_32_bits (ring->next_rptr_gpu_addr) &0xffffffff ); +radeon_ring_write (ring,1 );/* number of DWs to follow */ +radeon_ring_write (ring, next_rptr); + } + +/* IB packet must end on a 8 DW boundary */ +while ((ring->wptr &7 ) !=4 ) +radeon_ring_write (ring,SDMA_PACKET (SDMA_OPCODE_NOP ,0 ,0 )); +radeon_ring_write (ring,SDMA_PACKET (SDMA_OPCODE_INDIRECT_BUFFER ,0 , extra_bits)); +radeon_ring_write (ring, ib->gpu_addr &0xffffffe0 );/* base must be 32 byte aligned */ +radeon_ring_write (ring,upper_32_bits (ib->gpu_addr) &0xffffffff ); +radeon_ring_write (ring, ib->length_dw); + +} + +/** +* cik_sdma_fence_ring_emit - emit a fence on the DMA ring +* +* @rdev: radeon_device pointer +* @fence: radeon fence object +* +* Add a DMA fence packet to the ring to write +* the fence seq number and DMA trap packet to generate +* an interrupt if needed (CIK). +*/ +void cik_sdma_fence_ring_emit (struct radeon_device *rdev, +struct radeon_fence *fence) +{ +struct radeon_ring *ring = &rdev->ring[fence->ring]; +u64 addr = rdev->fence_drv[fence->ring].gpu_addr; +u32 extra_bits = (SDMA_POLL_REG_MEM_EXTRA_OP (1 ) | +SDMA_POLL_REG_MEM_EXTRA_FUNC (3 ));/* == */ +u32 ref_and_mask; + +if (fence->ring ==R600_RING_TYPE_DMA_INDEX ) + ref_and_mask =SDMA0 ; +else + ref_and_mask =SDMA1 ; + +/* write the fence */ +radeon_ring_write (ring,SDMA_PACKET (SDMA_OPCODE_FENCE ,0 ,0 )); +radeon_ring_write (ring, addr &0xffffffff ); +radeon_ring_write (ring,upper_32_bits (addr) &0xffffffff ); +radeon_ring_write (ring, fence->seq); +/* generate an interrupt */ +radeon_ring_write (ring,SDMA_PACKET (SDMA_OPCODE_TRAP ,0 ,0 )); +/* flush HDP */ +radeon_ring_write (ring,SDMA_PACKET (SDMA_OPCODE_POLL_REG_MEM ,0 , extra_bits)); +radeon_ring_write (ring,GPU_HDP_FLUSH_DONE ); +radeon_ring_write (ring,GPU_HDP_FLUSH_REQ ); +radeon_ring_write (ring, ref_and_mask);/* REFERENCE */ +radeon_ring_write (ring, ref_and_mask);/* MASK */ +radeon_ring_write (ring, (4 <<16 ) |10 );/* RETRY_COUNT, POLL_INTERVAL */ +} + +/** +* cik_sdma_semaphore_ring_emit - emit a semaphore on the dma ring +* +* @rdev: radeon_device pointer +* @ring: radeon_ring structure holding ring information +* @semaphore: radeon semaphore object +* @emit_wait: wait or signal semaphore +* +* Add a DMA semaphore packet to the ring wait on or signal +* other rings (CIK). +*/ +void cik_sdma_semaphore_ring_emit (struct radeon_device *rdev, +struct radeon_ring *ring, +struct radeon_semaphore *semaphore, +bool emit_wait) +{ +u64 addr = semaphore->gpu_addr; +u32 extra_bits = emit_wait ?0 :SDMA_SEMAPHORE_EXTRA_S ; + +radeon_ring_write (ring,SDMA_PACKET (SDMA_OPCODE_SEMAPHORE ,0 , extra_bits)); +radeon_ring_write (ring, addr &0xfffffff8 ); +radeon_ring_write (ring,upper_32_bits (addr) &0xffffffff ); +} + +/** +* cik_sdma_gfx_stop - stop the gfx async dma engines +* +* @rdev: radeon_device pointer +* +* Stop the gfx async dma ring buffers (CIK). +*/ +static void cik_sdma_gfx_stop (struct radeon_device *rdev) +{ +u32 rb_cntl, reg_offset; +int i; + +radeon_ttm_set_active_vram_size (rdev, rdev->mc.visible_vram_size); + +for (i =0 ; i <2 ; i++) { +if (i ==0 ) + reg_offset =SDMA0_REGISTER_OFFSET ; +else + reg_offset =SDMA1_REGISTER_OFFSET ; + rb_cntl =RREG32 (SDMA0_GFX_RB_CNTL + reg_offset); + rb_cntl &= ~SDMA_RB_ENABLE ; +WREG32 (SDMA0_GFX_RB_CNTL + reg_offset, rb_cntl); +WREG32 (SDMA0_GFX_IB_CNTL + reg_offset,0 ); + } +} + +/** +* cik_sdma_rlc_stop - stop the compute async dma engines +* +* @rdev: radeon_device pointer +* +* Stop the compute async dma queues (CIK). +*/ +static void cik_sdma_rlc_stop (struct radeon_device *rdev) +{ +/* XXX todo */ +} + +/** +* cik_sdma_enable - stop the async dma engines +* +* @rdev: radeon_device pointer +* @enable: enable/disable the DMA MEs. +* +* Halt or unhalt the async dma engines (CIK). +*/ +static void cik_sdma_enable (struct radeon_device *rdev,bool enable) +{ +u32 me_cntl, reg_offset; +int i; + +for (i =0 ; i <2 ; i++) { +if (i ==0 ) + reg_offset =SDMA0_REGISTER_OFFSET ; +else + reg_offset =SDMA1_REGISTER_OFFSET ; + me_cntl =RREG32 (SDMA0_ME_CNTL + reg_offset); +if (enable) + me_cntl &= ~SDMA_HALT ; +else + me_cntl |=SDMA_HALT ; +WREG32 (SDMA0_ME_CNTL + reg_offset, me_cntl); + } +} + +/** +* cik_sdma_gfx_resume - setup and start the async dma engines +* +* @rdev: radeon_device pointer +* +* Set up the gfx DMA ring buffers and enable them (CIK). +* Returns 0 for success, error for failure. +*/ +static int cik_sdma_gfx_resume (struct radeon_device *rdev) +{ +struct radeon_ring *ring; +u32 rb_cntl, ib_cntl; +u32 rb_bufsz; +u32 reg_offset, wb_offset; +int i, r; + +for (i =0 ; i <2 ; i++) { +if (i ==0 ) { + ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX ]; + reg_offset =SDMA0_REGISTER_OFFSET ; + wb_offset =R600_WB_DMA_RPTR_OFFSET ; + }else { + ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX ]; + reg_offset =SDMA1_REGISTER_OFFSET ; + wb_offset =CAYMAN_WB_DMA1_RPTR_OFFSET ; + } + +WREG32 (SDMA0_SEM_INCOMPLETE_TIMER_CNTL + reg_offset,0 ); +WREG32 (SDMA0_SEM_WAIT_FAIL_TIMER_CNTL + reg_offset,0 ); + +/* Set ring buffer size in dwords */ + rb_bufsz =drm_order (ring->ring_size /4 ); + rb_cntl = rb_bufsz <<1 ; +#ifdef __BIG_ENDIAN + rb_cntl |=SDMA_RB_SWAP_ENABLE |SDMA_RPTR_WRITEBACK_SWAP_ENABLE ; +#endif +WREG32 (SDMA0_GFX_RB_CNTL + reg_offset, rb_cntl); + +/* Initialize the ring buffer's read and write pointers */ +WREG32 (SDMA0_GFX_RB_RPTR + reg_offset,0 ); +WREG32 (SDMA0_GFX_RB_WPTR + reg_offset,0 ); + +/* set the wb address whether it's enabled or not */ +WREG32 (SDMA0_GFX_RB_RPTR_ADDR_HI + reg_offset, +upper_32_bits (rdev->wb.gpu_addr + wb_offset) &0xFFFFFFFF ); +WREG32 (SDMA0_GFX_RB_RPTR_ADDR_LO + reg_offset, + ((rdev->wb.gpu_addr + wb_offset) &0xFFFFFFFC )); + +if (rdev->wb.enabled) + rb_cntl |=SDMA_RPTR_WRITEBACK_ENABLE ; + +WREG32 (SDMA0_GFX_RB_BASE + reg_offset, ring->gpu_addr >>8 ); +WREG32 (SDMA0_GFX_RB_BASE_HI + reg_offset, ring->gpu_addr >>40 ); + + ring->wptr =0 ; +WREG32 (SDMA0_GFX_RB_WPTR + reg_offset, ring->wptr <<2 ); + + ring->rptr =RREG32 (SDMA0_GFX_RB_RPTR + reg_offset) >>2 ; + +/* enable DMA RB */ +WREG32 (SDMA0_GFX_RB_CNTL + reg_offset, rb_cntl |SDMA_RB_ENABLE ); + + ib_cntl =SDMA_IB_ENABLE ; +#ifdef __BIG_ENDIAN + ib_cntl |=SDMA_IB_SWAP_ENABLE ; +#endif +/* enable DMA IBs */ +WREG32 (SDMA0_GFX_IB_CNTL + reg_offset, ib_cntl); + + ring->ready = true; + + r =radeon_ring_test (rdev, ring->idx, ring); +if (r) { + ring->ready = false; +return r; + } + } + +radeon_ttm_set_active_vram_size (rdev, rdev->mc.real_vram_size); + +return 0 ; +} + +/** +* cik_sdma_rlc_resume - setup and start the async dma engines +* +* @rdev: radeon_device pointer +* +* Set up the compute DMA queues and enable them (CIK). +* Returns 0 for success, error for failure. +*/ +static int cik_sdma_rlc_resume (struct radeon_device *rdev) +{ +/* XXX todo */ +return 0 ; +} + +/** +* cik_sdma_load_microcode - load the sDMA ME ucode +* +* @rdev: radeon_device pointer +* +* Loads the sDMA0/1 ucode. +* Returns 0 for success, -EINVAL if the ucode is not available. +*/ +static int cik_sdma_load_microcode (struct radeon_device *rdev) +{ +const __be32 *fw_data; +int i; + +if (!rdev->sdma_fw) +return -EINVAL ; + +/* stop the gfx rings and rlc compute queues */ +cik_sdma_gfx_stop (rdev); +cik_sdma_rlc_stop (rdev); + +/* halt the MEs */ +cik_sdma_enable (rdev, false); + +/* sdma0 */ + fw_data = (const __be32 *)rdev->sdma_fw->data; +WREG32 (SDMA0_UCODE_ADDR +SDMA0_REGISTER_OFFSET ,0 ); +for (i =0 ; i <CIK_SDMA_UCODE_SIZE ; i++) +WREG32 (SDMA0_UCODE_DATA +SDMA0_REGISTER_OFFSET ,be32_to_cpup (fw_data++)); +WREG32 (SDMA0_UCODE_DATA +SDMA0_REGISTER_OFFSET ,CIK_SDMA_UCODE_VERSION ); + +/* sdma1 */ + fw_data = (const __be32 *)rdev->sdma_fw->data; +WREG32 (SDMA0_UCODE_ADDR +SDMA1_REGISTER_OFFSET ,0 ); +for (i =0 ; i <CIK_SDMA_UCODE_SIZE ; i++) +WREG32 (SDMA0_UCODE_DATA +SDMA1_REGISTER_OFFSET ,be32_to_cpup (fw_data++)); +WREG32 (SDMA0_UCODE_DATA +SDMA1_REGISTER_OFFSET ,CIK_SDMA_UCODE_VERSION ); + +WREG32 (SDMA0_UCODE_ADDR +SDMA0_REGISTER_OFFSET ,0 ); +WREG32 (SDMA0_UCODE_ADDR +SDMA1_REGISTER_OFFSET ,0 ); +return 0 ; +} + +/** +* cik_sdma_resume - setup and start the async dma engines +* +* @rdev: radeon_device pointer +* +* Set up the DMA engines and enable them (CIK). +* Returns 0 for success, error for failure. +*/ +static int cik_sdma_resume (struct radeon_device *rdev) +{ +int r; + +/* Reset dma */ +WREG32 (SRBM_SOFT_RESET ,SOFT_RESET_SDMA |SOFT_RESET_SDMA1 ); +RREG32 (SRBM_SOFT_RESET ); +udelay (50 ); +WREG32 (SRBM_SOFT_RESET ,0 ); +RREG32 (SRBM_SOFT_RESET ); + + r =cik_sdma_load_microcode (rdev); +if (r) +return r; + +/* unhalt the MEs */ +cik_sdma_enable (rdev, true); + +/* start the gfx rings and rlc compute queues */ + r =cik_sdma_gfx_resume (rdev); +if (r) +return r; + r =cik_sdma_rlc_resume (rdev); +if (r) +return r; + +return 0 ; +} + +/** +* cik_sdma_fini - tear down the async dma engines +* +* @rdev: radeon_device pointer +* +* Stop the async dma engines and free the rings (CIK). +*/ +static void cik_sdma_fini (struct radeon_device *rdev) +{ +/* stop the gfx rings and rlc compute queues */ +cik_sdma_gfx_stop (rdev); +cik_sdma_rlc_stop (rdev); +/* halt the MEs */ +cik_sdma_enable (rdev, false); +radeon_ring_fini (rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX ]); +radeon_ring_fini (rdev, &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX ]); +/* XXX - compute dma queue tear down */ +} + +/** +* cik_copy_dma - copy pages using the DMA engine +* +* @rdev: radeon_device pointer +* @src_offset: src GPU address +* @dst_offset: dst GPU address +* @num_gpu_pages: number of GPU pages to xfer +* @fence: radeon fence object +* +* Copy GPU paging using the DMA engine (CIK). +* Used by the radeon ttm implementation to move pages if +* registered as the asic copy callback. +*/ +int cik_copy_dma (struct radeon_device *rdev, +uint64_t src_offset,uint64_t dst_offset, +unsigned num_gpu_pages, +struct radeon_fence **fence) +{ +struct radeon_semaphore *sem =NULL ; +int ring_index = rdev->asic->copy.dma_ring_index; +struct radeon_ring *ring = &rdev->ring[ring_index]; +u32 size_in_bytes, cur_size_in_bytes; +int i, num_loops; +int r =0 ; + + r =radeon_semaphore_create (rdev, &sem); +if (r) { +DRM_ERROR ("radeon: moving bo (%d).\n" , r); +return r; + } + + size_in_bytes = (num_gpu_pages <<RADEON_GPU_PAGE_SHIFT ); + num_loops =DIV_ROUND_UP (size_in_bytes,0x1fffff ); + r =radeon_ring_lock (rdev, ring, num_loops *7 +14 ); +if (r) { +DRM_ERROR ("radeon: moving bo (%d).\n" , r); +radeon_semaphore_free (rdev, &sem,NULL ); +return r; + } + +if (radeon_fence_need_sync (*fence, ring->idx)) { +radeon_semaphore_sync_rings (rdev, sem, (*fence)->ring, + ring->idx); +radeon_fence_note_sync (*fence, ring->idx); + }else { +radeon_semaphore_free (rdev, &sem,NULL ); + } + +for (i =0 ; i < num_loops; i++) { + cur_size_in_bytes = size_in_bytes; +if (cur_size_in_bytes >0x1fffff ) + cur_size_in_bytes =0x1fffff ; + size_in_bytes -= cur_size_in_bytes; +radeon_ring_write (ring,SDMA_PACKET (SDMA_OPCODE_COPY ,SDMA_COPY_SUB_OPCODE_LINEAR ,0 )); +radeon_ring_write (ring, cur_size_in_bytes); +radeon_ring_write (ring,0 );/* src/dst endian swap */ +radeon_ring_write (ring, src_offset &0xffffffff ); +radeon_ring_write (ring,upper_32_bits (src_offset) &0xffffffff ); +radeon_ring_write (ring, dst_offset &0xfffffffc ); +radeon_ring_write (ring,upper_32_bits (dst_offset) &0xffffffff ); + src_offset += cur_size_in_bytes; + dst_offset += cur_size_in_bytes; + } + + r =radeon_fence_emit (rdev, fence, ring->idx); +if (r) { +radeon_ring_unlock_undo (rdev, ring); +return r; + } + +radeon_ring_unlock_commit (rdev, ring); +radeon_semaphore_free (rdev, &sem, *fence); + +return r; +} + +/** +* cik_sdma_ring_test - simple async dma engine test +* +* @rdev: radeon_device pointer +* @ring: radeon_ring structure holding ring information +* +* Test the DMA engine by writing using it to write an +* value to memory. (CIK). +* Returns 0 for success, error for failure. +*/ +int cik_sdma_ring_test (struct radeon_device *rdev, +struct radeon_ring *ring) +{ +unsigned i; +int r; +void __iomem *ptr = (void *)rdev->vram_scratch.ptr; +u32 tmp; + +if (!ptr) { +DRM_ERROR ("invalid vram scratch pointer\n" ); +return -EINVAL ; + } + + tmp =0xCAFEDEAD ; +writel (tmp, ptr); + + r =radeon_ring_lock (rdev, ring,4 ); +if (r) { +DRM_ERROR ("radeon: dma failed to lock ring %d (%d).\n" , ring->idx, r); +return r; + } +radeon_ring_write (ring,SDMA_PACKET (SDMA_OPCODE_WRITE ,SDMA_WRITE_SUB_OPCODE_LINEAR ,0 )); +radeon_ring_write (ring, rdev->vram_scratch.gpu_addr &0xfffffffc ); +radeon_ring_write (ring,upper_32_bits (rdev->vram_scratch.gpu_addr) &0xffffffff ); +radeon_ring_write (ring,1 );/* number of DWs to follow */ +radeon_ring_write (ring,0xDEADBEEF ); +radeon_ring_unlock_commit (rdev, ring); + +for (i =0 ; i < rdev->usec_timeout; i++) { + tmp =readl (ptr); +if (tmp ==0xDEADBEEF ) +break ; +DRM_UDELAY (1 ); + } + +if (i < rdev->usec_timeout) { +DRM_INFO ("ring test on %d succeeded in %d usecs\n" , ring->idx, i); + }else { +DRM_ERROR ("radeon: ring %d test failed (0x%08X)\n" , + ring->idx, tmp); + r = -EINVAL ; + } +return r; +} + +/** +* cik_sdma_ib_test - test an IB on the DMA engine +* +* @rdev: radeon_device pointer +* @ring: radeon_ring structure holding ring information +* +* Test a simple IB in the DMA ring (CIK). +* Returns 0 on success, error on failure. +*/ +int cik_sdma_ib_test (struct radeon_device *rdev,struct radeon_ring *ring) +{ +struct radeon_ib ib; +unsigned i; +int r; +void __iomem *ptr = (void *)rdev->vram_scratch.ptr; +u32 tmp =0 ; + +if (!ptr) { +DRM_ERROR ("invalid vram scratch pointer\n" ); +return -EINVAL ; + } + + tmp =0xCAFEDEAD ; +writel (tmp, ptr); + + r =radeon_ib_get (rdev, ring->idx, &ib,NULL ,256 ); +if (r) { +DRM_ERROR ("radeon: failed to get ib (%d).\n" , r); +return r; + } + + ib.ptr[0 ] =SDMA_PACKET (SDMA_OPCODE_WRITE ,SDMA_WRITE_SUB_OPCODE_LINEAR ,0 ); + ib.ptr[1 ] = rdev->vram_scratch.gpu_addr &0xfffffffc ; + ib.ptr[2 ] =upper_32_bits (rdev->vram_scratch.gpu_addr) &0xffffffff ; + ib.ptr[3 ] =1 ; + ib.ptr[4 ] =0xDEADBEEF ; + ib.length_dw =5 ; + + r =radeon_ib_schedule (rdev, &ib,NULL ); +if (r) { +radeon_ib_free (rdev, &ib); +DRM_ERROR ("radeon: failed to schedule ib (%d).\n" , r); +return r; + } + r =radeon_fence_wait (ib.fence, false); +if (r) { +DRM_ERROR ("radeon: fence wait failed (%d).\n" , r); +return r; + } +for (i =0 ; i < rdev->usec_timeout; i++) { + tmp =readl (ptr); +if (tmp ==0xDEADBEEF ) +break ; +DRM_UDELAY (1 ); + } +if (i < rdev->usec_timeout) { +DRM_INFO ("ib test on ring %d succeeded in %u usecs\n" , ib.fence->ring, i); + }else { +DRM_ERROR ("radeon: ib test failed (0x%08X)\n" , tmp); + r = -EINVAL ; + } +radeon_ib_free (rdev, &ib); +return r; +} +/** * cik_gpu_is_lockup - check if the 3D engine is locked up *
@@ -2330,6 +2925,32 @@ int cik_asic_reset(struct radeon_device *rdev)return cik_gfx_gpu_soft_reset (rdev); } +/** +* cik_sdma_is_lockup - Check if the DMA engine is locked up +* +* @rdev: radeon_device pointer +* @ring: radeon_ring structure holding ring information +* +* Check if the async DMA engine is locked up (CIK). +* Returns true if the engine appears to be locked up, false if not. +*/ +bool cik_sdma_is_lockup (struct radeon_device *rdev,struct radeon_ring *ring) +{ +u32 dma_status_reg; + +if (ring->idx ==R600_RING_TYPE_DMA_INDEX ) + dma_status_reg =RREG32 (SDMA0_STATUS_REG +SDMA0_REGISTER_OFFSET ); +else + dma_status_reg =RREG32 (SDMA0_STATUS_REG +SDMA1_REGISTER_OFFSET ); +if (dma_status_reg &SDMA_IDLE ) { +radeon_ring_lockup_update (ring); +return false; + } +/* force ring activities */ +radeon_ring_force_activity (rdev, ring); +return radeon_ring_test_lockup (rdev, ring); +} +/* MC */ /** * cik_mc_program - program the GPU memory controller
@@ -2588,10 +3209,17 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev)/* where to put LDS, scratch, GPUVM in FSA64 space */ for (i =0 ; i <16 ; i++) {WREG32 (SRBM_GFX_CNTL ,VMID (i)); +/* CP and shaders */ WREG32 (SH_MEM_CONFIG ,0 );WREG32 (SH_MEM_APE1_BASE ,1 );WREG32 (SH_MEM_APE1_LIMIT ,0 );WREG32 (SH_MEM_BASES ,0 ); +/* SDMA GFX */ +WREG32 (SDMA0_GFX_VIRTUAL_ADDR +SDMA0_REGISTER_OFFSET ,0 ); +WREG32 (SDMA0_GFX_APE1_CNTL +SDMA0_REGISTER_OFFSET ,0 ); +WREG32 (SDMA0_GFX_VIRTUAL_ADDR +SDMA1_REGISTER_OFFSET ,0 ); +WREG32 (SDMA0_GFX_APE1_CNTL +SDMA1_REGISTER_OFFSET ,0 ); +/* XXX SDMA RLC - todo */ }WREG32 (SRBM_GFX_CNTL ,0 );
@@ -2992,6 +3620,11 @@ static void cik_disable_interrupt_state(struct radeon_device *rdev)/* gfx ring */ WREG32 (CP_INT_CNTL_RING0 ,CNTX_BUSY_INT_ENABLE |CNTX_EMPTY_INT_ENABLE ); +/* sdma */ + tmp =RREG32 (SDMA0_CNTL +SDMA0_REGISTER_OFFSET ) & ~TRAP_ENABLE ; +WREG32 (SDMA0_CNTL +SDMA0_REGISTER_OFFSET , tmp); + tmp =RREG32 (SDMA0_CNTL +SDMA1_REGISTER_OFFSET ) & ~TRAP_ENABLE ; +WREG32 (SDMA0_CNTL +SDMA1_REGISTER_OFFSET , tmp);/* compute queues */ WREG32 (CP_ME1_PIPE0_INT_CNTL ,0 );WREG32 (CP_ME1_PIPE1_INT_CNTL ,0 );
@@ -3132,6 +3765,7 @@ int cik_irq_set(struct radeon_device *rdev)u32 crtc1 =0 , crtc2 =0 , crtc3 =0 , crtc4 =0 , crtc5 =0 , crtc6 =0 ;u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6;u32 grbm_int_cntl =0 ; +u32 dma_cntl, dma_cntl1;if (!rdev->irq.installed) {WARN (1 ,"Can't enable IRQ/MSI because no handler is installed\n" );
@@ -3152,6 +3786,9 @@ int cik_irq_set(struct radeon_device *rdev) hpd5 =RREG32 (DC_HPD5_INT_CONTROL ) & ~DC_HPDx_INT_EN; hpd6 =RREG32 (DC_HPD6_INT_CONTROL ) & ~DC_HPDx_INT_EN; + dma_cntl =RREG32 (SDMA0_CNTL +SDMA0_REGISTER_OFFSET ) & ~TRAP_ENABLE ; + dma_cntl1 =RREG32 (SDMA0_CNTL +SDMA1_REGISTER_OFFSET ) & ~TRAP_ENABLE ; +/* enable CP interrupts on all rings */ if (atomic_read (&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX ])) {DRM_DEBUG ("cik_irq_set: sw int gfx\n" );
@@ -3160,6 +3797,16 @@ int cik_irq_set(struct radeon_device *rdev)/* TODO: compute queues! */ /* CP_ME[1-2]_PIPE[0-3]_INT_CNTL */ +if (atomic_read (&rdev->irq.ring_int[R600_RING_TYPE_DMA_INDEX ])) { +DRM_DEBUG ("cik_irq_set: sw int dma\n" ); + dma_cntl |=TRAP_ENABLE ; + } + +if (atomic_read (&rdev->irq.ring_int[CAYMAN_RING_TYPE_DMA1_INDEX ])) { +DRM_DEBUG ("cik_irq_set: sw int dma1\n" ); + dma_cntl1 |=TRAP_ENABLE ; + } +if (rdev->irq.crtc_vblank_int[0 ] ||atomic_read (&rdev->irq.pflip[0 ])) {DRM_DEBUG ("cik_irq_set: vblank 0\n" );
@@ -3217,6 +3864,9 @@ int cik_irq_set(struct radeon_device *rdev)WREG32 (CP_INT_CNTL_RING0 , cp_int_cntl); +WREG32 (SDMA0_CNTL +SDMA0_REGISTER_OFFSET , dma_cntl); +WREG32 (SDMA0_CNTL +SDMA1_REGISTER_OFFSET , dma_cntl1); +WREG32 (GRBM_INT_CNTL , grbm_int_cntl);WREG32 (LB_INTERRUPT_MASK +EVERGREEN_CRTC0_REGISTER_OFFSET , crtc1);
@@ -3410,12 +4060,18 @@ static inline u32 cik_get_ih_wptr(struct radeon_device *rdev)* [31:8] - reserved * [59:32] - interrupt source data * [63:60] - reserved -* [71:64] - RINGID: ME_ID [1:0], PIPE_ID[1:0], QUEUE_ID[2:0] +* [71:64] - RINGID +* CP: +* ME_ID [1:0], PIPE_ID[1:0], QUEUE_ID[2:0] * QUEUE_ID - for compute, which of the 8 queues owned by the dispatcher * - for gfx, hw shader state (0=PS...5=LS, 6=CS) * ME_ID - 0 = gfx, 1 = first 4 CS pipes, 2 = second 4 CS pipes * PIPE_ID - ME0 0=3D * - ME1&2 compute dispatcher (4 pipes each) +* SDMA: +* INSTANCE_ID [1:0], QUEUE_ID[1:0] +* INSTANCE_ID - 0 = sdma0, 1 = sdma1 +* QUEUE_ID - 0 = gfx, 1 = rlc0, 2 = rlc1 * [79:72] - VMID * [95:80] - PASID * [127:96] - reserved
@@ -3465,10 +4121,6 @@ restart_ih: src_id =le32_to_cpu (rdev->ih.ring[ring_index]) &0xff ; src_data =le32_to_cpu (rdev->ih.ring[ring_index +1 ]) &0xfffffff ; ring_id =le32_to_cpu (rdev->ih.ring[ring_index +2 ]) &0xff ; -/* XXX check the bitfield order! */ - me_id = (ring_id &0x60 ) >>5 ; - pipe_id = (ring_id &0x18 ) >>3 ; - queue_id = (ring_id &0x7 ) >>0 ;switch (src_id) {case 1 :/* D1 vblank/vline */
@@ -3692,6 +4344,10 @@ restart_ih:break ;case 181 :/* CP EOP event */ DRM_DEBUG ("IH: CP EOP\n" ); +/* XXX check the bitfield order! */ + me_id = (ring_id &0x60 ) >>5 ; + pipe_id = (ring_id &0x18 ) >>3 ; + queue_id = (ring_id &0x7 ) >>0 ;switch (me_id) {case 0 :radeon_fence_process (rdev,RADEON_RING_TYPE_GFX_INDEX );
@@ -3727,6 +4383,10 @@ restart_ih:break ;case 185 :/* CP Privileged inst */ DRM_ERROR ("Illegal instruction in command stream\n" ); +/* XXX check the bitfield order! */ + me_id = (ring_id &0x60 ) >>5 ; + pipe_id = (ring_id &0x18 ) >>3 ; + queue_id = (ring_id &0x7 ) >>0 ;switch (me_id) {case 0 :/* This results in a full GPU reset, but all we need to do is soft
@@ -3742,6 +4402,79 @@ restart_ih:break ; }break ; +case 224 :/* SDMA trap event */ +/* XXX check the bitfield order! */ + me_id = (ring_id &0x3 ) >>0 ; + queue_id = (ring_id &0xc ) >>2 ; +DRM_DEBUG ("IH: SDMA trap\n" ); +switch (me_id) { +case 0 : +switch (queue_id) { +case 0 : +radeon_fence_process (rdev,R600_RING_TYPE_DMA_INDEX ); +break ; +case 1 : +/* XXX compute */ +break ; +case 2 : +/* XXX compute */ +break ; + } +break ; +case 1 : +switch (queue_id) { +case 0 : +radeon_fence_process (rdev,CAYMAN_RING_TYPE_DMA1_INDEX ); +break ; +case 1 : +/* XXX compute */ +break ; +case 2 : +/* XXX compute */ +break ; + } +break ; + } +break ; +case 241 :/* SDMA Privileged inst */ +case 247 :/* SDMA Privileged inst */ +DRM_ERROR ("Illegal instruction in SDMA command stream\n" ); +/* XXX check the bitfield order! */ + me_id = (ring_id &0x3 ) >>0 ; + queue_id = (ring_id &0xc ) >>2 ; +switch (me_id) { +case 0 : +switch (queue_id) { +case 0 : + queue_reset = true; +break ; +case 1 : +/* XXX compute */ + queue_reset = true; +break ; +case 2 : +/* XXX compute */ + queue_reset = true; +break ; + } +break ; +case 1 : +switch (queue_id) { +case 0 : + queue_reset = true; +break ; +case 1 : +/* XXX compute */ + queue_reset = true; +break ; +case 2 : +/* XXX compute */ + queue_reset = true; +break ; + } +break ; + } +break ;case 233 :/* GUI IDLE */ DRM_DEBUG ("IH: GUI idle\n" );break ;
drivers/gpu/drm/radeon/cikd.h +130 -0
140 lines not on this page · raw message
drivers/gpu/drm/radeon/radeon.h +1 -0
@@ -1726,6 +1726,7 @@ struct radeon_device {const struct firmware *ce_fw;/* SI CE firmware */ const struct firmware *uvd_fw;/* UVD firmware */ const struct firmware *mec_fw;/* CIK MEC firmware */ +const struct firmware *sdma_fw;/* CIK SDMA firmware */ struct r600_blit r600_blit;struct r600_vram_scratch vram_scratch;int msi_enabled;/* msi enabled */
Signature · 1 line
1.7.7.5
PATCH 21/165 drm/radeon: implement async vm_flush for the sDMA (v6)
In reply to [email protected]From: Alex Deucher <[email protected]>
Update the page table base address and flush the
VM TLB using the sDMA.
V2: update for 2 level PTs
V3: update vm flush
V4: update SH_MEM* regs
V5: switch back to old style VM TLB invalidate
V6: fix packet formatting
--- drivers/gpu/drm/radeon/cik.c | 70 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 70 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/cik.c +70 -0
@@ -3407,6 +3407,76 @@ void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)radeon_ring_write (ring,0x0 ); } +/** +* cik_dma_vm_flush - cik vm flush using sDMA +* +* @rdev: radeon_device pointer +* +* Update the page table base and flush the VM TLB +* using sDMA (CIK). +*/ +void cik_dma_vm_flush (struct radeon_device *rdev,int ridx,struct radeon_vm *vm) +{ +struct radeon_ring *ring = &rdev->ring[ridx]; +u32 extra_bits = (SDMA_POLL_REG_MEM_EXTRA_OP (1 ) | +SDMA_POLL_REG_MEM_EXTRA_FUNC (3 ));/* == */ +u32 ref_and_mask; + +if (vm ==NULL ) +return ; + +if (ridx ==R600_RING_TYPE_DMA_INDEX ) + ref_and_mask =SDMA0 ; +else + ref_and_mask =SDMA1 ; + +radeon_ring_write (ring,SDMA_PACKET (SDMA_OPCODE_SRBM_WRITE ,0 ,0xf000 )); +if (vm->id <8 ) { +radeon_ring_write (ring, (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id <<2 )) >>2 ); + }else { +radeon_ring_write (ring, (VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((vm->id -8 ) <<2 )) >>2 ); + } +radeon_ring_write (ring, vm->pd_gpu_addr >>12 ); + +/* update SH_MEM_* regs */ +radeon_ring_write (ring,SDMA_PACKET (SDMA_OPCODE_SRBM_WRITE ,0 ,0xf000 )); +radeon_ring_write (ring,SRBM_GFX_CNTL >>2 ); +radeon_ring_write (ring,VMID (vm->id)); + +radeon_ring_write (ring,SDMA_PACKET (SDMA_OPCODE_SRBM_WRITE ,0 ,0xf000 )); +radeon_ring_write (ring,SH_MEM_BASES >>2 ); +radeon_ring_write (ring,0 ); + +radeon_ring_write (ring,SDMA_PACKET (SDMA_OPCODE_SRBM_WRITE ,0 ,0xf000 )); +radeon_ring_write (ring,SH_MEM_CONFIG >>2 ); +radeon_ring_write (ring,0 ); + +radeon_ring_write (ring,SDMA_PACKET (SDMA_OPCODE_SRBM_WRITE ,0 ,0xf000 )); +radeon_ring_write (ring,SH_MEM_APE1_BASE >>2 ); +radeon_ring_write (ring,1 ); + +radeon_ring_write (ring,SDMA_PACKET (SDMA_OPCODE_SRBM_WRITE ,0 ,0xf000 )); +radeon_ring_write (ring,SH_MEM_APE1_LIMIT >>2 ); +radeon_ring_write (ring,0 ); + +radeon_ring_write (ring,SDMA_PACKET (SDMA_OPCODE_SRBM_WRITE ,0 ,0xf000 )); +radeon_ring_write (ring,SRBM_GFX_CNTL >>2 ); +radeon_ring_write (ring,VMID (0 )); + +/* flush HDP */ +radeon_ring_write (ring,SDMA_PACKET (SDMA_OPCODE_POLL_REG_MEM ,0 , extra_bits)); +radeon_ring_write (ring,GPU_HDP_FLUSH_DONE ); +radeon_ring_write (ring,GPU_HDP_FLUSH_REQ ); +radeon_ring_write (ring, ref_and_mask);/* REFERENCE */ +radeon_ring_write (ring, ref_and_mask);/* MASK */ +radeon_ring_write (ring, (4 <<16 ) |10 );/* RETRY_COUNT, POLL_INTERVAL */ + +/* flush TLB */ +radeon_ring_write (ring,SDMA_PACKET (SDMA_OPCODE_SRBM_WRITE ,0 ,0xf000 )); +radeon_ring_write (ring,VM_INVALIDATE_REQUEST >>2 ); +radeon_ring_write (ring,1 << vm->id); +} +/* * RLC * The RLC is a multi-purpose microengine that handles a
Signature · 1 line
1.7.7.5
PATCH 22/165 drm/radeon/cik: add support for doing async VM pt updates (v5)
In reply to [email protected]From: Alex Deucher <[email protected]>
Async page table updates using the sDMA engine. sDMA has a special packet for updating entries for contiguous pages that reduces overhead.
v2: add support for and use the CP for now.
v3: update for 2 level PTs
v4: rebase, fix DMA packet
v5: switch to using an IB
--- drivers/gpu/drm/radeon/cik.c | 109 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 109 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/cik.c +109 -0
@@ -3408,6 +3408,115 @@ void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) }/** +* cik_vm_set_page - update the page tables using sDMA +* +* @rdev: radeon_device pointer +* @ib: indirect buffer to fill with commands +* @pe: addr of the page entry +* @addr: dst addr to write into pe +* @count: number of page entries to update +* @incr: increase next addr by incr bytes +* @flags: access flags +* +* Update the page tables using CP or sDMA (CIK). +*/ +void cik_vm_set_page (struct radeon_device *rdev, +struct radeon_ib *ib, +uint64_t pe, +uint64_t addr,unsigned count, +uint32_t incr,uint32_t flags) +{ +uint32_t r600_flags =cayman_vm_page_flags (rdev, flags); +uint64_t value; +unsigned ndw; + +if (rdev->asic->vm.pt_ring_index ==RADEON_RING_TYPE_GFX_INDEX ) { +/* CP */ +while (count) { + ndw =2 + count *2 ; +if (ndw >0x3FFE ) + ndw =0x3FFE ; + + ib->ptr[ib->length_dw++] =PACKET3 (PACKET3_WRITE_DATA , ndw); + ib->ptr[ib->length_dw++] = (WRITE_DATA_ENGINE_SEL (0 ) | +WRITE_DATA_DST_SEL (1 )); + ib->ptr[ib->length_dw++] = pe; + ib->ptr[ib->length_dw++] =upper_32_bits (pe); +for (; ndw >2 ; ndw -=2 , --count, pe +=8 ) { +if (flags &RADEON_VM_PAGE_SYSTEM ) { + value =radeon_vm_map_gart (rdev, addr); + value &=0xFFFFFFFFFFFFF000ULL ; + }else if (flags &RADEON_VM_PAGE_VALID ) { + value = addr; + }else { + value =0 ; + } + addr += incr; + value |= r600_flags; + ib->ptr[ib->length_dw++] = value; + ib->ptr[ib->length_dw++] =upper_32_bits (value); + } + } + }else { +/* DMA */ +if (flags &RADEON_VM_PAGE_SYSTEM ) { +while (count) { + ndw = count *2 ; +if (ndw >0xFFFFE ) + ndw =0xFFFFE ; + +/* for non-physically contiguous pages (system) */ + ib->ptr[ib->length_dw++] =SDMA_PACKET (SDMA_OPCODE_WRITE ,SDMA_WRITE_SUB_OPCODE_LINEAR ,0 ); + ib->ptr[ib->length_dw++] = pe; + ib->ptr[ib->length_dw++] =upper_32_bits (pe); + ib->ptr[ib->length_dw++] = ndw; +for (; ndw >0 ; ndw -=2 , --count, pe +=8 ) { +if (flags &RADEON_VM_PAGE_SYSTEM ) { + value =radeon_vm_map_gart (rdev, addr); + value &=0xFFFFFFFFFFFFF000ULL ; + }else if (flags &RADEON_VM_PAGE_VALID ) { + value = addr; + }else { + value =0 ; + } + addr += incr; + value |= r600_flags; + ib->ptr[ib->length_dw++] = value; + ib->ptr[ib->length_dw++] =upper_32_bits (value); + } + } + }else { +while (count) { + ndw = count; +if (ndw >0x7FFFF ) + ndw =0x7FFFF ; + +if (flags &RADEON_VM_PAGE_VALID ) + value = addr; +else + value =0 ; +/* for physically contiguous pages (vram) */ + ib->ptr[ib->length_dw++] =SDMA_PACKET (SDMA_OPCODE_GENERATE_PTE_PDE ,0 ,0 ); + ib->ptr[ib->length_dw++] = pe;/* dst addr */ + ib->ptr[ib->length_dw++] =upper_32_bits (pe); + ib->ptr[ib->length_dw++] = r600_flags;/* mask */ + ib->ptr[ib->length_dw++] =0 ; + ib->ptr[ib->length_dw++] = value;/* value */ + ib->ptr[ib->length_dw++] =upper_32_bits (value); + ib->ptr[ib->length_dw++] = incr;/* increment size */ + ib->ptr[ib->length_dw++] =0 ; + ib->ptr[ib->length_dw++] = ndw;/* number of entries */ + pe += ndw *8 ; + addr += ndw * incr; + count -= ndw; + } + } +while (ib->length_dw &0x7 ) + ib->ptr[ib->length_dw++] =SDMA_PACKET (SDMA_OPCODE_NOP ,0 ,0 ); + } +} + +/** * cik_dma_vm_flush - cik vm flush using sDMA * * @rdev: radeon_device pointer
Signature · 1 line
1.7.7.5
PATCH 23/165 drm/radeon/cik: fill in startup/shutdown callbacks (v4)
In reply to [email protected]From: Alex Deucher <[email protected]>
v2: update to latest driver changes
v3: properly tear down vm on suspend
v4: fix up irq init ordering
--- drivers/gpu/drm/radeon/cik.c | 340 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 340 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/cik.c +340 -0
@@ -73,6 +73,8 @@ extern void r600_ih_ring_fini(struct radeon_device *rdev);extern void evergreen_mc_stop (struct radeon_device *rdev,struct evergreen_mc_save *save);extern void evergreen_mc_resume (struct radeon_device *rdev,struct evergreen_mc_save *save);extern void si_vram_gtt_location (struct radeon_device *rdev,struct radeon_mc *mc); +extern void si_rlc_fini (struct radeon_device *rdev); +extern int si_rlc_init (struct radeon_device *rdev);#define BONAIRE_IO_MC_REGS_SIZE 36
@@ -4681,3 +4683,341 @@ restart_ih:return IRQ_HANDLED ; } + +/* +* startup/shutdown callbacks +*/ +/** +* cik_startup - program the asic to a functional state +* +* @rdev: radeon_device pointer +* +* Programs the asic to a functional state (CIK). +* Called by cik_init() and cik_resume(). +* Returns 0 for success, error for failure. +*/ +static int cik_startup (struct radeon_device *rdev) +{ +struct radeon_ring *ring; +int r; + +if (rdev->flags &RADEON_IS_IGP ) { +if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw || + !rdev->mec_fw || !rdev->sdma_fw || !rdev->rlc_fw) { + r =cik_init_microcode (rdev); +if (r) { +DRM_ERROR ("Failed to load firmware!\n" ); +return r; + } + } + }else { +if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw || + !rdev->mec_fw || !rdev->sdma_fw || !rdev->rlc_fw || + !rdev->mc_fw) { + r =cik_init_microcode (rdev); +if (r) { +DRM_ERROR ("Failed to load firmware!\n" ); +return r; + } + } + + r =ci_mc_load_microcode (rdev); +if (r) { +DRM_ERROR ("Failed to load MC firmware!\n" ); +return r; + } + } + + r =r600_vram_scratch_init (rdev); +if (r) +return r; + +cik_mc_program (rdev); + r =cik_pcie_gart_enable (rdev); +if (r) +return r; +cik_gpu_init (rdev); + +/* allocate rlc buffers */ + r =si_rlc_init (rdev); +if (r) { +DRM_ERROR ("Failed to init rlc BOs!\n" ); +return r; + } + +/* allocate wb buffer */ + r =radeon_wb_init (rdev); +if (r) +return r; + + r =radeon_fence_driver_start_ring (rdev,RADEON_RING_TYPE_GFX_INDEX ); +if (r) { +dev_err (rdev->dev,"failed initializing CP fences (%d).\n" , r); +return r; + } + + r =radeon_fence_driver_start_ring (rdev,R600_RING_TYPE_DMA_INDEX ); +if (r) { +dev_err (rdev->dev,"failed initializing DMA fences (%d).\n" , r); +return r; + } + + r =radeon_fence_driver_start_ring (rdev,CAYMAN_RING_TYPE_DMA1_INDEX ); +if (r) { +dev_err (rdev->dev,"failed initializing DMA fences (%d).\n" , r); +return r; + } + +/* Enable IRQ */ +if (!rdev->irq.installed) { + r =radeon_irq_kms_init (rdev); +if (r) +return r; + } + + r =cik_irq_init (rdev); +if (r) { +DRM_ERROR ("radeon: IH init failed (%d).\n" , r); +radeon_irq_kms_fini (rdev); +return r; + } +cik_irq_set (rdev); + + ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX ]; + r =radeon_ring_init (rdev, ring, ring->ring_size,RADEON_WB_CP_RPTR_OFFSET , +CP_RB0_RPTR ,CP_RB0_WPTR , +0 ,0xfffff ,RADEON_CP_PACKET2 ); +if (r) +return r; + + ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX ]; + r =radeon_ring_init (rdev, ring, ring->ring_size,R600_WB_DMA_RPTR_OFFSET , +SDMA0_GFX_RB_RPTR +SDMA0_REGISTER_OFFSET , +SDMA0_GFX_RB_WPTR +SDMA0_REGISTER_OFFSET , +2 ,0xfffffffc ,SDMA_PACKET (SDMA_OPCODE_NOP ,0 ,0 )); +if (r) +return r; + + ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX ]; + r =radeon_ring_init (rdev, ring, ring->ring_size,CAYMAN_WB_DMA1_RPTR_OFFSET , +SDMA0_GFX_RB_RPTR +SDMA1_REGISTER_OFFSET , +SDMA0_GFX_RB_WPTR +SDMA1_REGISTER_OFFSET , +2 ,0xfffffffc ,SDMA_PACKET (SDMA_OPCODE_NOP ,0 ,0 )); +if (r) +return r; + + r =cik_cp_resume (rdev); +if (r) +return r; + + r =cik_sdma_resume (rdev); +if (r) +return r; + + r =radeon_ib_pool_init (rdev); +if (r) { +dev_err (rdev->dev,"IB initialization failed (%d).\n" , r); +return r; + } + + r =radeon_vm_manager_init (rdev); +if (r) { +dev_err (rdev->dev,"vm manager initialization failed (%d).\n" , r); +return r; + } + +return 0 ; +} + +/** +* cik_resume - resume the asic to a functional state +* +* @rdev: radeon_device pointer +* +* Programs the asic to a functional state (CIK). +* Called at resume. +* Returns 0 for success, error for failure. +*/ +int cik_resume (struct radeon_device *rdev) +{ +int r; + +/* Do not reset GPU before posting, on rv770 hw unlike on r500 hw, +* posting will perform necessary task to bring back GPU into good +* shape. +*/ +/* post card */ +atom_asic_init (rdev->mode_info.atom_context); + + rdev->accel_working = true; + r =cik_startup (rdev); +if (r) { +DRM_ERROR ("cik startup failed on resume\n" ); + rdev->accel_working = false; +return r; + } + +return r; + +} + +/** +* cik_suspend - suspend the asic +* +* @rdev: radeon_device pointer +* +* Bring the chip into a state suitable for suspend (CIK). +* Called at suspend. +* Returns 0 for success. +*/ +int cik_suspend (struct radeon_device *rdev) +{ +radeon_vm_manager_fini (rdev); +cik_cp_enable (rdev, false); +cik_sdma_enable (rdev, false); +cik_irq_suspend (rdev); +radeon_wb_disable (rdev); +cik_pcie_gart_disable (rdev); +return 0 ; +} + +/* Plan is to move initialization in that function and use +* helper function so that radeon_device_init pretty much +* do nothing more than calling asic specific function. This +* should also allow to remove a bunch of callback function +* like vram_info. +*/ +/** +* cik_init - asic specific driver and hw init +* +* @rdev: radeon_device pointer +* +* Setup asic specific driver variables and program the hw +* to a functional state (CIK). +* Called at driver startup. +* Returns 0 for success, errors for failure. +*/ +int cik_init (struct radeon_device *rdev) +{ +struct radeon_ring *ring; +int r; + +/* Read BIOS */ +if (!radeon_get_bios (rdev)) { +if (ASIC_IS_AVIVO (rdev)) +return -EINVAL ; + } +/* Must be an ATOMBIOS */ +if (!rdev->is_atom_bios) { +dev_err (rdev->dev,"Expecting atombios for cayman GPU\n" ); +return -EINVAL ; + } + r =radeon_atombios_init (rdev); +if (r) +return r; + +/* Post card if necessary */ +if (!radeon_card_posted (rdev)) { +if (!rdev->bios) { +dev_err (rdev->dev,"Card not posted and no BIOS - ignoring\n" ); +return -EINVAL ; + } +DRM_INFO ("GPU not posted. posting now...\n" ); +atom_asic_init (rdev->mode_info.atom_context); + } +/* Initialize scratch registers */ +cik_scratch_init (rdev); +/* Initialize surface registers */ +radeon_surface_init (rdev); +/* Initialize clocks */ +radeon_get_clock_info (rdev->ddev); + +/* Fence driver */ + r =radeon_fence_driver_init (rdev); +if (r) +return r; + +/* initialize memory controller */ + r =cik_mc_init (rdev); +if (r) +return r; +/* Memory manager */ + r =radeon_bo_init (rdev); +if (r) +return r; + + ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX ]; + ring->ring_obj =NULL ; +r600_ring_init (rdev, ring,1024 *1024 ); + + ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX ]; + ring->ring_obj =NULL ; +r600_ring_init (rdev, ring,256 *1024 ); + + ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX ]; + ring->ring_obj =NULL ; +r600_ring_init (rdev, ring,256 *1024 ); + + rdev->ih.ring_obj =NULL ; +r600_ih_ring_init (rdev,64 *1024 ); + + r =r600_pcie_gart_init (rdev); +if (r) +return r; + + rdev->accel_working = true; + r =cik_startup (rdev); +if (r) { +dev_err (rdev->dev,"disabling GPU acceleration\n" ); +cik_cp_fini (rdev); +cik_sdma_fini (rdev); +cik_irq_fini (rdev); +si_rlc_fini (rdev); +radeon_wb_fini (rdev); +radeon_ib_pool_fini (rdev); +radeon_vm_manager_fini (rdev); +radeon_irq_kms_fini (rdev); +cik_pcie_gart_fini (rdev); + rdev->accel_working = false; + } + +/* Don't start up if the MC ucode is missing. +* The default clocks and voltages before the MC ucode +* is loaded are not suffient for advanced operations. +*/ +if (!rdev->mc_fw && !(rdev->flags &RADEON_IS_IGP )) { +DRM_ERROR ("radeon: MC ucode required for NI+.\n" ); +return -EINVAL ; + } + +return 0 ; +} + +/** +* cik_fini - asic specific driver and hw fini +* +* @rdev: radeon_device pointer +* +* Tear down the asic specific driver variables and program the hw +* to an idle state (CIK). +* Called at driver unload. +*/ +void cik_fini (struct radeon_device *rdev) +{ +cik_cp_fini (rdev); +cik_sdma_fini (rdev); +cik_irq_fini (rdev); +si_rlc_fini (rdev); +radeon_wb_fini (rdev); +radeon_vm_manager_fini (rdev); +radeon_ib_pool_fini (rdev); +radeon_irq_kms_fini (rdev); +cik_pcie_gart_fini (rdev); +r600_vram_scratch_fini (rdev); +radeon_gem_fini (rdev); +radeon_fence_driver_fini (rdev); +radeon_bo_fini (rdev); +radeon_atombios_fini (rdev); +kfree (rdev->bios); + rdev->bios =NULL ; +}
Signature · 1 line
1.7.7.5
Re: [PATCH 023/165] drm/radeon/cik: fill in startup/shutdown callbacks (v4)
Am 26.06.2013 15:21, schrieb [email protected]:
Quoted 7 lines
From: Alex Deucher <[email protected]>
v2: update to latest driver changes
v3: properly tear down vm on suspend
v4: fix up irq init orderingSigned-off-by Alex Deucher <[email protected]>
Just a copy&paste error, but some comments are referring to cayman and r500/r700 generations.
With that fixed the patch is:
Quoted 359 lines
--- drivers/gpu/drm/radeon/cik.c | 340 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 340 insertions(+), 0 deletions(-)drivers/gpu/drm/radeon/cik.c +340
-0@@ -73,6 +73,8 @@ extern void r600_ih_ring_fini(struct radeon_device *rdev);extern void evergreen_mc_stop (struct radeon_device *rdev,struct evergreen_mc_save *save);extern void evergreen_mc_resume (struct radeon_device *rdev,struct evergreen_mc_save *save);extern void si_vram_gtt_location (struct radeon_device *rdev,struct radeon_mc *mc); +extern void si_rlc_fini (struct radeon_device *rdev); +extern int si_rlc_init (struct radeon_device *rdev);#define BONAIRE_IO_MC_REGS_SIZE 36@@ -4681,3 +4683,341 @@ restart_ih:return IRQ_HANDLED ; } + +/* +* startup/shutdown callbacks +*/ +/** +* cik_startup - program the asic to a functional state +* +* @rdev: radeon_device pointer +* +* Programs the asic to a functional state (CIK). +* Called by cik_init() and cik_resume(). +* Returns 0 for success, error for failure. +*/ +static int cik_startup (struct radeon_device *rdev) +{ +struct radeon_ring *ring; +int r; + +if (rdev->flags &RADEON_IS_IGP ) { +if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw || + !rdev->mec_fw || !rdev->sdma_fw || !rdev->rlc_fw) { + r =cik_init_microcode (rdev); +if (r) { +DRM_ERROR ("Failed to load firmware!\n" ); +return r; + } + } + }else { +if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw || + !rdev->mec_fw || !rdev->sdma_fw || !rdev->rlc_fw || + !rdev->mc_fw) { + r =cik_init_microcode (rdev); +if (r) { +DRM_ERROR ("Failed to load firmware!\n" ); +return r; + } + } + + r =ci_mc_load_microcode (rdev); +if (r) { +DRM_ERROR ("Failed to load MC firmware!\n" ); +return r; + } + } + + r =r600_vram_scratch_init (rdev); +if (r) +return r; + +cik_mc_program (rdev); + r =cik_pcie_gart_enable (rdev); +if (r) +return r; +cik_gpu_init (rdev); + +/* allocate rlc buffers */ + r =si_rlc_init (rdev); +if (r) { +DRM_ERROR ("Failed to init rlc BOs!\n" ); +return r; + } + +/* allocate wb buffer */ + r =radeon_wb_init (rdev); +if (r) +return r; + + r =radeon_fence_driver_start_ring (rdev,RADEON_RING_TYPE_GFX_INDEX ); +if (r) { +dev_err (rdev->dev,"failed initializing CP fences (%d).\n" , r); +return r; + } + + r =radeon_fence_driver_start_ring (rdev,R600_RING_TYPE_DMA_INDEX ); +if (r) { +dev_err (rdev->dev,"failed initializing DMA fences (%d).\n" , r); +return r; + } + + r =radeon_fence_driver_start_ring (rdev,CAYMAN_RING_TYPE_DMA1_INDEX ); +if (r) { +dev_err (rdev->dev,"failed initializing DMA fences (%d).\n" , r); +return r; + } + +/* Enable IRQ */ +if (!rdev->irq.installed) { + r =radeon_irq_kms_init (rdev); +if (r) +return r; + } + + r =cik_irq_init (rdev); +if (r) { +DRM_ERROR ("radeon: IH init failed (%d).\n" , r); +radeon_irq_kms_fini (rdev); +return r; + } +cik_irq_set (rdev); + + ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX ]; + r =radeon_ring_init (rdev, ring, ring->ring_size,RADEON_WB_CP_RPTR_OFFSET , +CP_RB0_RPTR ,CP_RB0_WPTR , +0 ,0xfffff ,RADEON_CP_PACKET2 ); +if (r) +return r; + + ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX ]; + r =radeon_ring_init (rdev, ring, ring->ring_size,R600_WB_DMA_RPTR_OFFSET , +SDMA0_GFX_RB_RPTR +SDMA0_REGISTER_OFFSET , +SDMA0_GFX_RB_WPTR +SDMA0_REGISTER_OFFSET , +2 ,0xfffffffc ,SDMA_PACKET (SDMA_OPCODE_NOP ,0 ,0 )); +if (r) +return r; + + ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX ]; + r =radeon_ring_init (rdev, ring, ring->ring_size,CAYMAN_WB_DMA1_RPTR_OFFSET , +SDMA0_GFX_RB_RPTR +SDMA1_REGISTER_OFFSET , +SDMA0_GFX_RB_WPTR +SDMA1_REGISTER_OFFSET , +2 ,0xfffffffc ,SDMA_PACKET (SDMA_OPCODE_NOP ,0 ,0 )); +if (r) +return r; + + r =cik_cp_resume (rdev); +if (r) +return r; + + r =cik_sdma_resume (rdev); +if (r) +return r; + + r =radeon_ib_pool_init (rdev); +if (r) { +dev_err (rdev->dev,"IB initialization failed (%d).\n" , r); +return r; + } + + r =radeon_vm_manager_init (rdev); +if (r) { +dev_err (rdev->dev,"vm manager initialization failed (%d).\n" , r); +return r; + } + +return 0 ; +} + +/** +* cik_resume - resume the asic to a functional state +* +* @rdev: radeon_device pointer +* +* Programs the asic to a functional state (CIK). +* Called at resume. +* Returns 0 for success, error for failure. +*/ +int cik_resume (struct radeon_device *rdev) +{ +int r; + +/* Do not reset GPU before posting, on rv770 hw unlike on r500 hw, +* posting will perform necessary task to bring back GPU into good +* shape. +*/ +/* post card */ +atom_asic_init (rdev->mode_info.atom_context); + + rdev->accel_working = true; + r =cik_startup (rdev); +if (r) { +DRM_ERROR ("cik startup failed on resume\n" ); + rdev->accel_working = false; +return r; + } + +return r; + +} + +/** +* cik_suspend - suspend the asic +* +* @rdev: radeon_device pointer +* +* Bring the chip into a state suitable for suspend (CIK). +* Called at suspend. +* Returns 0 for success. +*/ +int cik_suspend (struct radeon_device *rdev) +{ +radeon_vm_manager_fini (rdev); +cik_cp_enable (rdev, false); +cik_sdma_enable (rdev, false); +cik_irq_suspend (rdev); +radeon_wb_disable (rdev); +cik_pcie_gart_disable (rdev); +return 0 ; +} + +/* Plan is to move initialization in that function and use +* helper function so that radeon_device_init pretty much +* do nothing more than calling asic specific function. This +* should also allow to remove a bunch of callback function +* like vram_info. +*/ +/** +* cik_init - asic specific driver and hw init +* +* @rdev: radeon_device pointer +* +* Setup asic specific driver variables and program the hw +* to a functional state (CIK). +* Called at driver startup. +* Returns 0 for success, errors for failure. +*/ +int cik_init (struct radeon_device *rdev) +{ +struct radeon_ring *ring; +int r; + +/* Read BIOS */ +if (!radeon_get_bios (rdev)) { +if (ASIC_IS_AVIVO (rdev)) +return -EINVAL ; + } +/* Must be an ATOMBIOS */ +if (!rdev->is_atom_bios) { +dev_err (rdev->dev,"Expecting atombios for cayman GPU\n" ); +return -EINVAL ; + } + r =radeon_atombios_init (rdev); +if (r) +return r; + +/* Post card if necessary */ +if (!radeon_card_posted (rdev)) { +if (!rdev->bios) { +dev_err (rdev->dev,"Card not posted and no BIOS - ignoring\n" ); +return -EINVAL ; + } +DRM_INFO ("GPU not posted. posting now...\n" ); +atom_asic_init (rdev->mode_info.atom_context); + } +/* Initialize scratch registers */ +cik_scratch_init (rdev); +/* Initialize surface registers */ +radeon_surface_init (rdev); +/* Initialize clocks */ +radeon_get_clock_info (rdev->ddev); + +/* Fence driver */ + r =radeon_fence_driver_init (rdev); +if (r) +return r; + +/* initialize memory controller */ + r =cik_mc_init (rdev); +if (r) +return r; +/* Memory manager */ + r =radeon_bo_init (rdev); +if (r) +return r; + + ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX ]; + ring->ring_obj =NULL ; +r600_ring_init (rdev, ring,1024 *1024 ); + + ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX ]; + ring->ring_obj =NULL ; +r600_ring_init (rdev, ring,256 *1024 ); + + ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX ]; + ring->ring_obj =NULL ; +r600_ring_init (rdev, ring,256 *1024 ); + + rdev->ih.ring_obj =NULL ; +r600_ih_ring_init (rdev,64 *1024 ); + + r =r600_pcie_gart_init (rdev); +if (r) +return r; + + rdev->accel_working = true; + r =cik_startup (rdev); +if (r) { +dev_err (rdev->dev,"disabling GPU acceleration\n" ); +cik_cp_fini (rdev); +cik_sdma_fini (rdev); +cik_irq_fini (rdev); +si_rlc_fini (rdev); +radeon_wb_fini (rdev); +radeon_ib_pool_fini (rdev); +radeon_vm_manager_fini (rdev); +radeon_irq_kms_fini (rdev); +cik_pcie_gart_fini (rdev); + rdev->accel_working = false; + } + +/* Don't start up if the MC ucode is missing. +* The default clocks and voltages before the MC ucode +* is loaded are not suffient for advanced operations. +*/ +if (!rdev->mc_fw && !(rdev->flags &RADEON_IS_IGP )) { +DRM_ERROR ("radeon: MC ucode required for NI+.\n" ); +return -EINVAL ; + } + +return 0 ; +} + +/** +* cik_fini - asic specific driver and hw fini +* +* @rdev: radeon_device pointer +* +* Tear down the asic specific driver variables and program the hw +* to an idle state (CIK). +* Called at driver unload. +*/ +void cik_fini (struct radeon_device *rdev) +{ +cik_cp_fini (rdev); +cik_sdma_fini (rdev); +cik_irq_fini (rdev); +si_rlc_fini (rdev); +radeon_wb_fini (rdev); +radeon_vm_manager_fini (rdev); +radeon_ib_pool_fini (rdev); +radeon_irq_kms_fini (rdev); +cik_pcie_gart_fini (rdev); +r600_vram_scratch_fini (rdev); +radeon_gem_fini (rdev); +radeon_fence_driver_fini (rdev); +radeon_bo_fini (rdev); +radeon_atombios_fini (rdev); +kfree (rdev->bios); + rdev->bios =NULL ; +}
PATCH 24/165 drm/radeon: upstream ObjectID.h updates (v2)
In reply to [email protected]From: Alex Deucher <[email protected]>
v2: further updates
--- drivers/gpu/drm/radeon/ObjectID.h | 40 +++++++++++++++++++++++++++++++++++++ 1 files changed, 40 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/ObjectID.h +40 -0
@@ -69,6 +69,8 @@#define ENCODER_OBJECT_ID_ALMOND 0x22#define ENCODER_OBJECT_ID_TRAVIS 0x23#define ENCODER_OBJECT_ID_NUTMEG 0x22 +#define ENCODER_OBJECT_ID_HDMI_ANX9805 0x26 +/* Kaleidoscope (KLDSCP) Class Display Hardware (internal) */ #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 0x13#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 0x14
@@ -86,6 +88,8 @@#define ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 0x20#define ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 0x21#define ENCODER_OBJECT_ID_INTERNAL_VCE 0x24 +#define ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 0x25 +#define ENCODER_OBJECT_ID_INTERNAL_AMCLK 0x27#define ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO 0xFF
@@ -364,6 +368,14 @@ GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT) +#define ENCODER_INTERNAL_UNIPHY3_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_UNIPHY3_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 << OBJECT_ID_SHIFT) +#define ENCODER_GENERAL_EXTERNAL_DVO_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO << OBJECT_ID_SHIFT)
@@ -392,6 +404,10 @@ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ ENCODER_OBJECT_ID_INTERNAL_VCE << OBJECT_ID_SHIFT) +#define ENCODER_HDMI_ANX9805_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_HDMI_ANX9805 << OBJECT_ID_SHIFT) +/****************************************************/ /* Connector Object ID definition - Shared with BIOS */ /****************************************************/
@@ -461,6 +477,14 @@ GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT) +#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID5 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID5 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT) + +#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID6 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID6 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT) +#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT)
@@ -473,6 +497,10 @@ GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT) +#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID4 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT) +#define CONNECTOR_VGA_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT)
@@ -541,6 +569,18 @@ GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT) +#define CONNECTOR_HDMI_TYPE_A_ENUM_ID4 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT) + +#define CONNECTOR_HDMI_TYPE_A_ENUM_ID5 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID5 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT) + +#define CONNECTOR_HDMI_TYPE_A_ENUM_ID6 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID6 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT) +#define CONNECTOR_HDMI_TYPE_B_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_HDMI_TYPE_B << OBJECT_ID_SHIFT)
Signature · 1 line
1.7.7.5
PATCH 25/165 drm/radeon: upstream atombios.h updates (v2)
In reply to [email protected]From: Alex Deucher <[email protected]>
v2: further updates
--- drivers/gpu/drm/radeon/atombios.h | 486 ++++++++++++++++++++++++++++++++++--- 1 files changed, 454 insertions(+), 32 deletions(-)
drivers/gpu/drm/radeon/atombios.h +454 -32
@@ -74,6 +74,8 @@#define ATOM_PPLL2 1#define ATOM_DCPLL 2#define ATOM_PPLL0 2 +#define ATOM_PPLL3 3 +#define ATOM_EXT_PLL1 8#define ATOM_EXT_PLL2 9#define ATOM_EXT_CLOCK 10
@@ -259,7 +261,7 @@ typedef struct _ATOM_MASTER_LIST_OF_COMMAND_TABLES{USHORT AdjustDisplayPll;//Atomic Table, used by various SW componentes. USHORT AdjustMemoryController;//Atomic Table, indirectly used by various SW components,called from SetMemoryClock USHORT EnableASIC_StaticPwrMgt;//Atomic Table, only used by Bios -USHORT ASIC_StaticPwrMgtStatusChange;//Obsolete , only used by Bios +USHORT SetUniphyInstance;//Atomic Table, only used by Bios USHORT DAC_LoadDetection;//Atomic Table, directly used by various SW components,latest version 1.2 USHORT LVTMAEncoderControl;//Atomic Table,directly used by various SW components,latest version 1.3 USHORT HW_Misc_Operation;//Atomic Table, directly used by various SW components,latest version 1.1
@@ -271,7 +273,7 @@ typedef struct _ATOM_MASTER_LIST_OF_COMMAND_TABLES{USHORT TVEncoderControl;//Function Table,directly used by various SW components,latest version 1.1 USHORT PatchMCSetting;//only used by BIOS USHORT MC_SEQ_Control;//only used by BIOS -USHORT TV1OutputControl;//Atomic Table, Obsolete from Ry6xx, use DAC2 Output instead +USHORT Gfx_Harvesting;//Atomic Table, Obsolete from Ry6xx, Now only used by BIOS for GFX harvesting USHORT EnableScaler;//Atomic Table, used only by Bios USHORT BlankCRTC;//Atomic Table, directly used by various SW components,latest version 1.1 USHORT EnableCRTC;//Atomic Table, directly used by various SW components,latest version 1.1
@@ -328,7 +330,7 @@ typedef struct _ATOM_MASTER_LIST_OF_COMMAND_TABLES{#define UNIPHYTransmitterControl DIG1TransmitterControl#define LVTMATransmitterControl DIG2TransmitterControl#define SetCRTC_DPM_State GetConditionalGoldenSetting -#define SetUniphyInstance ASIC_StaticPwrMgtStatusChange +#define ASIC_StaticPwrMgtStatusChange SetUniphyInstance#define HPDInterruptService ReadHWAssistedI2CStatus#define EnableVGA_Access GetSCLKOverMCLKRatio#define EnableYUV GetDispObjectInfo
@@ -338,7 +340,7 @@ typedef struct _ATOM_MASTER_LIST_OF_COMMAND_TABLES{#define TMDSAEncoderControl PatchMCSetting#define LVDSEncoderControl MC_SEQ_Control#define LCD1OutputControl HW_Misc_Operation - +#define TV1OutputControl Gfx_Harvesting typedef struct _ATOM_MASTER_COMMAND_TABLE {
@@ -478,11 +480,11 @@ typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 {#if ATOM_BIG_ENDIAN -ULONG ucPostDiv;//return parameter: post divider which is used to program to register directly +ULONG ucPostDiv:8 ;//return parameter: post divider which is used to program to register directly ULONG ulClock:24 ;//Input= target clock, output = actual clock #else ULONG ulClock:24 ;//Input= target clock, output = actual clock -ULONG ucPostDiv;//return parameter: post divider which is used to program to register directly +ULONG ucPostDiv:8 ;//return parameter: post divider which is used to program to register directly #endif }COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 ;
@@ -504,6 +506,32 @@ typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5UCHAR ucReserved; }COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5 ; + +typedef struct _COMPUTE_GPU_CLOCK_INPUT_PARAMETERS_V1_6 +{ +ATOM_COMPUTE_CLOCK_FREQ ulClock;//Input Parameter +ULONG ulReserved[2 ]; +}COMPUTE_GPU_CLOCK_INPUT_PARAMETERS_V1_6 ; + +//ATOM_COMPUTE_CLOCK_FREQ.ulComputeClockFlag +#define COMPUTE_GPUCLK_INPUT_FLAG_CLK_TYPE_MASK 0x0f +#define COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK 0x00 +#define COMPUTE_GPUCLK_INPUT_FLAG_SCLK 0x01 + +typedef struct _COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_6 +{ +COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 ulClock;//Output Parameter: ucPostDiv=DFS divider +ATOM_S_MPLL_FB_DIVIDER ulFbDiv;//Output Parameter: PLL FB divider +UCHAR ucPllRefDiv;//Output Parameter: PLL ref divider +UCHAR ucPllPostDiv;//Output Parameter: PLL post divider +UCHAR ucPllCntlFlag;//Output Flags: control flag +UCHAR ucReserved; +}COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_6 ; + +//ucPllCntlFlag +#define SPLL_CNTL_FLAG_VCO_MODE_MASK 0x03 + +// ucInputFlag #define ATOM_PLL_INPUT_FLAG_PLL_STROBE_MODE_EN 1 // 1-StrobeMode, 0-PerformanceMode
@@ -1686,6 +1714,7 @@ typedef struct _PIXEL_CLOCK_PARAMETERS_V6#define PIXEL_CLOCK_V6_MISC_HDMI_30BPP 0x08#define PIXEL_CLOCK_V6_MISC_HDMI_48BPP 0x0c#define PIXEL_CLOCK_V6_MISC_REF_DIV_SRC 0x10 +#define PIXEL_CLOCK_V6_MISC_GEN_DPREFCLK 0x40 typedef struct _GET_DISP_PLL_STATUS_INPUT_PARAMETERS_V2 {
@@ -2102,6 +2131,17 @@ typedef struct _DVO_ENCODER_CONTROL_PARAMETERS_V3 }DVO_ENCODER_CONTROL_PARAMETERS_V3 ;#define DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 DVO_ENCODER_CONTROL_PARAMETERS_V3 +typedef struct _DVO_ENCODER_CONTROL_PARAMETERS_V1_4 +{ +USHORT usPixelClock; +UCHAR ucDVOConfig; +UCHAR ucAction;//ATOM_ENABLE/ATOM_DISABLE/ATOM_HPD_INIT +UCHAR ucBitPerColor;//please refer to definition of PANEL_xBIT_PER_COLOR +UCHAR ucReseved[3 ]; +}DVO_ENCODER_CONTROL_PARAMETERS_V1_4 ; +#define DVO_ENCODER_CONTROL_PS_ALLOCATION_V1_4 DVO_ENCODER_CONTROL_PARAMETERS_V1_4 + +//ucTableFormatRevision=1 //ucTableContentRevision=3 structure is not changed but usMisc add bit 1 as another input for // bit1=0: non-coherent mode
@@ -2165,7 +2205,7 @@ typedef struct _DVO_ENCODER_CONTROL_PARAMETERS_V3#define SET_ASIC_VOLTAGE_MODE_SOURCE_B 0x4#define SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE 0x0 -#define SET_ASIC_VOLTAGE_MODE_GET_GPIOVAL 0x1 +#define SET_ASIC_VOLTAGE_MODE_GET_GPIOVAL 0x1#define SET_ASIC_VOLTAGE_MODE_GET_GPIOMASK 0x2 typedef struct _SET_VOLTAGE_PARAMETERS
@@ -2200,15 +2240,20 @@ typedef struct _SET_VOLTAGE_PARAMETERS_V1_3//SET_VOLTAGE_PARAMETERS_V3.ucVoltageMode #define ATOM_SET_VOLTAGE 0 //Set voltage Level#define ATOM_INIT_VOLTAGE_REGULATOR 3 //Init Regulator -#define ATOM_SET_VOLTAGE_PHASE 4 //Set Vregulator Phase -#define ATOM_GET_MAX_VOLTAGE 6 //Get Max Voltage, not used in SetVoltageTable v1.3 -#define ATOM_GET_VOLTAGE_LEVEL 6 //Get Voltage level from vitual voltage ID +#define ATOM_SET_VOLTAGE_PHASE 4 //Set Vregulator Phase, only for SVID/PVID regulator +#define ATOM_GET_MAX_VOLTAGE 6 //Get Max Voltage, not used from SetVoltageTable v1.3 +#define ATOM_GET_VOLTAGE_LEVEL 6 //Get Voltage level from vitual voltage ID, not used for SetVoltage v1.4 +#define ATOM_GET_LEAKAGE_ID 8 //Get Leakage Voltage Id ( starting from SMU7x IP ), SetVoltage v1.4// define vitual voltage id in usVoltageLevel #define ATOM_VIRTUAL_VOLTAGE_ID0 0xff01#define ATOM_VIRTUAL_VOLTAGE_ID1 0xff02#define ATOM_VIRTUAL_VOLTAGE_ID2 0xff03#define ATOM_VIRTUAL_VOLTAGE_ID3 0xff04 +#define ATOM_VIRTUAL_VOLTAGE_ID4 0xff05 +#define ATOM_VIRTUAL_VOLTAGE_ID5 0xff06 +#define ATOM_VIRTUAL_VOLTAGE_ID6 0xff07 +#define ATOM_VIRTUAL_VOLTAGE_ID7 0xff08 typedef struct _SET_VOLTAGE_PS_ALLOCATION {
@@ -2628,7 +2673,8 @@ typedef struct _ATOM_FIRMWARE_INFO_V2_2ULONG ulFirmwareRevision;ULONG ulDefaultEngineClock;//In 10Khz unit ULONG ulDefaultMemoryClock;//In 10Khz unit -ULONG ulReserved[2 ]; +ULONG ulSPLL_OutputFreq;//In 10Khz unit +ULONG ulGPUPLL_OutputFreq;//In 10Khz unit ULONG ulReserved1;//Was ulMaxEngineClockPLL_Output; //In 10Khz unit* ULONG ulReserved2;//Was ulMaxMemoryClockPLL_Output; //In 10Khz unit* ULONG ulMaxPixelClockPLL_Output;//In 10Khz unit
@@ -3813,6 +3859,12 @@ typedef struct _ATOM_GPIO_PIN_ASSIGNMENTUCHAR ucGPIO_ID; }ATOM_GPIO_PIN_ASSIGNMENT ; +//ucGPIO_ID pre-define id for multiple usage +//from SMU7.x, if ucGPIO_ID=PP_AC_DC_SWITCH_GPIO_PINID in GPIO_LUTTable, AC/DC swithing feature is enable +#define PP_AC_DC_SWITCH_GPIO_PINID 60 +//from SMU7.x, if ucGPIO_ID=VDDC_REGULATOR_VRHOT_GPIO_PINID in GPIO_LUTable, VRHot feature is enable +#define VDDC_VRHOT_GPIO_PINID 61 + typedef struct _ATOM_GPIO_PIN_LUT { ATOM_COMMON_TABLE_HEADER sHeader;
@@ -4074,17 +4126,19 @@ typedef struct _EXT_DISPLAY_PATH//usCaps #define EXT_DISPLAY_PATH_CAPS__HBR2_DISABLE 0x01 +#define EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN 0x02typedef struct _ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO {ATOM_COMMON_TABLE_HEADER sHeader;UCHAR ucGuid [NUMBER_OF_UCHAR_FOR_GUID ];// a GUID is a 16 byte long string EXT_DISPLAY_PATH sPath[MAX_NUMBER_OF_EXT_DISPLAY_PATH ];// total of fixed 7 entries. -UCHAR ucChecksum;// a simple Checksum of the sum of whole structure equal to 0x0. +UCHAR ucChecksum;// a simple Checksum of the sum of whole structure equal to 0x0. UCHAR uc3DStereoPinId;// use for eDP panel UCHAR ucRemoteDisplayConfig;UCHAR uceDPToLVDSRxId; -UCHAR Reserved[4 ];// for potential expansion +UCHAR ucFixDPVoltageSwing;// usCaps[1]=1, this indicate DP_LANE_SET value +UCHAR Reserved[3 ];// for potential expansion }ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO ;//Related definitions, all records are different but they have a commond header
@@ -4416,6 +4470,13 @@ typedef struct _ATOM_VOLTAGE_CONTROL#define VOLTAGE_CONTROL_ID_CHL822x 0x08#define VOLTAGE_CONTROL_ID_VT1586M 0x09#define VOLTAGE_CONTROL_ID_UP1637 0x0A +#define VOLTAGE_CONTROL_ID_CHL8214 0x0B +#define VOLTAGE_CONTROL_ID_UP1801 0x0C +#define VOLTAGE_CONTROL_ID_ST6788A 0x0D +#define VOLTAGE_CONTROL_ID_CHLIR3564SVI2 0x0E +#define VOLTAGE_CONTROL_ID_AD527x 0x0F +#define VOLTAGE_CONTROL_ID_NCP81022 0x10 +#define VOLTAGE_CONTROL_ID_LTC2635 0x11 typedef struct _ATOM_VOLTAGE_OBJECT {
@@ -4458,6 +4519,15 @@ typedef struct _ATOM_VOLTAGE_OBJECT_HEADER_V3{USHORT usSize;//Size of Object }ATOM_VOLTAGE_OBJECT_HEADER_V3 ; +// ATOM_VOLTAGE_OBJECT_HEADER_V3.ucVoltageMode +#define VOLTAGE_OBJ_GPIO_LUT 0 //VOLTAGE and GPIO Lookup table ->ATOM_GPIO_VOLTAGE_OBJECT_V3 +#define VOLTAGE_OBJ_VR_I2C_INIT_SEQ 3 //VOLTAGE REGULATOR INIT sequece through I2C -> ATOM_I2C_VOLTAGE_OBJECT_V3 +#define VOLTAGE_OBJ_PHASE_LUT 4 //Set Vregulator Phase lookup table ->ATOM_GPIO_VOLTAGE_OBJECT_V3 +#define VOLTAGE_OBJ_SVID2 7 //Indicate voltage control by SVID2 ->ATOM_SVID2_VOLTAGE_OBJECT_V3 +#define VOLTAGE_OBJ_PWRBOOST_LEAKAGE_LUT 0x10 //Powerboost Voltage and LeakageId lookup table->ATOM_LEAKAGE_VOLTAGE_OBJECT_V3 +#define VOLTAGE_OBJ_HIGH_STATE_LEAKAGE_LUT 0x11 //High voltage state Voltage and LeakageId lookup table->ATOM_LEAKAGE_VOLTAGE_OBJECT_V3 +#define VOLTAGE_OBJ_HIGH1_STATE_LEAKAGE_LUT 0x12 //High1 voltage state Voltage and LeakageId lookup table->ATOM_LEAKAGE_VOLTAGE_OBJECT_V3 + typedef struct _VOLTAGE_LUT_ENTRY_V2 { ULONG ulVoltageId; // The Voltage ID which is used to program GPIO register
@@ -4473,7 +4543,7 @@ typedef struct _LEAKAGE_VOLTAGE_LUT_ENTRY_V2 typedef struct _ATOM_I2C_VOLTAGE_OBJECT_V3 { - ATOM_VOLTAGE_OBJECT_HEADER_V3 sHeader; + ATOM_VOLTAGE_OBJECT_HEADER_V3 sHeader; // voltage mode = VOLTAGE_OBJ_VR_I2C_INIT_SEQ UCHAR ucVoltageRegulatorId; //Indicate Voltage Regulator Id UCHAR ucVoltageControlI2cLine; UCHAR ucVoltageControlAddress;
@@ -4484,7 +4554,7 @@ typedef struct _ATOM_I2C_VOLTAGE_OBJECT_V3 typedef struct _ATOM_GPIO_VOLTAGE_OBJECT_V3 { - ATOM_VOLTAGE_OBJECT_HEADER_V3 sHeader; + ATOM_VOLTAGE_OBJECT_HEADER_V3 sHeader; // voltage mode = VOLTAGE_OBJ_GPIO_LUT or VOLTAGE_OBJ_PHASE_LUT UCHAR ucVoltageGpioCntlId; // default is 0 which indicate control through CG VID mode UCHAR ucGpioEntryNum; // indiate the entry numbers of Votlage/Gpio value Look up table UCHAR ucPhaseDelay; // phase delay in unit of micro second
@@ -4495,7 +4565,7 @@ typedef struct _ATOM_GPIO_VOLTAGE_OBJECT_V3 typedef struct _ATOM_LEAKAGE_VOLTAGE_OBJECT_V3 { - ATOM_VOLTAGE_OBJECT_HEADER_V3 sHeader; + ATOM_VOLTAGE_OBJECT_HEADER_V3 sHeader; // voltage mode = 0x10/0x11/0x12 UCHAR ucLeakageCntlId; // default is 0 UCHAR ucLeakageEntryNum; // indicate the entry number of LeakageId/Voltage Lut table UCHAR ucReserved[2];
@@ -4503,10 +4573,26 @@ typedef struct _ATOM_LEAKAGE_VOLTAGE_OBJECT_V3LEAKAGE_VOLTAGE_LUT_ENTRY_V2 asLeakageIdLut[1 ]; }ATOM_LEAKAGE_VOLTAGE_OBJECT_V3 ; + +typedef struct _ATOM_SVID2_VOLTAGE_OBJECT_V3 +{ +ATOM_VOLTAGE_OBJECT_HEADER_V3 sHeader;// voltage mode = VOLTAGE_OBJ_SVID2 +// 14:7 PSI0_VID +// 6 PSI0_EN +// 5 PSI1 +// 4:2 load line slope trim. +// 1:0 offset trim, +USHORT usLoadLine_PSI; +// GPU GPIO pin Id to SVID2 regulator VRHot pin. possible value 0~31. 0 means GPIO0, 31 means GPIO31 +UCHAR ucReserved[2 ]; +ULONG ulReserved; +}ATOM_SVID2_VOLTAGE_OBJECT_V3 ; +typedef union _ATOM_VOLTAGE_OBJECT_V3 {ATOM_GPIO_VOLTAGE_OBJECT_V3 asGpioVoltageObj;ATOM_I2C_VOLTAGE_OBJECT_V3 asI2cVoltageObj;ATOM_LEAKAGE_VOLTAGE_OBJECT_V3 asLeakageObj; +ATOM_SVID2_VOLTAGE_OBJECT_V3 asSVID2Obj; }ATOM_VOLTAGE_OBJECT_V3 ; typedef struct _ATOM_VOLTAGE_OBJECT_INFO_V3_1
@@ -4536,6 +4622,21 @@ typedef struct _ATOM_ASIC_PROFILING_INFOATOM_ASIC_PROFILE_VOLTAGE asVoltage; }ATOM_ASIC_PROFILING_INFO ; +typedef struct _ATOM_ASIC_PROFILING_INFO_V2_1 +{ +ATOM_COMMON_TABLE_HEADER asHeader; +UCHAR ucLeakageBinNum;// indicate the entry number of LeakageId/Voltage Lut table +USHORT usLeakageBinArrayOffset;// offset of USHORT Leakage Bin list array ( from lower LeakageId to higher) + +UCHAR ucElbVDDC_Num; +USHORT usElbVDDC_IdArrayOffset;// offset of USHORT virtual VDDC voltage id ( 0xff01~0xff08 ) +USHORT usElbVDDC_LevelArrayOffset;// offset of 2 dimension voltage level USHORT array + +UCHAR ucElbVDDCI_Num; +USHORT usElbVDDCI_IdArrayOffset;// offset of USHORT virtual VDDCI voltage id ( 0xff01~0xff08 ) +USHORT usElbVDDCI_LevelArrayOffset;// offset of 2 dimension voltage level USHORT array +}ATOM_ASIC_PROFILING_INFO_V2_1 ; + typedef struct _ATOM_POWER_SOURCE_OBJECT { UCHAR ucPwrSrcId; // Power source
@@ -4652,6 +4753,8 @@ typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V6#define SYS_INFO_LVDSMISC__888_BPC 0x04#define SYS_INFO_LVDSMISC__OVERRIDE_EN 0x08#define SYS_INFO_LVDSMISC__BLON_ACTIVE_LOW 0x10 +// new since Trinity +#define SYS_INFO_LVDSMISC__TRAVIS_LVDS_VOL_OVERRIDE_EN 0x20// not used any more #define SYS_INFO_LVDSMISC__VSYNC_ACTIVE_LOW 0x04
@@ -4752,6 +4855,29 @@ typedef struct _ATOM_FUSION_SYSTEM_INFO_V1ATOM_INTEGRATED_SYSTEM_INFO_V6 sIntegratedSysInfo;ULONG ulPowerplayTable[128 ]; }ATOM_FUSION_SYSTEM_INFO_V1 ; + + +typedef struct _ATOM_TDP_CONFIG_BITS +{ +#if ATOM_BIG_ENDIAN +ULONG uReserved:2 ; +ULONG uTDP_Value:14 ;// Original TDP value in tens of milli watts +ULONG uCTDP_Value:14 ;// Override value in tens of milli watts +ULONG uCTDP_Enable:2 ;// = (uCTDP_Value > uTDP_Value? 2: (uCTDP_Value < uTDP_Value)) +#else +ULONG uCTDP_Enable:2 ;// = (uCTDP_Value > uTDP_Value? 2: (uCTDP_Value < uTDP_Value)) +ULONG uCTDP_Value:14 ;// Override value in tens of milli watts +ULONG uTDP_Value:14 ;// Original TDP value in tens of milli watts +ULONG uReserved:2 ; +#endif +}ATOM_TDP_CONFIG_BITS ; + +typedef union _ATOM_TDP_CONFIG +{ +ATOM_TDP_CONFIG_BITS TDP_config; +ULONG TDP_config_all; +}ATOM_TDP_CONFIG ; +/********************************************************************************************************************** ATOM_FUSION_SYSTEM_INFO_V1 Description sIntegratedSysInfo: refer to ATOM_INTEGRATED_SYSTEM_INFO_V6 definition.
@@ -4784,7 +4910,8 @@ typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7UCHAR ucMemoryType;UCHAR ucUMAChannelNumber;UCHAR strVBIOSMsg[40 ]; -ULONG ulReserved[20 ]; +ATOM_TDP_CONFIG asTdpConfig; +ULONG ulReserved[19 ];ATOM_AVAILABLE_SCLK_LIST sAvail_SCLK[5 ];ULONG ulGMCRestoreResetTime;ULONG ulMinimumNClk;
@@ -4809,7 +4936,7 @@ typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7USHORT GnbTdpLimit;USHORT usMaxLVDSPclkFreqInSingleLink;UCHAR ucLvdsMisc; -UCHAR ucLVDSReserved; +UCHAR ucTravisLVDSVolAdjust;UCHAR ucLVDSPwrOnSeqDIGONtoDE_in4Ms;UCHAR ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;UCHAR ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
@@ -4817,7 +4944,7 @@ typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7UCHAR ucLVDSOffToOnDelay_in4Ms;UCHAR ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;UCHAR ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms; -UCHAR ucLVDSReserved1; +UCHAR ucMinAllowedBL_Level;ULONG ulLCDBitDepthControlVal;ULONG ulNbpStateMemclkFreq[4 ];USHORT usNBP2Voltage;
@@ -4846,6 +4973,7 @@ typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7#define SYS_INFO_GPUCAPS__TMDSHDMI_COHERENT_SINGLEPLL_MODE 0x01#define SYS_INFO_GPUCAPS__DP_SINGLEPLL_MODE 0x02#define SYS_INFO_GPUCAPS__DISABLE_AUX_MODE_DETECT 0x08 +#define SYS_INFO_GPUCAPS__ENABEL_DFS_BYPASS 0x10/********************************************************************************************************************** ATOM_INTEGRATED_SYSTEM_INFO_V1_7 Description
@@ -4945,6 +5073,9 @@ ucLVDSMisc: [bit0] LVDS 888bit panel mode =0: LVDS 888 pan [bit2] LVDS 888bit per color mode =0: 666 bit per color =1:888 bit per color [bit3] LVDS parameter override enable =0: ucLvdsMisc parameter are not used =1: ucLvdsMisc parameter should be used [bit4] Polarity of signal sent to digital BLON output pin. =0: not inverted(active high) =1: inverted ( active low ) + [bit5] Travid LVDS output voltage override enable, when =1, use ucTravisLVDSVolAdjust value to overwrite Traivs register LVDS_CTRL_4 +ucTravisLVDSVolAdjust When ucLVDSMisc[5]=1,it means platform SBIOS want to overwrite TravisLVDSVoltage. Then VBIOS will use ucTravisLVDSVolAdjust + value to program Travis register LVDS_CTRL_4 ucLVDSPwrOnSeqDIGONtoDE_in4Ms: LVDS power up sequence time in unit of 4ms, time delay from DIGON signal active to data enable signal active( DE ). =0 mean use VBIOS default which is 8 ( 32ms ). The LVDS power up sequence is as following: DIGON->DE->VARY_BL->BLON. This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable.
@@ -4964,18 +5095,241 @@ ucLVDSOffToOnDelay_in4Ms: LVDS power down sequence time in unit of 4ms.=0 means to use VBIOS default delay which is 125 ( 500ms ). This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable. -ucLVDSPwrOnVARY_BLtoBLON_in4Ms: LVDS power up sequence time in unit of 4ms. Time delay from VARY_BL signal on to DLON signal active. +ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms: +LVDS power up sequence time in unit of 4ms. Time delay from VARY_BL signal on to DLON signal active. =0 means to use VBIOS default delay which is 0 ( 0ms ). This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable. -ucLVDSPwrOffBLONtoVARY_BL_in4Ms: LVDS power down sequence time in unit of 4ms. Time delay from BLON signal off to VARY_BL signal off. +ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms: +LVDS power down sequence time in unit of 4ms. Time delay from BLON signal off to VARY_BL signal off. =0 means to use VBIOS default delay which is 0 ( 0ms ). This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable. +ucMinAllowedBL_Level: Lowest LCD backlight PWM level. This is customer platform specific parameters. By default it is 0. +ulNbpStateMemclkFreq[4]: system memory clock frequncey in unit of 10Khz in different NB pstate. **********************************************************************************************************************/ +// this IntegrateSystemInfoTable is used for Kaveri & Kabini APU +typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_8 +{ +ATOM_COMMON_TABLE_HEADER sHeader; +ULONG ulBootUpEngineClock; +ULONG ulDentistVCOFreq; +ULONG ulBootUpUMAClock; +ATOM_CLK_VOLT_CAPABILITY sDISPCLK_Voltage[4 ]; +ULONG ulBootUpReqDisplayVector; +ULONG ulVBIOSMisc; +ULONG ulGPUCapInfo; +ULONG ulDISP_CLK2Freq; +USHORT usRequestedPWMFreqInHz; +UCHAR ucHtcTmpLmt; +UCHAR ucHtcHystLmt; +ULONG ulReserved2; +ULONG ulSystemConfig; +ULONG ulCPUCapInfo; +ULONG ulReserved3; +USHORT usGPUReservedSysMemSize; +USHORT usExtDispConnInfoOffset; +USHORT usPanelRefreshRateRange; +UCHAR ucMemoryType; +UCHAR ucUMAChannelNumber; +UCHAR strVBIOSMsg[40 ]; +ATOM_TDP_CONFIG asTdpConfig; +ULONG ulReserved[19 ]; +ATOM_AVAILABLE_SCLK_LIST sAvail_SCLK[5 ]; +ULONG ulGMCRestoreResetTime; +ULONG ulReserved4; +ULONG ulIdleNClk; +ULONG ulDDR_DLL_PowerUpTime; +ULONG ulDDR_PLL_PowerUpTime; +USHORT usPCIEClkSSPercentage; +USHORT usPCIEClkSSType; +USHORT usLvdsSSPercentage; +USHORT usLvdsSSpreadRateIn10Hz; +USHORT usHDMISSPercentage; +USHORT usHDMISSpreadRateIn10Hz; +USHORT usDVISSPercentage; +USHORT usDVISSpreadRateIn10Hz; +ULONG ulGPUReservedSysMemBaseAddrLo; +ULONG ulGPUReservedSysMemBaseAddrHi; +ULONG ulReserved5[3 ]; +USHORT usMaxLVDSPclkFreqInSingleLink; +UCHAR ucLvdsMisc; +UCHAR ucTravisLVDSVolAdjust; +UCHAR ucLVDSPwrOnSeqDIGONtoDE_in4Ms; +UCHAR ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms; +UCHAR ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms; +UCHAR ucLVDSPwrOffSeqDEtoDIGON_in4Ms; +UCHAR ucLVDSOffToOnDelay_in4Ms; +UCHAR ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms; +UCHAR ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms; +UCHAR ucMinAllowedBL_Level; +ULONG ulLCDBitDepthControlVal; +ULONG ulNbpStateMemclkFreq[4 ]; +ULONG ulReserved6; +ULONG ulNbpStateNClkFreq[4 ]; +USHORT usNBPStateVoltage[4 ]; +USHORT usBootUpNBVoltage; +USHORT usReserved2; +ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO sExtDispConnInfo; +}ATOM_INTEGRATED_SYSTEM_INFO_V1_8 ; + +/********************************************************************************************************************** +ATOM_INTEGRATED_SYSTEM_INFO_V1_8 Description +ulBootUpEngineClock: VBIOS bootup Engine clock frequency, in 10kHz unit. if it is equal 0, then VBIOS use pre-defined bootup engine clock +ulDentistVCOFreq: Dentist VCO clock in 10kHz unit. +ulBootUpUMAClock: System memory boot up clock frequency in 10Khz unit. +sDISPCLK_Voltage: Report Display clock frequency requirement on GNB voltage(up to 4 voltage levels). ++ ulBootUpReqDisplayVector: VBIOS boot up display IDs, following are supported devices in Trinity projects: +ATOM_DEVICE_CRT1_SUPPORT 0x0001 +ATOM_DEVICE_DFP1_SUPPORT 0x0008 +ATOM_DEVICE_DFP6_SUPPORT 0x0040 +ATOM_DEVICE_DFP2_SUPPORT 0x0080 +ATOM_DEVICE_DFP3_SUPPORT 0x0200 +ATOM_DEVICE_DFP4_SUPPORT 0x0400 +ATOM_DEVICE_DFP5_SUPPORT 0x0800 +ATOM_DEVICE_LCD1_SUPPORT 0x0002 + +ulVBIOSMisc: Miscellenous flags for VBIOS requirement and interface +bit[0]=0: INT15 callback function Get LCD EDID ( ax=4e08, bl=1b ) is not supported by SBIOS. +=1: INT15 callback function Get LCD EDID ( ax=4e08, bl=1b ) is supported by SBIOS. +bit[1]=0: INT15 callback function Get boot display( ax=4e08, bl=01h) is not supported by SBIOS +=1: INT15 callback function Get boot display( ax=4e08, bl=01h) is supported by SBIOS +bit[2]=0: INT15 callback function Get panel Expansion ( ax=4e08, bl=02h) is not supported by SBIOS +=1: INT15 callback function Get panel Expansion ( ax=4e08, bl=02h) is supported by SBIOS +bit[3]=0: VBIOS fast boot is disable +=1: VBIOS fast boot is enable. ( VBIOS skip display device detection in every set mode if LCD panel is connect and LID is open) + +ulGPUCapInfo: bit[0~2]= Reserved +bit[3]=0: Enable AUX HW mode detection logic +=1: Disable AUX HW mode detection logic +bit[4]=0: Disable DFS bypass feature +=1: Enable DFS bypass feature + +usRequestedPWMFreqInHz: When it's set to 0x0 by SBIOS: the LCD BackLight is not controlled by GPU(SW). +Any attempt to change BL using VBIOS function or enable VariBri from PP table is not effective since ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU==0; ++ When it's set to a non-zero frequency, the BackLight is controlled by GPU (SW) in one of two ways below: +1. SW uses the GPU BL PWM output to control the BL, in chis case, this non-zero frequency determines what freq GPU should use; +VBIOS will set up proper PWM frequency and ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU==1,as the result, +Changing BL using VBIOS function is functional in both driver and non-driver present environment; +and enabling VariBri under the driver environment from PP table is optional. + +2. SW uses other means to control BL (like DPCD),this non-zero frequency serves as a flag only indicating +that BL control from GPU is expected. +VBIOS will NOT set up PWM frequency but make ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU==1 +Changing BL using VBIOS function could be functional in both driver and non-driver present environment,but +it's per platform +and enabling VariBri under the driver environment from PP table is optional. + +ucHtcTmpLmt: Refer to D18F3x64 bit[22:16], HtcTmpLmt. Threshold on value to enter HTC_active state. +ucHtcHystLmt: Refer to D18F3x64 bit[27:24], HtcHystLmt. +To calculate threshold off value to exit HTC_active state, which is Threshold on vlaue minus ucHtcHystLmt. + +ulSystemConfig: Bit[0]=0: PCIE Power Gating Disabled +=1: PCIE Power Gating Enabled +Bit[1]=0: DDR-DLL shut-down feature disabled. +1: DDR-DLL shut-down feature enabled. +Bit[2]=0: DDR-PLL Power down feature disabled. +1: DDR-PLL Power down feature enabled. +Bit[3]=0: GNB DPM is disabled +=1: GNB DPM is enabled +ulCPUCapInfo: TBD + +usExtDispConnInfoOffset: Offset to sExtDispConnInfo inside the structure +usPanelRefreshRateRange: Bit vector for LCD supported refresh rate range. If DRR is requestd by the platform, at least two bits need to be set +to indicate a range. +SUPPORTED_LCD_REFRESHRATE_30Hz 0x0004 +SUPPORTED_LCD_REFRESHRATE_40Hz 0x0008 +SUPPORTED_LCD_REFRESHRATE_50Hz 0x0010 +SUPPORTED_LCD_REFRESHRATE_60Hz 0x0020 + +ucMemoryType: [3:0]=1:DDR1;=2:DDR2;=3:DDR3;=5:GDDR5; [7:4] is reserved. +ucUMAChannelNumber: System memory channel numbers. + +strVBIOSMsg[40]: VBIOS boot up customized message string + +sAvail_SCLK[5]: Arrays to provide availabe list of SLCK and corresponding voltage, order from low to high + +ulGMCRestoreResetTime: GMC power restore and GMC reset time to calculate data reconnection latency. Unit in ns. +ulIdleNClk: NCLK speed while memory runs in self-refresh state, used to calculate self-refresh latency. Unit in 10kHz. +ulDDR_DLL_PowerUpTime: DDR PHY DLL power up time. Unit in ns. +ulDDR_PLL_PowerUpTime: DDR PHY PLL power up time. Unit in ns. + +usPCIEClkSSPercentage: PCIE Clock Spread Spectrum Percentage in unit 0.01%; 100 mean 1%. +usPCIEClkSSType: PCIE Clock Spread Spectrum Type. 0 for Down spread(default); 1 for Center spread. +usLvdsSSPercentage: LVDS panel ( not include eDP ) Spread Spectrum Percentage in unit of 0.01%, =0, use VBIOS default setting. +usLvdsSSpreadRateIn10Hz: LVDS panel ( not include eDP ) Spread Spectrum frequency in unit of 10Hz, =0, use VBIOS default setting. +usHDMISSPercentage: HDMI Spread Spectrum Percentage in unit 0.01%; 100 mean 1%, =0, use VBIOS default setting. +usHDMISSpreadRateIn10Hz: HDMI Spread Spectrum frequency in unit of 10Hz, =0, use VBIOS default setting. +usDVISSPercentage: DVI Spread Spectrum Percentage in unit 0.01%; 100 mean 1%, =0, use VBIOS default setting. +usDVISSpreadRateIn10Hz: DVI Spread Spectrum frequency in unit of 10Hz, =0, use VBIOS default setting. + +usGPUReservedSysMemSize: Reserved system memory size for ACP engine in APU GNB, units in MB. 0/2/4MB based on CMOS options, current default could be 0MB. KV only, not on KB. +ulGPUReservedSysMemBaseAddrLo: Low 32 bits base address to the reserved system memory. +ulGPUReservedSysMemBaseAddrHi: High 32 bits base address to the reserved system memory. + +usMaxLVDSPclkFreqInSingleLink: Max pixel clock LVDS panel single link, if=0 means VBIOS use default threhold, right now it is 85Mhz +ucLVDSMisc: [bit0] LVDS 888bit panel mode =0: LVDS 888 panel in LDI mode, =1: LVDS 888 panel in FPDI mode +[bit1] LVDS panel lower and upper link mapping =0: lower link and upper link not swap, =1: lower link and upper link are swapped +[bit2] LVDS 888bit per color mode =0: 666 bit per color =1:888 bit per color +[bit3] LVDS parameter override enable =0: ucLvdsMisc parameter are not used =1: ucLvdsMisc parameter should be used +[bit4] Polarity of signal sent to digital BLON output pin. =0: not inverted(active high) =1: inverted ( active low ) +[bit5] Travid LVDS output voltage override enable, when =1, use ucTravisLVDSVolAdjust value to overwrite Traivs register LVDS_CTRL_4 +ucTravisLVDSVolAdjust When ucLVDSMisc[5]=1,it means platform SBIOS want to overwrite TravisLVDSVoltage. Then VBIOS will use ucTravisLVDSVolAdjust +value to program Travis register LVDS_CTRL_4 +ucLVDSPwrOnSeqDIGONtoDE_in4Ms: +LVDS power up sequence time in unit of 4ms, time delay from DIGON signal active to data enable signal active( DE ). +=0 mean use VBIOS default which is 8 ( 32ms ). The LVDS power up sequence is as following: DIGON->DE->VARY_BL->BLON. +This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable. +ucLVDSPwrOnDEtoVARY_BL_in4Ms: +LVDS power up sequence time in unit of 4ms., time delay from DE( data enable ) active to Vary Brightness enable signal active( VARY_BL ). +=0 mean use VBIOS default which is 90 ( 360ms ). The LVDS power up sequence is as following: DIGON->DE->VARY_BL->BLON. +This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable. +ucLVDSPwrOffVARY_BLtoDE_in4Ms: +LVDS power down sequence time in unit of 4ms, time delay from data enable ( DE ) signal off to LCDVCC (DIGON) off. +=0 mean use VBIOS default delay which is 8 ( 32ms ). The LVDS power down sequence is as following: BLON->VARY_BL->DE->DIGON +This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable. +ucLVDSPwrOffDEtoDIGON_in4Ms: +LVDS power down sequence time in unit of 4ms, time delay from vary brightness enable signal( VARY_BL) off to data enable ( DE ) signal off. +=0 mean use VBIOS default which is 90 ( 360ms ). The LVDS power down sequence is as following: BLON->VARY_BL->DE->DIGON +This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable. +ucLVDSOffToOnDelay_in4Ms: +LVDS power down sequence time in unit of 4ms. Time delay from DIGON signal off to DIGON signal active. +=0 means to use VBIOS default delay which is 125 ( 500ms ). +This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable. +ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms: +LVDS power up sequence time in unit of 4ms. Time delay from VARY_BL signal on to DLON signal active. +=0 means to use VBIOS default delay which is 0 ( 0ms ). +This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable. + +ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms: +LVDS power down sequence time in unit of 4ms. Time delay from BLON signal off to VARY_BL signal off. +=0 means to use VBIOS default delay which is 0 ( 0ms ). +This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable. +ucMinAllowedBL_Level: Lowest LCD backlight PWM level. This is customer platform specific parameters. By default it is 0. + +ulLCDBitDepthControlVal: GPU display control encoder bit dither control setting, used to program register mmFMT_BIT_DEPTH_CONTROL + +ulNbpStateMemclkFreq[4]: system memory clock frequncey in unit of 10Khz in different NB P-State(P0, P1, P2 & P3). +ulNbpStateNClkFreq[4]: NB P-State NClk frequency in different NB P-State +usNBPStateVoltage[4]: NB P-State (P0/P1 & P2/P3) voltage; NBP3 refers to lowes voltage +usBootUpNBVoltage: NB P-State voltage during boot up before driver loaded +sExtDispConnInfo: Display connector information table provided to VBIOS + +**********************************************************************************************************************/ + +// this Table is used for Kaveri/Kabini APU +typedef struct _ATOM_FUSION_SYSTEM_INFO_V2 +{ +ATOM_INTEGRATED_SYSTEM_INFO_V1_8 sIntegratedSysInfo;// refer to ATOM_INTEGRATED_SYSTEM_INFO_V1_8 definition +ULONG ulPowerplayTable[128 ];// Update comments here to link new powerplay table definition structure +}ATOM_FUSION_SYSTEM_INFO_V2 ; + +/**************************************************************************/ // This portion is only used when ext thermal chip or engine/memory clock SS chip is populated on a design //Memory SS Info Table
@@ -5026,22 +5380,24 @@ typedef struct _ATOM_ASIC_SS_ASSIGNMENT//Define ucClockIndication, SW uses the IDs below to search if the SS is required/enabled on a clock branch/signal type. //SS is not required or enabled if a match is not found. -#define ASIC_INTERNAL_MEMORY_SS 1 -#define ASIC_INTERNAL_ENGINE_SS 2 -#define ASIC_INTERNAL_UVD_SS 3 -#define ASIC_INTERNAL_SS_ON_TMDS 4 -#define ASIC_INTERNAL_SS_ON_HDMI 5 -#define ASIC_INTERNAL_SS_ON_LVDS 6 -#define ASIC_INTERNAL_SS_ON_DP 7 -#define ASIC_INTERNAL_SS_ON_DCPLL 8 -#define ASIC_EXTERNAL_SS_ON_DP_CLOCK 9 -#define ASIC_INTERNAL_VCE_SS 10 +#define ASIC_INTERNAL_MEMORY_SS 1 +#define ASIC_INTERNAL_ENGINE_SS 2 +#define ASIC_INTERNAL_UVD_SS 3 +#define ASIC_INTERNAL_SS_ON_TMDS 4 +#define ASIC_INTERNAL_SS_ON_HDMI 5 +#define ASIC_INTERNAL_SS_ON_LVDS 6 +#define ASIC_INTERNAL_SS_ON_DP 7 +#define ASIC_INTERNAL_SS_ON_DCPLL 8 +#define ASIC_EXTERNAL_SS_ON_DP_CLOCK 9 +#define ASIC_INTERNAL_VCE_SS 10 +#define ASIC_INTERNAL_GPUPLL_SS 11 + typedef struct _ATOM_ASIC_SS_ASSIGNMENT_V2 { ULONG ulTargetClockRange; //For mem/engine/uvd, Clock Out frequence (VCO ), in unit of 10Khz //For TMDS/HDMI/LVDS, it is pixel clock , for DP, it is link clock ( 27000 or 16200 ) - USHORT usSpreadSpectrumPercentage; //in unit of 0.01% + USHORT usSpreadSpectrumPercentage; //in unit of 0.01% or 0.001%, decided by ucSpreadSpectrumMode bit4 USHORT usSpreadRateIn10Hz; //in unit of 10Hz, modulation freq UCHAR ucClockIndication; //Indicate which clock source needs SS UCHAR ucSpreadSpectrumMode; //Bit0=0 Down Spread,=1 Center Spread, bit1=0: internal SS bit1=1: external SS
@@ -5079,6 +5435,11 @@ typedef struct _ATOM_ASIC_SS_ASSIGNMENT_V3UCHAR ucReserved[2 ]; }ATOM_ASIC_SS_ASSIGNMENT_V3 ; +//ATOM_ASIC_SS_ASSIGNMENT_V3.ucSpreadSpectrumMode +#define SS_MODE_V3_CENTRE_SPREAD_MASK 0x01 +#define SS_MODE_V3_EXTERNAL_SS_MASK 0x02 +#define SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK 0x10 + typedef struct _ATOM_ASIC_INTERNAL_SS_INFO_V3 { ATOM_COMMON_TABLE_HEADER sHeader;
@@ -5719,6 +6080,7 @@ typedef struct _INDIRECT_IO_ACCESS#define INDIRECT_IO_PCIE 3#define INDIRECT_IO_PCIEP 4#define INDIRECT_IO_NBMISC 5 +#define INDIRECT_IO_SMU 5#define INDIRECT_IO_PLL_READ INDIRECT_IO_PLL | INDIRECT_READ#define INDIRECT_IO_PLL_WRITE INDIRECT_IO_PLL | INDIRECT_WRITE
@@ -5730,6 +6092,8 @@ typedef struct _INDIRECT_IO_ACCESS#define INDIRECT_IO_PCIEP_WRITE INDIRECT_IO_PCIEP | INDIRECT_WRITE#define INDIRECT_IO_NBMISC_READ INDIRECT_IO_NBMISC | INDIRECT_READ#define INDIRECT_IO_NBMISC_WRITE INDIRECT_IO_NBMISC | INDIRECT_WRITE +#define INDIRECT_IO_SMU_READ INDIRECT_IO_SMU | INDIRECT_READ +#define INDIRECT_IO_SMU_WRITE INDIRECT_IO_SMU | INDIRECT_WRITE typedef struct _ATOM_OEM_INFO {
@@ -5875,6 +6239,7 @@ typedef struct _ATOM_MC_INIT_PARAM_TABLE#define _64Mx32 0x43#define _128Mx8 0x51#define _128Mx16 0x52 +#define _128Mx32 0x53#define _256Mx8 0x61#define _256Mx16 0x62
@@ -5893,6 +6258,8 @@ typedef struct _ATOM_MC_INIT_PARAM_TABLE#define PROMOS MOSEL#define KRETON INFINEON#define ELIXIR NANYA +#define MEZZA ELPIDA +/////////////Support for GDDR5 MC uCode to reside in upper 64K of ROM/////////////
@@ -6625,6 +6992,10 @@ typedef struct _ATOM_DISP_OUT_INFO_V3ASIC_TRANSMITTER_INFO_V2 asTransmitterInfo[1 ];// for alligment only }ATOM_DISP_OUT_INFO_V3 ; +//ucDispCaps +#define DISPLAY_CAPS__DP_PCLK_FROM_PPLL 0x01 +#define DISPLAY_CAPS__FORCE_DISPDEV_CONNECTED 0x02 + typedef enum CORE_REF_CLK_SOURCE{ CLOCK_SRC_XTALIN=0, CLOCK_SRC_XO_IN=1,
@@ -6829,6 +7200,17 @@ typedef struct _DIG_TRANSMITTER_INFO_HEADER_V3_1{USHORT usPhyPllSettingOffset;// offset of CLOCK_CONDITION_SETTING_ENTRY* with Phy Pll Settings }DIG_TRANSMITTER_INFO_HEADER_V3_1 ; +typedef struct _DIG_TRANSMITTER_INFO_HEADER_V3_2 { +ATOM_COMMON_TABLE_HEADER sHeader; +USHORT usDPVsPreEmphSettingOffset;// offset of PHY_ANALOG_SETTING_INFO * with DP Voltage Swing and Pre-Emphasis for each Link clock +USHORT usPhyAnalogRegListOffset;// offset of CLOCK_CONDITION_REGESTER_INFO* with None-DP mode Analog Setting's register Info +USHORT usPhyAnalogSettingOffset;// offset of CLOCK_CONDITION_SETTING_ENTRY* with None-DP mode Analog Setting for each link clock range +USHORT usPhyPllRegListOffset;// offset of CLOCK_CONDITION_REGESTER_INFO* with Phy Pll register Info +USHORT usPhyPllSettingOffset;// offset of CLOCK_CONDITION_SETTING_ENTRY* with Phy Pll Settings +USHORT usDPSSRegListOffset;// offset of CLOCK_CONDITION_REGESTER_INFO* with Phy SS Pll register Info +USHORT usDPSSSettingOffset;// offset of CLOCK_CONDITION_SETTING_ENTRY* with Phy SS Pll Settings +}DIG_TRANSMITTER_INFO_HEADER_V3_2 ; + typedef struct _CLOCK_CONDITION_REGESTER_INFO{ USHORT usRegisterIndex; UCHAR ucStartBit;
@@ -6852,12 +7234,24 @@ typedef struct _PHY_CONDITION_REG_VAL{ULONG ulRegVal; }PHY_CONDITION_REG_VAL ; +typedef struct _PHY_CONDITION_REG_VAL_V2 { +ULONG ulCondition; +UCHAR ucCondition2; +ULONG ulRegVal; +}PHY_CONDITION_REG_VAL_V2 ; +typedef struct _PHY_CONDITION_REG_INFO {USHORT usRegIndex;USHORT usSize;PHY_CONDITION_REG_VAL asRegVal[1 ]; }PHY_CONDITION_REG_INFO ; +typedef struct _PHY_CONDITION_REG_INFO_V2 { +USHORT usRegIndex; +USHORT usSize; +PHY_CONDITION_REG_VAL_V2 asRegVal[1 ]; +}PHY_CONDITION_REG_INFO_V2 ; + typedef struct _PHY_ANALOG_SETTING_INFO{ UCHAR ucEncodeMode; UCHAR ucPhySel;
@@ -6865,6 +7259,25 @@ typedef struct _PHY_ANALOG_SETTING_INFO{PHY_CONDITION_REG_INFO asAnalogSetting[1 ]; }PHY_ANALOG_SETTING_INFO ; +typedef struct _PHY_ANALOG_SETTING_INFO_V2 { +UCHAR ucEncodeMode; +UCHAR ucPhySel; +USHORT usSize; +PHY_CONDITION_REG_INFO_V2 asAnalogSetting[1 ]; +}PHY_ANALOG_SETTING_INFO_V2 ; + +typedef struct _GFX_HAVESTING_PARAMETERS { +UCHAR ucGfxBlkId;//GFX blk id to be harvested, like CU, RB or PRIM +UCHAR ucReserved;//reserved +UCHAR ucActiveUnitNumPerSH;//requested active CU/RB/PRIM number per shader array +UCHAR ucMaxUnitNumPerSH;//max CU/RB/PRIM number per shader array +}GFX_HAVESTING_PARAMETERS ; + +//ucGfxBlkId +#define GFX_HARVESTING_CU_ID 0 +#define GFX_HARVESTING_RB_ID 1 +#define GFX_HARVESTING_PRIM_ID 2 +/****************************************************************************/ //Portion VI: Definitinos for vbios MC scratch registers that driver used /****************************************************************************/
@@ -6875,8 +7288,17 @@ typedef struct _PHY_ANALOG_SETTING_INFO{#define MC_MISC0__MEMORY_TYPE__GDDR3 0x30000000#define MC_MISC0__MEMORY_TYPE__GDDR4 0x40000000#define MC_MISC0__MEMORY_TYPE__GDDR5 0x50000000 +#define MC_MISC0__MEMORY_TYPE__HBM 0x60000000#define MC_MISC0__MEMORY_TYPE__DDR3 0xB0000000 +#define ATOM_MEM_TYPE_DDR_STRING "DDR" +#define ATOM_MEM_TYPE_DDR2_STRING "DDR2" +#define ATOM_MEM_TYPE_GDDR3_STRING "GDDR3" +#define ATOM_MEM_TYPE_GDDR4_STRING "GDDR4" +#define ATOM_MEM_TYPE_GDDR5_STRING "GDDR5" +#define ATOM_MEM_TYPE_HBM_STRING "HBM" +#define ATOM_MEM_TYPE_DDR3_STRING "DDR3" +/****************************************************************************/ //Portion VI: Definitinos being oboselete /****************************************************************************/
Signature · 6 lines
1.7.7.5 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 26/165 drm/radeon: atombios power table updates (v2)
In reply to [email protected]From: Alex Deucher <[email protected]>
v2: further updates
--- drivers/gpu/drm/radeon/atombios.h | 58 ++++++++++++++++++++++++++++++++++-- 1 files changed, 54 insertions(+), 4 deletions(-)
drivers/gpu/drm/radeon/atombios.h +54 -4
@@ -7696,6 +7696,7 @@ typedef struct _ATOM_PPLIB_THERMALCONTROLLER#define ATOM_PP_THERMALCONTROLLER_NISLANDS 15#define ATOM_PP_THERMALCONTROLLER_SISLANDS 16#define ATOM_PP_THERMALCONTROLLER_LM96163 17 +#define ATOM_PP_THERMALCONTROLLER_CISLANDS 18// Thermal controller 'combo type' to use an external controller for Fan control and an internal controller for thermal. // We probably should reserve the bit 0x80 for this use.
@@ -7738,6 +7739,8 @@ typedef struct _ATOM_PPLIB_EXTENDEDHEADER// Add extra system parameters here, always adjust size to include all fields. USHORT usVCETableOffset;//points to ATOM_PPLIB_VCE_Table USHORT usUVDTableOffset;//points to ATOM_PPLIB_UVD_Table +USHORT usSAMUTableOffset;//points to ATOM_PPLIB_SAMU_Table +USHORT usPPMTableOffset;//points to ATOM_PPLIB_PPM_Table }ATOM_PPLIB_EXTENDEDHEADER ;//// ATOM_PPLIB_POWERPLAYTABLE::ulPlatformCaps
@@ -7759,7 +7762,7 @@ typedef struct _ATOM_PPLIB_EXTENDEDHEADER#define ATOM_PP_PLATFORM_CAP_VDDCI_CONTROL 0x8000 // Does the driver control VDDCI independently from VDDC.#define ATOM_PP_PLATFORM_CAP_REGULATOR_HOT 0x00010000 // Enable the 'regulator hot' feature.#define ATOM_PP_PLATFORM_CAP_BACO 0x00020000 // Does the driver supports BACO state. - +#define ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE 0x00040000 // Does the driver supports new CAC voltage table. typedef struct _ATOM_PPLIB_POWERPLAYTABLE {
@@ -7820,7 +7823,7 @@ typedef struct _ATOM_PPLIB_POWERPLAYTABLE4USHORT usVddcDependencyOnMCLKOffset;USHORT usMaxClockVoltageOnDCOffset;USHORT usVddcPhaseShedLimitsTableOffset;// Points to ATOM_PPLIB_PhaseSheddingLimits_Table -USHORT usReserved; +USHORT usMvddDependencyOnMCLKOffset; }ATOM_PPLIB_POWERPLAYTABLE4 , *LPATOM_PPLIB_POWERPLAYTABLE4 ; typedef struct _ATOM_PPLIB_POWERPLAYTABLE5
@@ -7985,6 +7988,17 @@ typedef struct _ATOM_PPLIB_SI_CLOCK_INFO }ATOM_PPLIB_SI_CLOCK_INFO ; +typedef struct _ATOM_PPLIB_CI_CLOCK_INFO +{ +USHORT usEngineClockLow; +UCHAR ucEngineClockHigh; + +USHORT usMemoryClockLow; +UCHAR ucMemoryClockHigh; + +UCHAR ucPCIEGen; +USHORT usPCIELane; +}ATOM_PPLIB_CI_CLOCK_INFO ; typedef struct _ATOM_PPLIB_RS780_CLOCK_INFO
@@ -8102,8 +8116,8 @@ typedef struct _ATOM_PPLIB_Clock_Voltage_Limit_Tabletypedef struct _ATOM_PPLIB_CAC_Leakage_Record { -USHORT usVddc;// We use this field for the "fake" standardized VDDC for power calculations -ULONG ulLeakageValue; +USHORT usVddc;// We use this field for the "fake" standardized VDDC for power calculations; For CI and newer, we use this as the real VDDC value. +ULONG ulLeakageValue;// For CI and newer we use this as the "fake" standar VDDC value. }ATOM_PPLIB_CAC_Leakage_Record ; typedef struct _ATOM_PPLIB_CAC_Leakage_Table
@@ -8218,6 +8232,42 @@ typedef struct _ATOM_PPLIB_UVD_Table// ATOM_PPLIB_UVD_State_Table states; }ATOM_PPLIB_UVD_Table; + +typedef struct _ATOM_PPLIB_SAMClk_Voltage_Limit_Record +{ +USHORT usVoltage; +USHORT usSAMClockLow; +UCHAR ucSAMClockHigh; +}ATOM_PPLIB_SAMClk_Voltage_Limit_Record ; + +typedef struct _ATOM_PPLIB_SAMClk_Voltage_Limit_Table { +UCHAR numEntries; +ATOM_PPLIB_SAMClk_Voltage_Limit_Record entries[1 ]; +}ATOM_PPLIB_SAMClk_Voltage_Limit_Table ; + +typedef struct _ATOM_PPLIB_SAMU_Table +{ +UCHAR revid; +ATOM_PPLIB_SAMClk_Voltage_Limit_Table limits; +}ATOM_PPLIB_SAMU_Table ; + +#define ATOM_PPM_A_A 1 +#define ATOM_PPM_A_I 2 +typedef struct _ATOM_PPLIB_PPM_Table +{ +UCHAR ucRevId; +UCHAR ucPpmDesign;//A+I or A+A +USHORT usCpuCoreNumber; +ULONG ulPlatformTDP; +ULONG ulSmallACPlatformTDP; +ULONG ulPlatformTDC; +ULONG ulSmallACPlatformTDC; +ULONG ulApuTDP; +ULONG ulDGpuTDP; +ULONG ulDGpuUlvPower; +ULONG ulTjmax; +}ATOM_PPLIB_PPM_Table ; +/**************************************************************************/
Signature · 1 line
1.7.7.5
PATCH 27/165 drm/radeon: handle the integrated thermal controller on CI
In reply to [email protected]From: Alex Deucher <[email protected]>
No support for reading the temperature yet.
--- drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_atombios.c | 6 ++++++ 2 files changed, 7 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/radeon.h +1 -0
@@ -1033,6 +1033,7 @@ enum radeon_int_thermal_type {THERMAL_TYPE_SUMO ,THERMAL_TYPE_NI ,THERMAL_TYPE_SI , + THERMAL_TYPE_CI, }; struct radeon_voltage {
drivers/gpu/drm/radeon/radeon_atombios.c +6 -0
@@ -1927,6 +1927,7 @@ static const char *pp_lib_thermal_controller_names[] = {"Northern Islands" ,"Southern Islands" ,"lm96163" , + "Sea Islands", }; union power_info {
@@ -2209,6 +2210,11 @@ static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *r (controller->ucFanParameters & ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); rdev->pm.int_thermal_type =THERMAL_TYPE_SI ; + }else if (controller->ucType ==ATOM_PP_THERMALCONTROLLER_CISLANDS ) { +DRM_INFO ("Internal thermal controller %s fan control\n" , + (controller->ucFanParameters & +ATOM_PP_FANPARAMETERS_NOFAN ) ?"without" :"with" ); + rdev->pm.int_thermal_type =THERMAL_TYPE_CI ; } else if ((controller->ucType == ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) || (controller->ucType ==
Signature · 1 line
1.7.7.5
PATCH 28/165 drm/radeon: update power state parsing for CI
In reply to [email protected]From: Alex Deucher <[email protected]>
--- drivers/gpu/drm/radeon/radeon_atombios.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/radeon_atombios.c +10 -0
@@ -1945,6 +1945,7 @@ union pplib_clock_info {struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;struct _ATOM_PPLIB_SI_CLOCK_INFO si; +struct _ATOM_PPLIB_CI_CLOCK_INFO ci; };union pplib_power_state {
@@ -2353,6 +2354,15 @@ static bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev, sclk |= clock_info->rs780.ucLowEngineClockHigh <<16 ; rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; } + }else if (rdev->family >=CHIP_BONAIRE ) { + sclk =le16_to_cpu (clock_info->ci.usEngineClockLow); + sclk |= clock_info->ci.ucEngineClockHigh <<16 ; + mclk =le16_to_cpu (clock_info->ci.usMemoryClockLow); + mclk |= clock_info->ci.ucMemoryClockHigh <<16 ; + rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; + rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; + rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = +VOLTAGE_NONE ; }else if (rdev->family >=CHIP_TAHITI ) { sclk =le16_to_cpu (clock_info->si.usEngineClockLow); sclk |= clock_info->si.ucEngineClockHigh <<16 ;
Signature · 1 line
1.7.7.5
PATCH 29/165 drm/radeon/dce8: add support for display watermark setup
In reply to [email protected]From: Alex Deucher <[email protected]>
--- drivers/gpu/drm/radeon/cik.c | 537 +++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/cikd.h | 11 + 2 files changed, 548 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/cik.c +537 -0
@@ -5021,3 +5021,540 @@ void cik_fini(struct radeon_device *rdev)kfree (rdev->bios); rdev->bios =NULL ; } + +/* display watermark setup */ +/** +* dce8_line_buffer_adjust - Set up the line buffer +* +* @rdev: radeon_device pointer +* @radeon_crtc: the selected display controller +* @mode: the current display mode on the selected display +* controller +* +* Setup up the line buffer allocation for +* the selected display controller (CIK). +* Returns the line buffer size in pixels. +*/ +static u32 dce8_line_buffer_adjust (struct radeon_device *rdev, +struct radeon_crtc *radeon_crtc, +struct drm_display_mode *mode) +{ +u32 tmp; + +/* +* Line Buffer Setup +* There are 6 line buffers, one for each display controllers. +* There are 3 partitions per LB. Select the number of partitions +* to enable based on the display width. For display widths larger +* than 4096, you need use to use 2 display controllers and combine +* them using the stereo blender. +*/ +if (radeon_crtc->base.enabled && mode) { +if (mode->crtc_hdisplay <1920 ) + tmp =1 ; +else if (mode->crtc_hdisplay <2560 ) + tmp =2 ; +else if (mode->crtc_hdisplay <4096 ) + tmp =0 ; +else { +DRM_DEBUG_KMS ("Mode too big for LB!\n" ); + tmp =0 ; + } + }else + tmp =1 ; + +WREG32 (LB_MEMORY_CTRL + radeon_crtc->crtc_offset, +LB_MEMORY_CONFIG (tmp) |LB_MEMORY_SIZE (0x6B0 )); + +if (radeon_crtc->base.enabled && mode) { +switch (tmp) { +case 0 : +default : +return 4096 *2 ; +case 1 : +return 1920 *2 ; +case 2 : +return 2560 *2 ; + } + } + +/* controller not enabled, so no lb used */ +return 0 ; +} + +/** +* cik_get_number_of_dram_channels - get the number of dram channels +* +* @rdev: radeon_device pointer +* +* Look up the number of video ram channels (CIK). +* Used for display watermark bandwidth calculations +* Returns the number of dram channels +*/ +static u32 cik_get_number_of_dram_channels (struct radeon_device *rdev) +{ +u32 tmp =RREG32 (MC_SHARED_CHMAP ); + +switch ((tmp &NOOFCHAN_MASK ) >>NOOFCHAN_SHIFT ) { +case 0 : +default : +return 1 ; +case 1 : +return 2 ; +case 2 : +return 4 ; +case 3 : +return 8 ; +case 4 : +return 3 ; +case 5 : +return 6 ; +case 6 : +return 10 ; +case 7 : +return 12 ; +case 8 : +return 16 ; + } +} + +struct dce8_wm_params { +u32 dram_channels;/* number of dram channels */ +u32 yclk;/* bandwidth per dram data pin in kHz */ +u32 sclk;/* engine clock in kHz */ +u32 disp_clk;/* display clock in kHz */ +u32 src_width;/* viewport width */ +u32 active_time;/* active display time in ns */ +u32 blank_time;/* blank time in ns */ +bool interlaced;/* mode is interlaced */ +fixed20_12 vsc;/* vertical scale ratio */ +u32 num_heads;/* number of active crtcs */ +u32 bytes_per_pixel;/* bytes per pixel display + overlay */ +u32 lb_size;/* line buffer allocated to pipe */ +u32 vtaps;/* vertical scaler taps */ +}; + +/** +* dce8_dram_bandwidth - get the dram bandwidth +* +* @wm: watermark calculation data +* +* Calculate the raw dram bandwidth (CIK). +* Used for display watermark bandwidth calculations +* Returns the dram bandwidth in MBytes/s +*/ +static u32 dce8_dram_bandwidth (struct dce8_wm_params *wm) +{ +/* Calculate raw DRAM Bandwidth */ +fixed20_12 dram_efficiency;/* 0.7 */ +fixed20_12 yclk, dram_channels, bandwidth; +fixed20_12 a; + + a.full =dfixed_const (1000 ); + yclk.full =dfixed_const (wm->yclk); + yclk.full =dfixed_div (yclk, a); + dram_channels.full =dfixed_const (wm->dram_channels *4 ); + a.full =dfixed_const (10 ); + dram_efficiency.full =dfixed_const (7 ); + dram_efficiency.full =dfixed_div (dram_efficiency, a); + bandwidth.full =dfixed_mul (dram_channels, yclk); + bandwidth.full =dfixed_mul (bandwidth, dram_efficiency); + +return dfixed_trunc (bandwidth); +} + +/** +* dce8_dram_bandwidth_for_display - get the dram bandwidth for display +* +* @wm: watermark calculation data +* +* Calculate the dram bandwidth used for display (CIK). +* Used for display watermark bandwidth calculations +* Returns the dram bandwidth for display in MBytes/s +*/ +static u32 dce8_dram_bandwidth_for_display (struct dce8_wm_params *wm) +{ +/* Calculate DRAM Bandwidth and the part allocated to display. */ +fixed20_12 disp_dram_allocation;/* 0.3 to 0.7 */ +fixed20_12 yclk, dram_channels, bandwidth; +fixed20_12 a; + + a.full =dfixed_const (1000 ); + yclk.full =dfixed_const (wm->yclk); + yclk.full =dfixed_div (yclk, a); + dram_channels.full =dfixed_const (wm->dram_channels *4 ); + a.full =dfixed_const (10 ); + disp_dram_allocation.full =dfixed_const (3 );/* XXX worse case value 0.3 */ + disp_dram_allocation.full =dfixed_div (disp_dram_allocation, a); + bandwidth.full =dfixed_mul (dram_channels, yclk); + bandwidth.full =dfixed_mul (bandwidth, disp_dram_allocation); + +return dfixed_trunc (bandwidth); +} + +/** +* dce8_data_return_bandwidth - get the data return bandwidth +* +* @wm: watermark calculation data +* +* Calculate the data return bandwidth used for display (CIK). +* Used for display watermark bandwidth calculations +* Returns the data return bandwidth in MBytes/s +*/ +static u32 dce8_data_return_bandwidth (struct dce8_wm_params *wm) +{ +/* Calculate the display Data return Bandwidth */ +fixed20_12 return_efficiency;/* 0.8 */ +fixed20_12 sclk, bandwidth; +fixed20_12 a; + + a.full =dfixed_const (1000 ); + sclk.full =dfixed_const (wm->sclk); + sclk.full =dfixed_div (sclk, a); + a.full =dfixed_const (10 ); + return_efficiency.full =dfixed_const (8 ); + return_efficiency.full =dfixed_div (return_efficiency, a); + a.full =dfixed_const (32 ); + bandwidth.full =dfixed_mul (a, sclk); + bandwidth.full =dfixed_mul (bandwidth, return_efficiency); + +return dfixed_trunc (bandwidth); +} + +/** +* dce8_dmif_request_bandwidth - get the dmif bandwidth +* +* @wm: watermark calculation data +* +* Calculate the dmif bandwidth used for display (CIK). +* Used for display watermark bandwidth calculations +* Returns the dmif bandwidth in MBytes/s +*/ +static u32 dce8_dmif_request_bandwidth (struct dce8_wm_params *wm) +{ +/* Calculate the DMIF Request Bandwidth */ +fixed20_12 disp_clk_request_efficiency;/* 0.8 */ +fixed20_12 disp_clk, bandwidth; +fixed20_12 a, b; + + a.full =dfixed_const (1000 ); + disp_clk.full =dfixed_const (wm->disp_clk); + disp_clk.full =dfixed_div (disp_clk, a); + a.full =dfixed_const (32 ); + b.full =dfixed_mul (a, disp_clk); + + a.full =dfixed_const (10 ); + disp_clk_request_efficiency.full =dfixed_const (8 ); + disp_clk_request_efficiency.full =dfixed_div (disp_clk_request_efficiency, a); + + bandwidth.full =dfixed_mul (b, disp_clk_request_efficiency); + +return dfixed_trunc (bandwidth); +} + +/** +* dce8_available_bandwidth - get the min available bandwidth +* +* @wm: watermark calculation data +* +* Calculate the min available bandwidth used for display (CIK). +* Used for display watermark bandwidth calculations +* Returns the min available bandwidth in MBytes/s +*/ +static u32 dce8_available_bandwidth (struct dce8_wm_params *wm) +{ +/* Calculate the Available bandwidth. Display can use this temporarily but not in average. */ +u32 dram_bandwidth =dce8_dram_bandwidth (wm); +u32 data_return_bandwidth =dce8_data_return_bandwidth (wm); +u32 dmif_req_bandwidth =dce8_dmif_request_bandwidth (wm); + +return min (dram_bandwidth,min (data_return_bandwidth, dmif_req_bandwidth)); +} + +/** +* dce8_average_bandwidth - get the average available bandwidth +* +* @wm: watermark calculation data +* +* Calculate the average available bandwidth used for display (CIK). +* Used for display watermark bandwidth calculations +* Returns the average available bandwidth in MBytes/s +*/ +static u32 dce8_average_bandwidth (struct dce8_wm_params *wm) +{ +/* Calculate the display mode Average Bandwidth +* DisplayMode should contain the source and destination dimensions, +* timing, etc. +*/ +fixed20_12 bpp; +fixed20_12 line_time; +fixed20_12 src_width; +fixed20_12 bandwidth; +fixed20_12 a; + + a.full =dfixed_const (1000 ); + line_time.full =dfixed_const (wm->active_time + wm->blank_time); + line_time.full =dfixed_div (line_time, a); + bpp.full =dfixed_const (wm->bytes_per_pixel); + src_width.full =dfixed_const (wm->src_width); + bandwidth.full =dfixed_mul (src_width, bpp); + bandwidth.full =dfixed_mul (bandwidth, wm->vsc); + bandwidth.full =dfixed_div (bandwidth, line_time); + +return dfixed_trunc (bandwidth); +} + +/** +* dce8_latency_watermark - get the latency watermark +* +* @wm: watermark calculation data +* +* Calculate the latency watermark (CIK). +* Used for display watermark bandwidth calculations +* Returns the latency watermark in ns +*/ +static u32 dce8_latency_watermark (struct dce8_wm_params *wm) +{ +/* First calculate the latency in ns */ +u32 mc_latency =2000 ;/* 2000 ns. */ +u32 available_bandwidth =dce8_available_bandwidth (wm); +u32 worst_chunk_return_time = (512 *8 *1000 ) / available_bandwidth; +u32 cursor_line_pair_return_time = (128 *4 *1000 ) / available_bandwidth; +u32 dc_latency =40000000 / wm->disp_clk;/* dc pipe latency */ +u32 other_heads_data_return_time = ((wm->num_heads +1 ) * worst_chunk_return_time) + + (wm->num_heads * cursor_line_pair_return_time); +u32 latency = mc_latency + other_heads_data_return_time + dc_latency; +u32 max_src_lines_per_dst_line, lb_fill_bw, line_fill_time; +u32 tmp, dmif_size =12288 ; +fixed20_12 a, b, c; + +if (wm->num_heads ==0 ) +return 0 ; + + a.full =dfixed_const (2 ); + b.full =dfixed_const (1 ); +if ((wm->vsc.full > a.full) || + ((wm->vsc.full > b.full) && (wm->vtaps >=3 )) || + (wm->vtaps >=5 ) || + ((wm->vsc.full >= a.full) && wm->interlaced)) + max_src_lines_per_dst_line =4 ; +else + max_src_lines_per_dst_line =2 ; + + a.full =dfixed_const (available_bandwidth); + b.full =dfixed_const (wm->num_heads); + a.full =dfixed_div (a, b); + + b.full =dfixed_const (mc_latency +512 ); + c.full =dfixed_const (wm->disp_clk); + b.full =dfixed_div (b, c); + + c.full =dfixed_const (dmif_size); + b.full =dfixed_div (c, b); + + tmp =min (dfixed_trunc (a),dfixed_trunc (b)); + + b.full =dfixed_const (1000 ); + c.full =dfixed_const (wm->disp_clk); + b.full =dfixed_div (c, b); + c.full =dfixed_const (wm->bytes_per_pixel); + b.full =dfixed_mul (b, c); + + lb_fill_bw =min (tmp,dfixed_trunc (b)); + + a.full =dfixed_const (max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel); + b.full =dfixed_const (1000 ); + c.full =dfixed_const (lb_fill_bw); + b.full =dfixed_div (c, b); + a.full =dfixed_div (a, b); + line_fill_time =dfixed_trunc (a); + +if (line_fill_time < wm->active_time) +return latency; +else +return latency + (line_fill_time - wm->active_time); + +} + +/** +* dce8_average_bandwidth_vs_dram_bandwidth_for_display - check +* average and available dram bandwidth +* +* @wm: watermark calculation data +* +* Check if the display average bandwidth fits in the display +* dram bandwidth (CIK). +* Used for display watermark bandwidth calculations +* Returns true if the display fits, false if not. +*/ +static bool dce8_average_bandwidth_vs_dram_bandwidth_for_display (struct dce8_wm_params *wm) +{ +if (dce8_average_bandwidth (wm) <= + (dce8_dram_bandwidth_for_display (wm) / wm->num_heads)) +return true; +else +return false; +} + +/** +* dce8_average_bandwidth_vs_available_bandwidth - check +* average and available bandwidth +* +* @wm: watermark calculation data +* +* Check if the display average bandwidth fits in the display +* available bandwidth (CIK). +* Used for display watermark bandwidth calculations +* Returns true if the display fits, false if not. +*/ +static bool dce8_average_bandwidth_vs_available_bandwidth (struct dce8_wm_params *wm) +{ +if (dce8_average_bandwidth (wm) <= + (dce8_available_bandwidth (wm) / wm->num_heads)) +return true; +else +return false; +} + +/** +* dce8_check_latency_hiding - check latency hiding +* +* @wm: watermark calculation data +* +* Check latency hiding (CIK). +* Used for display watermark bandwidth calculations +* Returns true if the display fits, false if not. +*/ +static bool dce8_check_latency_hiding (struct dce8_wm_params *wm) +{ +u32 lb_partitions = wm->lb_size / wm->src_width; +u32 line_time = wm->active_time + wm->blank_time; +u32 latency_tolerant_lines; +u32 latency_hiding; +fixed20_12 a; + + a.full =dfixed_const (1 ); +if (wm->vsc.full > a.full) + latency_tolerant_lines =1 ; +else { +if (lb_partitions <= (wm->vtaps +1 )) + latency_tolerant_lines =1 ; +else + latency_tolerant_lines =2 ; + } + + latency_hiding = (latency_tolerant_lines * line_time + wm->blank_time); + +if (dce8_latency_watermark (wm) <= latency_hiding) +return true; +else +return false; +} + +/** +* dce8_program_watermarks - program display watermarks +* +* @rdev: radeon_device pointer +* @radeon_crtc: the selected display controller +* @lb_size: line buffer size +* @num_heads: number of display controllers in use +* +* Calculate and program the display watermarks for the +* selected display controller (CIK). +*/ +static void dce8_program_watermarks (struct radeon_device *rdev, +struct radeon_crtc *radeon_crtc, +u32 lb_size,u32 num_heads) +{ +struct drm_display_mode *mode = &radeon_crtc->base.mode; +struct dce8_wm_params wm; +u32 pixel_period; +u32 line_time =0 ; +u32 latency_watermark_a =0 , latency_watermark_b =0 ; +u32 tmp, wm_mask; + +if (radeon_crtc->base.enabled && num_heads && mode) { + pixel_period =1000000 / (u32 )mode->clock; + line_time =min ((u32 )mode->crtc_htotal * pixel_period, (u32 )65535 ); + + wm.yclk = rdev->pm.current_mclk *10 ; + wm.sclk = rdev->pm.current_sclk *10 ; + wm.disp_clk = mode->clock; + wm.src_width = mode->crtc_hdisplay; + wm.active_time = mode->crtc_hdisplay * pixel_period; + wm.blank_time = line_time - wm.active_time; + wm.interlaced = false; +if (mode->flags &DRM_MODE_FLAG_INTERLACE ) + wm.interlaced = true; + wm.vsc = radeon_crtc->vsc; + wm.vtaps =1 ; +if (radeon_crtc->rmx_type !=RMX_OFF ) + wm.vtaps =2 ; + wm.bytes_per_pixel =4 ;/* XXX: get this from fb config */ + wm.lb_size = lb_size; + wm.dram_channels =cik_get_number_of_dram_channels (rdev); + wm.num_heads = num_heads; + +/* set for high clocks */ + latency_watermark_a =min (dce8_latency_watermark (&wm), (u32 )65535 ); +/* set for low clocks */ +/* wm.yclk = low clk; wm.sclk = low clk */ + latency_watermark_b =min (dce8_latency_watermark (&wm), (u32 )65535 ); + +/* possibly force display priority to high */ +/* should really do this at mode validation time... */ +if (!dce8_average_bandwidth_vs_dram_bandwidth_for_display (&wm) || + !dce8_average_bandwidth_vs_available_bandwidth (&wm) || + !dce8_check_latency_hiding (&wm) || + (rdev->disp_priority ==2 )) { +DRM_DEBUG_KMS ("force priority to high\n" ); + } + } + +/* select wm A */ + wm_mask =RREG32 (DPG_WATERMARK_MASK_CONTROL + radeon_crtc->crtc_offset); + tmp = wm_mask; + tmp &= ~LATENCY_WATERMARK_MASK (3 ); + tmp |=LATENCY_WATERMARK_MASK (1 ); +WREG32 (DPG_WATERMARK_MASK_CONTROL + radeon_crtc->crtc_offset, tmp); +WREG32 (DPG_PIPE_LATENCY_CONTROL + radeon_crtc->crtc_offset, + (LATENCY_LOW_WATERMARK (latency_watermark_a) | +LATENCY_HIGH_WATERMARK (line_time))); +/* select wm B */ + tmp =RREG32 (DPG_WATERMARK_MASK_CONTROL + radeon_crtc->crtc_offset); + tmp &= ~LATENCY_WATERMARK_MASK (3 ); + tmp |=LATENCY_WATERMARK_MASK (2 ); +WREG32 (DPG_WATERMARK_MASK_CONTROL + radeon_crtc->crtc_offset, tmp); +WREG32 (DPG_PIPE_LATENCY_CONTROL + radeon_crtc->crtc_offset, + (LATENCY_LOW_WATERMARK (latency_watermark_b) | +LATENCY_HIGH_WATERMARK (line_time))); +/* restore original selection */ +WREG32 (DPG_WATERMARK_MASK_CONTROL + radeon_crtc->crtc_offset, wm_mask); +} + +/** +* dce8_bandwidth_update - program display watermarks +* +* @rdev: radeon_device pointer +* +* Calculate and program the display watermarks and line +* buffer allocation (CIK). +*/ +void dce8_bandwidth_update (struct radeon_device *rdev) +{ +struct drm_display_mode *mode =NULL ; +u32 num_heads =0 , lb_size; +int i; + +radeon_update_display_priority (rdev); + +for (i =0 ; i < rdev->num_crtc; i++) { +if (rdev->mode_info.crtcs[i]->base.enabled) + num_heads++; + } +for (i =0 ; i < rdev->num_crtc; i++) { + mode = &rdev->mode_info.crtcs[i]->base.mode; + lb_size =dce8_line_buffer_adjust (rdev, rdev->mode_info.crtcs[i], mode); +dce8_program_watermarks (rdev, rdev->mode_info.crtcs[i], lb_size, num_heads); + } +}
drivers/gpu/drm/radeon/cikd.h +11 -0
@@ -259,6 +259,17 @@#define SDMA0 (1 << 10)#define SDMA1 (1 << 11) +/* 0x6b04, 0x7704, 0x10304, 0x10f04, 0x11b04, 0x12704 */ +#define LB_MEMORY_CTRL 0x6b04 +#define LB_MEMORY_SIZE (x) ((x) << 0) +#define LB_MEMORY_CONFIG (x) ((x) << 20) + +#define DPG_WATERMARK_MASK_CONTROL 0x6cc8 +# define LATENCY_WATERMARK_MASK (x) ((x) << 8) +#define DPG_PIPE_LATENCY_CONTROL 0x6ccc +# define LATENCY_LOW_WATERMARK (x) ((x) << 0) +# define LATENCY_HIGH_WATERMARK (x) ((x) << 16) +/* 0x6b24, 0x7724, 0x10324, 0x10f24, 0x11b24, 0x12724 */ #define LB_VLINE_STATUS 0x6b24# define VLINE_OCCURRED (1 << 0)
Signature · 1 line
1.7.7.5
PATCH 30/165 drm/radeon/cik: add hw cursor support (v2)
In reply to [email protected]From: Alex Deucher <[email protected]>
CIK (DCE8) hw cursors are programmed the same as evergreen (DCE4) with the following caveats:
- cursors are now 128x128 pixels
- new alpha blend enable bit
v2: rebase
--- drivers/gpu/drm/radeon/cik_reg.h | 65 +++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon.h | 7 +++ drivers/gpu/drm/radeon/radeon_cursor.c | 10 ++--- drivers/gpu/drm/radeon/radeon_display.c | 16 +++++++- drivers/gpu/drm/radeon/radeon_mode.h | 2 + drivers/gpu/drm/radeon/radeon_reg.h | 1 + 6 files changed, 94 insertions(+), 7 deletions(-) create mode 100644 drivers/gpu/drm/radeon/cik_reg.h
drivers/gpu/drm/radeon/cik_reg.h new file +65 -0
@@ -0,0 +1,65 @@ +/* +* Copyright 2012 Advanced Micro Devices, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Authors: Alex Deucher +*/ +#ifndef __CIK_REG_H__ +#define __CIK_REG_H__ + +#define CIK_DC_GPIO_HPD_MASK 0x65b0 +#define CIK_DC_GPIO_HPD_A 0x65b4 +#define CIK_DC_GPIO_HPD_EN 0x65b8 +#define CIK_DC_GPIO_HPD_Y 0x65bc + +/* CUR blocks at 0x6998, 0x7598, 0x10198, 0x10d98, 0x11998, 0x12598 */ +#define CIK_CUR_CONTROL 0x6998 +# define CIK_CURSOR_EN (1 << 0) +# define CIK_CURSOR_MODE (x) (((x) & 0x3) << 8) +# define CIK_CURSOR_MONO 0 +# define CIK_CURSOR_24_1 1 +# define CIK_CURSOR_24_8_PRE_MULT 2 +# define CIK_CURSOR_24_8_UNPRE_MULT 3 +# define CIK_CURSOR_2X_MAGNIFY (1 << 16) +# define CIK_CURSOR_FORCE_MC_ON (1 << 20) +# define CIK_CURSOR_URGENT_CONTROL (x) (((x) & 0x7) << 24) +# define CIK_CURSOR_URGENT_ALWAYS 0 +# define CIK_CURSOR_URGENT_1_8 1 +# define CIK_CURSOR_URGENT_1_4 2 +# define CIK_CURSOR_URGENT_3_8 3 +# define CIK_CURSOR_URGENT_1_2 4 +#define CIK_CUR_SURFACE_ADDRESS 0x699c +# define CIK_CUR_SURFACE_ADDRESS_MASK 0xfffff000 +#define CIK_CUR_SIZE 0x69a0 +#define CIK_CUR_SURFACE_ADDRESS_HIGH 0x69a4 +#define CIK_CUR_POSITION 0x69a8 +#define CIK_CUR_HOT_SPOT 0x69ac +#define CIK_CUR_COLOR1 0x69b0 +#define CIK_CUR_COLOR2 0x69b4 +#define CIK_CUR_UPDATE 0x69b8 +# define CIK_CURSOR_UPDATE_PENDING (1 << 0) +# define CIK_CURSOR_UPDATE_TAKEN (1 << 1) +# define CIK_CURSOR_UPDATE_LOCK (1 << 16) +# define CIK_CURSOR_DISABLE_MULTIPLE_UPDATE (1 << 24) + +#define CIK_ALPHA_CONTROL 0x6af0 +# define CIK_CURSOR_ALPHA_BLND_ENA (1 << 1) + +#endif
drivers/gpu/drm/radeon/radeon.h +7 -0
@@ -150,6 +150,13 @@ extern int radeon_fastfb;#define RADEON_RESET_MC (1 << 10)#define RADEON_RESET_DISPLAY (1 << 11) +/* max cursor sizes (in pixels) */ +#define CURSOR_WIDTH 64 +#define CURSOR_HEIGHT 64 + +#define CIK_CURSOR_WIDTH 128 +#define CIK_CURSOR_HEIGHT 128 +/* * Errata workarounds. */
drivers/gpu/drm/radeon/radeon_cursor.c +4 -6
@@ -27,9 +27,6 @@#include <drm/radeon_drm.h> #include "radeon.h" -#define CURSOR_WIDTH 64 -#define CURSOR_HEIGHT 64 -static void radeon_lock_cursor (struct drm_crtc *crtc,bool lock) {struct radeon_device *rdev = crtc->dev->dev_private;
@@ -167,7 +164,8 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc, goto unpin; } -if ((width >CURSOR_WIDTH ) || (height >CURSOR_HEIGHT )) { +if ((width > radeon_crtc->max_cursor_width) || + (height > radeon_crtc->max_cursor_height)) {DRM_ERROR ("bad cursor width or height %d x %d\n" , width, height);return -EINVAL ; }
@@ -233,11 +231,11 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc,DRM_DEBUG ("x %d y %d c->x %d c->y %d\n" , x, y, crtc->x, crtc->y);if (x <0 ) { - xorigin =min (-x,CURSOR_WIDTH -1 ); + xorigin =min (-x, radeon_crtc->max_cursor_width -1 ); x =0 ; }if (y <0 ) { - yorigin =min (-y,CURSOR_HEIGHT -1 ); + yorigin =min (-y, radeon_crtc->max_cursor_height -1 ); y =0 ; }
drivers/gpu/drm/radeon/radeon_display.c +15 -1
@@ -153,7 +153,13 @@ static void dce5_crtc_load_lut(struct drm_crtc *crtc) NI_OUTPUT_CSC_OVL_MODE(NI_OUTPUT_CSC_BYPASS)));/* XXX match this to the depth of the crtc fmt block, move to modeset? */ WREG32 (0x6940 + radeon_crtc->crtc_offset,0 ); - +if (ASIC_IS_DCE8 (rdev)) { +/* XXX this only needs to be programmed once per crtc at startup, +* not sure where the best place for it is +*/ +WREG32 (CIK_ALPHA_CONTROL + radeon_crtc->crtc_offset, +CIK_CURSOR_ALPHA_BLND_ENA ); + } }static void legacy_crtc_load_lut (struct drm_crtc *crtc)
@@ -512,6 +518,14 @@ static void radeon_crtc_init(struct drm_device *dev, int index) radeon_crtc->crtc_id = index; rdev->mode_info.crtcs[index] = radeon_crtc; +if (rdev->family >=CHIP_BONAIRE ) { + radeon_crtc->max_cursor_width =CIK_CURSOR_WIDTH ; + radeon_crtc->max_cursor_height =CIK_CURSOR_HEIGHT ; + }else { + radeon_crtc->max_cursor_width =CURSOR_WIDTH ; + radeon_crtc->max_cursor_height =CURSOR_HEIGHT ; + } +#if 0 radeon_crtc->mode_set.crtc = &radeon_crtc->base; radeon_crtc->mode_set.connectors = (struct drm_connector **)(radeon_crtc +1 );
drivers/gpu/drm/radeon/radeon_mode.h +2 -0
@@ -307,6 +307,8 @@ struct radeon_crtc {uint64_t cursor_addr;int cursor_width;int cursor_height; +int max_cursor_width; +int max_cursor_height;uint32_t legacy_display_base_addr;uint32_t legacy_cursor_offset;enum radeon_rmx_type rmx_type;
drivers/gpu/drm/radeon/radeon_reg.h +1 -0
@@ -57,6 +57,7 @@#include "evergreen_reg.h" #include "ni_reg.h" #include "si_reg.h" +#include "cik_reg.h" #define RADEON_MC_AGP_LOCATION 0x014c#define RADEON_MC_AGP_START_MASK 0x0000FFFF
Signature · 1 line
1.7.7.5
PATCH 31/165 drm/radeon/dce8: properly handle interlaced timing
In reply to [email protected]From: Alex Deucher <[email protected]>
The register bits changed on DCE8 compared to previous families.
--- drivers/gpu/drm/radeon/atombios_encoders.c | 8 +++++++- drivers/gpu/drm/radeon/cik_reg.h | 3 +++ 2 files changed, 10 insertions(+), 1 deletions(-)
drivers/gpu/drm/radeon/atombios_encoders.c +7 -1
@@ -1962,7 +1962,13 @@ atombios_apply_encoder_quirks(struct drm_encoder *encoder,/* set scaler clears this on some chips */ if (ASIC_IS_AVIVO (rdev) && (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT )))) { -if (ASIC_IS_DCE4 (rdev)) { +if (ASIC_IS_DCE8 (rdev)) { +if (mode->flags &DRM_MODE_FLAG_INTERLACE ) +WREG32 (CIK_LB_DATA_FORMAT + radeon_crtc->crtc_offset, +CIK_INTERLEAVE_EN ); +else +WREG32 (CIK_LB_DATA_FORMAT + radeon_crtc->crtc_offset,0 ); + }else if (ASIC_IS_DCE4 (rdev)) {if (mode->flags &DRM_MODE_FLAG_INTERLACE )WREG32 (EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset,EVERGREEN_INTERLEAVE_EN );
drivers/gpu/drm/radeon/cik_reg.h +3 -0
@@ -62,4 +62,7 @@#define CIK_ALPHA_CONTROL 0x6af0# define CIK_CURSOR_ALPHA_BLND_ENA (1 << 1) +#define CIK_LB_DATA_FORMAT 0x6b00 +# define CIK_INTERLEAVE_EN (1 << 3) +#endif
Signature · 1 line
1.7.7.5
PATCH 32/165 drm/radeon/dce8: crtc_set_base updates
In reply to [email protected]From: Alex Deucher <[email protected]>
Some new fields and DESKTOP_HEIGHT register moved.
--- drivers/gpu/drm/radeon/atombios_crtc.c | 34 ++++++++++++-- drivers/gpu/drm/radeon/cik_reg.h | 79 ++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 5 deletions(-)
drivers/gpu/drm/radeon/atombios_crtc.c +29 -5
@@ -1143,7 +1143,9 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, }if (tiling_flags &RADEON_TILING_MACRO ) { -if (rdev->family >=CHIP_TAHITI ) +if (rdev->family >=CHIP_BONAIRE ) + tmp = rdev->config.cik.tile_config; +else if (rdev->family >=CHIP_TAHITI ) tmp = rdev->config.si.tile_config;else if (rdev->family >=CHIP_CAYMAN ) tmp = rdev->config.cayman.tile_config;
@@ -1170,11 +1172,29 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, fb_format |=EVERGREEN_GRPH_BANK_WIDTH (bankw); fb_format |=EVERGREEN_GRPH_BANK_HEIGHT (bankh); fb_format |=EVERGREEN_GRPH_MACRO_TILE_ASPECT (mtaspect); +if (rdev->family >=CHIP_BONAIRE ) { +/* XXX need to know more about the surface tiling mode */ + fb_format |=CIK_GRPH_MICRO_TILE_MODE (CIK_DISPLAY_MICRO_TILING ); + } }else if (tiling_flags &RADEON_TILING_MICRO ) fb_format |=EVERGREEN_GRPH_ARRAY_MODE (EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1 ); -if ((rdev->family ==CHIP_TAHITI ) || - (rdev->family ==CHIP_PITCAIRN )) +if (rdev->family >=CHIP_BONAIRE ) { +u32 num_pipe_configs = rdev->config.cik.max_tile_pipes; +u32 num_rb = rdev->config.cik.max_backends_per_se; +if (num_pipe_configs >8 ) + num_pipe_configs =8 ; +if (num_pipe_configs ==8 ) + fb_format |=CIK_GRPH_PIPE_CONFIG (CIK_ADDR_SURF_P8_32x32_16x16); +else if (num_pipe_configs ==4 ) { +if (num_rb ==4 ) + fb_format |=CIK_GRPH_PIPE_CONFIG (CIK_ADDR_SURF_P4_16x16); +else if (num_rb <4 ) + fb_format |=CIK_GRPH_PIPE_CONFIG (CIK_ADDR_SURF_P4_8x16); + }else if (num_pipe_configs ==2 ) + fb_format |=CIK_GRPH_PIPE_CONFIG (CIK_ADDR_SURF_P2 ); + }else if ((rdev->family ==CHIP_TAHITI ) || + (rdev->family ==CHIP_PITCAIRN )) fb_format |=SI_GRPH_PIPE_CONFIG (SI_ADDR_SURF_P8_32x32_8x16);else if (rdev->family ==CHIP_VERDE ) fb_format |=SI_GRPH_PIPE_CONFIG (SI_ADDR_SURF_P4_8x16);
@@ -1224,8 +1244,12 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,WREG32 (EVERGREEN_GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels);WREG32 (EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset,1 ); -WREG32 (EVERGREEN_DESKTOP_HEIGHT + radeon_crtc->crtc_offset, - target_fb->height); +if (rdev->family >=CHIP_BONAIRE ) +WREG32 (CIK_LB_DESKTOP_HEIGHT + radeon_crtc->crtc_offset, + target_fb->height); +else +WREG32 (EVERGREEN_DESKTOP_HEIGHT + radeon_crtc->crtc_offset, + target_fb->height); x &= ~3 ; y &= ~1 ; WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset,
drivers/gpu/drm/radeon/cik_reg.h +79 -0
89 lines not on this page · raw message
Signature · 1 line
1.7.7.5
PATCH 33/165 drm/radeon/atom: add DCE8 encoder support
In reply to [email protected]From: Alex Deucher <[email protected]>
--- drivers/gpu/drm/radeon/atombios_encoders.c | 27 ++++++++++++++++++++++++--- drivers/gpu/drm/radeon/radeon_display.c | 5 +++-- 2 files changed, 27 insertions(+), 5 deletions(-)
drivers/gpu/drm/radeon/atombios_encoders.c +24 -3
@@ -303,6 +303,7 @@ static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder)case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA :case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 :case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 : +case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 :return true;default :return false;
@@ -922,10 +923,14 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo args.v4.ucLaneNum =4 ;if (ENCODER_MODE_IS_DP (args.v4.ucEncoderMode)) { -if (dp_clock ==270000 ) - args.v1.ucConfig |=ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ ; -else if (dp_clock ==540000 ) +if (dp_clock ==540000 ) args.v1.ucConfig |=ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ ; +else if (dp_clock ==324000 ) + args.v1.ucConfig |=ATOM_ENCODER_CONFIG_V4_DPLINKRATE_3_24GHZ ; +else if (dp_clock ==270000 ) + args.v1.ucConfig |=ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ ; +else + args.v1.ucConfig |=ATOM_ENCODER_CONFIG_V4_DPLINKRATE_1_62GHZ ; } args.v4.acConfig.ucDigSel = dig->dig_encoder; args.v4.ucBitPerColor =radeon_atom_get_bpc (encoder);
@@ -1019,6 +1024,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_tcase ENCODER_OBJECT_ID_INTERNAL_UNIPHY :case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 :case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 : +case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 : index =GetIndexIntoMasterTable (COMMAND , UNIPHYTransmitterControl);break ;case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA :
@@ -1278,6 +1284,9 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_telse args.v5.ucPhyId =ATOM_PHY_ID_UNIPHYE ;break ; +case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 : + args.v5.ucPhyId =ATOM_PHY_ID_UNIPHYG ; +break ; }if (is_dp) args.v5.ucLaneNum = dp_lane_count;
@@ -1742,6 +1751,7 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)case ENCODER_OBJECT_ID_INTERNAL_UNIPHY :case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 :case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 : +case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 :case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA :radeon_atom_encoder_dpms_dig (encoder, mode);break ;
@@ -1879,6 +1889,7 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)case ENCODER_OBJECT_ID_INTERNAL_UNIPHY :case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 :case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 : +case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 :case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA : dig = radeon_encoder->enc_priv;switch (dig->dig_encoder) {
@@ -1900,6 +1911,9 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)case 5 : args.v2.ucEncoderID =ASIC_INT_DIG6_ENCODER_ID ;break ; +case 6 : + args.v2.ucEncoderID =ASIC_INT_DIG7_ENCODER_ID ; +break ; }break ;case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 :
@@ -2015,6 +2029,9 @@ static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)else return 4 ;break ; +case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 : +return 6 ; +break ; } }else if (ASIC_IS_DCE4 (rdev)) {/* DCE4/5 */
@@ -2099,6 +2116,7 @@ radeon_atom_encoder_init(struct radeon_device *rdev)case ENCODER_OBJECT_ID_INTERNAL_UNIPHY :case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 :case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 : +case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 :case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA :atombios_dig_transmitter_setup (encoder,ATOM_TRANSMITTER_ACTION_INIT ,0 ,0 );break ;
@@ -2143,6 +2161,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,case ENCODER_OBJECT_ID_INTERNAL_UNIPHY :case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 :case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 : +case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 :case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA :/* handled in dpms */ break ;
@@ -2408,6 +2427,7 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder)case ENCODER_OBJECT_ID_INTERNAL_UNIPHY :case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 :case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 : +case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 :case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA :/* handled in dpms */ break ;
@@ -2639,6 +2659,7 @@ radeon_add_atom_encoder(struct drm_device *dev,case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA :case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 :case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 : +case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 :if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT )) { radeon_encoder->rmx_type =RMX_FULL ;drm_encoder_init (dev, encoder, &radeon_atom_enc_funcs,DRM_MODE_ENCODER_LVDS );
drivers/gpu/drm/radeon/radeon_display.c +3 -2
@@ -544,7 +544,7 @@ static void radeon_crtc_init(struct drm_device *dev, int index)radeon_legacy_init_crtc (dev, radeon_crtc); } -static const char *encoder_names[37 ] = { +static const char *encoder_names[38 ] = {"NONE" ,"INTERNAL_LVDS" ,"INTERNAL_TMDS1" ,
@@ -581,7 +581,8 @@ static const char *encoder_names[37] = {"INTERNAL_UNIPHY2" ,"NUTMEG" ,"TRAVIS" , -"INTERNAL_VCE" +"INTERNAL_VCE" , + "INTERNAL_UNIPHY3", }; static const char *hpd_names[6] = {
Signature · 1 line
1.7.7.5
PATCH 34/165 drm/radeon/atom: add support for new DVO tables
In reply to [email protected]From: Alex Deucher <[email protected]>
--- drivers/gpu/drm/radeon/atombios_encoders.c | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-)
drivers/gpu/drm/radeon/atombios_encoders.c +8 -1
@@ -487,11 +487,11 @@ static u8 radeon_atom_get_bpc(struct drm_encoder *encoder) } } -union dvo_encoder_control {ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds;DVO_ENCODER_CONTROL_PS_ALLOCATION dvo;DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3; +DVO_ENCODER_CONTROL_PS_ALLOCATION_V1_4 dvo_v4; };void
@@ -541,6 +541,13 @@ atombios_dvo_setup(struct drm_encoder *encoder, int action) args.dvo_v3.usPixelClock =cpu_to_le16 (radeon_encoder->pixel_clock /10 ); args.dvo_v3.ucDVOConfig =0 ;/* XXX */ break ; +case 4 : +/* DCE8 */ + args.dvo_v4.ucAction = action; + args.dvo_v4.usPixelClock =cpu_to_le16 (radeon_encoder->pixel_clock /10 ); + args.dvo_v4.ucDVOConfig =0 ;/* XXX */ + args.dvo_v4.ucBitPerColor =radeon_atom_get_bpc (encoder); +break ;default :DRM_ERROR ("Unknown table version %d, %d\n" , frev, crev);break ;
Signature · 1 line
1.7.7.5
PATCH 35/165 drm/radeon: update DISPCLK programming for DCE8
In reply to [email protected]From: Alex Deucher <[email protected]>
--- drivers/gpu/drm/radeon/atombios_crtc.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/gpu/drm/radeon/atombios_crtc.c +1 -1
@@ -743,7 +743,7 @@ static void atombios_crtc_set_disp_eng_pll(struct radeon_device *rdev,* SetPixelClock provides the dividers */ args.v6.ulDispEngClkFreq =cpu_to_le32 (dispclk); -if (ASIC_IS_DCE61 (rdev)) +if (ASIC_IS_DCE61 (rdev) ||ASIC_IS_DCE8 (rdev)) args.v6.ucPpll =ATOM_EXT_PLL1 ;else if (ASIC_IS_DCE6 (rdev)) args.v6.ucPpll =ATOM_PPLL0 ;
Signature · 1 line
1.7.7.5
PATCH 36/165 drm/radeon: add support pll selection for DCE8 (v4)
In reply to [email protected]From: Alex Deucher <[email protected]>
v2: make PPLL0 is available for non-DP on CI
v3: rebase changes, update documentation
v4: fix kabini
--- drivers/gpu/drm/radeon/atombios_crtc.c | 48 +++++++++++++++++++++++++++++++- 1 files changed, 47 insertions(+), 1 deletions(-)
drivers/gpu/drm/radeon/atombios_crtc.c +47 -1
@@ -1621,6 +1621,12 @@ static int radeon_get_shared_nondp_ppll(struct drm_crtc *crtc)* * Asic specific PLL information * +* DCE 8.x +* KB/KV +* - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) +* CI +* - PPLL0, PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC +* * DCE 6.1 * - PPLL2 is only available to UNIPHYA (both DP and non-DP) * - PPLL0, PPLL1 are available for UNIPHYB/C/D/E/F (both DP and non-DP)
@@ -1647,7 +1653,47 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)u32 pll_in_use;int pll; -if (ASIC_IS_DCE61 (rdev)) { +if (ASIC_IS_DCE8 (rdev)) { +if (ENCODER_MODE_IS_DP (atombios_get_encoder_mode (radeon_crtc->encoder))) { +if (rdev->clock.dp_extclk) +/* skip PPLL programming if using ext clock */ +return ATOM_PPLL_INVALID ; +else { +/* use the same PPLL for all DP monitors */ + pll =radeon_get_shared_dp_ppll (crtc); +if (pll !=ATOM_PPLL_INVALID ) +return pll; + } + }else { +/* use the same PPLL for all monitors with the same clock */ + pll =radeon_get_shared_nondp_ppll (crtc); +if (pll !=ATOM_PPLL_INVALID ) +return pll; + } +/* otherwise, pick one of the plls */ +if ((rdev->family ==CHIP_KAVERI ) || + (rdev->family ==CHIP_KABINI )) { +/* KB/KV has PPLL1 and PPLL2 */ + pll_in_use =radeon_get_pll_use_mask (crtc); +if (!(pll_in_use & (1 <<ATOM_PPLL2 ))) +return ATOM_PPLL2 ; +if (!(pll_in_use & (1 <<ATOM_PPLL1 ))) +return ATOM_PPLL1 ; +DRM_ERROR ("unable to allocate a PPLL\n" ); +return ATOM_PPLL_INVALID ; + }else { +/* CI has PPLL0, PPLL1, and PPLL2 */ + pll_in_use =radeon_get_pll_use_mask (crtc); +if (!(pll_in_use & (1 <<ATOM_PPLL2 ))) +return ATOM_PPLL2 ; +if (!(pll_in_use & (1 <<ATOM_PPLL1 ))) +return ATOM_PPLL1 ; +if (!(pll_in_use & (1 <<ATOM_PPLL0 ))) +return ATOM_PPLL0 ; +DRM_ERROR ("unable to allocate a PPLL\n" ); +return ATOM_PPLL_INVALID ; + } + }else if (ASIC_IS_DCE61 (rdev)) {struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
Signature · 1 line
1.7.7.5
PATCH 37/165 drm/radeon: Handle PPLL0 powerdown on DCE8
In reply to [email protected]From: Alex Deucher <[email protected]>
Only Bonaire has PPLL0.
--- drivers/gpu/drm/radeon/atombios_crtc.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/gpu/drm/radeon/atombios_crtc.c +1 -1
@@ -1931,7 +1931,7 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)break ;case ATOM_PPLL0 :/* disable the ppll */ -if (ASIC_IS_DCE61 (rdev)) +if ((rdev->family ==CHIP_ARUBA ) || (rdev->family ==CHIP_BONAIRE ))atombios_crtc_program_pll (crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,0 ,0 ,ATOM_DISABLE ,0 ,0 ,0 ,0 ,0 , false, &ss);break ;
Signature · 1 line
1.7.7.5
PATCH 38/165 drm/radeon: use frac fb div on DCE8
In reply to [email protected]From: Alex Deucher <[email protected]>
--- drivers/gpu/drm/radeon/atombios_crtc.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/gpu/drm/radeon/atombios_crtc.c +1 -1
@@ -555,7 +555,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,if (rdev->family <CHIP_RV770 ) radeon_crtc->pll_flags |=RADEON_PLL_PREFER_MINM_OVER_MAXP ;/* use frac fb div on APUs */ -if (ASIC_IS_DCE41 (rdev) ||ASIC_IS_DCE61 (rdev)) +if (ASIC_IS_DCE41 (rdev) ||ASIC_IS_DCE61 (rdev) ||ASIC_IS_DCE8 (rdev)) radeon_crtc->pll_flags |=RADEON_PLL_USE_FRAC_FB_DIV ;/* use frac fb div on RS780/RS880 */ if ((rdev->family ==CHIP_RS780 ) || (rdev->family ==CHIP_RS880 ))
Signature · 1 line
1.7.7.5
PATCH 39/165 drm/radeon: add SS override support for KB/KV
In reply to [email protected]From: Alex Deucher <[email protected]>
--- drivers/gpu/drm/radeon/radeon_atombios.c | 17 +++++++++++++++++ 1 files changed, 17 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/radeon_atombios.c +17 -0
@@ -1269,6 +1269,7 @@ union igp_info {struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6;struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7; +struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_8 info_8; };bool radeon_atombios_sideport_present (struct radeon_device *rdev)
@@ -1438,6 +1439,22 @@ static void radeon_atombios_get_igp_ss_overrides(struct radeon_device *rdev,break ; }break ; +case 8 : +switch (id) { +case ASIC_INTERNAL_SS_ON_TMDS : + percentage =le16_to_cpu (igp_info->info_8.usDVISSPercentage); + rate =le16_to_cpu (igp_info->info_8.usDVISSpreadRateIn10Hz); +break ; +case ASIC_INTERNAL_SS_ON_HDMI : + percentage =le16_to_cpu (igp_info->info_8.usHDMISSPercentage); + rate =le16_to_cpu (igp_info->info_8.usHDMISSpreadRateIn10Hz); +break ; +case ASIC_INTERNAL_SS_ON_LVDS : + percentage =le16_to_cpu (igp_info->info_8.usLvdsSSPercentage); + rate =le16_to_cpu (igp_info->info_8.usLvdsSSpreadRateIn10Hz); +break ; + } +break ;default :DRM_ERROR ("Unsupported IGP table: %d %d\n" , frev, crev);break ;
Signature · 1 line
1.7.7.5
PATCH 40/165 drm/radeon: Update radeon_info_ioctl for CIK (v2)
In reply to [email protected]From: Alex Deucher <[email protected]>
v2: rebase changes, fix a couple missed cases
--- drivers/gpu/drm/radeon/radeon_kms.c | 33 ++++++++++++++++++++++++++------- 1 files changed, 26 insertions(+), 7 deletions(-)
drivers/gpu/drm/radeon/radeon_kms.c +26 -7
@@ -229,7 +229,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) *value = rdev->accel_working;break ;case RADEON_INFO_TILING_CONFIG : -if (rdev->family >=CHIP_TAHITI ) +if (rdev->family >=CHIP_BONAIRE ) + *value = rdev->config.cik.tile_config; +else if (rdev->family >=CHIP_TAHITI ) *value = rdev->config.si.tile_config;else if (rdev->family >=CHIP_CAYMAN ) *value = rdev->config.cayman.tile_config;
@@ -281,7 +283,10 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) *value = rdev->clock.spll.reference_freq *10 ;break ;case RADEON_INFO_NUM_BACKENDS : -if (rdev->family >=CHIP_TAHITI ) +if (rdev->family >=CHIP_BONAIRE ) + *value = rdev->config.cik.max_backends_per_se * + rdev->config.cik.max_shader_engines; +else if (rdev->family >=CHIP_TAHITI ) *value = rdev->config.si.max_backends_per_se * rdev->config.si.max_shader_engines;else if (rdev->family >=CHIP_CAYMAN )
@@ -298,7 +303,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) }break ;case RADEON_INFO_NUM_TILE_PIPES : -if (rdev->family >=CHIP_TAHITI ) +if (rdev->family >=CHIP_BONAIRE ) + *value = rdev->config.cik.max_tile_pipes; +else if (rdev->family >=CHIP_TAHITI ) *value = rdev->config.si.max_tile_pipes;else if (rdev->family >=CHIP_CAYMAN ) *value = rdev->config.cayman.max_tile_pipes;
@@ -316,7 +323,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) *value =1 ;break ;case RADEON_INFO_BACKEND_MAP : -if (rdev->family >=CHIP_TAHITI ) +if (rdev->family >=CHIP_BONAIRE ) +return -EINVAL ; +else if (rdev->family >=CHIP_TAHITI ) *value = rdev->config.si.backend_map;else if (rdev->family >=CHIP_CAYMAN ) *value = rdev->config.cayman.backend_map;
@@ -343,7 +352,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) *value =RADEON_IB_VM_MAX_SIZE ;break ;case RADEON_INFO_MAX_PIPES : -if (rdev->family >=CHIP_TAHITI ) +if (rdev->family >=CHIP_BONAIRE ) + *value = rdev->config.cik.max_cu_per_sh; +else if (rdev->family >=CHIP_TAHITI ) *value = rdev->config.si.max_cu_per_sh;else if (rdev->family >=CHIP_CAYMAN ) *value = rdev->config.cayman.max_pipes_per_simd;
@@ -367,7 +378,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) value64 =radeon_get_gpu_clock_counter (rdev);break ;case RADEON_INFO_MAX_SE : -if (rdev->family >=CHIP_TAHITI ) +if (rdev->family >=CHIP_BONAIRE ) + *value = rdev->config.cik.max_shader_engines; +else if (rdev->family >=CHIP_TAHITI ) *value = rdev->config.si.max_shader_engines;else if (rdev->family >=CHIP_CAYMAN ) *value = rdev->config.cayman.max_shader_engines;
@@ -377,7 +390,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) *value =1 ;break ;case RADEON_INFO_MAX_SH_PER_SE : -if (rdev->family >=CHIP_TAHITI ) +if (rdev->family >=CHIP_BONAIRE ) + *value = rdev->config.cik.max_sh_per_se; +else if (rdev->family >=CHIP_TAHITI ) *value = rdev->config.si.max_sh_per_se;else return -EINVAL ;
@@ -407,6 +422,10 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) }break ;case RADEON_INFO_SI_TILE_MODE_ARRAY : +if (rdev->family >=CHIP_BONAIRE ) { +DRM_DEBUG_KMS ("tile mode array is not implemented yet\n" ); +return -EINVAL ; + }if (rdev->family <CHIP_TAHITI ) {DRM_DEBUG_KMS ("tile mode array is si only!\n" );return -EINVAL ;
Signature · 1 line
1.7.7.5
PATCH 41/165 drm/radeon: add get_gpu_clock_counter() callback for cik
In reply to [email protected]From: Alex Deucher <[email protected]>
Used for GPU clock counter snapshots.
--- drivers/gpu/drm/radeon/cik.c | 21 +++++++++++++++++++++ drivers/gpu/drm/radeon/cikd.h | 4 +++- drivers/gpu/drm/radeon/radeon_asic.h | 5 +++++ 3 files changed, 29 insertions(+), 1 deletions(-)
drivers/gpu/drm/radeon/cik.c +21 -0
@@ -5558,3 +5558,24 @@ void dce8_bandwidth_update(struct radeon_device *rdev)dce8_program_watermarks (rdev, rdev->mode_info.crtcs[i], lb_size, num_heads); } } + +/** +* cik_get_gpu_clock_counter - return GPU clock counter snapshot +* +* @rdev: radeon_device pointer +* +* Fetches a GPU clock counter snapshot (SI). +* Returns the 64 bit clock counter snapshot. +*/ +uint64_t cik_get_gpu_clock_counter (struct radeon_device *rdev) +{ +uint64_t clock; + +mutex_lock (&rdev->gpu_clock_mutex); +WREG32 (RLC_CAPTURE_GPU_CLOCK_COUNT ,1 ); + clock = (uint64_t )RREG32 (RLC_GPU_CLOCK_COUNT_LSB ) | + ((uint64_t )RREG32 (RLC_GPU_CLOCK_COUNT_MSB ) <<32ULL ); +mutex_unlock (&rdev->gpu_clock_mutex); +return clock; +} +
drivers/gpu/drm/radeon/cikd.h +3 -1
@@ -730,7 +730,9 @@#define RLC_GPM_UCODE_ADDR 0xC388#define RLC_GPM_UCODE_DATA 0xC38C - +#define RLC_GPU_CLOCK_COUNT_LSB 0xC390 +#define RLC_GPU_CLOCK_COUNT_MSB 0xC394 +#define RLC_CAPTURE_GPU_CLOCK_COUNT 0xC398#define RLC_UCODE_CNTL 0xC39C#define RLC_CGCG_CGLS_CTRL 0xC424
drivers/gpu/drm/radeon/radeon_asic.h +5 -0
@@ -553,4 +553,9 @@ u32 si_get_xclk(struct radeon_device *rdev);uint64_t si_get_gpu_clock_counter (struct radeon_device *rdev);int si_set_uvd_clocks (struct radeon_device *rdev,u32 vclk,u32 dclk); +/* +* cik +*/ +uint64_t cik_get_gpu_clock_counter (struct radeon_device *rdev); +#endif
Signature · 1 line
1.7.7.5
PATCH 42/165 drm/radeon: update CIK soft reset
In reply to [email protected]From: Alex Deucher <[email protected]>
Update to the newer programming model.
--- drivers/gpu/drm/radeon/cik.c | 387 +++++++++++++++++++++++++---------------- drivers/gpu/drm/radeon/cikd.h | 12 ++ 2 files changed, 253 insertions(+), 146 deletions(-)
drivers/gpu/drm/radeon/cik.c +241 -146
@@ -72,9 +72,11 @@ extern int r600_ih_ring_alloc(struct radeon_device *rdev);extern void r600_ih_ring_fini (struct radeon_device *rdev);extern void evergreen_mc_stop (struct radeon_device *rdev,struct evergreen_mc_save *save);extern void evergreen_mc_resume (struct radeon_device *rdev,struct evergreen_mc_save *save); +extern bool evergreen_is_display_hung (struct radeon_device *rdev);extern void si_vram_gtt_location (struct radeon_device *rdev,struct radeon_mc *mc);extern void si_rlc_fini (struct radeon_device *rdev);extern int si_rlc_init (struct radeon_device *rdev); +static void cik_rlc_stop (struct radeon_device *rdev);#define BONAIRE_IO_MC_REGS_SIZE 36
@@ -2733,56 +2735,9 @@ int cik_sdma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)return r; } -/** -* cik_gpu_is_lockup - check if the 3D engine is locked up -* -* @rdev: radeon_device pointer -* @ring: radeon_ring structure holding ring information -* -* Check if the 3D engine is locked up (CIK). -* Returns true if the engine is locked, false if not. -*/ -bool cik_gpu_is_lockup (struct radeon_device *rdev,struct radeon_ring *ring) -{ -u32 srbm_status, srbm_status2; -u32 grbm_status, grbm_status2; -u32 grbm_status_se0, grbm_status_se1, grbm_status_se2, grbm_status_se3; - - srbm_status =RREG32 (SRBM_STATUS ); - srbm_status2 =RREG32 (SRBM_STATUS2 ); - grbm_status =RREG32 (GRBM_STATUS ); - grbm_status2 =RREG32 (GRBM_STATUS2 ); - grbm_status_se0 =RREG32 (GRBM_STATUS_SE0 ); - grbm_status_se1 =RREG32 (GRBM_STATUS_SE1 ); - grbm_status_se2 =RREG32 (GRBM_STATUS_SE2 ); - grbm_status_se3 =RREG32 (GRBM_STATUS_SE3 ); -if (!(grbm_status &GUI_ACTIVE )) { -radeon_ring_lockup_update (ring); -return false; - } -/* force CP activities */ -radeon_ring_force_activity (rdev, ring); -return radeon_ring_test_lockup (rdev, ring); -} -/** -* cik_gfx_gpu_soft_reset - soft reset the 3D engine and CPG -* -* @rdev: radeon_device pointer -* -* Soft reset the GFX engine and CPG blocks (CIK). -* XXX: deal with reseting RLC and CPF -* Returns 0 for success. -*/ -static int cik_gfx_gpu_soft_reset (struct radeon_device *rdev) +static void cik_print_gpu_status_regs (struct radeon_device *rdev) { -struct evergreen_mc_save save; -u32 grbm_reset =0 ; - -if (!(RREG32 (GRBM_STATUS ) &GUI_ACTIVE )) -return 0 ; - -dev_info (rdev->dev,"GPU GFX softreset \n" );dev_info (rdev->dev," GRBM_STATUS=0x%08X\n" ,RREG32 (GRBM_STATUS )); dev_info(rdev->dev, " GRBM_STATUS2=0x%08X\n",
@@ -2799,132 +2754,270 @@ static int cik_gfx_gpu_soft_reset(struct radeon_device *rdev) RREG32(SRBM_STATUS));dev_info (rdev->dev," SRBM_STATUS2=0x%08X\n" ,RREG32 (SRBM_STATUS2 )); -evergreen_mc_stop (rdev, &save); -if (radeon_mc_wait_for_idle (rdev)) { -dev_warn (rdev->dev,"Wait for MC idle timedout !\n" ); - } -/* Disable CP parsing/prefetching */ -WREG32 (CP_ME_CNTL ,CP_ME_HALT |CP_PFP_HALT |CP_CE_HALT ); +dev_info (rdev->dev," SDMA0_STATUS_REG = 0x%08X\n" , +RREG32 (SDMA0_STATUS_REG +SDMA0_REGISTER_OFFSET )); +dev_info (rdev->dev," SDMA1_STATUS_REG = 0x%08X\n" , +RREG32 (SDMA0_STATUS_REG +SDMA1_REGISTER_OFFSET )); +} -/* reset all the gfx block and all CPG blocks */ - grbm_reset =SOFT_RESET_CPG |SOFT_RESET_GFX ; +/** +* cik_gpu_check_soft_reset - check which blocks are busy +* +* @rdev: radeon_device pointer +* +* Check which blocks are busy and return the relevant reset +* mask to be used by cik_gpu_soft_reset(). +* Returns a mask of the blocks to be reset. +*/ +static u32 cik_gpu_check_soft_reset (struct radeon_device *rdev) +{ +u32 reset_mask =0 ; +u32 tmp; -dev_info (rdev->dev," GRBM_SOFT_RESET=0x%08X\n" , grbm_reset); -WREG32 (GRBM_SOFT_RESET , grbm_reset); - (void )RREG32 (GRBM_SOFT_RESET ); -udelay (50 ); -WREG32 (GRBM_SOFT_RESET ,0 ); - (void )RREG32 (GRBM_SOFT_RESET ); -/* Wait a little for things to settle down */ -udelay (50 ); -dev_info (rdev->dev," GRBM_STATUS=0x%08X\n" , -RREG32 (GRBM_STATUS )); -dev_info (rdev->dev," GRBM_STATUS2=0x%08X\n" , -RREG32 (GRBM_STATUS2 )); -dev_info (rdev->dev," GRBM_STATUS_SE0=0x%08X\n" , -RREG32 (GRBM_STATUS_SE0 )); -dev_info (rdev->dev," GRBM_STATUS_SE1=0x%08X\n" , -RREG32 (GRBM_STATUS_SE1 )); -dev_info (rdev->dev," GRBM_STATUS_SE2=0x%08X\n" , -RREG32 (GRBM_STATUS_SE2 )); -dev_info (rdev->dev," GRBM_STATUS_SE3=0x%08X\n" , -RREG32 (GRBM_STATUS_SE3 )); -dev_info (rdev->dev," SRBM_STATUS=0x%08X\n" , -RREG32 (SRBM_STATUS )); -dev_info (rdev->dev," SRBM_STATUS2=0x%08X\n" , -RREG32 (SRBM_STATUS2 )); -evergreen_mc_resume (rdev, &save); -return 0 ; +/* GRBM_STATUS */ + tmp =RREG32 (GRBM_STATUS ); +if (tmp & (PA_BUSY |SC_BUSY | +BCI_BUSY |SX_BUSY | +TA_BUSY |VGT_BUSY | +DB_BUSY |CB_BUSY | +GDS_BUSY |SPI_BUSY | +IA_BUSY |IA_BUSY_NO_DMA )) + reset_mask |=RADEON_RESET_GFX ; + +if (tmp & (CP_BUSY |CP_COHERENCY_BUSY )) + reset_mask |=RADEON_RESET_CP ; + +/* GRBM_STATUS2 */ + tmp =RREG32 (GRBM_STATUS2 ); +if (tmp &RLC_BUSY ) + reset_mask |=RADEON_RESET_RLC ; + +/* SDMA0_STATUS_REG */ + tmp =RREG32 (SDMA0_STATUS_REG +SDMA0_REGISTER_OFFSET ); +if (!(tmp &SDMA_IDLE )) + reset_mask |=RADEON_RESET_DMA ; + +/* SDMA1_STATUS_REG */ + tmp =RREG32 (SDMA0_STATUS_REG +SDMA1_REGISTER_OFFSET ); +if (!(tmp &SDMA_IDLE )) + reset_mask |=RADEON_RESET_DMA1 ; + +/* SRBM_STATUS2 */ + tmp =RREG32 (SRBM_STATUS2 ); +if (tmp &SDMA_BUSY ) + reset_mask |=RADEON_RESET_DMA ; + +if (tmp &SDMA1_BUSY ) + reset_mask |=RADEON_RESET_DMA1 ; + +/* SRBM_STATUS */ + tmp =RREG32 (SRBM_STATUS ); + +if (tmp &IH_BUSY ) + reset_mask |=RADEON_RESET_IH ; + +if (tmp &SEM_BUSY ) + reset_mask |=RADEON_RESET_SEM ; + +if (tmp &GRBM_RQ_PENDING ) + reset_mask |=RADEON_RESET_GRBM ; + +if (tmp &VMC_BUSY ) + reset_mask |=RADEON_RESET_VMC ; + +if (tmp & (MCB_BUSY |MCB_NON_DISPLAY_BUSY | +MCC_BUSY |MCD_BUSY )) + reset_mask |=RADEON_RESET_MC ; + +if (evergreen_is_display_hung (rdev)) + reset_mask |=RADEON_RESET_DISPLAY ; + +/* Skip MC reset as it's mostly likely not hung, just busy */ +if (reset_mask &RADEON_RESET_MC ) { +DRM_DEBUG ("MC busy: 0x%08X, clearing.\n" , reset_mask); + reset_mask &= ~RADEON_RESET_MC ; + } + +return reset_mask; }/** -* cik_compute_gpu_soft_reset - soft reset CPC +* cik_gpu_soft_reset - soft reset GPU * * @rdev: radeon_device pointer +* @reset_mask: mask of which blocks to reset * -* Soft reset the CPC blocks (CIK). -* XXX: deal with reseting RLC and CPF -* Returns 0 for success. +* Soft reset the blocks specified in @reset_mask. */ -static int cik_compute_gpu_soft_reset (struct radeon_device *rdev) +static void cik_gpu_soft_reset (struct radeon_device *rdev,u32 reset_mask) {struct evergreen_mc_save save; -u32 grbm_reset =0 ; +u32 grbm_soft_reset =0 , srbm_soft_reset =0 ; +u32 tmp; + +if (reset_mask ==0 ) +return ; + +dev_info (rdev->dev,"GPU softreset: 0x%08X\n" , reset_mask); + +cik_print_gpu_status_regs (rdev); +dev_info (rdev->dev," VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n" , +RREG32 (VM_CONTEXT1_PROTECTION_FAULT_ADDR )); +dev_info (rdev->dev," VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n" , +RREG32 (VM_CONTEXT1_PROTECTION_FAULT_STATUS )); + +/* stop the rlc */ +cik_rlc_stop (rdev); + +/* Disable GFX parsing/prefetching */ +WREG32 (CP_ME_CNTL ,CP_ME_HALT |CP_PFP_HALT |CP_CE_HALT ); + +/* Disable MEC parsing/prefetching */ +WREG32 (CP_MEC_CNTL ,MEC_ME1_HALT |MEC_ME2_HALT ); + +if (reset_mask &RADEON_RESET_DMA ) { +/* sdma0 */ + tmp =RREG32 (SDMA0_ME_CNTL +SDMA0_REGISTER_OFFSET ); + tmp |=SDMA_HALT ; +WREG32 (SDMA0_ME_CNTL +SDMA0_REGISTER_OFFSET , tmp); + } +if (reset_mask &RADEON_RESET_DMA1 ) { +/* sdma1 */ + tmp =RREG32 (SDMA0_ME_CNTL +SDMA1_REGISTER_OFFSET ); + tmp |=SDMA_HALT ; +WREG32 (SDMA0_ME_CNTL +SDMA1_REGISTER_OFFSET , tmp); + } -dev_info (rdev->dev,"GPU compute softreset \n" ); -dev_info (rdev->dev," GRBM_STATUS=0x%08X\n" , -RREG32 (GRBM_STATUS )); -dev_info (rdev->dev," GRBM_STATUS2=0x%08X\n" , -RREG32 (GRBM_STATUS2 )); -dev_info (rdev->dev," GRBM_STATUS_SE0=0x%08X\n" , -RREG32 (GRBM_STATUS_SE0 )); -dev_info (rdev->dev," GRBM_STATUS_SE1=0x%08X\n" , -RREG32 (GRBM_STATUS_SE1 )); -dev_info (rdev->dev," GRBM_STATUS_SE2=0x%08X\n" , -RREG32 (GRBM_STATUS_SE2 )); -dev_info (rdev->dev," GRBM_STATUS_SE3=0x%08X\n" , -RREG32 (GRBM_STATUS_SE3 )); -dev_info (rdev->dev," SRBM_STATUS=0x%08X\n" , -RREG32 (SRBM_STATUS )); -dev_info (rdev->dev," SRBM_STATUS2=0x%08X\n" , -RREG32 (SRBM_STATUS2 ));evergreen_mc_stop (rdev, &save); -if (radeon_mc_wait_for_idle (rdev)) { +if (evergreen_mc_wait_for_idle (rdev)) {dev_warn (rdev->dev,"Wait for MC idle timedout !\n" ); } -/* Disable CP parsing/prefetching */ -WREG32 (CP_MEC_CNTL ,MEC_ME1_HALT |MEC_ME2_HALT ); -/* reset all the CPC blocks */ - grbm_reset =SOFT_RESET_CPG ; +if (reset_mask & (RADEON_RESET_GFX |RADEON_RESET_COMPUTE |RADEON_RESET_CP )) + grbm_soft_reset =SOFT_RESET_CP |SOFT_RESET_GFX ; + +if (reset_mask &RADEON_RESET_CP ) { + grbm_soft_reset |=SOFT_RESET_CP ; + + srbm_soft_reset |=SOFT_RESET_GRBM ; + } + +if (reset_mask &RADEON_RESET_DMA ) + srbm_soft_reset |=SOFT_RESET_SDMA ; + +if (reset_mask &RADEON_RESET_DMA1 ) + srbm_soft_reset |=SOFT_RESET_SDMA1 ; + +if (reset_mask &RADEON_RESET_DISPLAY ) + srbm_soft_reset |=SOFT_RESET_DC ; + +if (reset_mask &RADEON_RESET_RLC ) + grbm_soft_reset |=SOFT_RESET_RLC ; + +if (reset_mask &RADEON_RESET_SEM ) + srbm_soft_reset |=SOFT_RESET_SEM ; + +if (reset_mask &RADEON_RESET_IH ) + srbm_soft_reset |=SOFT_RESET_IH ; + +if (reset_mask &RADEON_RESET_GRBM ) + srbm_soft_reset |=SOFT_RESET_GRBM ; + +if (reset_mask &RADEON_RESET_VMC ) + srbm_soft_reset |=SOFT_RESET_VMC ; + +if (!(rdev->flags &RADEON_IS_IGP )) { +if (reset_mask &RADEON_RESET_MC ) + srbm_soft_reset |=SOFT_RESET_MC ; + } + +if (grbm_soft_reset) { + tmp =RREG32 (GRBM_SOFT_RESET ); + tmp |= grbm_soft_reset; +dev_info (rdev->dev,"GRBM_SOFT_RESET=0x%08X\n" , tmp); +WREG32 (GRBM_SOFT_RESET , tmp); + tmp =RREG32 (GRBM_SOFT_RESET ); + +udelay (50 ); + + tmp &= ~grbm_soft_reset; +WREG32 (GRBM_SOFT_RESET , tmp); + tmp =RREG32 (GRBM_SOFT_RESET ); + } + +if (srbm_soft_reset) { + tmp =RREG32 (SRBM_SOFT_RESET ); + tmp |= srbm_soft_reset; +dev_info (rdev->dev,"SRBM_SOFT_RESET=0x%08X\n" , tmp); +WREG32 (SRBM_SOFT_RESET , tmp); + tmp =RREG32 (SRBM_SOFT_RESET ); + +udelay (50 ); + + tmp &= ~srbm_soft_reset; +WREG32 (SRBM_SOFT_RESET , tmp); + tmp =RREG32 (SRBM_SOFT_RESET ); + } -dev_info (rdev->dev," GRBM_SOFT_RESET=0x%08X\n" , grbm_reset); -WREG32 (GRBM_SOFT_RESET , grbm_reset); - (void )RREG32 (GRBM_SOFT_RESET ); -udelay (50 ); -WREG32 (GRBM_SOFT_RESET ,0 ); - (void )RREG32 (GRBM_SOFT_RESET );/* Wait a little for things to settle down */ udelay (50 ); -dev_info (rdev->dev," GRBM_STATUS=0x%08X\n" , -RREG32 (GRBM_STATUS )); -dev_info (rdev->dev," GRBM_STATUS2=0x%08X\n" , -RREG32 (GRBM_STATUS2 )); -dev_info (rdev->dev," GRBM_STATUS_SE0=0x%08X\n" , -RREG32 (GRBM_STATUS_SE0 )); -dev_info (rdev->dev," GRBM_STATUS_SE1=0x%08X\n" , -RREG32 (GRBM_STATUS_SE1 )); -dev_info (rdev->dev," GRBM_STATUS_SE2=0x%08X\n" , -RREG32 (GRBM_STATUS_SE2 )); -dev_info (rdev->dev," GRBM_STATUS_SE3=0x%08X\n" , -RREG32 (GRBM_STATUS_SE3 )); -dev_info (rdev->dev," SRBM_STATUS=0x%08X\n" , -RREG32 (SRBM_STATUS )); -dev_info (rdev->dev," SRBM_STATUS2=0x%08X\n" , -RREG32 (SRBM_STATUS2 )); +evergreen_mc_resume (rdev, &save); -return 0 ; +udelay (50 ); + +cik_print_gpu_status_regs (rdev); }/** -* cik_asic_reset - soft reset compute and gfx +* cik_asic_reset - soft reset GPU * * @rdev: radeon_device pointer * -* Soft reset the CPC blocks (CIK). -* XXX: make this more fine grained and only reset -* what is necessary. +* Look up which blocks are hung and attempt +* to reset them. * Returns 0 for success. */ int cik_asic_reset (struct radeon_device *rdev) { -int r; +u32 reset_mask; - r =cik_compute_gpu_soft_reset (rdev); -if (r) -dev_info (rdev->dev,"Compute reset failed!\n" ); + reset_mask =cik_gpu_check_soft_reset (rdev); + +if (reset_mask) +r600_set_bios_scratch_engine_hung (rdev, true); + +cik_gpu_soft_reset (rdev, reset_mask); -return cik_gfx_gpu_soft_reset (rdev); + reset_mask =cik_gpu_check_soft_reset (rdev); + +if (!reset_mask) +r600_set_bios_scratch_engine_hung (rdev, false); + +return 0 ; +} + +/** +* cik_gfx_is_lockup - check if the 3D engine is locked up +* +* @rdev: radeon_device pointer +* @ring: radeon_ring structure holding ring information +* +* Check if the 3D engine is locked up (CIK). +* Returns true if the engine is locked, false if not. +*/ +bool cik_gfx_is_lockup (struct radeon_device *rdev,struct radeon_ring *ring) +{ +u32 reset_mask =cik_gpu_check_soft_reset (rdev); + +if (!(reset_mask & (RADEON_RESET_GFX | +RADEON_RESET_COMPUTE | +RADEON_RESET_CP ))) { +radeon_ring_lockup_update (ring); +return false; + } +/* force CP activities */ +radeon_ring_force_activity (rdev, ring); +return radeon_ring_test_lockup (rdev, ring); }/**
@@ -2938,13 +3031,15 @@ int cik_asic_reset(struct radeon_device *rdev)*/ bool cik_sdma_is_lockup (struct radeon_device *rdev,struct radeon_ring *ring) { -u32 dma_status_reg; +u32 reset_mask =cik_gpu_check_soft_reset (rdev); +u32 mask;if (ring->idx ==R600_RING_TYPE_DMA_INDEX ) - dma_status_reg =RREG32 (SDMA0_STATUS_REG +SDMA0_REGISTER_OFFSET ); + mask =RADEON_RESET_DMA ;else - dma_status_reg =RREG32 (SDMA0_STATUS_REG +SDMA1_REGISTER_OFFSET ); -if (dma_status_reg &SDMA_IDLE ) { + mask =RADEON_RESET_DMA1 ; + +if (!(reset_mask & mask)) {radeon_ring_lockup_update (ring);return false; }
drivers/gpu/drm/radeon/cikd.h +12 -0
@@ -40,7 +40,19 @@#define QUEUEID (x) ((x) << 8)#define SRBM_STATUS2 0xE4C +#define SDMA_BUSY (1 << 5) +#define SDMA1_BUSY (1 << 6)#define SRBM_STATUS 0xE50 +#define UVD_RQ_PENDING (1 << 1) +#define GRBM_RQ_PENDING (1 << 5) +#define VMC_BUSY (1 << 8) +#define MCB_BUSY (1 << 9) +#define MCB_NON_DISPLAY_BUSY (1 << 10) +#define MCC_BUSY (1 << 11) +#define MCD_BUSY (1 << 12) +#define SEM_BUSY (1 << 14) +#define IH_BUSY (1 << 17) +#define UVD_BUSY (1 << 19)#define SRBM_SOFT_RESET 0xE60#define SOFT_RESET_BIF (1 << 1)
Signature · 1 line
1.7.7.5
PATCH 43/165 drm/radeon: add indirect register accessors for SMC registers
In reply to [email protected]From: Alex Deucher <[email protected]>
--- drivers/gpu/drm/radeon/evergreen_reg.h | 4 ++++ drivers/gpu/drm/radeon/radeon.h | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/evergreen_reg.h +4 -0
@@ -24,6 +24,10 @@#ifndef __EVERGREEN_REG_H__#define __EVERGREEN_REG_H__ +/* trinity */ +#define TN_SMC_IND_INDEX_0 0x200 +#define TN_SMC_IND_DATA_0 0x204 +/* evergreen */ #define EVERGREEN_VGA_MEMORY_BASE_ADDRESS 0x310#define EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH 0x324
drivers/gpu/drm/radeon/radeon.h +17 -0
@@ -1806,6 +1806,8 @@ void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v);#define WREG32_PCIE (reg, v) rv370_pcie_wreg(rdev, (reg), (v))#define RREG32_PCIE_PORT (reg) rdev->pciep_rreg(rdev, (reg))#define WREG32_PCIE_PORT (reg, v) rdev->pciep_wreg(rdev, (reg), (v)) +#define RREG32_SMC (reg) tn_smc_rreg(rdev, (reg)) +#define WREG32_SMC (reg, v) tn_smc_wreg(rdev, (reg), (v))#define WREG32_P (reg, val, mask) \ do { \ uint32_t tmp_ = RREG32(reg); \
@@ -1844,6 +1846,21 @@ static inline void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uinWREG32 (RADEON_PCIE_DATA , (v)); } +static inline u32 tn_smc_rreg (struct radeon_device *rdev,u32 reg) +{ +u32 r; + +WREG32 (TN_SMC_IND_INDEX_0 , (reg)); + r =RREG32 (TN_SMC_IND_DATA_0 ); +return r; +} + +static inline void tn_smc_wreg (struct radeon_device *rdev,u32 reg,u32 v) +{ +WREG32 (TN_SMC_IND_INDEX_0 , (reg)); +WREG32 (TN_SMC_IND_DATA_0 , (v)); +} +void r100_pll_errata_after_index (struct radeon_device *rdev);
Signature · 1 line
1.7.7.5
PATCH 44/165 drm/radeon: add get_xclk() callback for CIK
In reply to [email protected]From: Alex Deucher <[email protected]>
--- drivers/gpu/drm/radeon/cik.c | 22 ++++++++++++++++++++++ drivers/gpu/drm/radeon/cikd.h | 7 +++++++ drivers/gpu/drm/radeon/radeon_asic.h | 1 + 3 files changed, 30 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/cik.c +22 -0
@@ -78,6 +78,28 @@ extern void si_rlc_fini(struct radeon_device *rdev);extern int si_rlc_init (struct radeon_device *rdev);static void cik_rlc_stop (struct radeon_device *rdev); +/** +* cik_get_xclk - get the xclk +* +* @rdev: radeon_device pointer +* +* Returns the reference clock used by the gfx engine +* (CIK). +*/ +u32 cik_get_xclk (struct radeon_device *rdev) +{ +u32 reference_clock = rdev->clock.spll.reference_freq; + +if (rdev->flags &RADEON_IS_IGP ) { +if (RREG32_SMC (GENERAL_PWRMGT ) &GPU_COUNTER_CLK ) +return reference_clock /2 ; + }else { +if (RREG32_SMC (CG_CLKPIN_CNTL ) &XTALIN_DIVIDE ) +return reference_clock /4 ; + } +return reference_clock; +} +#define BONAIRE_IO_MC_REGS_SIZE 36 static const u32 bonaire_io_mc_regs[BONAIRE_IO_MC_REGS_SIZE][2] =
drivers/gpu/drm/radeon/cikd.h +7 -0
@@ -28,6 +28,13 @@#define CIK_RB_BITMAP_WIDTH_PER_SH 2 +/* SMC IND registers */ +#define GENERAL_PWRMGT 0xC0200000 +# define GPU_COUNTER_CLK (1 << 15) + +#define CG_CLKPIN_CNTL 0xC05001A0 +# define XTALIN_DIVIDE (1 << 1) +#define VGA_HDP_CONTROL 0x328#define VGA_MEMORY_DISABLE (1 << 4)
drivers/gpu/drm/radeon/radeon_asic.h +1 -0
@@ -557,5 +557,6 @@ int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);* cik */ uint64_t cik_get_gpu_clock_counter (struct radeon_device *rdev); +u32 cik_get_xclk (struct radeon_device *rdev);#endif
Signature · 1 line
1.7.7.5
PATCH 45/165 drm/radeon/cik: add pcie_port indirect register accessors
In reply to [email protected]From: Alex Deucher <[email protected]>
--- drivers/gpu/drm/radeon/cik.c | 21 +++++++++++++++++++++ drivers/gpu/drm/radeon/cikd.h | 3 +++ drivers/gpu/drm/radeon/radeon_asic.c | 6 +++++- drivers/gpu/drm/radeon/radeon_asic.h | 2 ++ 4 files changed, 31 insertions(+), 1 deletions(-)
drivers/gpu/drm/radeon/cik.c +21 -0
@@ -78,6 +78,27 @@ extern void si_rlc_fini(struct radeon_device *rdev);extern int si_rlc_init (struct radeon_device *rdev);static void cik_rlc_stop (struct radeon_device *rdev); +/* +* Indirect registers accessor +*/ +u32 cik_pciep_rreg (struct radeon_device *rdev,u32 reg) +{ +u32 r; + +WREG32 (PCIE_INDEX , reg); + (void )RREG32 (PCIE_INDEX ); + r =RREG32 (PCIE_DATA ); +return r; +} + +void cik_pciep_wreg (struct radeon_device *rdev,u32 reg,u32 v) +{ +WREG32 (PCIE_INDEX , reg); + (void )RREG32 (PCIE_INDEX ); +WREG32 (PCIE_DATA , v); + (void )RREG32 (PCIE_DATA ); +} +/** * cik_get_xclk - get the xclk *
drivers/gpu/drm/radeon/cikd.h +3 -0
@@ -35,6 +35,9 @@#define CG_CLKPIN_CNTL 0xC05001A0# define XTALIN_DIVIDE (1 << 1) +#define PCIE_INDEX 0x38 +#define PCIE_DATA 0x3C +#define VGA_HDP_CONTROL 0x328#define VGA_MEMORY_DISABLE (1 << 4)
drivers/gpu/drm/radeon/radeon_asic.c +5 -1
@@ -126,7 +126,11 @@ static void radeon_register_accessor_init(struct radeon_device *rdev) rdev->mc_rreg = &rs780_mc_rreg; rdev->mc_wreg = &rs780_mc_wreg; } -if (rdev->family >=CHIP_R600 ) { + +if (rdev->family >=CHIP_BONAIRE ) { + rdev->pciep_rreg = &cik_pciep_rreg; + rdev->pciep_wreg = &cik_pciep_wreg; + }else if (rdev->family >=CHIP_R600 ) { rdev->pciep_rreg = &r600_pciep_rreg; rdev->pciep_wreg = &r600_pciep_wreg; }
drivers/gpu/drm/radeon/radeon_asic.h +2 -0
@@ -558,5 +558,7 @@ int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);*/ uint64_t cik_get_gpu_clock_counter (struct radeon_device *rdev);u32 cik_get_xclk (struct radeon_device *rdev); +uint32_t cik_pciep_rreg (struct radeon_device *rdev,uint32_t reg); +void cik_pciep_wreg (struct radeon_device *rdev,uint32_t reg,uint32_t v);#endif
Signature · 1 line
1.7.7.5
PATCH 46/165 drm/radeon: update radeon_atom_get_clock_dividers() for SI
In reply to [email protected]From: Alex Deucher <[email protected]>
SI uses v5 of the command table and uses a different table for memory PLLs.
--- drivers/gpu/drm/radeon/radeon_atombios.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-)
drivers/gpu/drm/radeon/radeon_atombios.c +5 -1
@@ -2732,7 +2732,8 @@ int radeon_atom_get_clock_dividers(struct radeon_device *rdev,break ;case 2 :case 3 : -/* r6xx, r7xx, evergreen, ni */ +case 5 : +/* r6xx, r7xx, evergreen, ni, si */ if (rdev->family <=CHIP_RV770 ) { args.v2.ucAction = clock_type; args.v2.ulClock =cpu_to_le32 (clock);/* 10 khz */
@@ -2765,6 +2766,9 @@ int radeon_atom_get_clock_dividers(struct radeon_device *rdev, dividers->vco_mode = (args.v3.ucCntlFlag &ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE ) ?1 :0 ; }else { +/* for SI we use ComputeMemoryClockParam for memory plls */ +if (rdev->family >=CHIP_TAHITI ) +return -EINVAL ; args.v5.ulClockParams =cpu_to_le32 ((clock_type <<24 ) | clock);if (strobe_mode) args.v5.ucInputFlag =ATOM_PLL_INPUT_FLAG_PLL_STROBE_MODE_EN ;
Signature · 1 line
1.7.7.5
PATCH 47/165 drm/radeon: update radeon_atom_get_clock_dividers for CIK
In reply to [email protected]From: Alex Deucher <[email protected]>
CIK uses a slightly different variant of the table structs and params.
--- drivers/gpu/drm/radeon/radeon_atombios.c | 20 +++++++++++++++++++- drivers/gpu/drm/radeon/radeon_mode.h | 3 +++ 2 files changed, 22 insertions(+), 1 deletions(-)
drivers/gpu/drm/radeon/radeon_atombios.c +19 -1
@@ -2700,6 +2700,8 @@ union get_clock_dividers {struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3 v3;struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 v4;struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5 v5; +struct _COMPUTE_GPU_CLOCK_INPUT_PARAMETERS_V1_6 v6_in; +struct _COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_6 v6_out; }; int radeon_atom_get_clock_dividers(struct radeon_device *rdev,
@@ -2794,9 +2796,25 @@ int radeon_atom_get_clock_dividers(struct radeon_device *rdev,atom_execute_table (rdev->mode_info.atom_context, index, (uint32_t *)&args); - dividers->post_div = args.v4.ucPostDiv; + dividers->post_divider = dividers->post_div = args.v4.ucPostDiv; dividers->real_clock =le32_to_cpu (args.v4.ulClock);break ; +case 6 : +/* CI */ +/* COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, COMPUTE_GPUCLK_INPUT_FLAG_SCLK */ + args.v6_in.ulClock.ulComputeClockFlag = clock_type; + args.v6_in.ulClock.ulClockFreq =cpu_to_le32 (clock);/* 10 khz */ + +atom_execute_table (rdev->mode_info.atom_context, index, (uint32_t *)&args); + + dividers->whole_fb_div =le16_to_cpu (args.v6_out.ulFbDiv.usFbDiv); + dividers->frac_fb_div =le16_to_cpu (args.v6_out.ulFbDiv.usFbDivFrac); + dividers->ref_div = args.v6_out.ucPllRefDiv; + dividers->post_div = args.v6_out.ucPllPostDiv; + dividers->flags = args.v6_out.ucPllCntlFlag; + dividers->real_clock =le32_to_cpu (args.v6_out.ulClock.ulClock); + dividers->post_divider = args.v6_out.ulClock.ucPostDiv; +break ;default :return -EINVAL ; }
drivers/gpu/drm/radeon/radeon_mode.h +3 -0
@@ -514,6 +514,9 @@ struct atom_clock_dividers {bool enable_dithen;u32 vco_mode;u32 real_clock; +/* added for CI */ +u32 post_divider; +u32 flags; }; extern enum radeon_tv_std
Signature · 1 line
1.7.7.5
PATCH 48/165 drm/radeon: add UVD support for CIK (v3)
In reply to [email protected]From: Christian König <[email protected]>
v2: agd5f: fix clock dividers setup for bonaire
v3: agd5f: rebase
--- drivers/gpu/drm/radeon/cik.c | 111 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/cikd.h | 28 +++++++++ drivers/gpu/drm/radeon/radeon_asic.h | 2 + drivers/gpu/drm/radeon/radeon_uvd.c | 8 +++ 4 files changed, 149 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/cik.c +111 -0
@@ -1495,6 +1495,9 @@ static void cik_gpu_init(struct radeon_device *rdev)WREG32 (DMIF_ADDR_CALC , gb_addr_config);WREG32 (SDMA0_TILING_CONFIG +SDMA0_REGISTER_OFFSET , gb_addr_config &0x70 );WREG32 (SDMA0_TILING_CONFIG +SDMA1_REGISTER_OFFSET , gb_addr_config &0x70 ); +WREG32 (UVD_UDEC_ADDR_CONFIG , gb_addr_config); +WREG32 (UVD_UDEC_DB_ADDR_CONFIG , gb_addr_config); +WREG32 (UVD_UDEC_DBW_ADDR_CONFIG , gb_addr_config);cik_tiling_mode_table_init (rdev);
@@ -4906,6 +4909,16 @@ static int cik_startup(struct radeon_device *rdev)return r; } + r =cik_uvd_resume (rdev); +if (!r) { + r =radeon_fence_driver_start_ring (rdev, +R600_RING_TYPE_UVD_INDEX ); +if (r) +dev_err (rdev->dev,"UVD fences init error (%d).\n" , r); + } +if (r) + rdev->ring[R600_RING_TYPE_UVD_INDEX ].ring_size =0 ; +/* Enable IRQ */ if (!rdev->irq.installed) { r =radeon_irq_kms_init (rdev);
@@ -4952,6 +4965,18 @@ static int cik_startup(struct radeon_device *rdev)if (r)return r; + ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX ]; +if (ring->ring_size) { + r =radeon_ring_init (rdev, ring, ring->ring_size, +R600_WB_UVD_RPTR_OFFSET , +UVD_RBC_RB_RPTR ,UVD_RBC_RB_WPTR , +0 ,0xfffff ,RADEON_CP_PACKET2 ); +if (!r) + r =r600_uvd_init (rdev); +if (r) +DRM_ERROR ("radeon: failed initializing UVD (%d).\n" , r); + } + r =radeon_ib_pool_init (rdev);if (r) {dev_err (rdev->dev,"IB initialization failed (%d).\n" , r);
@@ -5013,6 +5038,8 @@ int cik_suspend(struct radeon_device *rdev)radeon_vm_manager_fini (rdev);cik_cp_enable (rdev, false);cik_sdma_enable (rdev, false); +r600_uvd_rbc_stop (rdev); +radeon_uvd_suspend (rdev);cik_irq_suspend (rdev);radeon_wb_disable (rdev);cik_pcie_gart_disable (rdev);
@@ -5096,6 +5123,13 @@ int cik_init(struct radeon_device *rdev) ring->ring_obj =NULL ;r600_ring_init (rdev, ring,256 *1024 ); + r =radeon_uvd_init (rdev); +if (!r) { + ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX ]; + ring->ring_obj =NULL ; +r600_ring_init (rdev, ring,4096 ); + } + rdev->ih.ring_obj =NULL ;r600_ih_ring_init (rdev,64 *1024 );
@@ -5150,6 +5184,7 @@ void cik_fini(struct radeon_device *rdev)radeon_vm_manager_fini (rdev);radeon_ib_pool_fini (rdev);radeon_irq_kms_fini (rdev); +radeon_uvd_fini (rdev);cik_pcie_gart_fini (rdev);r600_vram_scratch_fini (rdev);radeon_gem_fini (rdev);
@@ -5717,3 +5752,79 @@ uint64_t cik_get_gpu_clock_counter(struct radeon_device *rdev)return clock; } +static int cik_set_uvd_clock (struct radeon_device *rdev,u32 clock, +u32 cntl_reg,u32 status_reg) +{ +int r, i; +struct atom_clock_dividers dividers; +uint32_t tmp; + + r =radeon_atom_get_clock_dividers (rdev,COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK , + clock, false, ÷rs); +if (r) +return r; + + tmp =RREG32_SMC (cntl_reg); + tmp &= ~(DCLK_DIR_CNTL_EN |DCLK_DIVIDER_MASK ); + tmp |= dividers.post_divider; +WREG32_SMC (cntl_reg, tmp); + +for (i =0 ; i <100 ; i++) { +if (RREG32_SMC (status_reg) &DCLK_STATUS ) +break ; +mdelay (10 ); + } +if (i ==100 ) +return -ETIMEDOUT ; + +return 0 ; +} + +int cik_set_uvd_clocks (struct radeon_device *rdev,u32 vclk,u32 dclk) +{ +int r =0 ; + + r =cik_set_uvd_clock (rdev, vclk,CG_VCLK_CNTL ,CG_VCLK_STATUS ); +if (r) +return r; + + r =cik_set_uvd_clock (rdev, dclk,CG_DCLK_CNTL ,CG_DCLK_STATUS ); +return r; +} + +int cik_uvd_resume (struct radeon_device *rdev) +{ +uint64_t addr; +uint32_t size; +int r; + + r =radeon_uvd_resume (rdev); +if (r) +return r; + +/* programm the VCPU memory controller bits 0-27 */ + addr = rdev->uvd.gpu_addr >>3 ; + size =RADEON_GPU_PAGE_ALIGN (rdev->uvd_fw->size +4 ) >>3 ; +WREG32 (UVD_VCPU_CACHE_OFFSET0 , addr); +WREG32 (UVD_VCPU_CACHE_SIZE0 , size); + + addr += size; + size =RADEON_UVD_STACK_SIZE >>3 ; +WREG32 (UVD_VCPU_CACHE_OFFSET1 , addr); +WREG32 (UVD_VCPU_CACHE_SIZE1 , size); + + addr += size; + size =RADEON_UVD_HEAP_SIZE >>3 ; +WREG32 (UVD_VCPU_CACHE_OFFSET2 , addr); +WREG32 (UVD_VCPU_CACHE_SIZE2 , size); + +/* bits 28-31 */ + addr = (rdev->uvd.gpu_addr >>28 ) &0xF ; +WREG32 (UVD_LMI_ADDR_EXT , (addr <<12 ) | (addr <<0 )); + +/* bits 32-39 */ + addr = (rdev->uvd.gpu_addr >>32 ) &0xFF ; +WREG32 (UVD_LMI_EXT40_ADDR , addr | (0x9 <<16 ) | (0x1 <<31 )); + +return 0 ; +}
drivers/gpu/drm/radeon/cikd.h +28 -0
@@ -1204,4 +1204,32 @@# define SDMA_SRBM_WRITE_EXTRA_BYTE_ENABLE (x) ((x) << 12)/* byte mask */ +/* UVD */ + +#define UVD_UDEC_ADDR_CONFIG 0xef4c +#define UVD_UDEC_DB_ADDR_CONFIG 0xef50 +#define UVD_UDEC_DBW_ADDR_CONFIG 0xef54 + +#define UVD_LMI_EXT40_ADDR 0xf498 +#define UVD_LMI_ADDR_EXT 0xf594 +#define UVD_VCPU_CACHE_OFFSET0 0xf608 +#define UVD_VCPU_CACHE_SIZE0 0xf60c +#define UVD_VCPU_CACHE_OFFSET1 0xf610 +#define UVD_VCPU_CACHE_SIZE1 0xf614 +#define UVD_VCPU_CACHE_OFFSET2 0xf618 +#define UVD_VCPU_CACHE_SIZE2 0xf61c + +#define UVD_RBC_RB_RPTR 0xf690 +#define UVD_RBC_RB_WPTR 0xf694 + +/* UVD clocks */ + +#define CG_DCLK_CNTL 0xC050009C +# define DCLK_DIVIDER_MASK 0x7f +# define DCLK_DIR_CNTL_EN (1 << 8) +#define CG_DCLK_STATUS 0xC05000A0 +# define DCLK_STATUS (1 << 0) +#define CG_VCLK_CNTL 0xC05000A4 +#define CG_VCLK_STATUS 0xC05000A8 +#endif
drivers/gpu/drm/radeon/radeon_asic.h +2 -0
@@ -560,5 +560,7 @@ uint64_t cik_get_gpu_clock_counter(struct radeon_device *rdev);u32 cik_get_xclk (struct radeon_device *rdev);uint32_t cik_pciep_rreg (struct radeon_device *rdev,uint32_t reg);void cik_pciep_wreg (struct radeon_device *rdev,uint32_t reg,uint32_t v); +int cik_set_uvd_clocks (struct radeon_device *rdev,u32 vclk,u32 dclk); +int cik_uvd_resume (struct radeon_device *rdev);#endif
drivers/gpu/drm/radeon/radeon_uvd.c +8 -0
@@ -44,11 +44,13 @@#define FIRMWARE_CYPRESS "radeon/CYPRESS_uvd.bin"#define FIRMWARE_SUMO "radeon/SUMO_uvd.bin"#define FIRMWARE_TAHITI "radeon/TAHITI_uvd.bin" +#define FIRMWARE_BONAIRE "radeon/BONAIRE_uvd.bin"MODULE_FIRMWARE (FIRMWARE_RV710 );MODULE_FIRMWARE (FIRMWARE_CYPRESS );MODULE_FIRMWARE (FIRMWARE_SUMO );MODULE_FIRMWARE (FIRMWARE_TAHITI ); +MODULE_FIRMWARE (FIRMWARE_BONAIRE );static void radeon_uvd_idle_work_handler (struct work_struct *work);
@@ -100,6 +102,12 @@ int radeon_uvd_init(struct radeon_device *rdev) fw_name =FIRMWARE_TAHITI ;break ; +case CHIP_BONAIRE : +case CHIP_KABINI : +case CHIP_KAVERI : + fw_name =FIRMWARE_BONAIRE ; +break ; +default :return -EINVAL ; }
Signature · 6 lines
1.7.7.5 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 49/165 drm/radeon/cik: add srbm_select function
In reply to [email protected]From: Alex Deucher <[email protected]>
Allows us to select instanced registers based on:
- ME (micro engine
- Pipe
- Queue
- VMID
Switch MC setup to use this new function.
--- drivers/gpu/drm/radeon/cik.c | 27 +++++++++++++++++++++++++-- 1 files changed, 25 insertions(+), 2 deletions(-)
drivers/gpu/drm/radeon/cik.c +25 -2
@@ -163,6 +163,29 @@ static const u32 bonaire_io_mc_regs[BONAIRE_IO_MC_REGS_SIZE][2] = {0x0000009f, 0x00b48000} }; +/** +* cik_srbm_select - select specific register instances +* +* @rdev: radeon_device pointer +* @me: selected ME (micro engine) +* @pipe: pipe +* @queue: queue +* @vmid: VMID +* +* Switches the currently active registers instances. Some +* registers are instanced per VMID, others are instanced per +* me/pipe/queue combination. +*/ +static void cik_srbm_select (struct radeon_device *rdev, +u32 me,u32 pipe,u32 queue,u32 vmid) +{ +u32 srbm_gfx_cntl = (PIPEID (pipe &0x3 ) | +MEID (me &0x3 ) | +VMID (vmid &0xf ) | +QUEUEID (queue &0x7 )); +WREG32 (SRBM_GFX_CNTL , srbm_gfx_cntl); +} +/* ucode loading */ /** * ci_mc_load_microcode - load MC ucode into the hw
@@ -3351,7 +3374,7 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev)/* XXX SH_MEM regs */ /* where to put LDS, scratch, GPUVM in FSA64 space */ for (i =0 ; i <16 ; i++) { -WREG32 (SRBM_GFX_CNTL ,VMID (i)); +cik_srbm_select (rdev,0 ,0 ,0 , i);/* CP and shaders */ WREG32 (SH_MEM_CONFIG ,0 );WREG32 (SH_MEM_APE1_BASE ,1 );
@@ -3364,7 +3387,7 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev)WREG32 (SDMA0_GFX_APE1_CNTL +SDMA1_REGISTER_OFFSET ,0 );/* XXX SDMA RLC - todo */ } -WREG32 (SRBM_GFX_CNTL ,0 ); +cik_srbm_select (rdev,0 ,0 ,0 ,0 );cik_pcie_gart_tlb_flush (rdev); DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
Signature · 1 line
1.7.7.5
PATCH 50/165 drm/radeon: use callbacks for ring pointer handling
In reply to [email protected]From: Alex Deucher <[email protected]>
Add callbacks to the radeon_ring struct to handle rptr/wptr fetchs and wptr updates.
We currently use one version for all rings, but this allows us to override with a ring specific versions.
Needed for compute rings on CIK.
--- drivers/gpu/drm/radeon/radeon.h | 5 +++ drivers/gpu/drm/radeon/radeon_ring.c | 55 +++++++++++++++++++++++++-------- 2 files changed, 46 insertions(+), 14 deletions(-)
drivers/gpu/drm/radeon/radeon.h +5 -0
@@ -695,6 +695,11 @@ struct radeon_ring {u32 idx;u64 last_semaphore_signal_addr;u64 last_semaphore_wait_addr; +struct { +u32 (*get_rptr)(struct radeon_device *rdev,struct radeon_ring *ring); +u32 (*get_wptr)(struct radeon_device *rdev,struct radeon_ring *ring); +void (*set_wptr)(struct radeon_device *rdev,struct radeon_ring *ring); + } funcs; };/*
drivers/gpu/drm/radeon/radeon_ring.c +41 -14
98 lines not on this page · raw message
Signature · 1 line
1.7.7.5
Re: [PATCH 050/165] drm/radeon: use callbacks for ring pointer handling
Am 26.06.2013 15:22, schrieb [email protected]:
Quoted 10 lines
From: Alex Deucher <[email protected]>
Add callbacks to the
radeon_ringstruct to handle rptr/wptr fetchs and wptr updates.
We currently use one version for all rings, but this allows us to override with a ring specific versions.Needed for compute rings on CIK.
Signed-off-by Alex Deucher <[email protected]>
I'm ok with the general idea but let's put those callback into the radeon_asic.ring structure where they belong.
With this we should be able to remove most of the UVD and ptr_reg_shift/ptr_reg_mask special case handling.
Christian.
Quoted 130 lines
--- drivers/gpu/drm/radeon/radeon.h | 5 +++ drivers/gpu/drm/radeon/radeon_ring.c | 55 +++++++++++++++++++++++++-------- 2 files changed, 46 insertions(+), 14 deletions(-)drivers/gpu/drm/radeon/radeon.h +5
-0@@ -695,6 +695,11 @@ struct radeon_ring {u32 idx;u64 last_semaphore_signal_addr;u64 last_semaphore_wait_addr; +struct { +u32 (*get_rptr)(struct radeon_device *rdev,struct radeon_ring *ring); +u32 (*get_wptr)(struct radeon_device *rdev,struct radeon_ring *ring); +void (*set_wptr)(struct radeon_device *rdev,struct radeon_ring *ring); + } funcs; };/* drivers/gpu/drm/radeon/radeon_ring.c +41
-14@@ -357,6 +357,38 @@ bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev, } } +static u32 radeon_ring_get_rptr (struct radeon_device *rdev, +struct radeon_ring *ring) +{ +u32 rptr; + +if (rdev->wb.enabled && ring != &rdev->ring[R600_RING_TYPE_UVD_INDEX ]) + rptr =le32_to_cpu (rdev->wb.wb[ring->rptr_offs/4 ]); +else + rptr =RREG32 (ring->rptr_reg); + rptr = (rptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift; + +return rptr; +} + +static u32 radeon_ring_get_wptr (struct radeon_device *rdev, +struct radeon_ring *ring) +{ +u32 wptr; + + wptr =RREG32 (ring->wptr_reg); + wptr = (wptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift; + +return wptr; +} + +static void radeon_ring_set_wptr (struct radeon_device *rdev, +struct radeon_ring *ring) +{ +WREG32 (ring->wptr_reg, (ring->wptr << ring->ptr_reg_shift) & ring->ptr_reg_mask); + (void )RREG32 (ring->wptr_reg); +} +/** * radeon_ring_free_size - update the free size * @@ -367,13 +399,7 @@ bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev,*/ void radeon_ring_free_size (struct radeon_device *rdev,struct radeon_ring *ring) { -u32 rptr; - -if (rdev->wb.enabled && ring != &rdev->ring[R600_RING_TYPE_UVD_INDEX ]) - rptr =le32_to_cpu (rdev->wb.wb[ring->rptr_offs/4 ]); -else - rptr =RREG32 (ring->rptr_reg); - ring->rptr = (rptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift; + ring->rptr = ring->funcs.get_rptr (rdev, ring);/* This works because ring_size is a power of 2 */ ring->ring_free_dw = (ring->rptr + (ring->ring_size /4 )); ring->ring_free_dw -= ring->wptr;@@ -458,8 +484,7 @@ void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring)radeon_ring_write (ring, ring->nop); }DRM_MEMORYBARRIER (); -WREG32 (ring->wptr_reg, (ring->wptr << ring->ptr_reg_shift) & ring->ptr_reg_mask); - (void )RREG32 (ring->wptr_reg); + ring->funcs.set_wptr (rdev, ring); }/** @@ -561,7 +586,6 @@ void radeon_ring_lockup_update(struct radeon_ring *ring)bool radeon_ring_test_lockup (struct radeon_device *rdev,struct radeon_ring *ring) {unsigned long cjiffies, elapsed; -uint32_t rptr; cjiffies = jiffies;if (!time_after (cjiffies, ring->last_activity)) {@@ -569,8 +593,7 @@ bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *rinradeon_ring_lockup_update (ring);return false; } - rptr =RREG32 (ring->rptr_reg); - ring->rptr = (rptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift; + ring->rptr = ring->funcs.get_rptr (rdev, ring);if (ring->rptr != ring->last_rptr) {/* CP is still working no lockup */ radeon_ring_lockup_update (ring);@@ -708,6 +731,10 @@ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsig ring->ptr_reg_shift = ptr_reg_shift; ring->ptr_reg_mask = ptr_reg_mask; ring->nop = nop; +/* set the ptr callbacks */ + ring->funcs.get_rptr = &radeon_ring_get_rptr; + ring->funcs.get_wptr = &radeon_ring_get_wptr; + ring->funcs.set_wptr = &radeon_ring_set_wptr;/* Allocate ring buffer */ if (ring->ring_obj ==NULL ) { r = radeon_bo_create(rdev, ring->ring_size, PAGE_SIZE, true,@@ -797,9 +824,9 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data)radeon_ring_free_size (rdev, ring); count = (ring->ring_size /4 ) - ring->ring_free_dw; - tmp =RREG32 (ring->wptr_reg) >> ring->ptr_reg_shift; + tmp = ring->funcs.get_wptr (rdev, ring);seq_printf (m,"wptr(0x%04x): 0x%08x [%5d]\n" , ring->wptr_reg, tmp, tmp); - tmp =RREG32 (ring->rptr_reg) >> ring->ptr_reg_shift; + tmp = ring->funcs.get_rptr (rdev, ring);seq_printf (m,"rptr(0x%04x): 0x%08x [%5d]\n" , ring->rptr_reg, tmp, tmp);if (ring->rptr_save_reg) { seq_printf(m, "rptr next(0x%04x): 0x%08x\n", ring->rptr_save_reg,
PATCH 51/165 drm/radeon: implement simple doorbell page allocator
In reply to [email protected]From: Alex Deucher <[email protected]>
The doorbell aperture is a PCI BAR whose pages can be mapped to compute resources for things like wptrs for userspace queues.
This patch maps the BAR and sets up a simple allocator to allocate pages from the BAR.
--- drivers/gpu/drm/radeon/cik.c | 38 +++++++++++++ drivers/gpu/drm/radeon/radeon.h | 21 +++++++ drivers/gpu/drm/radeon/radeon_device.c | 94 ++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/cik.c +38 -0
@@ -121,6 +121,44 @@ u32 cik_get_xclk(struct radeon_device *rdev)return reference_clock; } +/** +* cik_mm_rdoorbell - read a doorbell dword +* +* @rdev: radeon_device pointer +* @offset: byte offset into the aperture +* +* Returns the value in the doorbell aperture at the +* requested offset (CIK). +*/ +u32 cik_mm_rdoorbell (struct radeon_device *rdev,u32 offset) +{ +if (offset < rdev->doorbell.size) { +return readl (((void __iomem *)rdev->doorbell.ptr) + offset); + }else { +DRM_ERROR ("reading beyond doorbell aperture: 0x%08x!\n" , offset); +return 0 ; + } +} + +/** +* cik_mm_wdoorbell - write a doorbell dword +* +* @rdev: radeon_device pointer +* @offset: byte offset into the aperture +* @v: value to write +* +* Writes @v to the doorbell aperture at the +* requested offset (CIK). +*/ +void cik_mm_wdoorbell (struct radeon_device *rdev,u32 offset,u32 v) +{ +if (offset < rdev->doorbell.size) { +writel (v, ((void __iomem *)rdev->doorbell.ptr) + offset); + }else { +DRM_ERROR ("writing beyond doorbell aperture: 0x%08x!\n" , offset); + } +} +#define BONAIRE_IO_MC_REGS_SIZE 36 static const u32 bonaire_io_mc_regs[BONAIRE_IO_MC_REGS_SIZE][2] =
drivers/gpu/drm/radeon/radeon.h +21 -0
@@ -556,6 +556,20 @@ struct radeon_scratch {int radeon_scratch_get (struct radeon_device *rdev,uint32_t *reg);void radeon_scratch_free (struct radeon_device *rdev,uint32_t reg); +/* +* GPU doorbell structures, functions & helpers +*/ +struct radeon_doorbell { +u32 num_pages; +bool free[1024 ]; +/* doorbell mmio */ +resource_size_t base; +resource_size_t size; +void __iomem *ptr; +}; + +int radeon_doorbell_get (struct radeon_device *rdev,u32 *page); +void radeon_doorbell_free (struct radeon_device *rdev,u32 doorbell);/* * IRQS.
@@ -1711,6 +1725,7 @@ struct radeon_device {struct radeon_gart gart;struct radeon_mode_info mode_info;struct radeon_scratch scratch; +struct radeon_doorbell doorbell;struct radeon_mman mman;struct radeon_fence_driver fence_drv[RADEON_NUM_RINGS ];wait_queue_head_t fence_queue;
@@ -1784,6 +1799,9 @@ void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v,u32 r100_io_rreg (struct radeon_device *rdev,u32 reg);void r100_io_wreg (struct radeon_device *rdev,u32 reg,u32 v); +u32 cik_mm_rdoorbell (struct radeon_device *rdev,u32 offset); +void cik_mm_wdoorbell (struct radeon_device *rdev,u32 offset,u32 v); +/* * Cast helper */
@@ -1833,6 +1851,9 @@ void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v);#define RREG32_IO (reg) r100_io_rreg(rdev, (reg))#define WREG32_IO (reg, v) r100_io_wreg(rdev, (reg), (v)) +#define RDOORBELL32 (offset) cik_mm_rdoorbell(rdev, (offset)) +#define WDOORBELL32 (offset, v) cik_mm_wdoorbell(rdev, (offset), (v)) +/* * Indirect registers accessor */
drivers/gpu/drm/radeon/radeon_device.c +94 -0
112 lines not on this page · raw message
Signature · 1 line
1.7.7.5
Re: [PATCH 051/165] drm/radeon: implement simple doorbell page allocator
Quoted 8 lines · On Wed, Jun 26, 2013 at 09:22:11AM -0400, [email protected] wrote:
From: Alex Deucher <[email protected]>
The doorbell aperture is a PCI BAR whose pages can be mapped to compute resources for things like wptrs for userspace queues.
This patch maps the BAR and sets up a simple allocator to allocate pages from the BAR.
This doorbell stuff is cryptic, is that some memory on the GPU ? Or is it more like a register file ? ie what is backing the pci bar.
Also probably want to use bitmap as i dont think gcc will turn bool array into a bitmap.
Cheers,
Jerome
Quoted 236 lines
Signed-off-by Alex Deucher <[email protected]>--- drivers/gpu/drm/radeon/cik.c | 38 +++++++++++++ drivers/gpu/drm/radeon/radeon.h | 21 +++++++ drivers/gpu/drm/radeon/radeon_device.c | 94 ++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 0 deletions(-)drivers/gpu/drm/radeon/cik.c +38
-0@@ -121,6 +121,44 @@ u32 cik_get_xclk(struct radeon_device *rdev)return reference_clock; } +/** +* cik_mm_rdoorbell - read a doorbell dword +* +* @rdev: radeon_device pointer +* @offset: byte offset into the aperture +* +* Returns the value in the doorbell aperture at the +* requested offset (CIK). +*/ +u32 cik_mm_rdoorbell (struct radeon_device *rdev,u32 offset) +{ +if (offset < rdev->doorbell.size) { +return readl (((void __iomem *)rdev->doorbell.ptr) + offset); + }else { +DRM_ERROR ("reading beyond doorbell aperture: 0x%08x!\n" , offset); +return 0 ; + } +} + +/** +* cik_mm_wdoorbell - write a doorbell dword +* +* @rdev: radeon_device pointer +* @offset: byte offset into the aperture +* @v: value to write +* +* Writes @v to the doorbell aperture at the +* requested offset (CIK). +*/ +void cik_mm_wdoorbell (struct radeon_device *rdev,u32 offset,u32 v) +{ +if (offset < rdev->doorbell.size) { +writel (v, ((void __iomem *)rdev->doorbell.ptr) + offset); + }else { +DRM_ERROR ("writing beyond doorbell aperture: 0x%08x!\n" , offset); + } +} +#define BONAIRE_IO_MC_REGS_SIZE 36 static const u32 bonaire_io_mc_regs[BONAIRE_IO_MC_REGS_SIZE][2] =drivers/gpu/drm/radeon/radeon.h +21
-0@@ -556,6 +556,20 @@ struct radeon_scratch {int radeon_scratch_get (struct radeon_device *rdev,uint32_t *reg);void radeon_scratch_free (struct radeon_device *rdev,uint32_t reg); +/* +* GPU doorbell structures, functions & helpers +*/ +struct radeon_doorbell { +u32 num_pages; +bool free[1024 ]; +/* doorbell mmio */ +resource_size_t base; +resource_size_t size; +void __iomem *ptr; +}; + +int radeon_doorbell_get (struct radeon_device *rdev,u32 *page); +void radeon_doorbell_free (struct radeon_device *rdev,u32 doorbell);/* * IRQS. @@ -1711,6 +1725,7 @@ struct radeon_device {struct radeon_gart gart;struct radeon_mode_info mode_info;struct radeon_scratch scratch; +struct radeon_doorbell doorbell;struct radeon_mman mman;struct radeon_fence_driver fence_drv[RADEON_NUM_RINGS ];wait_queue_head_t fence_queue;@@ -1784,6 +1799,9 @@ void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v,u32 r100_io_rreg (struct radeon_device *rdev,u32 reg);void r100_io_wreg (struct radeon_device *rdev,u32 reg,u32 v); +u32 cik_mm_rdoorbell (struct radeon_device *rdev,u32 offset); +void cik_mm_wdoorbell (struct radeon_device *rdev,u32 offset,u32 v); +/* * Cast helper */ @@ -1833,6 +1851,9 @@ void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v);#define RREG32_IO (reg) r100_io_rreg(rdev, (reg))#define WREG32_IO (reg, v) r100_io_wreg(rdev, (reg), (v)) +#define RDOORBELL32 (offset) cik_mm_rdoorbell(rdev, (offset)) +#define WDOORBELL32 (offset, v) cik_mm_wdoorbell(rdev, (offset), (v)) +/* * Indirect registers accessor */ drivers/gpu/drm/radeon/radeon_device.c +94
-0@@ -232,6 +232,94 @@ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) }/* +* GPU doorbell aperture helpers function. +*/ +/** +* radeon_doorbell_init - Init doorbell driver information. +* +* @rdev: radeon_device pointer +* +* Init doorbell driver information (CIK) +* Returns 0 on success, error on failure. +*/ +int radeon_doorbell_init (struct radeon_device *rdev) +{ +int i; + +/* doorbell bar mapping */ + rdev->doorbell.base =pci_resource_start (rdev->pdev,2 ); + rdev->doorbell.size =pci_resource_len (rdev->pdev,2 ); + +/* limit to 4 MB for now */ +if (rdev->doorbell.size > (4 *1024 *1024 )) + rdev->doorbell.size =4 *1024 *1024 ; + + rdev->doorbell.ptr =ioremap (rdev->doorbell.base, rdev->doorbell.size); +if (rdev->doorbell.ptr ==NULL ) { +return -ENOMEM ; + } +DRM_INFO ("doorbell mmio base: 0x%08X\n" , (uint32_t )rdev->doorbell.base); +DRM_INFO ("doorbell mmio size: %u\n" , (unsigned )rdev->doorbell.size); + + rdev->doorbell.num_pages = rdev->doorbell.size /PAGE_SIZE ; + +for (i =0 ; i < rdev->doorbell.num_pages; i++) { + rdev->doorbell.free[i] = true; + } +return 0 ; +} + +/** +* radeon_doorbell_fini - Tear down doorbell driver information. +* +* @rdev: radeon_device pointer +* +* Tear down doorbell driver information (CIK) +*/ +void radeon_doorbell_fini (struct radeon_device *rdev) +{ +iounmap (rdev->doorbell.ptr); + rdev->doorbell.ptr =NULL ; +} + +/** +* radeon_doorbell_get - Allocate a doorbell page +* +* @rdev: radeon_device pointer +* @doorbell: doorbell page number +* +* Allocate a doorbell page for use by the driver (all asics). +* Returns 0 on success or -EINVAL on failure. +*/ +int radeon_doorbell_get (struct radeon_device *rdev,u32 *doorbell) +{ +int i; + +for (i =0 ; i < rdev->doorbell.num_pages; i++) { +if (rdev->doorbell.free[i]) { + rdev->doorbell.free[i] = false; + *doorbell = i; +return 0 ; + } + } +return -EINVAL ; +} + +/** +* radeon_doorbell_free - Free a doorbell page +* +* @rdev: radeon_device pointer +* @doorbell: doorbell page number +* +* Free a doorbell page allocated for use by the driver (all asics) +*/ +void radeon_doorbell_free (struct radeon_device *rdev,u32 doorbell) +{ +if (doorbell < rdev->doorbell.num_pages) + rdev->doorbell.free[doorbell] = true; +} + +/* * radeon_wb_*() * Writeback is the the method by which the the GPU updates special pages * in memory with the status of certain GPU events (fences, ring pointers, @@ -1162,6 +1250,10 @@ int radeon_device_init(struct radeon_device *rdev,DRM_INFO ("register mmio base: 0x%08X\n" , (uint32_t )rdev->rmmio_base);DRM_INFO ("register mmio size: %u\n" , (unsigned )rdev->rmmio_size); +/* doorbell bar mapping */ +if (rdev->family >=CHIP_BONAIRE ) +radeon_doorbell_init (rdev); +/* io port mapping */ for (i =0 ; i <DEVICE_COUNT_RESOURCE ; i++) {if (pci_resource_flags (rdev->pdev, i) &IORESOURCE_IO ) {@@ -1239,6 +1331,8 @@ void radeon_device_fini(struct radeon_device *rdev) rdev->rio_mem =NULL ;iounmap (rdev->rmmio); rdev->rmmio =NULL ; +if (rdev->family >=CHIP_BONAIRE ) +radeon_doorbell_fini (rdev);radeon_debugfs_remove_files (rdev); }Signature · 6 lines
1.7.7.5 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 051/165] drm/radeon: implement simple doorbell page allocator
Quoted 7 lines · Jerome Glisse
Quoted 6 lines · On Wed, Jun 26, 2013 at 09:22:11AM -0400, [email protected] wrote:
From: Alex Deucher <[email protected]>
The doorbell aperture is a PCI BAR whose pages can be mapped to compute resources for things like wptrs for userspace queues.
Quoted 6 lines
Quoted 2 lines
This patch maps the BAR and sets up a simple allocator to allocate pages from the BAR.
This doorbell stuff is cryptic, is that some memory on the GPU ? Or is it more like a register file ? ie what is backing the pci bar.
There's no memory backing it. It's just an aperture that the GPU can selectively listens to. You assign dw offsets from the doorbell aperture for things like the wrptr for compute rings. When the driver or process write a new wtpr value to the offset assigned to it's specific ring, the GPU starts processing it. Like ringing a doorbell.
Alex
Quoted 242 lines
Also probably want to use bitmap as i dont think gcc will turn bool array into a bitmap.
Cheers,
JeromeQuoted 236 lines
Signed-off-by Alex Deucher <[email protected]>--- drivers/gpu/drm/radeon/cik.c | 38 +++++++++++++ drivers/gpu/drm/radeon/radeon.h | 21 +++++++ drivers/gpu/drm/radeon/radeon_device.c | 94 ++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 0 deletions(-)drivers/gpu/drm/radeon/cik.c +38
-0@@ -121,6 +121,44 @@ u32 cik_get_xclk(struct radeon_device *rdev)return reference_clock; } +/** +* cik_mm_rdoorbell - read a doorbell dword +* +* @rdev: radeon_device pointer +* @offset: byte offset into the aperture +* +* Returns the value in the doorbell aperture at the +* requested offset (CIK). +*/ +u32 cik_mm_rdoorbell (struct radeon_device *rdev,u32 offset) +{ +if (offset < rdev->doorbell.size) { +return readl (((void __iomem *)rdev->doorbell.ptr) + offset); + }else { +DRM_ERROR ("reading beyond doorbell aperture: 0x%08x!\n" , offset); +return 0 ; + } +} + +/** +* cik_mm_wdoorbell - write a doorbell dword +* +* @rdev: radeon_device pointer +* @offset: byte offset into the aperture +* @v: value to write +* +* Writes @v to the doorbell aperture at the +* requested offset (CIK). +*/ +void cik_mm_wdoorbell (struct radeon_device *rdev,u32 offset,u32 v) +{ +if (offset < rdev->doorbell.size) { +writel (v, ((void __iomem *)rdev->doorbell.ptr) + offset); + }else { +DRM_ERROR ("writing beyond doorbell aperture: 0x%08x!\n" , offset); + } +} +#define BONAIRE_IO_MC_REGS_SIZE 36 static const u32 bonaire_io_mc_regs[BONAIRE_IO_MC_REGS_SIZE][2] =drivers/gpu/drm/radeon/radeon.h +21
-0@@ -556,6 +556,20 @@ struct radeon_scratch {int radeon_scratch_get (struct radeon_device *rdev,uint32_t *reg);void radeon_scratch_free (struct radeon_device *rdev,uint32_t reg); +/* +* GPU doorbell structures, functions & helpers +*/ +struct radeon_doorbell { +u32 num_pages; +bool free[1024 ]; +/* doorbell mmio */ +resource_size_t base; +resource_size_t size; +void __iomem *ptr; +}; + +int radeon_doorbell_get (struct radeon_device *rdev,u32 *page); +void radeon_doorbell_free (struct radeon_device *rdev,u32 doorbell);/* * IRQS. @@ -1711,6 +1725,7 @@ struct radeon_device {struct radeon_gart gart;struct radeon_mode_info mode_info;struct radeon_scratch scratch; +struct radeon_doorbell doorbell;struct radeon_mman mman;struct radeon_fence_driver fence_drv[RADEON_NUM_RINGS ];wait_queue_head_t fence_queue;@@ -1784,6 +1799,9 @@ void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v,u32 r100_io_rreg (struct radeon_device *rdev,u32 reg);void r100_io_wreg (struct radeon_device *rdev,u32 reg,u32 v); +u32 cik_mm_rdoorbell (struct radeon_device *rdev,u32 offset); +void cik_mm_wdoorbell (struct radeon_device *rdev,u32 offset,u32 v); +/* * Cast helper */ @@ -1833,6 +1851,9 @@ void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v);#define RREG32_IO (reg) r100_io_rreg(rdev, (reg))#define WREG32_IO (reg, v) r100_io_wreg(rdev, (reg), (v)) +#define RDOORBELL32 (offset) cik_mm_rdoorbell(rdev, (offset)) +#define WDOORBELL32 (offset, v) cik_mm_wdoorbell(rdev, (offset), (v)) +/* * Indirect registers accessor */ drivers/gpu/drm/radeon/radeon_device.c +94
-1@@ -232,6 +232,94 @@ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) }/* +* GPU doorbell aperture helpers function. +*/ +/** +* radeon_doorbell_init - Init doorbell driver information. +* +* @rdev: radeon_device pointer +* +* Init doorbell driver information (CIK) +* Returns 0 on success, error on failure. +*/ +int radeon_doorbell_init (struct radeon_device *rdev) +{ +int i; + +/* doorbell bar mapping */ + rdev->doorbell.base =pci_resource_start (rdev->pdev,2 ); + rdev->doorbell.size =pci_resource_len (rdev->pdev,2 ); + +/* limit to 4 MB for now */ +if (rdev->doorbell.size > (4 *1024 *1024 )) + rdev->doorbell.size =4 *1024 *1024 ; + + rdev->doorbell.ptr =ioremap (rdev->doorbell.base, rdev->doorbell.size); +if (rdev->doorbell.ptr ==NULL ) { +return -ENOMEM ; + } +DRM_INFO ("doorbell mmio base: 0x%08X\n" , (uint32_t )rdev->doorbell.base); +DRM_INFO ("doorbell mmio size: %u\n" , (unsigned )rdev->doorbell.size); + + rdev->doorbell.num_pages = rdev->doorbell.size /PAGE_SIZE ; + +for (i =0 ; i < rdev->doorbell.num_pages; i++) { + rdev->doorbell.free[i] = true; + } +return 0 ; +} + +/** +* radeon_doorbell_fini - Tear down doorbell driver information. +* +* @rdev: radeon_device pointer +* +* Tear down doorbell driver information (CIK) +*/ +void radeon_doorbell_fini (struct radeon_device *rdev) +{ +iounmap (rdev->doorbell.ptr); + rdev->doorbell.ptr =NULL ; +} + +/** +* radeon_doorbell_get - Allocate a doorbell page +* +* @rdev: radeon_device pointer +* @doorbell: doorbell page number +* +* Allocate a doorbell page for use by the driver (all asics). +* Returns 0 on success or -EINVAL on failure. +*/ +int radeon_doorbell_get (struct radeon_device *rdev,u32 *doorbell) +{ +int i; + +for (i =0 ; i < rdev->doorbell.num_pages; i++) { +if (rdev->doorbell.free[i]) { + rdev->doorbell.free[i] = false; + *doorbell = i; +return 0 ; + } + } +return -EINVAL ; +} + +/** +* radeon_doorbell_free - Free a doorbell page +* +* @rdev: radeon_device pointer +* @doorbell: doorbell page number +* +* Free a doorbell page allocated for use by the driver (all asics) +*/ +void radeon_doorbell_free (struct radeon_device *rdev,u32 doorbell) +{ +if (doorbell < rdev->doorbell.num_pages) + rdev->doorbell.free[doorbell] = true; +} + +/* * radeon_wb_*() * Writeback is the the method by which the the GPU updates special pages * in memory with the status of certain GPU events (fences, ring pointers, @@ -1162,6 +1250,10 @@ int radeon_device_init(struct radeon_device *rdev,DRM_INFO ("register mmio base: 0x%08X\n" , (uint32_t )rdev->rmmio_base);DRM_INFO ("register mmio size: %u\n" , (unsigned )rdev->rmmio_size); +/* doorbell bar mapping */ +if (rdev->family >=CHIP_BONAIRE ) +radeon_doorbell_init (rdev); +/* io port mapping */ for (i =0 ; i <DEVICE_COUNT_RESOURCE ; i++) {if (pci_resource_flags (rdev->pdev, i) &IORESOURCE_IO ) {@@ -1239,6 +1331,8 @@ void radeon_device_fini(struct radeon_device *rdev) rdev->rio_mem =NULL ;iounmap (rdev->rmmio); rdev->rmmio =NULL ; +if (rdev->family >=CHIP_BONAIRE ) +radeon_doorbell_fini (rdev);radeon_debugfs_remove_files (rdev); } --1.7.7.5
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 52/165 drm/radeon/cik: Add support for compute queues (v2)
In reply to [email protected]From: Alex Deucher <[email protected]>
On CIK, the compute rings work slightly differently than on previous asics, however the basic concepts are the same.
The main differences:
- New MEC engines for compute queues
- Multiple queues per MEC:
- CI/KB: 1 MEC, 4 pipes per MEC, 8 queues per pipe = 32 queues
- KV: 2 MEC, 4 pipes per MEC, 8 queues per pipe = 64 queues
- Queues can be allocated and scheduled by another queue
- New doorbell aperture allows you to assign space in the aperture for the wptr which allows for userspace access to queues
v2: add wptr shadow, fix eop setup
--- drivers/gpu/drm/radeon/cik.c | 528 +++++++++++++++++++++++++++++++++++- drivers/gpu/drm/radeon/cikd.h | 62 +++++ drivers/gpu/drm/radeon/radeon.h | 19 ++ drivers/gpu/drm/radeon/radeon_cs.c | 4 +- 4 files changed, 601 insertions(+), 12 deletions(-)
drivers/gpu/drm/radeon/cik.c +519 -9
@@ -1687,6 +1687,7 @@ int cik_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)radeon_ring_write (ring, ((scratch -PACKET3_SET_UCONFIG_REG_START ) >>2 ));radeon_ring_write (ring,0xDEADBEEF );radeon_ring_unlock_commit (rdev, ring); +for (i =0 ; i < rdev->usec_timeout; i++) { tmp =RREG32 (scratch);if (tmp ==0xDEADBEEF )
@@ -2112,6 +2113,51 @@ static int cik_cp_gfx_resume(struct radeon_device *rdev)return 0 ; } +static u32 cik_compute_ring_get_rptr (struct radeon_device *rdev, +struct radeon_ring *ring) +{ +u32 rptr; + + + +if (rdev->wb.enabled) { + rptr =le32_to_cpu (rdev->wb.wb[ring->rptr_offs/4 ]); + }else { +cik_srbm_select (rdev, ring->me, ring->pipe, ring->queue,0 ); + rptr =RREG32 (CP_HQD_PQ_RPTR ); +cik_srbm_select (rdev,0 ,0 ,0 ,0 ); + } + rptr = (rptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift; + +return rptr; +} + +static u32 cik_compute_ring_get_wptr (struct radeon_device *rdev, +struct radeon_ring *ring) +{ +u32 wptr; + +if (rdev->wb.enabled) { + wptr =le32_to_cpu (rdev->wb.wb[ring->wptr_offs/4 ]); + }else { +cik_srbm_select (rdev, ring->me, ring->pipe, ring->queue,0 ); + wptr =RREG32 (CP_HQD_PQ_WPTR ); +cik_srbm_select (rdev,0 ,0 ,0 ,0 ); + } + wptr = (wptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift; + +return wptr; +} + +static void cik_compute_ring_set_wptr (struct radeon_device *rdev, +struct radeon_ring *ring) +{ +u32 wptr = (ring->wptr << ring->ptr_reg_shift) & ring->ptr_reg_mask; + + rdev->wb.wb[ring->wptr_offs/4 ] =cpu_to_le32 (wptr); +WDOORBELL32 (ring->doorbell_offset, wptr); +} +/** * cik_cp_compute_enable - enable/disable the compute CP MEs *
@@ -2176,7 +2222,8 @@ static int cik_cp_compute_load_microcode(struct radeon_device *rdev)*/ static int cik_cp_compute_start (struct radeon_device *rdev) { -//todo +cik_cp_compute_enable (rdev, true); +return 0 ; }
@@ -2190,10 +2237,171 @@ static int cik_cp_compute_start(struct radeon_device *rdev)*/ static void cik_cp_compute_fini (struct radeon_device *rdev) { +int i, idx, r; +cik_cp_compute_enable (rdev, false); -//todo + +for (i =0 ; i <2 ; i++) { +if (i ==0 ) + idx =CAYMAN_RING_TYPE_CP1_INDEX ; +else + idx =CAYMAN_RING_TYPE_CP2_INDEX ; + +if (rdev->ring[idx].mqd_obj) { + r =radeon_bo_reserve (rdev->ring[idx].mqd_obj, false); +if (unlikely (r !=0 )) +dev_warn (rdev->dev,"(%d) reserve MQD bo failed\n" , r); + +radeon_bo_unpin (rdev->ring[idx].mqd_obj); +radeon_bo_unreserve (rdev->ring[idx].mqd_obj); + +radeon_bo_unref (&rdev->ring[idx].mqd_obj); + rdev->ring[idx].mqd_obj =NULL ; + } + } +} + +static void cik_mec_fini (struct radeon_device *rdev) +{ +int r; + +if (rdev->mec.hpd_eop_obj) { + r =radeon_bo_reserve (rdev->mec.hpd_eop_obj, false); +if (unlikely (r !=0 )) +dev_warn (rdev->dev,"(%d) reserve HPD EOP bo failed\n" , r); +radeon_bo_unpin (rdev->mec.hpd_eop_obj); +radeon_bo_unreserve (rdev->mec.hpd_eop_obj); + +radeon_bo_unref (&rdev->mec.hpd_eop_obj); + rdev->mec.hpd_eop_obj =NULL ; + } +} + +#define MEC_HPD_SIZE 2048 + +static int cik_mec_init (struct radeon_device *rdev) +{ +int r; +u32 *hpd; + +/* +* KV: 2 MEC, 4 Pipes/MEC, 8 Queues/Pipe - 64 Queues total +* CI/KB: 1 MEC, 4 Pipes/MEC, 8 Queues/Pipe - 32 Queues total +*/ +if (rdev->family ==CHIP_KAVERI ) + rdev->mec.num_mec =2 ; +else + rdev->mec.num_mec =1 ; + rdev->mec.num_pipe =4 ; + rdev->mec.num_queue = rdev->mec.num_mec * rdev->mec.num_pipe *8 ; + +if (rdev->mec.hpd_eop_obj ==NULL ) { + r =radeon_bo_create (rdev, + rdev->mec.num_mec *rdev->mec.num_pipe *MEC_HPD_SIZE *2 , +PAGE_SIZE , true, +RADEON_GEM_DOMAIN_GTT ,NULL , + &rdev->mec.hpd_eop_obj); +if (r) { +dev_warn (rdev->dev,"(%d) create HDP EOP bo failed\n" , r); +return r; + } + } + + r =radeon_bo_reserve (rdev->mec.hpd_eop_obj, false); +if (unlikely (r !=0 )) { +cik_mec_fini (rdev); +return r; + } + r =radeon_bo_pin (rdev->mec.hpd_eop_obj,RADEON_GEM_DOMAIN_GTT , + &rdev->mec.hpd_eop_gpu_addr); +if (r) { +dev_warn (rdev->dev,"(%d) pin HDP EOP bo failed\n" , r); +cik_mec_fini (rdev); +return r; + } + r =radeon_bo_kmap (rdev->mec.hpd_eop_obj, (void **)&hpd); +if (r) { +dev_warn (rdev->dev,"(%d) map HDP EOP bo failed\n" , r); +cik_mec_fini (rdev); +return r; + } + +/* clear memory. Not sure if this is required or not */ +memset (hpd,0 , rdev->mec.num_mec *rdev->mec.num_pipe *MEC_HPD_SIZE *2 ); + +radeon_bo_kunmap (rdev->mec.hpd_eop_obj); +radeon_bo_unreserve (rdev->mec.hpd_eop_obj); + +return 0 ; } +struct hqd_registers +{ +u32 cp_mqd_base_addr; +u32 cp_mqd_base_addr_hi; +u32 cp_hqd_active; +u32 cp_hqd_vmid; +u32 cp_hqd_persistent_state; +u32 cp_hqd_pipe_priority; +u32 cp_hqd_queue_priority; +u32 cp_hqd_quantum; +u32 cp_hqd_pq_base; +u32 cp_hqd_pq_base_hi; +u32 cp_hqd_pq_rptr; +u32 cp_hqd_pq_rptr_report_addr; +u32 cp_hqd_pq_rptr_report_addr_hi; +u32 cp_hqd_pq_wptr_poll_addr; +u32 cp_hqd_pq_wptr_poll_addr_hi; +u32 cp_hqd_pq_doorbell_control; +u32 cp_hqd_pq_wptr; +u32 cp_hqd_pq_control; +u32 cp_hqd_ib_base_addr; +u32 cp_hqd_ib_base_addr_hi; +u32 cp_hqd_ib_rptr; +u32 cp_hqd_ib_control; +u32 cp_hqd_iq_timer; +u32 cp_hqd_iq_rptr; +u32 cp_hqd_dequeue_request; +u32 cp_hqd_dma_offload; +u32 cp_hqd_sema_cmd; +u32 cp_hqd_msg_type; +u32 cp_hqd_atomic0_preop_lo; +u32 cp_hqd_atomic0_preop_hi; +u32 cp_hqd_atomic1_preop_lo; +u32 cp_hqd_atomic1_preop_hi; +u32 cp_hqd_hq_scheduler0; +u32 cp_hqd_hq_scheduler1; +u32 cp_mqd_control; +}; + +struct bonaire_mqd +{ +u32 header; +u32 dispatch_initiator; +u32 dimensions[3 ]; +u32 start_idx[3 ]; +u32 num_threads[3 ]; +u32 pipeline_stat_enable; +u32 perf_counter_enable; +u32 pgm[2 ]; +u32 tba[2 ]; +u32 tma[2 ]; +u32 pgm_rsrc[2 ]; +u32 vmid; +u32 resource_limits; +u32 static_thread_mgmt01[2 ]; +u32 tmp_ring_size; +u32 static_thread_mgmt23[2 ]; +u32 restart[3 ]; +u32 thread_trace_enable; +u32 reserved1; +u32 user_data[16 ]; +u32 vgtcs_invoke_count[2 ]; +struct hqd_registers queue_state; +u32 dequeue_cntr; +u32 interrupt_queue[64 ]; +}; +/** * cik_cp_compute_resume - setup the compute queue registers *
@@ -2205,24 +2413,247 @@ static void cik_cp_compute_fini(struct radeon_device *rdev)*/ static int cik_cp_compute_resume (struct radeon_device *rdev) { -int r; +int r, i, idx; +u32 tmp; +bool use_doorbell = true; +u64 hqd_gpu_addr; +u64 mqd_gpu_addr; +u64 eop_gpu_addr; +u64 wb_gpu_addr; +u32 *buf; +struct bonaire_mqd *mqd; -//todo r =cik_cp_compute_start (rdev);if (r)return r; + +/* fix up chicken bits */ + tmp =RREG32 (CP_CPF_DEBUG ); + tmp |= (1 <<23 ); +WREG32 (CP_CPF_DEBUG , tmp); + +/* init the pipes */ +for (i =0 ; i < (rdev->mec.num_pipe * rdev->mec.num_mec); i++) { +int me = (i <4 ) ?1 :2 ; +int pipe = (i <4 ) ? i : (i -4 ); + + eop_gpu_addr = rdev->mec.hpd_eop_gpu_addr + (i *MEC_HPD_SIZE *2 ); + +cik_srbm_select (rdev, me, pipe,0 ,0 ); + +/* write the EOP addr */ +WREG32 (CP_HPD_EOP_BASE_ADDR , eop_gpu_addr >>8 ); +WREG32 (CP_HPD_EOP_BASE_ADDR_HI ,upper_32_bits (eop_gpu_addr) >>8 ); + +/* set the VMID assigned */ +WREG32 (CP_HPD_EOP_VMID ,0 ); + +/* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */ + tmp =RREG32 (CP_HPD_EOP_CONTROL ); + tmp &= ~EOP_SIZE_MASK ; + tmp |=drm_order (MEC_HPD_SIZE /8 ); +WREG32 (CP_HPD_EOP_CONTROL , tmp); + } +cik_srbm_select (rdev,0 ,0 ,0 ,0 ); + +/* init the queues. Just two for now. */ +for (i =0 ; i <2 ; i++) { +if (i ==0 ) + idx =CAYMAN_RING_TYPE_CP1_INDEX ; +else + idx =CAYMAN_RING_TYPE_CP2_INDEX ; + +if (rdev->ring[idx].mqd_obj ==NULL ) { + r =radeon_bo_create (rdev, +sizeof (struct bonaire_mqd ), +PAGE_SIZE , true, +RADEON_GEM_DOMAIN_GTT ,NULL , + &rdev->ring[idx].mqd_obj); +if (r) { +dev_warn (rdev->dev,"(%d) create MQD bo failed\n" , r); +return r; + } + } + + r =radeon_bo_reserve (rdev->ring[idx].mqd_obj, false); +if (unlikely (r !=0 )) { +cik_cp_compute_fini (rdev); +return r; + } + r =radeon_bo_pin (rdev->ring[idx].mqd_obj,RADEON_GEM_DOMAIN_GTT , + &mqd_gpu_addr); +if (r) { +dev_warn (rdev->dev,"(%d) pin MQD bo failed\n" , r); +cik_cp_compute_fini (rdev); +return r; + } + r =radeon_bo_kmap (rdev->ring[idx].mqd_obj, (void **)&buf); +if (r) { +dev_warn (rdev->dev,"(%d) map MQD bo failed\n" , r); +cik_cp_compute_fini (rdev); +return r; + } + +/* doorbell offset */ + rdev->ring[idx].doorbell_offset = + (rdev->ring[idx].doorbell_page_num *PAGE_SIZE ) +0 ; + +/* init the mqd struct */ +memset (buf,0 ,sizeof (struct bonaire_mqd )); + + mqd = (struct bonaire_mqd *)buf; + mqd->header =0xC0310800 ; + mqd->static_thread_mgmt01[0 ] =0xffffffff ; + mqd->static_thread_mgmt01[1 ] =0xffffffff ; + mqd->static_thread_mgmt23[0 ] =0xffffffff ; + mqd->static_thread_mgmt23[1 ] =0xffffffff ; + +cik_srbm_select (rdev, rdev->ring[idx].me, + rdev->ring[idx].pipe, + rdev->ring[idx].queue,0 ); + +/* disable wptr polling */ + tmp =RREG32 (CP_PQ_WPTR_POLL_CNTL ); + tmp &= ~WPTR_POLL_EN ; +WREG32 (CP_PQ_WPTR_POLL_CNTL , tmp); + +/* enable doorbell? */ + mqd->queue_state.cp_hqd_pq_doorbell_control = +RREG32 (CP_HQD_PQ_DOORBELL_CONTROL ); +if (use_doorbell) + mqd->queue_state.cp_hqd_pq_doorbell_control |=DOORBELL_EN ; +else + mqd->queue_state.cp_hqd_pq_doorbell_control &= ~DOORBELL_EN ; +WREG32 (CP_HQD_PQ_DOORBELL_CONTROL , + mqd->queue_state.cp_hqd_pq_doorbell_control); + +/* disable the queue if it's active */ + mqd->queue_state.cp_hqd_dequeue_request =0 ; + mqd->queue_state.cp_hqd_pq_rptr =0 ; + mqd->queue_state.cp_hqd_pq_wptr=0 ; +if (RREG32 (CP_HQD_ACTIVE ) &1 ) { +WREG32 (CP_HQD_DEQUEUE_REQUEST ,1 ); +for (i =0 ; i < rdev->usec_timeout; i++) { +if (!(RREG32 (CP_HQD_ACTIVE ) &1 )) +break ; +udelay (1 ); + } +WREG32 (CP_HQD_DEQUEUE_REQUEST , mqd->queue_state.cp_hqd_dequeue_request); +WREG32 (CP_HQD_PQ_RPTR , mqd->queue_state.cp_hqd_pq_rptr); +WREG32 (CP_HQD_PQ_WPTR , mqd->queue_state.cp_hqd_pq_wptr); + } + +/* set the pointer to the MQD */ + mqd->queue_state.cp_mqd_base_addr = mqd_gpu_addr &0xfffffffc ; + mqd->queue_state.cp_mqd_base_addr_hi =upper_32_bits (mqd_gpu_addr); +WREG32 (CP_MQD_BASE_ADDR , mqd->queue_state.cp_mqd_base_addr); +WREG32 (CP_MQD_BASE_ADDR_HI , mqd->queue_state.cp_mqd_base_addr_hi); +/* set MQD vmid to 0 */ + mqd->queue_state.cp_mqd_control =RREG32 (CP_MQD_CONTROL ); + mqd->queue_state.cp_mqd_control &= ~MQD_VMID_MASK ; +WREG32 (CP_MQD_CONTROL , mqd->queue_state.cp_mqd_control); + +/* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */ + hqd_gpu_addr = rdev->ring[idx].gpu_addr >>8 ; + mqd->queue_state.cp_hqd_pq_base = hqd_gpu_addr; + mqd->queue_state.cp_hqd_pq_base_hi =upper_32_bits (hqd_gpu_addr); +WREG32 (CP_HQD_PQ_BASE , mqd->queue_state.cp_hqd_pq_base); +WREG32 (CP_HQD_PQ_BASE_HI , mqd->queue_state.cp_hqd_pq_base_hi); + +/* set up the HQD, this is similar to CP_RB0_CNTL */ + mqd->queue_state.cp_hqd_pq_control =RREG32 (CP_HQD_PQ_CONTROL ); + mqd->queue_state.cp_hqd_pq_control &= + ~(QUEUE_SIZE_MASK |RPTR_BLOCK_SIZE_MASK ); + + mqd->queue_state.cp_hqd_pq_control |= +drm_order (rdev->ring[idx].ring_size /8 ); + mqd->queue_state.cp_hqd_pq_control |= + (drm_order (RADEON_GPU_PAGE_SIZE /8 ) <<8 ); +#ifdef __BIG_ENDIAN + mqd->queue_state.cp_hqd_pq_control |=BUF_SWAP_32BIT ; +#endif + mqd->queue_state.cp_hqd_pq_control &= + ~(UNORD_DISPATCH |ROQ_PQ_IB_FLIP |PQ_VOLATILE ); + mqd->queue_state.cp_hqd_pq_control |= +PRIV_STATE |KMD_QUEUE ;/* assuming kernel queue control */ +WREG32 (CP_HQD_PQ_CONTROL , mqd->queue_state.cp_hqd_pq_control); + +/* only used if CP_PQ_WPTR_POLL_CNTL.WPTR_POLL_EN=1 */ +if (i ==0 ) + wb_gpu_addr = rdev->wb.gpu_addr +CIK_WB_CP1_WPTR_OFFSET ; +else + wb_gpu_addr = rdev->wb.gpu_addr +CIK_WB_CP2_WPTR_OFFSET ; + mqd->queue_state.cp_hqd_pq_wptr_poll_addr = wb_gpu_addr &0xfffffffc ; + mqd->queue_state.cp_hqd_pq_wptr_poll_addr_hi =upper_32_bits (wb_gpu_addr) &0xffff ; +WREG32 (CP_HQD_PQ_WPTR_POLL_ADDR , mqd->queue_state.cp_hqd_pq_wptr_poll_addr); +WREG32 (CP_HQD_PQ_WPTR_POLL_ADDR_HI , + mqd->queue_state.cp_hqd_pq_wptr_poll_addr_hi); + +/* set the wb address wether it's enabled or not */ +if (i ==0 ) + wb_gpu_addr = rdev->wb.gpu_addr +RADEON_WB_CP1_RPTR_OFFSET ; +else + wb_gpu_addr = rdev->wb.gpu_addr +RADEON_WB_CP2_RPTR_OFFSET ; + mqd->queue_state.cp_hqd_pq_rptr_report_addr = wb_gpu_addr &0xfffffffc ; + mqd->queue_state.cp_hqd_pq_rptr_report_addr_hi = +upper_32_bits (wb_gpu_addr) &0xffff ; +WREG32 (CP_HQD_PQ_RPTR_REPORT_ADDR , + mqd->queue_state.cp_hqd_pq_rptr_report_addr); +WREG32 (CP_HQD_PQ_RPTR_REPORT_ADDR_HI , + mqd->queue_state.cp_hqd_pq_rptr_report_addr_hi); + +/* enable the doorbell if requested */ +if (use_doorbell) { + mqd->queue_state.cp_hqd_pq_doorbell_control = +RREG32 (CP_HQD_PQ_DOORBELL_CONTROL ); + mqd->queue_state.cp_hqd_pq_doorbell_control &= ~DOORBELL_OFFSET_MASK ; + mqd->queue_state.cp_hqd_pq_doorbell_control |= +DOORBELL_OFFSET (rdev->ring[idx].doorbell_offset /4 ); + mqd->queue_state.cp_hqd_pq_doorbell_control |=DOORBELL_EN ; + mqd->queue_state.cp_hqd_pq_doorbell_control &= + ~(DOORBELL_SOURCE |DOORBELL_HIT ); + + }else { + mqd->queue_state.cp_hqd_pq_doorbell_control =0 ; + } +WREG32 (CP_HQD_PQ_DOORBELL_CONTROL , + mqd->queue_state.cp_hqd_pq_doorbell_control); + +/* read and write pointers, similar to CP_RB0_WPTR/_RPTR */ + rdev->ring[idx].wptr =0 ; + mqd->queue_state.cp_hqd_pq_wptr = rdev->ring[idx].wptr; +WREG32 (CP_HQD_PQ_WPTR , mqd->queue_state.cp_hqd_pq_wptr); + rdev->ring[idx].rptr =RREG32 (CP_HQD_PQ_RPTR ); + mqd->queue_state.cp_hqd_pq_rptr = rdev->ring[idx].rptr; + +/* set the vmid for the queue */ + mqd->queue_state.cp_hqd_vmid =0 ; +WREG32 (CP_HQD_VMID , mqd->queue_state.cp_hqd_vmid); + +/* activate the queue */ + mqd->queue_state.cp_hqd_active =1 ; +WREG32 (CP_HQD_ACTIVE , mqd->queue_state.cp_hqd_active); + +cik_srbm_select (rdev,0 ,0 ,0 ,0 ); + +radeon_bo_kunmap (rdev->ring[idx].mqd_obj); +radeon_bo_unreserve (rdev->ring[idx].mqd_obj); + + rdev->ring[idx].ready = true; + r =radeon_ring_test (rdev, idx, &rdev->ring[idx]); +if (r) + rdev->ring[idx].ready = false; + } +return 0 ; } -/* XXX temporary wrappers to handle both compute and gfx */ -/* XXX */ static void cik_cp_enable (struct radeon_device *rdev,bool enable) {cik_cp_gfx_enable (rdev, enable);cik_cp_compute_enable (rdev, enable); } -/* XXX */ static int cik_cp_load_microcode (struct radeon_device *rdev) {int r;
@@ -2237,14 +2668,12 @@ static int cik_cp_load_microcode(struct radeon_device *rdev)return 0 ; } -/* XXX */ static void cik_cp_fini (struct radeon_device *rdev) {cik_cp_gfx_fini (rdev);cik_cp_compute_fini (rdev); } -/* XXX */ static int cik_cp_resume (struct radeon_device *rdev) {int r;
@@ -2865,6 +3294,22 @@ static void cik_print_gpu_status_regs(struct radeon_device *rdev) RREG32(SDMA0_STATUS_REG + SDMA0_REGISTER_OFFSET));dev_info (rdev->dev," SDMA1_STATUS_REG = 0x%08X\n" ,RREG32 (SDMA0_STATUS_REG +SDMA1_REGISTER_OFFSET )); +dev_info (rdev->dev," CP_STAT = 0x%08x\n" ,RREG32 (CP_STAT )); +dev_info (rdev->dev," CP_STALLED_STAT1 = 0x%08x\n" , +RREG32 (CP_STALLED_STAT1 )); +dev_info (rdev->dev," CP_STALLED_STAT2 = 0x%08x\n" , +RREG32 (CP_STALLED_STAT2 )); +dev_info (rdev->dev," CP_STALLED_STAT3 = 0x%08x\n" , +RREG32 (CP_STALLED_STAT3 )); +dev_info (rdev->dev," CP_CPF_BUSY_STAT = 0x%08x\n" , +RREG32 (CP_CPF_BUSY_STAT )); +dev_info (rdev->dev," CP_CPF_STALLED_STAT1 = 0x%08x\n" , +RREG32 (CP_CPF_STALLED_STAT1 )); +dev_info (rdev->dev," CP_CPF_STATUS = 0x%08x\n" ,RREG32 (CP_CPF_STATUS )); +dev_info (rdev->dev," CP_CPC_BUSY_STAT = 0x%08x\n" ,RREG32 (CP_CPC_BUSY_STAT )); +dev_info (rdev->dev," CP_CPC_STALLED_STAT1 = 0x%08x\n" , +RREG32 (CP_CPC_STALLED_STAT1 )); +dev_info (rdev->dev," CP_CPC_STATUS = 0x%08x\n" ,RREG32 (CP_CPC_STATUS )); }/**
@@ -4952,12 +5397,31 @@ static int cik_startup(struct radeon_device *rdev)if (r)return r; +/* allocate rlc buffers */ + r =cik_mec_init (rdev); +if (r) { +DRM_ERROR ("Failed to init MEC BOs!\n" ); +return r; + } + r =radeon_fence_driver_start_ring (rdev,RADEON_RING_TYPE_GFX_INDEX );if (r) {dev_err (rdev->dev,"failed initializing CP fences (%d).\n" , r);return r; } + r =radeon_fence_driver_start_ring (rdev,CAYMAN_RING_TYPE_CP1_INDEX ); +if (r) { +dev_err (rdev->dev,"failed initializing CP fences (%d).\n" , r); +return r; + } + + r =radeon_fence_driver_start_ring (rdev,CAYMAN_RING_TYPE_CP2_INDEX ); +if (r) { +dev_err (rdev->dev,"failed initializing CP fences (%d).\n" , r); +return r; + } + r =radeon_fence_driver_start_ring (rdev,R600_RING_TYPE_DMA_INDEX );if (r) {dev_err (rdev->dev,"failed initializing DMA fences (%d).\n" , r);
@@ -5002,6 +5466,36 @@ static int cik_startup(struct radeon_device *rdev)if (r)return r; +/* set up the compute queues */ + ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX ]; + r =radeon_ring_init (rdev, ring, ring->ring_size,RADEON_WB_CP1_RPTR_OFFSET , +CP_HQD_PQ_RPTR ,CP_HQD_PQ_WPTR , +0 ,0xfffff ,RADEON_CP_PACKET2 ); +if (r) +return r; + ring->me =1 ;/* first MEC */ + ring->pipe =0 ;/* first pipe */ + ring->queue =0 ;/* first queue */ + ring->wptr_offs =CIK_WB_CP1_WPTR_OFFSET ; + ring->funcs.get_rptr = &cik_compute_ring_get_rptr; + ring->funcs.get_wptr = &cik_compute_ring_get_wptr; + ring->funcs.set_wptr = &cik_compute_ring_set_wptr; + + ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX ]; + r =radeon_ring_init (rdev, ring, ring->ring_size,RADEON_WB_CP2_RPTR_OFFSET , +CP_HQD_PQ_RPTR ,CP_HQD_PQ_WPTR , +0 ,0xffffffff ,RADEON_CP_PACKET2 ); +if (r) +return r; +/* dGPU only have 1 MEC */ + ring->me =1 ;/* first MEC */ + ring->pipe =0 ;/* first pipe */ + ring->queue =1 ;/* second queue */ + ring->wptr_offs =CIK_WB_CP2_WPTR_OFFSET ; + ring->funcs.get_rptr = &cik_compute_ring_get_rptr; + ring->funcs.get_wptr = &cik_compute_ring_get_wptr; + ring->funcs.set_wptr = &cik_compute_ring_set_wptr; + ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX ]; r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET, SDMA0_GFX_RB_RPTR + SDMA0_REGISTER_OFFSET,
@@ -5176,6 +5670,20 @@ int cik_init(struct radeon_device *rdev) ring->ring_obj =NULL ;r600_ring_init (rdev, ring,1024 *1024 ); + ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX ]; + ring->ring_obj =NULL ; +r600_ring_init (rdev, ring,1024 *1024 ); + r =radeon_doorbell_get (rdev, &ring->doorbell_page_num); +if (r) +return r; + + ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX ]; + ring->ring_obj =NULL ; +r600_ring_init (rdev, ring,1024 *1024 ); + r =radeon_doorbell_get (rdev, &ring->doorbell_page_num); +if (r) +return r; + ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX ]; ring->ring_obj =NULL ;r600_ring_init (rdev, ring,256 *1024 );
@@ -5206,6 +5714,7 @@ int cik_init(struct radeon_device *rdev)cik_sdma_fini (rdev);cik_irq_fini (rdev);si_rlc_fini (rdev); +cik_mec_fini (rdev);radeon_wb_fini (rdev);radeon_ib_pool_fini (rdev);radeon_vm_manager_fini (rdev);
@@ -5241,6 +5750,7 @@ void cik_fini(struct radeon_device *rdev)cik_sdma_fini (rdev);cik_irq_fini (rdev);si_rlc_fini (rdev); +cik_mec_fini (rdev);radeon_wb_fini (rdev);radeon_vm_manager_fini (rdev);radeon_ib_pool_fini (rdev);
drivers/gpu/drm/radeon/cikd.h +62 -0
86 lines not on this page · raw message
drivers/gpu/drm/radeon/radeon.h +19 -0
@@ -714,6 +714,22 @@ struct radeon_ring {u32 (*get_wptr)(struct radeon_device *rdev,struct radeon_ring *ring);void (*set_wptr)(struct radeon_device *rdev,struct radeon_ring *ring); } funcs; +/* for CIK queues */ +u32 me; +u32 pipe; +u32 queue; +struct radeon_bo *mqd_obj; +u32 doorbell_page_num; +u32 doorbell_offset; +unsigned wptr_offs; +}; + +struct radeon_mec { +struct radeon_bo *hpd_eop_obj; +u64 hpd_eop_gpu_addr; +u32 num_pipe; +u32 num_mec; +u32 num_queue; };/*
@@ -971,6 +987,8 @@ struct radeon_wb {#define CAYMAN_WB_DMA1_RPTR_OFFSET 2304#define R600_WB_UVD_RPTR_OFFSET 2560#define R600_WB_EVENT_OFFSET 3072 +#define CIK_WB_CP1_WPTR_OFFSET 3328 +#define CIK_WB_CP2_WPTR_OFFSET 3584/** * struct radeon_pm - power management datas
@@ -1760,6 +1778,7 @@ struct radeon_device {int msi_enabled;/* msi enabled */ struct r600_ih ih;/* r6/700 interrupt ring */ struct si_rlc rlc; +struct radeon_mec mec;struct work_struct hotplug_work;struct work_struct audio_work;struct work_struct reset_work;
drivers/gpu/drm/radeon/radeon_cs.c +1 -3
@@ -121,9 +121,7 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority p->ring =RADEON_RING_TYPE_GFX_INDEX ;break ;case RADEON_CS_RING_COMPUTE : -if (p->rdev->family >=CHIP_BONAIRE ) - p->ring =RADEON_RING_TYPE_GFX_INDEX ; -else if (p->rdev->family >=CHIP_TAHITI ) { +if (p->rdev->family >=CHIP_TAHITI ) {if (p->priority >0 ) p->ring =CAYMAN_RING_TYPE_CP1_INDEX ;else
Signature · 1 line
1.7.7.5
Re: [PATCH 052/165] drm/radeon/cik: Add support for compute queues (v2)
Quoted 14 lines · On Wed, Jun 26, 2013 at 09:22:12AM -0400, [email protected] wrote:
From: Alex Deucher <[email protected]>
On CIK, the compute rings work slightly differently than on previous asics, however the basic concepts are the same.
The main differences:
- New MEC engines for compute queues
- Multiple queues per MEC:
- CI/KB: 1 MEC, 4 pipes per MEC, 8 queues per pipe = 32 queues
- KV: 2 MEC, 4 pipes per MEC, 8 queues per pipe = 64 queues
- Queues can be allocated and scheduled by another queue
- New doorbell aperture allows you to assign space in the aperture for the wptr which allows for userspace access to queues
Quoted 3 lines
v2: add wptr shadow, fix eop setup
Signed-off-by Alex Deucher <[email protected]>
Minor nitpick below otherwise
Quoted 267 lines
--- drivers/gpu/drm/radeon/cik.c | 528 +++++++++++++++++++++++++++++++++++- drivers/gpu/drm/radeon/cikd.h | 62 +++++ drivers/gpu/drm/radeon/radeon.h | 19 ++ drivers/gpu/drm/radeon/radeon_cs.c | 4 +- 4 files changed, 601 insertions(+), 12 deletions(-)drivers/gpu/drm/radeon/cik.c +218
-3@@ -1687,6 +1687,7 @@ int cik_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)radeon_ring_write (ring, ((scratch -PACKET3_SET_UCONFIG_REG_START ) >>2 ));radeon_ring_write (ring,0xDEADBEEF );radeon_ring_unlock_commit (rdev, ring); +for (i =0 ; i < rdev->usec_timeout; i++) { tmp =RREG32 (scratch);if (tmp ==0xDEADBEEF )@@ -2112,6 +2113,51 @@ static int cik_cp_gfx_resume(struct radeon_device *rdev)return 0 ; } +static u32 cik_compute_ring_get_rptr (struct radeon_device *rdev, +struct radeon_ring *ring) +{ +u32 rptr; + + + +if (rdev->wb.enabled) { + rptr =le32_to_cpu (rdev->wb.wb[ring->rptr_offs/4 ]); + }else { +cik_srbm_select (rdev, ring->me, ring->pipe, ring->queue,0 ); + rptr =RREG32 (CP_HQD_PQ_RPTR ); +cik_srbm_select (rdev,0 ,0 ,0 ,0 ); + } + rptr = (rptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift; + +return rptr; +} + +static u32 cik_compute_ring_get_wptr (struct radeon_device *rdev, +struct radeon_ring *ring) +{ +u32 wptr; + +if (rdev->wb.enabled) { + wptr =le32_to_cpu (rdev->wb.wb[ring->wptr_offs/4 ]); + }else { +cik_srbm_select (rdev, ring->me, ring->pipe, ring->queue,0 ); + wptr =RREG32 (CP_HQD_PQ_WPTR ); +cik_srbm_select (rdev,0 ,0 ,0 ,0 ); + } + wptr = (wptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift; + +return wptr; +} + +static void cik_compute_ring_set_wptr (struct radeon_device *rdev, +struct radeon_ring *ring) +{ +u32 wptr = (ring->wptr << ring->ptr_reg_shift) & ring->ptr_reg_mask; + + rdev->wb.wb[ring->wptr_offs/4 ] =cpu_to_le32 (wptr); +WDOORBELL32 (ring->doorbell_offset, wptr); +} +/** * cik_cp_compute_enable - enable/disable the compute CP MEs * @@ -2176,7 +2222,8 @@ static int cik_cp_compute_load_microcode(struct radeon_device *rdev)*/ static int cik_cp_compute_start (struct radeon_device *rdev) { -//todo +cik_cp_compute_enable (rdev, true); +return 0 ; }@@ -2190,10 +2237,171 @@ static int cik_cp_compute_start(struct radeon_device *rdev)*/ static void cik_cp_compute_fini (struct radeon_device *rdev) { +int i, idx, r; +cik_cp_compute_enable (rdev, false); -//todo + +for (i =0 ; i <2 ; i++) { +if (i ==0 ) + idx =CAYMAN_RING_TYPE_CP1_INDEX ; +else + idx =CAYMAN_RING_TYPE_CP2_INDEX ; + +if (rdev->ring[idx].mqd_obj) { + r =radeon_bo_reserve (rdev->ring[idx].mqd_obj, false); +if (unlikely (r !=0 )) +dev_warn (rdev->dev,"(%d) reserve MQD bo failed\n" , r); + +radeon_bo_unpin (rdev->ring[idx].mqd_obj); +radeon_bo_unreserve (rdev->ring[idx].mqd_obj); + +radeon_bo_unref (&rdev->ring[idx].mqd_obj); + rdev->ring[idx].mqd_obj =NULL ; + } + } +} + +static void cik_mec_fini (struct radeon_device *rdev) +{ +int r; + +if (rdev->mec.hpd_eop_obj) { + r =radeon_bo_reserve (rdev->mec.hpd_eop_obj, false); +if (unlikely (r !=0 )) +dev_warn (rdev->dev,"(%d) reserve HPD EOP bo failed\n" , r); +radeon_bo_unpin (rdev->mec.hpd_eop_obj); +radeon_bo_unreserve (rdev->mec.hpd_eop_obj); + +radeon_bo_unref (&rdev->mec.hpd_eop_obj); + rdev->mec.hpd_eop_obj =NULL ; + } +} + +#define MEC_HPD_SIZE 2048 + +static int cik_mec_init (struct radeon_device *rdev) +{ +int r; +u32 *hpd; + +/* +* KV: 2 MEC, 4 Pipes/MEC, 8 Queues/Pipe - 64 Queues total +* CI/KB: 1 MEC, 4 Pipes/MEC, 8 Queues/Pipe - 32 Queues total +*/ +if (rdev->family ==CHIP_KAVERI ) + rdev->mec.num_mec =2 ; +else + rdev->mec.num_mec =1 ; + rdev->mec.num_pipe =4 ; + rdev->mec.num_queue = rdev->mec.num_mec * rdev->mec.num_pipe *8 ; + +if (rdev->mec.hpd_eop_obj ==NULL ) { + r =radeon_bo_create (rdev, + rdev->mec.num_mec *rdev->mec.num_pipe *MEC_HPD_SIZE *2 , +PAGE_SIZE , true, +RADEON_GEM_DOMAIN_GTT ,NULL , + &rdev->mec.hpd_eop_obj); +if (r) { +dev_warn (rdev->dev,"(%d) create HDP EOP bo failed\n" , r); +return r; + } + } + + r =radeon_bo_reserve (rdev->mec.hpd_eop_obj, false); +if (unlikely (r !=0 )) { +cik_mec_fini (rdev); +return r; + } + r =radeon_bo_pin (rdev->mec.hpd_eop_obj,RADEON_GEM_DOMAIN_GTT , + &rdev->mec.hpd_eop_gpu_addr); +if (r) { +dev_warn (rdev->dev,"(%d) pin HDP EOP bo failed\n" , r); +cik_mec_fini (rdev); +return r; + } + r =radeon_bo_kmap (rdev->mec.hpd_eop_obj, (void **)&hpd); +if (r) { +dev_warn (rdev->dev,"(%d) map HDP EOP bo failed\n" , r); +cik_mec_fini (rdev); +return r; + } + +/* clear memory. Not sure if this is required or not */ +memset (hpd,0 , rdev->mec.num_mec *rdev->mec.num_pipe *MEC_HPD_SIZE *2 ); + +radeon_bo_kunmap (rdev->mec.hpd_eop_obj); +radeon_bo_unreserve (rdev->mec.hpd_eop_obj); + +return 0 ; } +struct hqd_registers +{ +u32 cp_mqd_base_addr; +u32 cp_mqd_base_addr_hi; +u32 cp_hqd_active; +u32 cp_hqd_vmid; +u32 cp_hqd_persistent_state; +u32 cp_hqd_pipe_priority; +u32 cp_hqd_queue_priority; +u32 cp_hqd_quantum; +u32 cp_hqd_pq_base; +u32 cp_hqd_pq_base_hi; +u32 cp_hqd_pq_rptr; +u32 cp_hqd_pq_rptr_report_addr; +u32 cp_hqd_pq_rptr_report_addr_hi; +u32 cp_hqd_pq_wptr_poll_addr; +u32 cp_hqd_pq_wptr_poll_addr_hi; +u32 cp_hqd_pq_doorbell_control; +u32 cp_hqd_pq_wptr; +u32 cp_hqd_pq_control; +u32 cp_hqd_ib_base_addr; +u32 cp_hqd_ib_base_addr_hi; +u32 cp_hqd_ib_rptr; +u32 cp_hqd_ib_control; +u32 cp_hqd_iq_timer; +u32 cp_hqd_iq_rptr; +u32 cp_hqd_dequeue_request; +u32 cp_hqd_dma_offload; +u32 cp_hqd_sema_cmd; +u32 cp_hqd_msg_type; +u32 cp_hqd_atomic0_preop_lo; +u32 cp_hqd_atomic0_preop_hi; +u32 cp_hqd_atomic1_preop_lo; +u32 cp_hqd_atomic1_preop_hi; +u32 cp_hqd_hq_scheduler0; +u32 cp_hqd_hq_scheduler1; +u32 cp_mqd_control; +}; + +struct bonaire_mqd +{ +u32 header; +u32 dispatch_initiator; +u32 dimensions[3 ]; +u32 start_idx[3 ]; +u32 num_threads[3 ]; +u32 pipeline_stat_enable; +u32 perf_counter_enable; +u32 pgm[2 ]; +u32 tba[2 ]; +u32 tma[2 ]; +u32 pgm_rsrc[2 ]; +u32 vmid; +u32 resource_limits; +u32 static_thread_mgmt01[2 ]; +u32 tmp_ring_size; +u32 static_thread_mgmt23[2 ]; +u32 restart[3 ]; +u32 thread_trace_enable; +u32 reserved1; +u32 user_data[16 ]; +u32 vgtcs_invoke_count[2 ]; +struct hqd_registers queue_state; +u32 dequeue_cntr; +u32 interrupt_queue[64 ]; +}; +/** * cik_cp_compute_resume - setup the compute queue registers * @@ -2205,24 +2413,247 @@ static void cik_cp_compute_fini(struct radeon_device *rdev)*/ static int cik_cp_compute_resume (struct radeon_device *rdev) { -int r; +int r, i, idx; +u32 tmp; +bool use_doorbell = true; +u64 hqd_gpu_addr; +u64 mqd_gpu_addr; +u64 eop_gpu_addr; +u64 wb_gpu_addr; +u32 *buf;
drivers/gpu/drm/radeon/cik.c static void cik_cp_compute_fini(struct radeon_device *rdev) · line 2432
Quoted 10 lines
drivers/gpu/drm/radeon/cik.c +5
-1+struct bonaire_mqd *mqd; -//todo r =cik_cp_compute_start (rdev);if (r)return r; + +/* fix up chicken bits */ + tmp =RREG32 (CP_CPF_DEBUG ); + tmp |= (1 <<23 );
What is this chicken bit ? Is it tasty ?
Quoted 269 lines
drivers/gpu/drm/radeon/cik.c +231
-5+WREG32 (CP_CPF_DEBUG , tmp); + +/* init the pipes */ +for (i =0 ; i < (rdev->mec.num_pipe * rdev->mec.num_mec); i++) { +int me = (i <4 ) ?1 :2 ; +int pipe = (i <4 ) ? i : (i -4 ); + + eop_gpu_addr = rdev->mec.hpd_eop_gpu_addr + (i *MEC_HPD_SIZE *2 ); + +cik_srbm_select (rdev, me, pipe,0 ,0 ); + +/* write the EOP addr */ +WREG32 (CP_HPD_EOP_BASE_ADDR , eop_gpu_addr >>8 ); +WREG32 (CP_HPD_EOP_BASE_ADDR_HI ,upper_32_bits (eop_gpu_addr) >>8 ); + +/* set the VMID assigned */ +WREG32 (CP_HPD_EOP_VMID ,0 ); + +/* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */ + tmp =RREG32 (CP_HPD_EOP_CONTROL ); + tmp &= ~EOP_SIZE_MASK ; + tmp |=drm_order (MEC_HPD_SIZE /8 ); +WREG32 (CP_HPD_EOP_CONTROL , tmp); + } +cik_srbm_select (rdev,0 ,0 ,0 ,0 ); + +/* init the queues. Just two for now. */ +for (i =0 ; i <2 ; i++) { +if (i ==0 ) + idx =CAYMAN_RING_TYPE_CP1_INDEX ; +else + idx =CAYMAN_RING_TYPE_CP2_INDEX ; + +if (rdev->ring[idx].mqd_obj ==NULL ) { + r =radeon_bo_create (rdev, +sizeof (struct bonaire_mqd ), +PAGE_SIZE , true, +RADEON_GEM_DOMAIN_GTT ,NULL , + &rdev->ring[idx].mqd_obj); +if (r) { +dev_warn (rdev->dev,"(%d) create MQD bo failed\n" , r); +return r; + } + } + + r =radeon_bo_reserve (rdev->ring[idx].mqd_obj, false); +if (unlikely (r !=0 )) { +cik_cp_compute_fini (rdev); +return r; + } + r =radeon_bo_pin (rdev->ring[idx].mqd_obj,RADEON_GEM_DOMAIN_GTT , + &mqd_gpu_addr); +if (r) { +dev_warn (rdev->dev,"(%d) pin MQD bo failed\n" , r); +cik_cp_compute_fini (rdev); +return r; + } + r =radeon_bo_kmap (rdev->ring[idx].mqd_obj, (void **)&buf); +if (r) { +dev_warn (rdev->dev,"(%d) map MQD bo failed\n" , r); +cik_cp_compute_fini (rdev); +return r; + } + +/* doorbell offset */ + rdev->ring[idx].doorbell_offset = + (rdev->ring[idx].doorbell_page_num *PAGE_SIZE ) +0 ; + +/* init the mqd struct */ +memset (buf,0 ,sizeof (struct bonaire_mqd )); + + mqd = (struct bonaire_mqd *)buf; + mqd->header =0xC0310800 ; + mqd->static_thread_mgmt01[0 ] =0xffffffff ; + mqd->static_thread_mgmt01[1 ] =0xffffffff ; + mqd->static_thread_mgmt23[0 ] =0xffffffff ; + mqd->static_thread_mgmt23[1 ] =0xffffffff ; + +cik_srbm_select (rdev, rdev->ring[idx].me, + rdev->ring[idx].pipe, + rdev->ring[idx].queue,0 ); + +/* disable wptr polling */ + tmp =RREG32 (CP_PQ_WPTR_POLL_CNTL ); + tmp &= ~WPTR_POLL_EN ; +WREG32 (CP_PQ_WPTR_POLL_CNTL , tmp); + +/* enable doorbell? */ + mqd->queue_state.cp_hqd_pq_doorbell_control = +RREG32 (CP_HQD_PQ_DOORBELL_CONTROL ); +if (use_doorbell) + mqd->queue_state.cp_hqd_pq_doorbell_control |=DOORBELL_EN ; +else + mqd->queue_state.cp_hqd_pq_doorbell_control &= ~DOORBELL_EN ; +WREG32 (CP_HQD_PQ_DOORBELL_CONTROL , + mqd->queue_state.cp_hqd_pq_doorbell_control); + +/* disable the queue if it's active */ + mqd->queue_state.cp_hqd_dequeue_request =0 ; + mqd->queue_state.cp_hqd_pq_rptr =0 ; + mqd->queue_state.cp_hqd_pq_wptr=0 ; +if (RREG32 (CP_HQD_ACTIVE ) &1 ) { +WREG32 (CP_HQD_DEQUEUE_REQUEST ,1 ); +for (i =0 ; i < rdev->usec_timeout; i++) { +if (!(RREG32 (CP_HQD_ACTIVE ) &1 )) +break ; +udelay (1 ); + } +WREG32 (CP_HQD_DEQUEUE_REQUEST , mqd->queue_state.cp_hqd_dequeue_request); +WREG32 (CP_HQD_PQ_RPTR , mqd->queue_state.cp_hqd_pq_rptr); +WREG32 (CP_HQD_PQ_WPTR , mqd->queue_state.cp_hqd_pq_wptr); + } + +/* set the pointer to the MQD */ + mqd->queue_state.cp_mqd_base_addr = mqd_gpu_addr &0xfffffffc ; + mqd->queue_state.cp_mqd_base_addr_hi =upper_32_bits (mqd_gpu_addr); +WREG32 (CP_MQD_BASE_ADDR , mqd->queue_state.cp_mqd_base_addr); +WREG32 (CP_MQD_BASE_ADDR_HI , mqd->queue_state.cp_mqd_base_addr_hi); +/* set MQD vmid to 0 */ + mqd->queue_state.cp_mqd_control =RREG32 (CP_MQD_CONTROL ); + mqd->queue_state.cp_mqd_control &= ~MQD_VMID_MASK ; +WREG32 (CP_MQD_CONTROL , mqd->queue_state.cp_mqd_control); + +/* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */ + hqd_gpu_addr = rdev->ring[idx].gpu_addr >>8 ; + mqd->queue_state.cp_hqd_pq_base = hqd_gpu_addr; + mqd->queue_state.cp_hqd_pq_base_hi =upper_32_bits (hqd_gpu_addr); +WREG32 (CP_HQD_PQ_BASE , mqd->queue_state.cp_hqd_pq_base); +WREG32 (CP_HQD_PQ_BASE_HI , mqd->queue_state.cp_hqd_pq_base_hi); + +/* set up the HQD, this is similar to CP_RB0_CNTL */ + mqd->queue_state.cp_hqd_pq_control =RREG32 (CP_HQD_PQ_CONTROL ); + mqd->queue_state.cp_hqd_pq_control &= + ~(QUEUE_SIZE_MASK |RPTR_BLOCK_SIZE_MASK ); + + mqd->queue_state.cp_hqd_pq_control |= +drm_order (rdev->ring[idx].ring_size /8 ); + mqd->queue_state.cp_hqd_pq_control |= + (drm_order (RADEON_GPU_PAGE_SIZE /8 ) <<8 ); +#ifdef __BIG_ENDIAN + mqd->queue_state.cp_hqd_pq_control |=BUF_SWAP_32BIT ; +#endif + mqd->queue_state.cp_hqd_pq_control &= + ~(UNORD_DISPATCH |ROQ_PQ_IB_FLIP |PQ_VOLATILE ); + mqd->queue_state.cp_hqd_pq_control |= +PRIV_STATE |KMD_QUEUE ;/* assuming kernel queue control */ +WREG32 (CP_HQD_PQ_CONTROL , mqd->queue_state.cp_hqd_pq_control); + +/* only used if CP_PQ_WPTR_POLL_CNTL.WPTR_POLL_EN=1 */ +if (i ==0 ) + wb_gpu_addr = rdev->wb.gpu_addr +CIK_WB_CP1_WPTR_OFFSET ; +else + wb_gpu_addr = rdev->wb.gpu_addr +CIK_WB_CP2_WPTR_OFFSET ; + mqd->queue_state.cp_hqd_pq_wptr_poll_addr = wb_gpu_addr &0xfffffffc ; + mqd->queue_state.cp_hqd_pq_wptr_poll_addr_hi =upper_32_bits (wb_gpu_addr) &0xffff ; +WREG32 (CP_HQD_PQ_WPTR_POLL_ADDR , mqd->queue_state.cp_hqd_pq_wptr_poll_addr); +WREG32 (CP_HQD_PQ_WPTR_POLL_ADDR_HI , + mqd->queue_state.cp_hqd_pq_wptr_poll_addr_hi); + +/* set the wb address wether it's enabled or not */ +if (i ==0 ) + wb_gpu_addr = rdev->wb.gpu_addr +RADEON_WB_CP1_RPTR_OFFSET ; +else + wb_gpu_addr = rdev->wb.gpu_addr +RADEON_WB_CP2_RPTR_OFFSET ; + mqd->queue_state.cp_hqd_pq_rptr_report_addr = wb_gpu_addr &0xfffffffc ; + mqd->queue_state.cp_hqd_pq_rptr_report_addr_hi = +upper_32_bits (wb_gpu_addr) &0xffff ; +WREG32 (CP_HQD_PQ_RPTR_REPORT_ADDR , + mqd->queue_state.cp_hqd_pq_rptr_report_addr); +WREG32 (CP_HQD_PQ_RPTR_REPORT_ADDR_HI , + mqd->queue_state.cp_hqd_pq_rptr_report_addr_hi); + +/* enable the doorbell if requested */ +if (use_doorbell) { + mqd->queue_state.cp_hqd_pq_doorbell_control = +RREG32 (CP_HQD_PQ_DOORBELL_CONTROL ); + mqd->queue_state.cp_hqd_pq_doorbell_control &= ~DOORBELL_OFFSET_MASK ; + mqd->queue_state.cp_hqd_pq_doorbell_control |= +DOORBELL_OFFSET (rdev->ring[idx].doorbell_offset /4 ); + mqd->queue_state.cp_hqd_pq_doorbell_control |=DOORBELL_EN ; + mqd->queue_state.cp_hqd_pq_doorbell_control &= + ~(DOORBELL_SOURCE |DOORBELL_HIT ); + + }else { + mqd->queue_state.cp_hqd_pq_doorbell_control =0 ; + } +WREG32 (CP_HQD_PQ_DOORBELL_CONTROL , + mqd->queue_state.cp_hqd_pq_doorbell_control); + +/* read and write pointers, similar to CP_RB0_WPTR/_RPTR */ + rdev->ring[idx].wptr =0 ; + mqd->queue_state.cp_hqd_pq_wptr = rdev->ring[idx].wptr; +WREG32 (CP_HQD_PQ_WPTR , mqd->queue_state.cp_hqd_pq_wptr); + rdev->ring[idx].rptr =RREG32 (CP_HQD_PQ_RPTR ); + mqd->queue_state.cp_hqd_pq_rptr = rdev->ring[idx].rptr; + +/* set the vmid for the queue */ + mqd->queue_state.cp_hqd_vmid =0 ; +WREG32 (CP_HQD_VMID , mqd->queue_state.cp_hqd_vmid); + +/* activate the queue */ + mqd->queue_state.cp_hqd_active =1 ; +WREG32 (CP_HQD_ACTIVE , mqd->queue_state.cp_hqd_active); + +cik_srbm_select (rdev,0 ,0 ,0 ,0 ); + +radeon_bo_kunmap (rdev->ring[idx].mqd_obj); +radeon_bo_unreserve (rdev->ring[idx].mqd_obj); + + rdev->ring[idx].ready = true; + r =radeon_ring_test (rdev, idx, &rdev->ring[idx]); +if (r) + rdev->ring[idx].ready = false; + } +return 0 ; } -/* XXX temporary wrappers to handle both compute and gfx */ -/* XXX */ static void cik_cp_enable (struct radeon_device *rdev,bool enable) {cik_cp_gfx_enable (rdev, enable);cik_cp_compute_enable (rdev, enable); } -/* XXX */ static int cik_cp_load_microcode (struct radeon_device *rdev) {int r;@@ -2237,14 +2668,12 @@ static int cik_cp_load_microcode(struct radeon_device *rdev)return 0 ; } -/* XXX */ static void cik_cp_fini (struct radeon_device *rdev) {cik_cp_gfx_fini (rdev);cik_cp_compute_fini (rdev); } -/* XXX */ static int cik_cp_resume (struct radeon_device *rdev) {int r;@@ -2865,6 +3294,22 @@ static void cik_print_gpu_status_regs(struct radeon_device *rdev) RREG32(SDMA0_STATUS_REG + SDMA0_REGISTER_OFFSET));dev_info (rdev->dev," SDMA1_STATUS_REG = 0x%08X\n" ,RREG32 (SDMA0_STATUS_REG +SDMA1_REGISTER_OFFSET )); +dev_info (rdev->dev," CP_STAT = 0x%08x\n" ,RREG32 (CP_STAT )); +dev_info (rdev->dev," CP_STALLED_STAT1 = 0x%08x\n" , +RREG32 (CP_STALLED_STAT1 )); +dev_info (rdev->dev," CP_STALLED_STAT2 = 0x%08x\n" , +RREG32 (CP_STALLED_STAT2 )); +dev_info (rdev->dev," CP_STALLED_STAT3 = 0x%08x\n" , +RREG32 (CP_STALLED_STAT3 )); +dev_info (rdev->dev," CP_CPF_BUSY_STAT = 0x%08x\n" , +RREG32 (CP_CPF_BUSY_STAT )); +dev_info (rdev->dev," CP_CPF_STALLED_STAT1 = 0x%08x\n" , +RREG32 (CP_CPF_STALLED_STAT1 )); +dev_info (rdev->dev," CP_CPF_STATUS = 0x%08x\n" ,RREG32 (CP_CPF_STATUS )); +dev_info (rdev->dev," CP_CPC_BUSY_STAT = 0x%08x\n" ,RREG32 (CP_CPC_BUSY_STAT )); +dev_info (rdev->dev," CP_CPC_STALLED_STAT1 = 0x%08x\n" , +RREG32 (CP_CPC_STALLED_STAT1 )); +dev_info (rdev->dev," CP_CPC_STATUS = 0x%08x\n" ,RREG32 (CP_CPC_STATUS )); }/**
drivers/gpu/drm/radeon/cik.c static int cik_startup(struct radeon_device *rdev) · line 5400
Quoted 4 lines
drivers/gpu/drm/radeon/cik.c +1
-0@@ -4952,12 +5397,31 @@ static int cik_startup(struct radeon_device *rdev)if (r)return r; +/* allocate rlc buffers */
Init mec not allocate rlc ...
Quoted 261 lines
drivers/gpu/drm/radeon/cik.c +64
-0+ r =cik_mec_init (rdev); +if (r) { +DRM_ERROR ("Failed to init MEC BOs!\n" ); +return r; + } + r =radeon_fence_driver_start_ring (rdev,RADEON_RING_TYPE_GFX_INDEX );if (r) {dev_err (rdev->dev,"failed initializing CP fences (%d).\n" , r);return r; } + r =radeon_fence_driver_start_ring (rdev,CAYMAN_RING_TYPE_CP1_INDEX ); +if (r) { +dev_err (rdev->dev,"failed initializing CP fences (%d).\n" , r); +return r; + } + + r =radeon_fence_driver_start_ring (rdev,CAYMAN_RING_TYPE_CP2_INDEX ); +if (r) { +dev_err (rdev->dev,"failed initializing CP fences (%d).\n" , r); +return r; + } + r =radeon_fence_driver_start_ring (rdev,R600_RING_TYPE_DMA_INDEX );if (r) {dev_err (rdev->dev,"failed initializing DMA fences (%d).\n" , r);@@ -5002,6 +5466,36 @@ static int cik_startup(struct radeon_device *rdev)if (r)return r; +/* set up the compute queues */ + ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX ]; + r =radeon_ring_init (rdev, ring, ring->ring_size,RADEON_WB_CP1_RPTR_OFFSET , +CP_HQD_PQ_RPTR ,CP_HQD_PQ_WPTR , +0 ,0xfffff ,RADEON_CP_PACKET2 ); +if (r) +return r; + ring->me =1 ;/* first MEC */ + ring->pipe =0 ;/* first pipe */ + ring->queue =0 ;/* first queue */ + ring->wptr_offs =CIK_WB_CP1_WPTR_OFFSET ; + ring->funcs.get_rptr = &cik_compute_ring_get_rptr; + ring->funcs.get_wptr = &cik_compute_ring_get_wptr; + ring->funcs.set_wptr = &cik_compute_ring_set_wptr; + + ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX ]; + r =radeon_ring_init (rdev, ring, ring->ring_size,RADEON_WB_CP2_RPTR_OFFSET , +CP_HQD_PQ_RPTR ,CP_HQD_PQ_WPTR , +0 ,0xffffffff ,RADEON_CP_PACKET2 ); +if (r) +return r; +/* dGPU only have 1 MEC */ + ring->me =1 ;/* first MEC */ + ring->pipe =0 ;/* first pipe */ + ring->queue =1 ;/* second queue */ + ring->wptr_offs =CIK_WB_CP2_WPTR_OFFSET ; + ring->funcs.get_rptr = &cik_compute_ring_get_rptr; + ring->funcs.get_wptr = &cik_compute_ring_get_wptr; + ring->funcs.set_wptr = &cik_compute_ring_set_wptr; + ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX ]; r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET, SDMA0_GFX_RB_RPTR + SDMA0_REGISTER_OFFSET,@@ -5176,6 +5670,20 @@ int cik_init(struct radeon_device *rdev) ring->ring_obj =NULL ;r600_ring_init (rdev, ring,1024 *1024 ); + ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX ]; + ring->ring_obj =NULL ; +r600_ring_init (rdev, ring,1024 *1024 ); + r =radeon_doorbell_get (rdev, &ring->doorbell_page_num); +if (r) +return r; + + ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX ]; + ring->ring_obj =NULL ; +r600_ring_init (rdev, ring,1024 *1024 ); + r =radeon_doorbell_get (rdev, &ring->doorbell_page_num); +if (r) +return r; + ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX ]; ring->ring_obj =NULL ;r600_ring_init (rdev, ring,256 *1024 );@@ -5206,6 +5714,7 @@ int cik_init(struct radeon_device *rdev)cik_sdma_fini (rdev);cik_irq_fini (rdev);si_rlc_fini (rdev); +cik_mec_fini (rdev);radeon_wb_fini (rdev);radeon_ib_pool_fini (rdev);radeon_vm_manager_fini (rdev);@@ -5241,6 +5750,7 @@ void cik_fini(struct radeon_device *rdev)cik_sdma_fini (rdev);cik_irq_fini (rdev);si_rlc_fini (rdev); +cik_mec_fini (rdev);radeon_wb_fini (rdev);radeon_vm_manager_fini (rdev);radeon_ib_pool_fini (rdev);drivers/gpu/drm/radeon/cikd.h +62
-0@@ -460,6 +460,13 @@# define RDERR_INT_ENABLE (1 << 0)# define GUI_IDLE_INT_ENABLE (1 << 19) +#define CP_CPC_STATUS 0x8210 +#define CP_CPC_BUSY_STAT 0x8214 +#define CP_CPC_STALLED_STAT1 0x8218 +#define CP_CPF_STATUS 0x821c +#define CP_CPF_BUSY_STAT 0x8220 +#define CP_CPF_STALLED_STAT1 0x8224 +#define CP_MEC_CNTL 0x8234#define MEC_ME2_HALT (1 << 28)#define MEC_ME1_HALT (1 << 30)@@ -468,6 +475,12 @@#define MEC_ME2_HALT (1 << 28)#define MEC_ME1_HALT (1 << 30) +#define CP_STALLED_STAT3 0x8670 +#define CP_STALLED_STAT1 0x8674 +#define CP_STALLED_STAT2 0x8678 + +#define CP_STAT 0x8680 +#define CP_ME_CNTL 0x86D8#define CP_CE_HALT (1 << 24)#define CP_PFP_HALT (1 << 26)@@ -701,6 +714,11 @@# define CP_RINGID1_INT_STAT (1 << 30)# define CP_RINGID0_INT_STAT (1 << 31) +#define CP_CPF_DEBUG 0xC200 + +#define CP_PQ_WPTR_POLL_CNTL 0xC20C +#define WPTR_POLL_EN (1 << 31) +#define CP_ME1_PIPE0_INT_CNTL 0xC214#define CP_ME1_PIPE1_INT_CNTL 0xC218#define CP_ME1_PIPE2_INT_CNTL 0xC21C@@ -773,6 +791,50 @@#define RLC_GPM_SCRATCH_ADDR 0xC4B0#define RLC_GPM_SCRATCH_DATA 0xC4B4 +#define CP_HPD_EOP_BASE_ADDR 0xC904 +#define CP_HPD_EOP_BASE_ADDR_HI 0xC908 +#define CP_HPD_EOP_VMID 0xC90C +#define CP_HPD_EOP_CONTROL 0xC910 +#define EOP_SIZE (x) ((x) << 0) +#define EOP_SIZE_MASK (0x3f << 0) +#define CP_MQD_BASE_ADDR 0xC914 +#define CP_MQD_BASE_ADDR_HI 0xC918 +#define CP_HQD_ACTIVE 0xC91C +#define CP_HQD_VMID 0xC920 + +#define CP_HQD_PQ_BASE 0xC934 +#define CP_HQD_PQ_BASE_HI 0xC938 +#define CP_HQD_PQ_RPTR 0xC93C +#define CP_HQD_PQ_RPTR_REPORT_ADDR 0xC940 +#define CP_HQD_PQ_RPTR_REPORT_ADDR_HI 0xC944 +#define CP_HQD_PQ_WPTR_POLL_ADDR 0xC948 +#define CP_HQD_PQ_WPTR_POLL_ADDR_HI 0xC94C +#define CP_HQD_PQ_DOORBELL_CONTROL 0xC950 +#define DOORBELL_OFFSET (x) ((x) << 2) +#define DOORBELL_OFFSET_MASK (0x1fffff << 2) +#define DOORBELL_SOURCE (1 << 28) +#define DOORBELL_SCHD_HIT (1 << 29) +#define DOORBELL_EN (1 << 30) +#define DOORBELL_HIT (1 << 31) +#define CP_HQD_PQ_WPTR 0xC954 +#define CP_HQD_PQ_CONTROL 0xC958 +#define QUEUE_SIZE (x) ((x) << 0) +#define QUEUE_SIZE_MASK (0x3f << 0) +#define RPTR_BLOCK_SIZE (x) ((x) << 8) +#define RPTR_BLOCK_SIZE_MASK (0x3f << 8) +#define PQ_VOLATILE (1 << 26) +#define NO_UPDATE_RPTR (1 << 27) +#define UNORD_DISPATCH (1 << 28) +#define ROQ_PQ_IB_FLIP (1 << 29) +#define PRIV_STATE (1 << 30) +#define KMD_QUEUE (1 << 31) + +#define CP_HQD_DEQUEUE_REQUEST 0xC974 + +#define CP_MQD_CONTROL 0xC99C +#define MQD_VMID (x) ((x) << 0) +#define MQD_VMID_MASK (0xf << 0) +#define PA_SC_RASTER_CONFIG 0x28350# define RASTER_CONFIG_RB_MAP_0 0# define RASTER_CONFIG_RB_MAP_1 1drivers/gpu/drm/radeon/radeon.h +19
-0@@ -714,6 +714,22 @@ struct radeon_ring {u32 (*get_wptr)(struct radeon_device *rdev,struct radeon_ring *ring);void (*set_wptr)(struct radeon_device *rdev,struct radeon_ring *ring); } funcs; +/* for CIK queues */ +u32 me; +u32 pipe; +u32 queue; +struct radeon_bo *mqd_obj; +u32 doorbell_page_num; +u32 doorbell_offset; +unsigned wptr_offs; +}; + +struct radeon_mec { +struct radeon_bo *hpd_eop_obj; +u64 hpd_eop_gpu_addr; +u32 num_pipe; +u32 num_mec; +u32 num_queue; };/* @@ -971,6 +987,8 @@ struct radeon_wb {#define CAYMAN_WB_DMA1_RPTR_OFFSET 2304#define R600_WB_UVD_RPTR_OFFSET 2560#define R600_WB_EVENT_OFFSET 3072 +#define CIK_WB_CP1_WPTR_OFFSET 3328 +#define CIK_WB_CP2_WPTR_OFFSET 3584/** * struct radeon_pm - power management datas @@ -1760,6 +1778,7 @@ struct radeon_device {int msi_enabled;/* msi enabled */ struct r600_ih ih;/* r6/700 interrupt ring */ struct si_rlc rlc; +struct radeon_mec mec;struct work_struct hotplug_work;struct work_struct audio_work;struct work_struct reset_work;drivers/gpu/drm/radeon/radeon_cs.c +1
-3@@ -121,9 +121,7 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority p->ring =RADEON_RING_TYPE_GFX_INDEX ;break ;case RADEON_CS_RING_COMPUTE : -if (p->rdev->family >=CHIP_BONAIRE ) - p->ring =RADEON_RING_TYPE_GFX_INDEX ; -else if (p->rdev->family >=CHIP_TAHITI ) { +if (p->rdev->family >=CHIP_TAHITI ) {if (p->priority >0 ) p->ring =CAYMAN_RING_TYPE_CP1_INDEX ;else Signature · 6 lines
1.7.7.5 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 53/165 drm/radeon/cik: switch to type3 nop packet for compute rings
In reply to [email protected]From: Alex Deucher <[email protected]>
Type 2 packets are deprecated on CIK MEC and we should use type 3 nop packets. Setting the count field to the max value (0x3fff) indicates that only one dword should be skipped like a type 2 packet.
--- drivers/gpu/drm/radeon/cik.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/radeon/cik.c +2 -2
@@ -5470,7 +5470,7 @@ static int cik_startup(struct radeon_device *rdev) ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX ]; r =radeon_ring_init (rdev, ring, ring->ring_size,RADEON_WB_CP1_RPTR_OFFSET ,CP_HQD_PQ_RPTR ,CP_HQD_PQ_WPTR , -0 ,0xfffff ,RADEON_CP_PACKET2 ); +0 ,0xfffff ,PACKET3 (PACKET3_NOP ,0x3FFF ));if (r)return r; ring->me =1 ;/* first MEC */
@@ -5484,7 +5484,7 @@ static int cik_startup(struct radeon_device *rdev) ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX ]; r =radeon_ring_init (rdev, ring, ring->ring_size,RADEON_WB_CP2_RPTR_OFFSET ,CP_HQD_PQ_RPTR ,CP_HQD_PQ_WPTR , -0 ,0xffffffff ,RADEON_CP_PACKET2 ); +0 ,0xffffffff ,PACKET3 (PACKET3_NOP ,0x3FFF ));if (r)return r;/* dGPU only have 1 MEC */
Signature · 1 line
1.7.7.5
Re: [PATCH 053/165] drm/radeon/cik: switch to type3 nop packet for compute rings
Quoted 8 lines · On Wed, Jun 26, 2013 at 09:22:13AM -0400, [email protected] wrote:
From: Alex Deucher <[email protected]>
Type 2 packets are deprecated on CIK MEC and we should use type 3 nop packets. Setting the count field to the max value (
0x3fff) indicates that only one dword should be skipped like a type 2 packet.Signed-off-by Alex Deucher <[email protected]>
What about adding same comment in the code and not only in git commit message.
Quoted 33 lines
--- drivers/gpu/drm/radeon/cik.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)drivers/gpu/drm/radeon/cik.c +2
-2@@ -5470,7 +5470,7 @@ static int cik_startup(struct radeon_device *rdev) ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX ]; r =radeon_ring_init (rdev, ring, ring->ring_size,RADEON_WB_CP1_RPTR_OFFSET ,CP_HQD_PQ_RPTR ,CP_HQD_PQ_WPTR , -0 ,0xfffff ,RADEON_CP_PACKET2 ); +0 ,0xfffff ,PACKET3 (PACKET3_NOP ,0x3FFF ));if (r)return r; ring->me =1 ;/* first MEC */ @@ -5484,7 +5484,7 @@ static int cik_startup(struct radeon_device *rdev) ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX ]; r =radeon_ring_init (rdev, ring, ring->ring_size,RADEON_WB_CP2_RPTR_OFFSET ,CP_HQD_PQ_RPTR ,CP_HQD_PQ_WPTR , -0 ,0xffffffff ,RADEON_CP_PACKET2 ); +0 ,0xffffffff ,PACKET3 (PACKET3_NOP ,0x3FFF ));if (r)return r;/* dGPU only have 1 MEC */ Signature · 6 lines
1.7.7.5 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 54/165 drm/radeon: fix up ring functions for compute rings
In reply to [email protected]From: Alex Deucher <[email protected]>
The compute rings use RELEASE_MEM rather then EOP packets for writing fences and there is no SYNC_PFP_ME packet on the compute rings.
--- drivers/gpu/drm/radeon/cik.c | 53 +++++++++++++++++++++++++++++++++++++---- 1 files changed, 47 insertions(+), 6 deletions(-)
drivers/gpu/drm/radeon/cik.c +47 -6
@@ -1706,7 +1706,7 @@ int cik_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) }/** -* cik_fence_ring_emit - emit a fence on the gfx ring +* cik_fence_gfx_ring_emit - emit a fence on the gfx ring * * @rdev: radeon_device pointer * @fence: radeon fence object
@@ -1714,8 +1714,8 @@ int cik_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)* Emits a fence sequnce number on the gfx ring and flushes * GPU caches. */ -void cik_fence_ring_emit (struct radeon_device *rdev, -struct radeon_fence *fence) +void cik_fence_gfx_ring_emit (struct radeon_device *rdev, +struct radeon_fence *fence) {struct radeon_ring *ring = &rdev->ring[fence->ring];u64 addr = rdev->fence_drv[fence->ring].gpu_addr;
@@ -1742,6 +1742,44 @@ void cik_fence_ring_emit(struct radeon_device *rdev,radeon_ring_write (ring,0 ); } +/** +* cik_fence_compute_ring_emit - emit a fence on the compute ring +* +* @rdev: radeon_device pointer +* @fence: radeon fence object +* +* Emits a fence sequnce number on the compute ring and flushes +* GPU caches. +*/ +void cik_fence_compute_ring_emit (struct radeon_device *rdev, +struct radeon_fence *fence) +{ +struct radeon_ring *ring = &rdev->ring[fence->ring]; +u64 addr = rdev->fence_drv[fence->ring].gpu_addr; + +/* RELEASE_MEM - flush caches, send int */ +radeon_ring_write (ring,PACKET3 (PACKET3_RELEASE_MEM ,5 )); +radeon_ring_write (ring, (EOP_TCL1_ACTION_EN | +EOP_TC_ACTION_EN | +EVENT_TYPE (CACHE_FLUSH_AND_INV_TS_EVENT ) | +EVENT_INDEX (5 ))); +radeon_ring_write (ring,DATA_SEL (1 ) |INT_SEL (2 )); +radeon_ring_write (ring, addr &0xfffffffc ); +radeon_ring_write (ring,upper_32_bits (addr)); +radeon_ring_write (ring, fence->seq); +radeon_ring_write (ring,0 ); +/* HDP flush */ +/* We should be using the new WAIT_REG_MEM special op packet here +* but it causes the CP to hang +*/ +radeon_ring_write (ring,PACKET3 (PACKET3_WRITE_DATA ,3 )); +radeon_ring_write (ring, (WRITE_DATA_ENGINE_SEL (0 ) | +WRITE_DATA_DST_SEL (0 ))); +radeon_ring_write (ring,HDP_MEM_COHERENCY_FLUSH_CNTL >>2 ); +radeon_ring_write (ring,0 ); +radeon_ring_write (ring,0 ); +} + void cik_semaphore_ring_emit(struct radeon_device *rdev, struct radeon_ring *ring, struct radeon_semaphore *semaphore,
@@ -4051,9 +4089,12 @@ void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)radeon_ring_write (ring,0 );radeon_ring_write (ring,1 << vm->id); -/* sync PFP to ME, otherwise we might get invalid PFP reads */ -radeon_ring_write (ring,PACKET3 (PACKET3_PFP_SYNC_ME ,0 )); -radeon_ring_write (ring,0x0 ); +/* compute doesn't have PFP */ +if (ridx ==RADEON_RING_TYPE_GFX_INDEX ) { +/* sync PFP to ME, otherwise we might get invalid PFP reads */ +radeon_ring_write (ring,PACKET3 (PACKET3_PFP_SYNC_ME ,0 )); +radeon_ring_write (ring,0x0 ); + } }/**
Signature · 1 line
1.7.7.5
PATCH 55/165 drm/radeon/cik: add support for compute interrupts
In reply to [email protected]From: Alex Deucher <[email protected]>
--- drivers/gpu/drm/radeon/cik.c | 121 ++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 116 insertions(+), 5 deletions(-)
drivers/gpu/drm/radeon/cik.c +116 -5
@@ -4631,6 +4631,8 @@ int cik_irq_set(struct radeon_device *rdev) {u32 cp_int_cntl =CNTX_BUSY_INT_ENABLE |CNTX_EMPTY_INT_ENABLE |PRIV_INSTR_INT_ENABLE |PRIV_REG_INT_ENABLE ; +u32 cp_m1p0, cp_m1p1, cp_m1p2, cp_m1p3; +u32 cp_m2p0, cp_m2p1, cp_m2p2, cp_m2p3;u32 crtc1 =0 , crtc2 =0 , crtc3 =0 , crtc4 =0 , crtc5 =0 , crtc6 =0 ;u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6;u32 grbm_int_cntl =0 ;
@@ -4658,13 +4660,106 @@ int cik_irq_set(struct radeon_device *rdev) dma_cntl =RREG32 (SDMA0_CNTL +SDMA0_REGISTER_OFFSET ) & ~TRAP_ENABLE ; dma_cntl1 =RREG32 (SDMA0_CNTL +SDMA1_REGISTER_OFFSET ) & ~TRAP_ENABLE ; + cp_m1p0 =RREG32 (CP_ME1_PIPE0_INT_CNTL ) & ~TIME_STAMP_INT_ENABLE ; + cp_m1p1 =RREG32 (CP_ME1_PIPE1_INT_CNTL ) & ~TIME_STAMP_INT_ENABLE ; + cp_m1p2 =RREG32 (CP_ME1_PIPE2_INT_CNTL ) & ~TIME_STAMP_INT_ENABLE ; + cp_m1p3 =RREG32 (CP_ME1_PIPE3_INT_CNTL ) & ~TIME_STAMP_INT_ENABLE ; + cp_m2p0 =RREG32 (CP_ME2_PIPE0_INT_CNTL ) & ~TIME_STAMP_INT_ENABLE ; + cp_m2p1 =RREG32 (CP_ME2_PIPE1_INT_CNTL ) & ~TIME_STAMP_INT_ENABLE ; + cp_m2p2 =RREG32 (CP_ME2_PIPE2_INT_CNTL ) & ~TIME_STAMP_INT_ENABLE ; + cp_m2p3 =RREG32 (CP_ME2_PIPE3_INT_CNTL ) & ~TIME_STAMP_INT_ENABLE ; +/* enable CP interrupts on all rings */ if (atomic_read (&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX ])) {DRM_DEBUG ("cik_irq_set: sw int gfx\n" ); cp_int_cntl |=TIME_STAMP_INT_ENABLE ; } -/* TODO: compute queues! */ -/* CP_ME[1-2]_PIPE[0-3]_INT_CNTL */ +if (atomic_read (&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP1_INDEX ])) { +struct radeon_ring *ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX ]; +DRM_DEBUG ("si_irq_set: sw int cp1\n" ); +if (ring->me ==1 ) { +switch (ring->pipe) { +case 0 : + cp_m1p0 |=TIME_STAMP_INT_ENABLE ; +break ; +case 1 : + cp_m1p1 |=TIME_STAMP_INT_ENABLE ; +break ; +case 2 : + cp_m1p2 |=TIME_STAMP_INT_ENABLE ; +break ; +case 3 : + cp_m1p2 |=TIME_STAMP_INT_ENABLE ; +break ; +default : +DRM_DEBUG ("si_irq_set: sw int cp1 invalid pipe %d\n" , ring->pipe); +break ; + } + }else if (ring->me ==2 ) { +switch (ring->pipe) { +case 0 : + cp_m2p0 |=TIME_STAMP_INT_ENABLE ; +break ; +case 1 : + cp_m2p1 |=TIME_STAMP_INT_ENABLE ; +break ; +case 2 : + cp_m2p2 |=TIME_STAMP_INT_ENABLE ; +break ; +case 3 : + cp_m2p2 |=TIME_STAMP_INT_ENABLE ; +break ; +default : +DRM_DEBUG ("si_irq_set: sw int cp1 invalid pipe %d\n" , ring->pipe); +break ; + } + }else { +DRM_DEBUG ("si_irq_set: sw int cp1 invalid me %d\n" , ring->me); + } + } +if (atomic_read (&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP2_INDEX ])) { +struct radeon_ring *ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX ]; +DRM_DEBUG ("si_irq_set: sw int cp2\n" ); +if (ring->me ==1 ) { +switch (ring->pipe) { +case 0 : + cp_m1p0 |=TIME_STAMP_INT_ENABLE ; +break ; +case 1 : + cp_m1p1 |=TIME_STAMP_INT_ENABLE ; +break ; +case 2 : + cp_m1p2 |=TIME_STAMP_INT_ENABLE ; +break ; +case 3 : + cp_m1p2 |=TIME_STAMP_INT_ENABLE ; +break ; +default : +DRM_DEBUG ("si_irq_set: sw int cp2 invalid pipe %d\n" , ring->pipe); +break ; + } + }else if (ring->me ==2 ) { +switch (ring->pipe) { +case 0 : + cp_m2p0 |=TIME_STAMP_INT_ENABLE ; +break ; +case 1 : + cp_m2p1 |=TIME_STAMP_INT_ENABLE ; +break ; +case 2 : + cp_m2p2 |=TIME_STAMP_INT_ENABLE ; +break ; +case 3 : + cp_m2p2 |=TIME_STAMP_INT_ENABLE ; +break ; +default : +DRM_DEBUG ("si_irq_set: sw int cp2 invalid pipe %d\n" , ring->pipe); +break ; + } + }else { +DRM_DEBUG ("si_irq_set: sw int cp2 invalid me %d\n" , ring->me); + } + }if (atomic_read (&rdev->irq.ring_int[R600_RING_TYPE_DMA_INDEX ])) {DRM_DEBUG ("cik_irq_set: sw int dma\n" );
@@ -4736,6 +4831,15 @@ int cik_irq_set(struct radeon_device *rdev)WREG32 (SDMA0_CNTL +SDMA0_REGISTER_OFFSET , dma_cntl);WREG32 (SDMA0_CNTL +SDMA1_REGISTER_OFFSET , dma_cntl1); +WREG32 (CP_ME1_PIPE0_INT_CNTL , cp_m1p0); +WREG32 (CP_ME1_PIPE1_INT_CNTL , cp_m1p1); +WREG32 (CP_ME1_PIPE2_INT_CNTL , cp_m1p2); +WREG32 (CP_ME1_PIPE3_INT_CNTL , cp_m1p3); +WREG32 (CP_ME2_PIPE0_INT_CNTL , cp_m2p0); +WREG32 (CP_ME2_PIPE1_INT_CNTL , cp_m2p1); +WREG32 (CP_ME2_PIPE2_INT_CNTL , cp_m2p2); +WREG32 (CP_ME2_PIPE3_INT_CNTL , cp_m2p3); +WREG32 (GRBM_INT_CNTL , grbm_int_cntl);WREG32 (LB_INTERRUPT_MASK +EVERGREEN_CRTC0_REGISTER_OFFSET , crtc1);
@@ -4957,6 +5061,8 @@ static inline u32 cik_get_ih_wptr(struct radeon_device *rdev)*/ int cik_irq_process (struct radeon_device *rdev) { +struct radeon_ring *cp1_ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX ]; +struct radeon_ring *cp2_ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX ];u32 wptr;u32 rptr;u32 src_id, src_data, ring_id;
@@ -5222,10 +5328,11 @@ restart_ih:radeon_fence_process (rdev,RADEON_RING_TYPE_GFX_INDEX );break ;case 1 : -/* XXX compute */ -break ;case 2 : -/* XXX compute */ +if ((cp1_ring->me == me_id) & (cp1_ring->pipe == pipe_id)) +radeon_fence_process (rdev,CAYMAN_RING_TYPE_CP1_INDEX ); +if ((cp2_ring->me == me_id) & (cp2_ring->pipe == pipe_id)) +radeon_fence_process (rdev,CAYMAN_RING_TYPE_CP2_INDEX );break ; }break ;
@@ -5244,9 +5351,11 @@ restart_ih:break ;case 1 :/* XXX compute */ + queue_reset = true;break ;case 2 :/* XXX compute */ + queue_reset = true;break ; }break ;
@@ -5265,9 +5374,11 @@ restart_ih:break ;case 1 :/* XXX compute */ + queue_reset = true;break ;case 2 :/* XXX compute */ + queue_reset = true;break ; }break ;
Signature · 1 line
1.7.7.5
PATCH 56/165 drm/radeon/cik: add support for golden register init
In reply to [email protected]From: Alex Deucher <[email protected]>
--- drivers/gpu/drm/radeon/cik.c | 438 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 438 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/cik.c +438 -0
@@ -99,6 +99,439 @@ void cik_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v) (void )RREG32 (PCIE_DATA ); } +static const u32 bonaire_golden_spm_registers[] = +{ +0x30800 ,0xe0ffffff ,0xe0000000 +}; + +static const u32 bonaire_golden_common_registers[] = +{ +0xc770 ,0xffffffff ,0x00000800 , +0xc774 ,0xffffffff ,0x00000800 , +0xc798 ,0xffffffff ,0x00007fbf , +0xc79c ,0xffffffff ,0x00007faf +}; + +static const u32 bonaire_golden_registers[] = +{ +0x3354 ,0x00000333 ,0x00000333 , +0x3350 ,0x000c0fc0 ,0x00040200 , +0x9a10 ,0x00010000 ,0x00058208 , +0x3c000 ,0xffff1fff ,0x00140000 , +0x3c200 ,0xfdfc0fff ,0x00000100 , +0x3c234 ,0x40000000 ,0x40000200 , +0x9830 ,0xffffffff ,0x00000000 , +0x9834 ,0xf00fffff ,0x00000400 , +0x9838 ,0x0002021c ,0x00020200 , +0xc78 ,0x00000080 ,0x00000000 , +0x5bb0 ,0x000000f0 ,0x00000070 , +0x5bc0 ,0xf0311fff ,0x80300000 , +0x98f8 ,0x73773777 ,0x12010001 , +0x350c ,0x00810000 ,0x408af000 , +0x7030 ,0x31000111 ,0x00000011 , +0x2f48 ,0x73773777 ,0x12010001 , +0x220c ,0x00007fb6 ,0x0021a1b1 , +0x2210 ,0x00007fb6 ,0x002021b1 , +0x2180 ,0x00007fb6 ,0x00002191 , +0x2218 ,0x00007fb6 ,0x002121b1 , +0x221c ,0x00007fb6 ,0x002021b1 , +0x21dc ,0x00007fb6 ,0x00002191 , +0x21e0 ,0x00007fb6 ,0x00002191 , +0x3628 ,0x0000003f ,0x0000000a , +0x362c ,0x0000003f ,0x0000000a , +0x2ae4 ,0x00073ffe ,0x000022a2 , +0x240c ,0x000007ff ,0x00000000 , +0x8a14 ,0xf000003f ,0x00000007 , +0x8bf0 ,0x00002001 ,0x00000001 , +0x8b24 ,0xffffffff ,0x00ffffff , +0x30a04 ,0x0000ff0f ,0x00000000 , +0x28a4c ,0x07ffffff ,0x06000000 , +0x4d8 ,0x00000fff ,0x00000100 , +0x3e78 ,0x00000001 ,0x00000002 , +0x9100 ,0x03000000 ,0x0362c688 , +0x8c00 ,0x000000ff ,0x00000001 , +0xe40 ,0x00001fff ,0x00001fff , +0x9060 ,0x0000007f ,0x00000020 , +0x9508 ,0x00010000 ,0x00010000 , +0xac14 ,0x000003ff ,0x000000f3 , +0xac0c ,0xffffffff ,0x00001032 +}; + +static const u32 bonaire_mgcg_cgcg_init[] = +{ +0xc420 ,0xffffffff ,0xfffffffc , +0x30800 ,0xffffffff ,0xe0000000 , +0x3c2a0 ,0xffffffff ,0x00000100 , +0x3c208 ,0xffffffff ,0x00000100 , +0x3c2c0 ,0xffffffff ,0xc0000100 , +0x3c2c8 ,0xffffffff ,0xc0000100 , +0x3c2c4 ,0xffffffff ,0xc0000100 , +0x55e4 ,0xffffffff ,0x00600100 , +0x3c280 ,0xffffffff ,0x00000100 , +0x3c214 ,0xffffffff ,0x06000100 , +0x3c220 ,0xffffffff ,0x00000100 , +0x3c218 ,0xffffffff ,0x06000100 , +0x3c204 ,0xffffffff ,0x00000100 , +0x3c2e0 ,0xffffffff ,0x00000100 , +0x3c224 ,0xffffffff ,0x00000100 , +0x3c200 ,0xffffffff ,0x00000100 , +0x3c230 ,0xffffffff ,0x00000100 , +0x3c234 ,0xffffffff ,0x00000100 , +0x3c250 ,0xffffffff ,0x00000100 , +0x3c254 ,0xffffffff ,0x00000100 , +0x3c258 ,0xffffffff ,0x00000100 , +0x3c25c ,0xffffffff ,0x00000100 , +0x3c260 ,0xffffffff ,0x00000100 , +0x3c27c ,0xffffffff ,0x00000100 , +0x3c278 ,0xffffffff ,0x00000100 , +0x3c210 ,0xffffffff ,0x06000100 , +0x3c290 ,0xffffffff ,0x00000100 , +0x3c274 ,0xffffffff ,0x00000100 , +0x3c2b4 ,0xffffffff ,0x00000100 , +0x3c2b0 ,0xffffffff ,0x00000100 , +0x3c270 ,0xffffffff ,0x00000100 , +0x30800 ,0xffffffff ,0xe0000000 , +0x3c020 ,0xffffffff ,0x00010000 , +0x3c024 ,0xffffffff ,0x00030002 , +0x3c028 ,0xffffffff ,0x00040007 , +0x3c02c ,0xffffffff ,0x00060005 , +0x3c030 ,0xffffffff ,0x00090008 , +0x3c034 ,0xffffffff ,0x00010000 , +0x3c038 ,0xffffffff ,0x00030002 , +0x3c03c ,0xffffffff ,0x00040007 , +0x3c040 ,0xffffffff ,0x00060005 , +0x3c044 ,0xffffffff ,0x00090008 , +0x3c048 ,0xffffffff ,0x00010000 , +0x3c04c ,0xffffffff ,0x00030002 , +0x3c050 ,0xffffffff ,0x00040007 , +0x3c054 ,0xffffffff ,0x00060005 , +0x3c058 ,0xffffffff ,0x00090008 , +0x3c05c ,0xffffffff ,0x00010000 , +0x3c060 ,0xffffffff ,0x00030002 , +0x3c064 ,0xffffffff ,0x00040007 , +0x3c068 ,0xffffffff ,0x00060005 , +0x3c06c ,0xffffffff ,0x00090008 , +0x3c070 ,0xffffffff ,0x00010000 , +0x3c074 ,0xffffffff ,0x00030002 , +0x3c078 ,0xffffffff ,0x00040007 , +0x3c07c ,0xffffffff ,0x00060005 , +0x3c080 ,0xffffffff ,0x00090008 , +0x3c084 ,0xffffffff ,0x00010000 , +0x3c088 ,0xffffffff ,0x00030002 , +0x3c08c ,0xffffffff ,0x00040007 , +0x3c090 ,0xffffffff ,0x00060005 , +0x3c094 ,0xffffffff ,0x00090008 , +0x3c098 ,0xffffffff ,0x00010000 , +0x3c09c ,0xffffffff ,0x00030002 , +0x3c0a0 ,0xffffffff ,0x00040007 , +0x3c0a4 ,0xffffffff ,0x00060005 , +0x3c0a8 ,0xffffffff ,0x00090008 , +0x3c000 ,0xffffffff ,0x96e00200 , +0x8708 ,0xffffffff ,0x00900100 , +0xc424 ,0xffffffff ,0x0020003f , +0x38 ,0xffffffff ,0x0140001c , +0x3c ,0x000f0000 ,0x000f0000 , +0x220 ,0xffffffff ,0xC060000C , +0x224 ,0xc0000fff ,0x00000100 , +0xf90 ,0xffffffff ,0x00000100 , +0xf98 ,0x00000101 ,0x00000000 , +0x20a8 ,0xffffffff ,0x00000104 , +0x55e4 ,0xff000fff ,0x00000100 , +0x30cc ,0xc0000fff ,0x00000104 , +0xc1e4 ,0x00000001 ,0x00000001 , +0xd00c ,0xff000ff0 ,0x00000100 , +0xd80c ,0xff000ff0 ,0x00000100 +}; + +static const u32 spectre_golden_spm_registers[] = +{ +0x30800 ,0xe0ffffff ,0xe0000000 +}; + +static const u32 spectre_golden_common_registers[] = +{ +0xc770 ,0xffffffff ,0x00000800 , +0xc774 ,0xffffffff ,0x00000800 , +0xc798 ,0xffffffff ,0x00007fbf , +0xc79c ,0xffffffff ,0x00007faf +}; + +static const u32 spectre_golden_registers[] = +{ +0x3c000 ,0xffff1fff ,0x96940200 , +0x3c00c ,0xffff0001 ,0xff000000 , +0x3c200 ,0xfffc0fff ,0x00000100 , +0x6ed8 ,0x00010101 ,0x00010000 , +0x9834 ,0xf00fffff ,0x00000400 , +0x9838 ,0xfffffffc ,0x00020200 , +0x5bb0 ,0x000000f0 ,0x00000070 , +0x5bc0 ,0xf0311fff ,0x80300000 , +0x98f8 ,0x73773777 ,0x12010001 , +0x9b7c ,0x00ff0000 ,0x00fc0000 , +0x2f48 ,0x73773777 ,0x12010001 , +0x8a14 ,0xf000003f ,0x00000007 , +0x8b24 ,0xffffffff ,0x00ffffff , +0x28350 ,0x3f3f3fff ,0x00000082 , +0x28355 ,0x0000003f ,0x00000000 , +0x3e78 ,0x00000001 ,0x00000002 , +0x913c ,0xffff03df ,0x00000004 , +0xc768 ,0x00000008 ,0x00000008 , +0x8c00 ,0x000008ff ,0x00000800 , +0x9508 ,0x00010000 ,0x00010000 , +0xac0c ,0xffffffff ,0x54763210 , +0x214f8 ,0x01ff01ff ,0x00000002 , +0x21498 ,0x007ff800 ,0x00200000 , +0x2015c ,0xffffffff ,0x00000f40 , +0x30934 ,0xffffffff ,0x00000001 +}; + +static const u32 spectre_mgcg_cgcg_init[] = +{ +0xc420 ,0xffffffff ,0xfffffffc , +0x30800 ,0xffffffff ,0xe0000000 , +0x3c2a0 ,0xffffffff ,0x00000100 , +0x3c208 ,0xffffffff ,0x00000100 , +0x3c2c0 ,0xffffffff ,0x00000100 , +0x3c2c8 ,0xffffffff ,0x00000100 , +0x3c2c4 ,0xffffffff ,0x00000100 , +0x55e4 ,0xffffffff ,0x00600100 , +0x3c280 ,0xffffffff ,0x00000100 , +0x3c214 ,0xffffffff ,0x06000100 , +0x3c220 ,0xffffffff ,0x00000100 , +0x3c218 ,0xffffffff ,0x06000100 , +0x3c204 ,0xffffffff ,0x00000100 , +0x3c2e0 ,0xffffffff ,0x00000100 , +0x3c224 ,0xffffffff ,0x00000100 , +0x3c200 ,0xffffffff ,0x00000100 , +0x3c230 ,0xffffffff ,0x00000100 , +0x3c234 ,0xffffffff ,0x00000100 , +0x3c250 ,0xffffffff ,0x00000100 , +0x3c254 ,0xffffffff ,0x00000100 , +0x3c258 ,0xffffffff ,0x00000100 , +0x3c25c ,0xffffffff ,0x00000100 , +0x3c260 ,0xffffffff ,0x00000100 , +0x3c27c ,0xffffffff ,0x00000100 , +0x3c278 ,0xffffffff ,0x00000100 , +0x3c210 ,0xffffffff ,0x06000100 , +0x3c290 ,0xffffffff ,0x00000100 , +0x3c274 ,0xffffffff ,0x00000100 , +0x3c2b4 ,0xffffffff ,0x00000100 , +0x3c2b0 ,0xffffffff ,0x00000100 , +0x3c270 ,0xffffffff ,0x00000100 , +0x30800 ,0xffffffff ,0xe0000000 , +0x3c020 ,0xffffffff ,0x00010000 , +0x3c024 ,0xffffffff ,0x00030002 , +0x3c028 ,0xffffffff ,0x00040007 , +0x3c02c ,0xffffffff ,0x00060005 , +0x3c030 ,0xffffffff ,0x00090008 , +0x3c034 ,0xffffffff ,0x00010000 , +0x3c038 ,0xffffffff ,0x00030002 , +0x3c03c ,0xffffffff ,0x00040007 , +0x3c040 ,0xffffffff ,0x00060005 , +0x3c044 ,0xffffffff ,0x00090008 , +0x3c048 ,0xffffffff ,0x00010000 , +0x3c04c ,0xffffffff ,0x00030002 , +0x3c050 ,0xffffffff ,0x00040007 , +0x3c054 ,0xffffffff ,0x00060005 , +0x3c058 ,0xffffffff ,0x00090008 , +0x3c05c ,0xffffffff ,0x00010000 , +0x3c060 ,0xffffffff ,0x00030002 , +0x3c064 ,0xffffffff ,0x00040007 , +0x3c068 ,0xffffffff ,0x00060005 , +0x3c06c ,0xffffffff ,0x00090008 , +0x3c070 ,0xffffffff ,0x00010000 , +0x3c074 ,0xffffffff ,0x00030002 , +0x3c078 ,0xffffffff ,0x00040007 , +0x3c07c ,0xffffffff ,0x00060005 , +0x3c080 ,0xffffffff ,0x00090008 , +0x3c084 ,0xffffffff ,0x00010000 , +0x3c088 ,0xffffffff ,0x00030002 , +0x3c08c ,0xffffffff ,0x00040007 , +0x3c090 ,0xffffffff ,0x00060005 , +0x3c094 ,0xffffffff ,0x00090008 , +0x3c098 ,0xffffffff ,0x00010000 , +0x3c09c ,0xffffffff ,0x00030002 , +0x3c0a0 ,0xffffffff ,0x00040007 , +0x3c0a4 ,0xffffffff ,0x00060005 , +0x3c0a8 ,0xffffffff ,0x00090008 , +0x3c0ac ,0xffffffff ,0x00010000 , +0x3c0b0 ,0xffffffff ,0x00030002 , +0x3c0b4 ,0xffffffff ,0x00040007 , +0x3c0b8 ,0xffffffff ,0x00060005 , +0x3c0bc ,0xffffffff ,0x00090008 , +0x3c000 ,0xffffffff ,0x96e00200 , +0x8708 ,0xffffffff ,0x00900100 , +0xc424 ,0xffffffff ,0x0020003f , +0x38 ,0xffffffff ,0x0140001c , +0x3c ,0x000f0000 ,0x000f0000 , +0x220 ,0xffffffff ,0xC060000C , +0x224 ,0xc0000fff ,0x00000100 , +0xf90 ,0xffffffff ,0x00000100 , +0xf98 ,0x00000101 ,0x00000000 , +0x20a8 ,0xffffffff ,0x00000104 , +0x55e4 ,0xff000fff ,0x00000100 , +0x30cc ,0xc0000fff ,0x00000104 , +0xc1e4 ,0x00000001 ,0x00000001 , +0xd00c ,0xff000ff0 ,0x00000100 , +0xd80c ,0xff000ff0 ,0x00000100 +}; + +static const u32 kalindi_golden_spm_registers[] = +{ +0x30800 ,0xe0ffffff ,0xe0000000 +}; + +static const u32 kalindi_golden_common_registers[] = +{ +0xc770 ,0xffffffff ,0x00000800 , +0xc774 ,0xffffffff ,0x00000800 , +0xc798 ,0xffffffff ,0x00007fbf , +0xc79c ,0xffffffff ,0x00007faf +}; + +static const u32 kalindi_golden_registers[] = +{ +0x3c000 ,0xffffdfff ,0x6e944040 , +0x55e4 ,0xff607fff ,0xfc000100 , +0x3c220 ,0xff000fff ,0x00000100 , +0x3c224 ,0xff000fff ,0x00000100 , +0x3c200 ,0xfffc0fff ,0x00000100 , +0x6ed8 ,0x00010101 ,0x00010000 , +0x9830 ,0xffffffff ,0x00000000 , +0x9834 ,0xf00fffff ,0x00000400 , +0x5bb0 ,0x000000f0 ,0x00000070 , +0x5bc0 ,0xf0311fff ,0x80300000 , +0x98f8 ,0x73773777 ,0x12010001 , +0x98fc ,0xffffffff ,0x00000010 , +0x9b7c ,0x00ff0000 ,0x00fc0000 , +0x8030 ,0x00001f0f ,0x0000100a , +0x2f48 ,0x73773777 ,0x12010001 , +0x2408 ,0x000fffff ,0x000c007f , +0x8a14 ,0xf000003f ,0x00000007 , +0x8b24 ,0x3fff3fff ,0x00ffcfff , +0x30a04 ,0x0000ff0f ,0x00000000 , +0x28a4c ,0x07ffffff ,0x06000000 , +0x4d8 ,0x00000fff ,0x00000100 , +0x3e78 ,0x00000001 ,0x00000002 , +0xc768 ,0x00000008 ,0x00000008 , +0x8c00 ,0x000000ff ,0x00000003 , +0x214f8 ,0x01ff01ff ,0x00000002 , +0x21498 ,0x007ff800 ,0x00200000 , +0x2015c ,0xffffffff ,0x00000f40 , +0x88c4 ,0x001f3ae3 ,0x00000082 , +0x88d4 ,0x0000001f ,0x00000010 , +0x30934 ,0xffffffff ,0x00000000 +}; + +static const u32 kalindi_mgcg_cgcg_init[] = +{ +0xc420 ,0xffffffff ,0xfffffffc , +0x30800 ,0xffffffff ,0xe0000000 , +0x3c2a0 ,0xffffffff ,0x00000100 , +0x3c208 ,0xffffffff ,0x00000100 , +0x3c2c0 ,0xffffffff ,0x00000100 , +0x3c2c8 ,0xffffffff ,0x00000100 , +0x3c2c4 ,0xffffffff ,0x00000100 , +0x55e4 ,0xffffffff ,0x00600100 , +0x3c280 ,0xffffffff ,0x00000100 , +0x3c214 ,0xffffffff ,0x06000100 , +0x3c220 ,0xffffffff ,0x00000100 , +0x3c218 ,0xffffffff ,0x06000100 , +0x3c204 ,0xffffffff ,0x00000100 , +0x3c2e0 ,0xffffffff ,0x00000100 , +0x3c224 ,0xffffffff ,0x00000100 , +0x3c200 ,0xffffffff ,0x00000100 , +0x3c230 ,0xffffffff ,0x00000100 , +0x3c234 ,0xffffffff ,0x00000100 , +0x3c250 ,0xffffffff ,0x00000100 , +0x3c254 ,0xffffffff ,0x00000100 , +0x3c258 ,0xffffffff ,0x00000100 , +0x3c25c ,0xffffffff ,0x00000100 , +0x3c260 ,0xffffffff ,0x00000100 , +0x3c27c ,0xffffffff ,0x00000100 , +0x3c278 ,0xffffffff ,0x00000100 , +0x3c210 ,0xffffffff ,0x06000100 , +0x3c290 ,0xffffffff ,0x00000100 , +0x3c274 ,0xffffffff ,0x00000100 , +0x3c2b4 ,0xffffffff ,0x00000100 , +0x3c2b0 ,0xffffffff ,0x00000100 , +0x3c270 ,0xffffffff ,0x00000100 , +0x30800 ,0xffffffff ,0xe0000000 , +0x3c020 ,0xffffffff ,0x00010000 , +0x3c024 ,0xffffffff ,0x00030002 , +0x3c028 ,0xffffffff ,0x00040007 , +0x3c02c ,0xffffffff ,0x00060005 , +0x3c030 ,0xffffffff ,0x00090008 , +0x3c034 ,0xffffffff ,0x00010000 , +0x3c038 ,0xffffffff ,0x00030002 , +0x3c03c ,0xffffffff ,0x00040007 , +0x3c040 ,0xffffffff ,0x00060005 , +0x3c044 ,0xffffffff ,0x00090008 , +0x3c000 ,0xffffffff ,0x96e00200 , +0x8708 ,0xffffffff ,0x00900100 , +0xc424 ,0xffffffff ,0x0020003f , +0x38 ,0xffffffff ,0x0140001c , +0x3c ,0x000f0000 ,0x000f0000 , +0x220 ,0xffffffff ,0xC060000C , +0x224 ,0xc0000fff ,0x00000100 , +0x20a8 ,0xffffffff ,0x00000104 , +0x55e4 ,0xff000fff ,0x00000100 , +0x30cc ,0xc0000fff ,0x00000104 , +0xc1e4 ,0x00000001 ,0x00000001 , +0xd00c ,0xff000ff0 ,0x00000100 , +0xd80c ,0xff000ff0 ,0x00000100 +}; + +static void cik_init_golden_registers (struct radeon_device *rdev) +{ +switch (rdev->family) { +case CHIP_BONAIRE : +radeon_program_register_sequence (rdev, + bonaire_mgcg_cgcg_init, + (const u32 )ARRAY_SIZE (bonaire_mgcg_cgcg_init)); +radeon_program_register_sequence (rdev, + bonaire_golden_registers, + (const u32 )ARRAY_SIZE (bonaire_golden_registers)); +radeon_program_register_sequence (rdev, + bonaire_golden_common_registers, + (const u32 )ARRAY_SIZE (bonaire_golden_common_registers)); +radeon_program_register_sequence (rdev, + bonaire_golden_spm_registers, + (const u32 )ARRAY_SIZE (bonaire_golden_spm_registers)); +break ; +case CHIP_KABINI : +radeon_program_register_sequence (rdev, + kalindi_mgcg_cgcg_init, + (const u32 )ARRAY_SIZE (kalindi_mgcg_cgcg_init)); +radeon_program_register_sequence (rdev, + kalindi_golden_registers, + (const u32 )ARRAY_SIZE (kalindi_golden_registers)); +radeon_program_register_sequence (rdev, + kalindi_golden_common_registers, + (const u32 )ARRAY_SIZE (kalindi_golden_common_registers)); +radeon_program_register_sequence (rdev, + kalindi_golden_spm_registers, + (const u32 )ARRAY_SIZE (kalindi_golden_spm_registers)); +break ; +case CHIP_KAVERI : +radeon_program_register_sequence (rdev, + spectre_mgcg_cgcg_init, + (const u32 )ARRAY_SIZE (spectre_mgcg_cgcg_init)); +radeon_program_register_sequence (rdev, + spectre_golden_registers, + (const u32 )ARRAY_SIZE (spectre_golden_registers)); +radeon_program_register_sequence (rdev, + spectre_golden_common_registers, + (const u32 )ARRAY_SIZE (spectre_golden_common_registers)); +radeon_program_register_sequence (rdev, + spectre_golden_spm_registers, + (const u32 )ARRAY_SIZE (spectre_golden_spm_registers)); +break ; +default : +break ; + } +} +/** * cik_get_xclk - get the xclk *
@@ -5719,6 +6152,9 @@ int cik_resume(struct radeon_device *rdev)/* post card */ atom_asic_init (rdev->mode_info.atom_context); +/* init golden registers */ +cik_init_golden_registers (rdev); + rdev->accel_working = true; r =cik_startup (rdev);if (r) {
@@ -5797,6 +6233,8 @@ int cik_init(struct radeon_device *rdev)DRM_INFO ("GPU not posted. posting now...\n" );atom_asic_init (rdev->mode_info.atom_context); } +/* init golden registers */ +cik_init_golden_registers (rdev);/* Initialize scratch registers */ cik_scratch_init (rdev);/* Initialize surface registers */
Signature · 1 line
1.7.7.5
PATCH 57/165 drm/radeon: add radeon_asic struct for CIK (v11)
In reply to [email protected]From: Alex Deucher <[email protected]>
v2: fix up for latest reset changes
v3: use CP for pt updates for now
v4: update for 2 level PTs
v5: update for ib_parse removal
v6: vm_flush api change
v7: rebase
v8: fix gfx ring function pointers
v9: fix vm_set_page function params
v10: update for compute changes
v11: cleanup for release
--- drivers/gpu/drm/radeon/radeon_asic.c | 287 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon_asic.h | 47 ++++++ 2 files changed, 334 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/radeon_asic.c +287 -0
@@ -1923,6 +1923,280 @@ static struct radeon_asic si_asic = { }, }; +static struct radeon_asic ci_asic = { + .init = &cik_init, + .fini = &cik_fini, + .suspend = &cik_suspend, + .resume = &cik_resume, + .asic_reset = &cik_asic_reset, + .vga_set_state = &r600_vga_set_state, + .ioctl_wait_idle =NULL , + .gui_idle = &r600_gui_idle, + .mc_wait_for_idle = &evergreen_mc_wait_for_idle, + .get_xclk = &cik_get_xclk, + .get_gpu_clock_counter = &cik_get_gpu_clock_counter, + .gart = { + .tlb_flush = &cik_pcie_gart_tlb_flush, + .set_page = &rs600_gart_set_page, + }, + .vm = { + .init = &cik_vm_init, + .fini = &cik_vm_fini, + .pt_ring_index =R600_RING_TYPE_DMA_INDEX , + .set_page = &cik_vm_set_page, + }, + .ring = { + [RADEON_RING_TYPE_GFX_INDEX ] = { + .ib_execute = &cik_ring_ib_execute, + .ib_parse = &cik_ib_parse, + .emit_fence = &cik_fence_gfx_ring_emit, + .emit_semaphore = &cik_semaphore_ring_emit, + .cs_parse =NULL , + .ring_test = &cik_ring_test, + .ib_test = &cik_ib_test, + .is_lockup = &cik_gfx_is_lockup, + .vm_flush = &cik_vm_flush, + }, + [CAYMAN_RING_TYPE_CP1_INDEX ] = { + .ib_execute = &cik_ring_ib_execute, + .ib_parse = &cik_ib_parse, + .emit_fence = &cik_fence_compute_ring_emit, + .emit_semaphore = &cik_semaphore_ring_emit, + .cs_parse =NULL , + .ring_test = &cik_ring_test, + .ib_test = &cik_ib_test, + .is_lockup = &cik_gfx_is_lockup, + .vm_flush = &cik_vm_flush, + }, + [CAYMAN_RING_TYPE_CP2_INDEX ] = { + .ib_execute = &cik_ring_ib_execute, + .ib_parse = &cik_ib_parse, + .emit_fence = &cik_fence_compute_ring_emit, + .emit_semaphore = &cik_semaphore_ring_emit, + .cs_parse =NULL , + .ring_test = &cik_ring_test, + .ib_test = &cik_ib_test, + .is_lockup = &cik_gfx_is_lockup, + .vm_flush = &cik_vm_flush, + }, + [R600_RING_TYPE_DMA_INDEX ] = { + .ib_execute = &cik_sdma_ring_ib_execute, + .ib_parse = &cik_ib_parse, + .emit_fence = &cik_sdma_fence_ring_emit, + .emit_semaphore = &cik_sdma_semaphore_ring_emit, + .cs_parse =NULL , + .ring_test = &cik_sdma_ring_test, + .ib_test = &cik_sdma_ib_test, + .is_lockup = &cik_sdma_is_lockup, + .vm_flush = &cik_dma_vm_flush, + }, + [CAYMAN_RING_TYPE_DMA1_INDEX ] = { + .ib_execute = &cik_sdma_ring_ib_execute, + .ib_parse = &cik_ib_parse, + .emit_fence = &cik_sdma_fence_ring_emit, + .emit_semaphore = &cik_sdma_semaphore_ring_emit, + .cs_parse =NULL , + .ring_test = &cik_sdma_ring_test, + .ib_test = &cik_sdma_ib_test, + .is_lockup = &cik_sdma_is_lockup, + .vm_flush = &cik_dma_vm_flush, + }, + [R600_RING_TYPE_UVD_INDEX ] = { + .ib_execute = &r600_uvd_ib_execute, + .emit_fence = &r600_uvd_fence_emit, + .emit_semaphore = &cayman_uvd_semaphore_emit, + .cs_parse = &radeon_uvd_cs_parse, + .ring_test = &r600_uvd_ring_test, + .ib_test = &r600_uvd_ib_test, + .is_lockup = &radeon_ring_test_lockup, + } + }, + .irq = { + .set = &cik_irq_set, + .process = &cik_irq_process, + }, + .display = { + .bandwidth_update = &dce8_bandwidth_update, + .get_vblank_counter = &evergreen_get_vblank_counter, + .wait_for_vblank = &dce4_wait_for_vblank, + }, + .copy = { + .blit =NULL , + .blit_ring_index =RADEON_RING_TYPE_GFX_INDEX , + .dma = &cik_copy_dma, + .dma_ring_index =R600_RING_TYPE_DMA_INDEX , + .copy = &cik_copy_dma, + .copy_ring_index =R600_RING_TYPE_DMA_INDEX , + }, + .surface = { + .set_reg = r600_set_surface_reg, + .clear_reg = r600_clear_surface_reg, + }, + .hpd = { + .init = &evergreen_hpd_init, + .fini = &evergreen_hpd_fini, + .sense = &evergreen_hpd_sense, + .set_polarity = &evergreen_hpd_set_polarity, + }, + .pm = { + .misc = &evergreen_pm_misc, + .prepare = &evergreen_pm_prepare, + .finish = &evergreen_pm_finish, + .init_profile = &sumo_pm_init_profile, + .get_dynpm_state = &r600_pm_get_dynpm_state, + .get_engine_clock = &radeon_atom_get_engine_clock, + .set_engine_clock = &radeon_atom_set_engine_clock, + .get_memory_clock = &radeon_atom_get_memory_clock, + .set_memory_clock = &radeon_atom_set_memory_clock, + .get_pcie_lanes =NULL , + .set_pcie_lanes =NULL , + .set_clock_gating =NULL , + .set_uvd_clocks = &cik_set_uvd_clocks, + }, + .pflip = { + .pre_page_flip = &evergreen_pre_page_flip, + .page_flip = &evergreen_page_flip, + .post_page_flip = &evergreen_post_page_flip, + }, +}; + +static struct radeon_asic kv_asic = { + .init = &cik_init, + .fini = &cik_fini, + .suspend = &cik_suspend, + .resume = &cik_resume, + .asic_reset = &cik_asic_reset, + .vga_set_state = &r600_vga_set_state, + .ioctl_wait_idle =NULL , + .gui_idle = &r600_gui_idle, + .mc_wait_for_idle = &evergreen_mc_wait_for_idle, + .get_xclk = &cik_get_xclk, + .get_gpu_clock_counter = &cik_get_gpu_clock_counter, + .gart = { + .tlb_flush = &cik_pcie_gart_tlb_flush, + .set_page = &rs600_gart_set_page, + }, + .vm = { + .init = &cik_vm_init, + .fini = &cik_vm_fini, + .pt_ring_index =R600_RING_TYPE_DMA_INDEX , + .set_page = &cik_vm_set_page, + }, + .ring = { + [RADEON_RING_TYPE_GFX_INDEX ] = { + .ib_execute = &cik_ring_ib_execute, + .ib_parse = &cik_ib_parse, + .emit_fence = &cik_fence_gfx_ring_emit, + .emit_semaphore = &cik_semaphore_ring_emit, + .cs_parse =NULL , + .ring_test = &cik_ring_test, + .ib_test = &cik_ib_test, + .is_lockup = &cik_gfx_is_lockup, + .vm_flush = &cik_vm_flush, + }, + [CAYMAN_RING_TYPE_CP1_INDEX ] = { + .ib_execute = &cik_ring_ib_execute, + .ib_parse = &cik_ib_parse, + .emit_fence = &cik_fence_compute_ring_emit, + .emit_semaphore = &cik_semaphore_ring_emit, + .cs_parse =NULL , + .ring_test = &cik_ring_test, + .ib_test = &cik_ib_test, + .is_lockup = &cik_gfx_is_lockup, + .vm_flush = &cik_vm_flush, + }, + [CAYMAN_RING_TYPE_CP2_INDEX ] = { + .ib_execute = &cik_ring_ib_execute, + .ib_parse = &cik_ib_parse, + .emit_fence = &cik_fence_compute_ring_emit, + .emit_semaphore = &cik_semaphore_ring_emit, + .cs_parse =NULL , + .ring_test = &cik_ring_test, + .ib_test = &cik_ib_test, + .is_lockup = &cik_gfx_is_lockup, + .vm_flush = &cik_vm_flush, + }, + [R600_RING_TYPE_DMA_INDEX ] = { + .ib_execute = &cik_sdma_ring_ib_execute, + .ib_parse = &cik_ib_parse, + .emit_fence = &cik_sdma_fence_ring_emit, + .emit_semaphore = &cik_sdma_semaphore_ring_emit, + .cs_parse =NULL , + .ring_test = &cik_sdma_ring_test, + .ib_test = &cik_sdma_ib_test, + .is_lockup = &cik_sdma_is_lockup, + .vm_flush = &cik_dma_vm_flush, + }, + [CAYMAN_RING_TYPE_DMA1_INDEX ] = { + .ib_execute = &cik_sdma_ring_ib_execute, + .ib_parse = &cik_ib_parse, + .emit_fence = &cik_sdma_fence_ring_emit, + .emit_semaphore = &cik_sdma_semaphore_ring_emit, + .cs_parse =NULL , + .ring_test = &cik_sdma_ring_test, + .ib_test = &cik_sdma_ib_test, + .is_lockup = &cik_sdma_is_lockup, + .vm_flush = &cik_dma_vm_flush, + }, + [R600_RING_TYPE_UVD_INDEX ] = { + .ib_execute = &r600_uvd_ib_execute, + .emit_fence = &r600_uvd_fence_emit, + .emit_semaphore = &cayman_uvd_semaphore_emit, + .cs_parse = &radeon_uvd_cs_parse, + .ring_test = &r600_uvd_ring_test, + .ib_test = &r600_uvd_ib_test, + .is_lockup = &radeon_ring_test_lockup, + } + }, + .irq = { + .set = &cik_irq_set, + .process = &cik_irq_process, + }, + .display = { + .bandwidth_update = &dce8_bandwidth_update, + .get_vblank_counter = &evergreen_get_vblank_counter, + .wait_for_vblank = &dce4_wait_for_vblank, + }, + .copy = { + .blit =NULL , + .blit_ring_index =RADEON_RING_TYPE_GFX_INDEX , + .dma = &cik_copy_dma, + .dma_ring_index =R600_RING_TYPE_DMA_INDEX , + .copy = &cik_copy_dma, + .copy_ring_index =R600_RING_TYPE_DMA_INDEX , + }, + .surface = { + .set_reg = r600_set_surface_reg, + .clear_reg = r600_clear_surface_reg, + }, + .hpd = { + .init = &evergreen_hpd_init, + .fini = &evergreen_hpd_fini, + .sense = &evergreen_hpd_sense, + .set_polarity = &evergreen_hpd_set_polarity, + }, + .pm = { + .misc = &evergreen_pm_misc, + .prepare = &evergreen_pm_prepare, + .finish = &evergreen_pm_finish, + .init_profile = &sumo_pm_init_profile, + .get_dynpm_state = &r600_pm_get_dynpm_state, + .get_engine_clock = &radeon_atom_get_engine_clock, + .set_engine_clock = &radeon_atom_set_engine_clock, + .get_memory_clock = &radeon_atom_get_memory_clock, + .set_memory_clock = &radeon_atom_set_memory_clock, + .get_pcie_lanes =NULL , + .set_pcie_lanes =NULL , + .set_clock_gating =NULL , + .set_uvd_clocks = &cik_set_uvd_clocks, + }, + .pflip = { + .pre_page_flip = &evergreen_pre_page_flip, + .page_flip = &evergreen_page_flip, + .post_page_flip = &evergreen_post_page_flip, + }, +}; +/** * radeon_asic_init - register asic specific callbacks *
@@ -2086,6 +2360,19 @@ int radeon_asic_init(struct radeon_device *rdev)else rdev->has_uvd = true;break ; +case CHIP_BONAIRE : + rdev->asic = &ci_asic; + rdev->num_crtc =6 ; +break ; +case CHIP_KAVERI : +case CHIP_KABINI : + rdev->asic = &kv_asic; +/* set num crtcs */ +if (rdev->family ==CHIP_KAVERI ) + rdev->num_crtc =4 ; +else + rdev->num_crtc =2 ; +break ;default :/* FIXME: not supported yet */ return -EINVAL ;
drivers/gpu/drm/radeon/radeon_asic.h +47 -0
58 lines not on this page · raw message
Signature · 1 line
1.7.7.5
PATCH 58/165 drm/radeon: add cik tile mode array query
In reply to [email protected]From: Alex Deucher <[email protected]>
--- drivers/gpu/drm/radeon/cik.c | 4 ++++ drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_drv.c | 3 ++- drivers/gpu/drm/radeon/radeon_kms.c | 14 +++++++------- 4 files changed, 14 insertions(+), 8 deletions(-)
drivers/gpu/drm/radeon/cik.c +4 -0
@@ -1059,6 +1059,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev) gb_tile_moden =0 ;break ; } + rdev->config.cik.tile_mode_array[reg_offset] = gb_tile_moden;WREG32 (GB_TILE_MODE0 + (reg_offset *4 ), gb_tile_moden); }for (reg_offset =0 ; reg_offset < num_secondary_tile_mode_states; reg_offset++) {
@@ -1277,6 +1278,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev) gb_tile_moden =0 ;break ; } + rdev->config.cik.tile_mode_array[reg_offset] = gb_tile_moden;WREG32 (GB_TILE_MODE0 + (reg_offset *4 ), gb_tile_moden); } }else if (num_rbs <4 ) {
@@ -1402,6 +1404,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev) gb_tile_moden =0 ;break ; } + rdev->config.cik.tile_mode_array[reg_offset] = gb_tile_moden;WREG32 (GB_TILE_MODE0 + (reg_offset *4 ), gb_tile_moden); } }
@@ -1619,6 +1622,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev) gb_tile_moden =0 ;break ; } + rdev->config.cik.tile_mode_array[reg_offset] = gb_tile_moden;WREG32 (GB_TILE_MODE0 + (reg_offset *4 ), gb_tile_moden); }for (reg_offset =0 ; reg_offset < num_secondary_tile_mode_states; reg_offset++) {
drivers/gpu/drm/radeon/radeon.h +1 -0
@@ -1588,6 +1588,7 @@ struct cik_asic {unsigned multi_gpu_tile_size;unsigned tile_config; +uint32_t tile_mode_array[32 ]; };union radeon_asic_config {
drivers/gpu/drm/radeon/radeon_drv.c +2 -1
@@ -74,9 +74,10 @@* 2.31.0 - Add fastfb support for rs690 * 2.32.0 - new info request for rings working * 2.33.0 - Add SI tiling mode array query +* 2.34.0 - Add CIK tiling mode array query */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 33 +#define KMS_DRIVER_MINOR 34#define KMS_DRIVER_PATCHLEVEL 0int radeon_driver_load_kms (struct drm_device *dev,unsigned long flags);int radeon_driver_unload_kms (struct drm_device *dev);
drivers/gpu/drm/radeon/radeon_kms.c +7 -7
@@ -423,15 +423,15 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)break ;case RADEON_INFO_SI_TILE_MODE_ARRAY :if (rdev->family >=CHIP_BONAIRE ) { -DRM_DEBUG_KMS ("tile mode array is not implemented yet\n" ); + value = rdev->config.cik.tile_mode_array; + value_size =sizeof (uint32_t )*32 ; + }else if (rdev->family >=CHIP_TAHITI ) { + value = rdev->config.si.tile_mode_array; + value_size =sizeof (uint32_t )*32 ; + }else { +DRM_DEBUG_KMS ("tile mode array is si+ only!\n" );return -EINVAL ; } -if (rdev->family <CHIP_TAHITI ) { -DRM_DEBUG_KMS ("tile mode array is si only!\n" ); -return -EINVAL ; - } - value = rdev->config.si.tile_mode_array; - value_size =sizeof (uint32_t )*32 ;break ;default :DRM_DEBUG_KMS ("Invalid request %d\n" , info->request);
Signature · 1 line
1.7.7.5
PATCH 59/165 drm/radeon: add current Bonaire PCI ids
In reply to [email protected]From: Alex Deucher <[email protected]>
--- include/drm/drm_pciids.h | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-)
include/drm/drm_pciids.h +8 -0
@@ -152,6 +152,14 @@ {0x1002, 0x6621, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6623, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6631, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6640, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6641, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6658, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x665c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x665d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6663, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6664, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
Signature · 1 line
1.7.7.5
PATCH 60/165 drm/radeon: add current KB pci ids
In reply to [email protected]From: Alex Deucher <[email protected]>
--- include/drm/drm_pciids.h | 16 ++++++++++++++++ 1 files changed, 16 insertions(+), 0 deletions(-)
include/drm/drm_pciids.h +16 -0
@@ -588,6 +588,22 @@ {0x1002, 0x9808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x980A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9830, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9831, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9832, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9833, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9836, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9837, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9838, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9839, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x983a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x983b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x983c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x983d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x983e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x983f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
Signature · 1 line
1.7.7.5
PATCH 61/165 drm/radeon/kms: add accessors for RCU indirect space
In reply to [email protected]From: Alex Deucher <[email protected]>
--- drivers/gpu/drm/radeon/evergreen.c | 6 ++---- drivers/gpu/drm/radeon/r600_reg.h | 3 +++ drivers/gpu/drm/radeon/radeon.h | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 4 deletions(-)
drivers/gpu/drm/radeon/evergreen.c +2 -4
@@ -3120,10 +3120,8 @@ static void evergreen_gpu_init(struct radeon_device *rdev)u32 efuse_straps_4;u32 efuse_straps_3; -WREG32 (RCU_IND_INDEX ,0x204 ); - efuse_straps_4 =RREG32 (RCU_IND_DATA ); -WREG32 (RCU_IND_INDEX ,0x203 ); - efuse_straps_3 =RREG32 (RCU_IND_DATA ); + efuse_straps_4 =RREG32_RCU (0x204 ); + efuse_straps_3 =RREG32_RCU (0x203 ); tmp = (((efuse_straps_4 &0xf ) <<4 ) | ((efuse_straps_3 &0xf0000000 ) >>28 )); }else {
drivers/gpu/drm/radeon/r600_reg.h +3 -0
@@ -31,6 +31,9 @@#define R600_PCIE_PORT_INDEX 0x0038#define R600_PCIE_PORT_DATA 0x003c +#define R600_RCU_INDEX 0x0100 +#define R600_RCU_DATA 0x0104 +#define R600_MC_VM_FB_LOCATION 0x2180#define R600_MC_FB_BASE_MASK 0x0000FFFF#define R600_MC_FB_BASE_SHIFT 0
drivers/gpu/drm/radeon/radeon.h +17 -0
@@ -1851,6 +1851,8 @@ void cik_mm_wdoorbell(struct radeon_device *rdev, u32 offset, u32 v);#define WREG32_PCIE_PORT (reg, v) rdev->pciep_wreg(rdev, (reg), (v))#define RREG32_SMC (reg) tn_smc_rreg(rdev, (reg))#define WREG32_SMC (reg, v) tn_smc_wreg(rdev, (reg), (v)) +#define RREG32_RCU (reg) r600_rcu_rreg(rdev, (reg)) +#define WREG32_RCU (reg, v) r600_rcu_wreg(rdev, (reg), (v))#define WREG32_P (reg, val, mask) \ do { \ uint32_t tmp_ = RREG32(reg); \
@@ -1907,6 +1909,21 @@ static inline void tn_smc_wreg(struct radeon_device *rdev, u32 reg, u32 v)WREG32 (TN_SMC_IND_DATA_0 , (v)); } +static inline u32 r600_rcu_rreg (struct radeon_device *rdev,u32 reg) +{ +u32 r; + +WREG32 (R600_RCU_INDEX , ((reg) &0x1fff )); + r =RREG32 (R600_RCU_DATA ); +return r; +} + +static inline void r600_rcu_wreg (struct radeon_device *rdev,u32 reg,u32 v) +{ +WREG32 (R600_RCU_INDEX , ((reg) &0x1fff )); +WREG32 (R600_RCU_DATA , (v)); +} +void r100_pll_errata_after_index (struct radeon_device *rdev);
Signature · 1 line
1.7.7.5
PATCH 62/165 drm/radeon/evergreen: add indirect register accessors for CG registers
In reply to [email protected]From: Alex Deucher <[email protected]>
--- drivers/gpu/drm/radeon/evergreen_reg.h | 3 +++ drivers/gpu/drm/radeon/radeon.h | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/evergreen_reg.h +3 -0
@@ -44,6 +44,9 @@#define EVERGREEN_AUDIO_PLL1_DIV 0x5b4#define EVERGREEN_AUDIO_PLL1_UNK 0x5bc +#define EVERGREEN_CG_IND_ADDR 0x8f8 +#define EVERGREEN_CG_IND_DATA 0x8fc +#define EVERGREEN_AUDIO_ENABLE 0x5e78#define EVERGREEN_AUDIO_VENDOR_ID 0x5ec0
drivers/gpu/drm/radeon/radeon.h +17 -0
@@ -1853,6 +1853,8 @@ void cik_mm_wdoorbell(struct radeon_device *rdev, u32 offset, u32 v);#define WREG32_SMC (reg, v) tn_smc_wreg(rdev, (reg), (v))#define RREG32_RCU (reg) r600_rcu_rreg(rdev, (reg))#define WREG32_RCU (reg, v) r600_rcu_wreg(rdev, (reg), (v)) +#define RREG32_CG (reg) eg_cg_rreg(rdev, (reg)) +#define WREG32_CG (reg, v) eg_cg_wreg(rdev, (reg), (v))#define WREG32_P (reg, val, mask) \ do { \ uint32_t tmp_ = RREG32(reg); \
@@ -1924,6 +1926,21 @@ static inline void r600_rcu_wreg(struct radeon_device *rdev, u32 reg, u32 v)WREG32 (R600_RCU_DATA , (v)); } +static inline u32 eg_cg_rreg (struct radeon_device *rdev,u32 reg) +{ +u32 r; + +WREG32 (EVERGREEN_CG_IND_ADDR , ((reg) &0xffff )); + r =RREG32 (EVERGREEN_CG_IND_DATA ); +return r; +} + +static inline void eg_cg_wreg (struct radeon_device *rdev,u32 reg,u32 v) +{ +WREG32 (EVERGREEN_CG_IND_ADDR , ((reg) &0xffff )); +WREG32 (EVERGREEN_CG_IND_DATA , (v)); +} +void r100_pll_errata_after_index (struct radeon_device *rdev);
Signature · 1 line
1.7.7.5
PATCH 63/165 drm/radeon: make get_temperature functions a callback
In reply to [email protected]From: Alex Deucher <[email protected]>
--- drivers/gpu/drm/radeon/radeon.h | 7 ++----- drivers/gpu/drm/radeon/radeon_asic.c | 8 ++++++++ drivers/gpu/drm/radeon/radeon_asic.h | 5 +++++ drivers/gpu/drm/radeon/radeon_pm.c | 26 ++++---------------------- 4 files changed, 19 insertions(+), 27 deletions(-)
drivers/gpu/drm/radeon/radeon.h +2 -5
@@ -220,11 +220,6 @@ int radeon_atom_get_clock_dividers(struct radeon_device *rdev, struct atom_clock_dividers *dividers);void radeon_atom_set_voltage (struct radeon_device *rdev,u16 voltage_level,u8 voltage_type);void rs690_pm_info (struct radeon_device *rdev); -extern int rv6xx_get_temp (struct radeon_device *rdev); -extern int rv770_get_temp (struct radeon_device *rdev); -extern int evergreen_get_temp (struct radeon_device *rdev); -extern int sumo_get_temp (struct radeon_device *rdev); -extern int si_get_temp (struct radeon_device *rdev);extern void evergreen_tiling_fields (unsigned tiling_flags,unsigned *bankw,unsigned *bankh,unsigned *mtaspect,unsigned *tile_split);
@@ -1396,6 +1391,7 @@ struct radeon_asic {void (*set_pcie_lanes)(struct radeon_device *rdev,int lanes);void (*set_clock_gating)(struct radeon_device *rdev,int enable);int (*set_uvd_clocks)(struct radeon_device *rdev,u32 vclk,u32 dclk); +int (*get_temperature)(struct radeon_device *rdev); } pm;/* pageflipping */ struct {
@@ -2065,6 +2061,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);#define radeon_set_pcie_lanes (rdev, l) (rdev)->asic->pm.set_pcie_lanes((rdev), (l))#define radeon_set_clock_gating (rdev, e) (rdev)->asic->pm.set_clock_gating((rdev), (e))#define radeon_set_uvd_clocks (rdev, v, d) (rdev)->asic->pm.set_uvd_clocks((rdev), (v), (d)) +#define radeon_get_temperature (rdev) (rdev)->asic->pm.get_temperature((rdev))#define radeon_set_surface_reg (rdev, r, f, p, o, s) ((rdev)->asic->surface.set_reg((rdev), (r), (f), (p), (o), (s)))#define radeon_clear_surface_reg (rdev, r) ((rdev)->asic->surface.clear_reg((rdev), (r)))#define radeon_bandwidth_update (rdev) (rdev)->asic->display.bandwidth_update((rdev))
drivers/gpu/drm/radeon/radeon_asic.c +8 -0
@@ -1016,6 +1016,7 @@ static struct radeon_asic r600_asic = { .get_pcie_lanes = &r600_get_pcie_lanes, .set_pcie_lanes = &r600_set_pcie_lanes, .set_clock_gating = NULL, + .get_temperature = &rv6xx_get_temp, }, .pflip = { .pre_page_flip = &rs600_pre_page_flip,
@@ -1104,6 +1105,7 @@ static struct radeon_asic rs780_asic = { .get_pcie_lanes = NULL, .set_pcie_lanes = NULL, .set_clock_gating = NULL, + .get_temperature = &rv6xx_get_temp, }, .pflip = { .pre_page_flip = &rs600_pre_page_flip,
@@ -1202,6 +1204,7 @@ static struct radeon_asic rv770_asic = { .set_pcie_lanes = &r600_set_pcie_lanes, .set_clock_gating = &radeon_atom_set_clock_gating, .set_uvd_clocks = &rv770_set_uvd_clocks, + .get_temperature = &rv770_get_temp, }, .pflip = { .pre_page_flip = &rs600_pre_page_flip,
@@ -1300,6 +1303,7 @@ static struct radeon_asic evergreen_asic = { .set_pcie_lanes = &r600_set_pcie_lanes, .set_clock_gating = NULL, .set_uvd_clocks = &evergreen_set_uvd_clocks, + .get_temperature = &evergreen_get_temp, }, .pflip = { .pre_page_flip = &evergreen_pre_page_flip,
@@ -1398,6 +1402,7 @@ static struct radeon_asic sumo_asic = { .set_pcie_lanes = NULL, .set_clock_gating = NULL, .set_uvd_clocks = &sumo_set_uvd_clocks, + .get_temperature = &sumo_get_temp, }, .pflip = { .pre_page_flip = &evergreen_pre_page_flip,
@@ -1496,6 +1501,7 @@ static struct radeon_asic btc_asic = { .set_pcie_lanes = &r600_set_pcie_lanes, .set_clock_gating = NULL, .set_uvd_clocks = &evergreen_set_uvd_clocks, + .get_temperature = &evergreen_get_temp, }, .pflip = { .pre_page_flip = &evergreen_pre_page_flip,
@@ -1637,6 +1643,7 @@ static struct radeon_asic cayman_asic = { .set_pcie_lanes = &r600_set_pcie_lanes, .set_clock_gating = NULL, .set_uvd_clocks = &evergreen_set_uvd_clocks, + .get_temperature = &evergreen_get_temp, }, .pflip = { .pre_page_flip = &evergreen_pre_page_flip,
@@ -1915,6 +1922,7 @@ static struct radeon_asic si_asic = { .set_pcie_lanes = &r600_set_pcie_lanes, .set_clock_gating = NULL, .set_uvd_clocks = &si_set_uvd_clocks, + .get_temperature = &si_get_temp, }, .pflip = { .pre_page_flip = &evergreen_pre_page_flip,
drivers/gpu/drm/radeon/radeon_asic.h +5 -0
@@ -395,6 +395,7 @@ void r600_kms_blit_copy(struct radeon_device *rdev,int r600_mc_wait_for_idle (struct radeon_device *rdev);u32 r600_get_xclk (struct radeon_device *rdev);uint64_t r600_get_gpu_clock_counter (struct radeon_device *rdev); +int rv6xx_get_temp (struct radeon_device *rdev);/* uvd */ int r600_uvd_init (struct radeon_device *rdev);
@@ -428,6 +429,7 @@ int rv770_copy_dma(struct radeon_device *rdev,u32 rv770_get_xclk (struct radeon_device *rdev);int rv770_uvd_resume (struct radeon_device *rdev);int rv770_set_uvd_clocks (struct radeon_device *rdev,u32 vclk,u32 dclk); +int rv770_get_temp (struct radeon_device *rdev);/* * evergreen
@@ -482,6 +484,8 @@ int evergreen_copy_dma(struct radeon_device *rdev, struct radeon_fence **fence);void evergreen_hdmi_enable (struct drm_encoder *encoder,bool enable);void evergreen_hdmi_setmode (struct drm_encoder *encoder,struct drm_display_mode *mode); +int evergreen_get_temp (struct radeon_device *rdev); +int sumo_get_temp (struct radeon_device *rdev);/* * cayman
@@ -552,6 +556,7 @@ void si_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)u32 si_get_xclk (struct radeon_device *rdev);uint64_t si_get_gpu_clock_counter (struct radeon_device *rdev);int si_set_uvd_clocks (struct radeon_device *rdev,u32 vclk,u32 dclk); +int si_get_temp (struct radeon_device *rdev);/* DCE8 - CIK */ void dce8_bandwidth_update (struct radeon_device *rdev);
drivers/gpu/drm/radeon/radeon_pm.c +4 -22
@@ -434,27 +434,10 @@ static ssize_t radeon_hwmon_show_temp(struct device *dev,struct radeon_device *rdev = ddev->dev_private;int temp; -switch (rdev->pm.int_thermal_type) { -case THERMAL_TYPE_RV6XX : - temp =rv6xx_get_temp (rdev); -break ; -case THERMAL_TYPE_RV770 : - temp =rv770_get_temp (rdev); -break ; -case THERMAL_TYPE_EVERGREEN : -case THERMAL_TYPE_NI : - temp =evergreen_get_temp (rdev); -break ; -case THERMAL_TYPE_SUMO : - temp =sumo_get_temp (rdev); -break ; -case THERMAL_TYPE_SI : - temp =si_get_temp (rdev); -break ; -default : +if (rdev->asic->pm.get_temperature) + temp =radeon_get_temperature (rdev); +else temp =0 ; -break ; - }return snprintf (buf,PAGE_SIZE ,"%d\n" , temp); }
@@ -492,8 +475,7 @@ static int radeon_hwmon_init(struct radeon_device *rdev)case THERMAL_TYPE_NI :case THERMAL_TYPE_SUMO :case THERMAL_TYPE_SI : -/* No support for TN yet */ -if (rdev->family ==CHIP_ARUBA ) +if (rdev->asic->pm.get_temperature ==NULL )return err; rdev->pm.int_hwmon_dev =hwmon_device_register (rdev->dev);if (IS_ERR (rdev->pm.int_hwmon_dev)) {
Signature · 1 line
1.7.7.5
PATCH 64/165 drm/radeon: add support for thermal sensor on tn
In reply to [email protected]From: Alex Deucher <[email protected]>
--- drivers/gpu/drm/radeon/ni.c | 8 ++++++++ drivers/gpu/drm/radeon/nid.h | 3 +++ drivers/gpu/drm/radeon/radeon_asic.c | 1 + drivers/gpu/drm/radeon/radeon_asic.h | 1 + 4 files changed, 13 insertions(+), 0 deletions(-)
drivers/gpu/drm/radeon/ni.c +8 -0
@@ -692,6 +692,14 @@ out:return err; } +int tn_get_temp (struct radeon_device *rdev) +{ +u32 temp =RREG32_SMC (TN_CURRENT_GNB_TEMP ) &0x7ff ; +int actual_temp = (temp /8 ) -49 ; + +return actual_temp *1000 ; +} +/* * Core functions */
drivers/gpu/drm/radeon/nid.h +3 -0
@@ -489,6 +489,9 @@# define CACHE_FLUSH_AND_INV_EVENT_TS (0x14 << 0)# define CACHE_FLUSH_AND_INV_EVENT (0x16 << 0) +/* TN SMU registers */ +#define TN_CURRENT_GNB_TEMP 0x1F390 +/* * UVD */
drivers/gpu/drm/radeon/radeon_asic.c +1 -0
@@ -1783,6 +1783,7 @@ static struct radeon_asic trinity_asic = { .set_pcie_lanes = NULL, .set_clock_gating = NULL, .set_uvd_clocks = &sumo_set_uvd_clocks, + .get_temperature = &tn_get_temp, }, .pflip = { .pre_page_flip = &evergreen_pre_page_flip,
drivers/gpu/drm/radeon/radeon_asic.h +1 -0
@@ -486,6 +486,7 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable);void evergreen_hdmi_setmode (struct drm_encoder *encoder,struct drm_display_mode *mode);int evergreen_get_temp (struct radeon_device *rdev);int sumo_get_temp (struct radeon_device *rdev); +int tn_get_temp (struct radeon_device *rdev);/* * cayman
Signature · 1 line
1.7.7.5
PATCH 65/165 drm/radeon/kms: move ucode defines to a separate header
In reply to [email protected]From: Alex Deucher <[email protected]>
Avoids confusion and duplication.
--- drivers/gpu/drm/radeon/evergreen.c | 4 +-- drivers/gpu/drm/radeon/ni.c | 13 +-------- drivers/gpu/drm/radeon/r600.c | 25 +++++------------ drivers/gpu/drm/radeon/radeon_ucode.h | 47 +++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 33 deletions(-) create mode 100644 drivers/gpu/drm/radeon/radeon_ucode.h
drivers/gpu/drm/radeon/evergreen.c +1 -3
@@ -33,9 +33,7 @@#include "avivod.h" #include "evergreen_reg.h" #include "evergreen_blit_shaders.h" - -#define EVERGREEN_PFP_UCODE_SIZE 1120 -#define EVERGREEN_PM4_UCODE_SIZE 1376 +#include "radeon_ucode.h" static const u32 crtc_offsets[6 ] = {
drivers/gpu/drm/radeon/ni.c +1 -12
@@ -33,6 +33,7 @@#include "atom.h" #include "ni_reg.h" #include "cayman_blit_shaders.h" +#include "radeon_ucode.h" extern bool evergreen_is_display_hung (struct radeon_device *rdev);extern void evergreen_print_gpu_status_regs (struct radeon_device *rdev);
@@ -47,18 +48,6 @@ extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev);extern void si_rlc_fini (struct radeon_device *rdev);extern int si_rlc_init (struct radeon_device *rdev); -#define EVERGREEN_PFP_UCODE_SIZE 1120 -#define EVERGREEN_PM4_UCODE_SIZE 1376 -#define EVERGREEN_RLC_UCODE_SIZE 768 -#define BTC_MC_UCODE_SIZE 6024 - -#define CAYMAN_PFP_UCODE_SIZE 2176 -#define CAYMAN_PM4_UCODE_SIZE 2176 -#define CAYMAN_RLC_UCODE_SIZE 1024 -#define CAYMAN_MC_UCODE_SIZE 6037 - -#define ARUBA_RLC_UCODE_SIZE 1536 -/* Firmware Names */ MODULE_FIRMWARE ("radeon/BARTS_pfp.bin" );MODULE_FIRMWARE ("radeon/BARTS_me.bin" );
drivers/gpu/drm/radeon/r600.c +7 -18
@@ -38,18 +38,7 @@#include "r600d.h" #include "atom.h" #include "avivod.h" - -#define PFP_UCODE_SIZE 576 -#define PM4_UCODE_SIZE 1792 -#define RLC_UCODE_SIZE 768 -#define R700_PFP_UCODE_SIZE 848 -#define R700_PM4_UCODE_SIZE 1360 -#define R700_RLC_UCODE_SIZE 1024 -#define EVERGREEN_PFP_UCODE_SIZE 1120 -#define EVERGREEN_PM4_UCODE_SIZE 1376 -#define EVERGREEN_RLC_UCODE_SIZE 768 -#define CAYMAN_RLC_UCODE_SIZE 1024 -#define ARUBA_RLC_UCODE_SIZE 1536 +#include "radeon_ucode.h" /* Firmware Names */ MODULE_FIRMWARE ("radeon/R600_pfp.bin" );
@@ -2246,9 +2235,9 @@ int r600_init_microcode(struct radeon_device *rdev) me_req_size =R700_PM4_UCODE_SIZE *4 ; rlc_req_size =R700_RLC_UCODE_SIZE *4 ; }else { - pfp_req_size =PFP_UCODE_SIZE *4 ; - me_req_size =PM4_UCODE_SIZE *12 ; - rlc_req_size =RLC_UCODE_SIZE *4 ; + pfp_req_size =R600_PFP_UCODE_SIZE *4 ; + me_req_size =R600_PM4_UCODE_SIZE *12 ; + rlc_req_size =R600_RLC_UCODE_SIZE *4 ; }DRM_INFO ("Loading %s Microcode\n" , chip_name);
@@ -2331,13 +2320,13 @@ static int r600_cp_load_microcode(struct radeon_device *rdev) fw_data = (const __be32 *)rdev->me_fw->data;WREG32 (CP_ME_RAM_WADDR ,0 ); -for (i =0 ; i <PM4_UCODE_SIZE *3 ; i++) +for (i =0 ; i <R600_PM4_UCODE_SIZE *3 ; i++)WREG32 (CP_ME_RAM_DATA ,be32_to_cpup (fw_data++)); fw_data = (const __be32 *)rdev->pfp_fw->data;WREG32 (CP_PFP_UCODE_ADDR ,0 ); -for (i =0 ; i <PFP_UCODE_SIZE ; i++) +for (i =0 ; i <R600_PFP_UCODE_SIZE ; i++)WREG32 (CP_PFP_UCODE_DATA ,be32_to_cpup (fw_data++));
@@ -3839,7 +3828,7 @@ static int r600_rlc_init(struct radeon_device *rdev)WREG32 (RLC_UCODE_DATA ,be32_to_cpup (fw_data++)); } }else { -for (i =0 ; i <RLC_UCODE_SIZE ; i++) { +for (i =0 ; i <R600_RLC_UCODE_SIZE ; i++) {WREG32 (RLC_UCODE_ADDR , i);WREG32 (RLC_UCODE_DATA ,be32_to_cpup (fw_data++)); }
drivers/gpu/drm/radeon/radeon_ucode.h new file +47 -0
47 lines not on this page · raw message
Signature · 1 line
1.7.7.5