drm-misc-next for 5.14:
UAPI Changes: * Use DRM driver names for fbdev Cross-subsystem Changes: Core Changes: * Fix leaked DMA handles * Improve documentation around DRM_CLIENT_CAP_* * Cleanups * dp_mst: Use kHz as link-rate unit during init * fourcc: Remove drm_gem_format_name() and drm_format_name_buf * gem-cma: Fix mmap for buffers with write combining * ttm: Don't override pre-set vm_ops; ttm_bo_mmap() removal and cleanups Driver Changes: * drm/amdgpu: Fix hot unplug during suspend; Implement mmap as GEM object function; Use %p4cc format-string modifier; Cleanups * drm/bridge: Cdns: Fix PM reference leak, Cleanups; Lt8912b: Fix Coccinelle warnings; Fix Kconfig dependencies; Fixes and cleanups * drm/hisilicon/kirin: Cleanups * drm/nouveau: Implement mmap as GEM object function * drm/radeon: Implement mmap as GEM object function * drm/rockchip: Remove generic drivers during init; Add scaling for RK3036 win1; Fix missing registers for RK3066 and 3188; Add alpha support for RK3036, RK3066, RK3126 and RK3188; Fixes and cleanups * drm/simpledrm: Use %p4cc: format-string modifier * drm/vmwgfx: Cleanups * fbdev/matrox: Use modern module_init() -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEchf7rIzpz2NEoWjlaA3BHVMLeiMFAmC2S24ACgkQaA3BHVML eiPiSwgAuWKdl4QNoMquYwORm96NHVQaWxtrLzc7QanEKz4eyMJ7MQlC1ifX0101 5qEkCx4it3wZPmMyN1GZtqwvu38zyXqPTwqA5f6Llb7xNiYxc2e69xT/K/zm3Qs0 sSC7pUeQKtVfye9eciOF9n/TMfnFqsePCUUg7QUqv/V/tb43dm5OVo6bDVzGKlNY wmlmt3vfdxMWnFVrB3qh/3Um3KAs+lLiMnMX33hqbDkGXeI0rBAHC4MAkcOdWZzl CFIjKfrc5aQUJXFBA2t352LGncgC4TwgkA4Ajr+YIcDcmzJLIZP/Irt8CwR6aYZl 37ZN45vJ7OZVpupyVr3C/cYEu0KhAg== =vdZ6 -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2021-06-01' of git://anongit.freedesktop.org/drm/drm-misc into drm-next drm-misc-next for 5.14: UAPI Changes: * Use DRM driver names for fbdev Cross-subsystem Changes: Core Changes: * Fix leaked DMA handles * Improve documentation around DRM_CLIENT_CAP_* * Cleanups * dp_mst: Use kHz as link-rate unit during init * fourcc: Remove drm_gem_format_name() and drm_format_name_buf * gem-cma: Fix mmap for buffers with write combining * ttm: Don't override pre-set vm_ops; ttm_bo_mmap() removal and cleanups Driver Changes: * drm/amdgpu: Fix hot unplug during suspend; Implement mmap as GEM object function; Use %p4cc format-string modifier; Cleanups * drm/bridge: Cdns: Fix PM reference leak, Cleanups; Lt8912b: Fix Coccinelle warnings; Fix Kconfig dependencies; Fixes and cleanups * drm/hisilicon/kirin: Cleanups * drm/nouveau: Implement mmap as GEM object function * drm/radeon: Implement mmap as GEM object function * drm/rockchip: Remove generic drivers during init; Add scaling for RK3036 win1; Fix missing registers for RK3066 and 3188; Add alpha support for RK3036, RK3066, RK3126 and RK3188; Fixes and cleanups * drm/simpledrm: Use %p4cc: format-string modifier * drm/vmwgfx: Cleanups * fbdev/matrox: Use modern module_init() Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/YLZOKiYE6XFmE/MH@linux-uq9g.fritz.box
This commit is contained in:
commit
43ed3c6c78
@ -11,7 +11,9 @@ maintainers:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: brcm,bcm2835-vec
|
||||
enum:
|
||||
- brcm,bcm2711-vec
|
||||
- brcm,bcm2835-vec
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -0,0 +1,82 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/bridge/google,cros-ec-anx7688.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ChromeOS EC ANX7688 HDMI to DP Converter through Type-C Port
|
||||
|
||||
maintainers:
|
||||
- Nicolas Boichat <drinkcat@chromium.org>
|
||||
- Enric Balletbo i Serra <enric.balletbo@collabora.com>
|
||||
|
||||
description: |
|
||||
ChromeOS EC ANX7688 is a display bridge that converts HDMI 2.0 to
|
||||
DisplayPort 1.3 Ultra-HDi (4096x2160p60). It is an Analogix ANX7688 chip
|
||||
which is connected to and operated by the ChromeOS Embedded Controller
|
||||
(See google,cros-ec.yaml). It is accessed using I2C tunneling through
|
||||
the EC and therefore its node should be a child of an EC I2C tunnel node
|
||||
(See google,cros-ec-i2c-tunnel.yaml).
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: google,cros-ec-anx7688
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
description: I2C address of the device.
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: Video port for HDMI input.
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: USB Type-c connector.
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c_tunnel_b: i2c-tunnel1 {
|
||||
compatible = "google,cros-ec-i2c-tunnel";
|
||||
google,remote-bus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
anx7688: anx7688@2c {
|
||||
compatible = "google,cros-ec-anx7688";
|
||||
reg = <0x2c>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
anx7688_in: endpoint {
|
||||
remote-endpoint = <&hdmi0_out>;
|
||||
};
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
anx7688_out: endpoint {
|
||||
remote-endpoint = <&typec_connector>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -1,54 +0,0 @@
|
||||
* Faraday TV Encoder TVE200
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: must be one of:
|
||||
"faraday,tve200"
|
||||
"cortina,gemini-tvc", "faraday,tve200"
|
||||
|
||||
- reg: base address and size of the control registers block
|
||||
|
||||
- interrupts: contains an interrupt specifier for the interrupt
|
||||
line from the TVE200
|
||||
|
||||
- clock-names: should contain "PCLK" for the clock line clocking the
|
||||
silicon and "TVE" for the 27MHz clock to the video driver
|
||||
|
||||
- clocks: contains phandle and clock specifier pairs for the entries
|
||||
in the clock-names property. See
|
||||
Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||
|
||||
Optional properties:
|
||||
|
||||
- resets: contains the reset line phandle for the block
|
||||
|
||||
Required sub-nodes:
|
||||
|
||||
- port: describes LCD panel signals, following the common binding
|
||||
for video transmitter interfaces; see
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
This port should have the properties:
|
||||
reg = <0>;
|
||||
It should have one endpoint connected to a remote endpoint where
|
||||
the display is connected.
|
||||
|
||||
Example:
|
||||
|
||||
display-controller@6a000000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "faraday,tve200";
|
||||
reg = <0x6a000000 0x1000>;
|
||||
interrupts = <13 IRQ_TYPE_EDGE_RISING>;
|
||||
resets = <&syscon GEMINI_RESET_TVC>;
|
||||
clocks = <&syscon GEMINI_CLK_GATE_TVC>,
|
||||
<&syscon GEMINI_CLK_TVC>;
|
||||
clock-names = "PCLK", "TVE";
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
display_out: endpoint {
|
||||
remote-endpoint = <&panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
@ -0,0 +1,68 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/faraday,tve200.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Faraday TV Encoder TVE200
|
||||
|
||||
maintainers:
|
||||
- Linus Walleij <linus.walleij@linaro.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: faraday,tve200
|
||||
- items:
|
||||
- const: cortina,gemini-tvc
|
||||
- const: faraday,tve200
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
minItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: PCLK
|
||||
- const: TVE
|
||||
|
||||
clocks:
|
||||
minItems: 2
|
||||
|
||||
resets:
|
||||
minItems: 1
|
||||
|
||||
port:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clock-names
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/cortina,gemini-clock.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/reset/cortina,gemini-reset.h>
|
||||
display-controller@6a000000 {
|
||||
compatible = "faraday,tve200";
|
||||
reg = <0x6a000000 0x1000>;
|
||||
interrupts = <13 IRQ_TYPE_EDGE_RISING>;
|
||||
resets = <&syscon GEMINI_RESET_TVC>;
|
||||
clocks = <&syscon GEMINI_CLK_GATE_TVC>,
|
||||
<&syscon GEMINI_CLK_TVC>;
|
||||
clock-names = "PCLK", "TVE";
|
||||
|
||||
port {
|
||||
display_out: endpoint {
|
||||
remote-endpoint = <&panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
@ -99,7 +99,6 @@ config DRM_FBDEV_EMULATION
|
||||
bool "Enable legacy fbdev support for your modesetting driver"
|
||||
depends on DRM
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_KMS_FB_HELPER
|
||||
select FB
|
||||
select FB_CFB_FILLRECT
|
||||
select FB_CFB_COPYAREA
|
||||
|
@ -1078,7 +1078,7 @@ struct amdgpu_device {
|
||||
uint32_t ras_hw_enabled;
|
||||
uint32_t ras_enabled;
|
||||
|
||||
bool in_pci_err_recovery;
|
||||
bool no_hw_access;
|
||||
struct pci_saved_state *pci_state;
|
||||
|
||||
struct amdgpu_reset_control *reset_cntl;
|
||||
@ -1101,7 +1101,9 @@ static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_device *bdev)
|
||||
|
||||
int amdgpu_device_init(struct amdgpu_device *adev,
|
||||
uint32_t flags);
|
||||
void amdgpu_device_fini(struct amdgpu_device *adev);
|
||||
void amdgpu_device_fini_hw(struct amdgpu_device *adev);
|
||||
void amdgpu_device_fini_sw(struct amdgpu_device *adev);
|
||||
|
||||
int amdgpu_gpu_wait_for_idle(struct amdgpu_device *adev);
|
||||
|
||||
void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
|
||||
@ -1321,6 +1323,8 @@ void amdgpu_driver_lastclose_kms(struct drm_device *dev);
|
||||
int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv);
|
||||
void amdgpu_driver_postclose_kms(struct drm_device *dev,
|
||||
struct drm_file *file_priv);
|
||||
void amdgpu_driver_release_kms(struct drm_device *dev);
|
||||
|
||||
int amdgpu_device_ip_suspend(struct amdgpu_device *adev);
|
||||
int amdgpu_device_suspend(struct drm_device *dev, bool fbcon);
|
||||
int amdgpu_device_resume(struct drm_device *dev, bool fbcon);
|
||||
|
@ -170,7 +170,7 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_device_fini(struct amdgpu_device *adev)
|
||||
void amdgpu_amdkfd_device_fini_sw(struct amdgpu_device *adev)
|
||||
{
|
||||
if (adev->kfd.dev) {
|
||||
kgd2kfd_device_exit(adev->kfd.dev);
|
||||
|
@ -142,7 +142,7 @@ void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev,
|
||||
const void *ih_ring_entry);
|
||||
void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev);
|
||||
void amdgpu_amdkfd_device_init(struct amdgpu_device *adev);
|
||||
void amdgpu_amdkfd_device_fini(struct amdgpu_device *adev);
|
||||
void amdgpu_amdkfd_device_fini_sw(struct amdgpu_device *adev);
|
||||
int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type engine,
|
||||
uint32_t vmid, uint64_t gpu_addr,
|
||||
uint32_t *ib_cmd, uint32_t ib_len);
|
||||
|
@ -1768,6 +1768,15 @@ static ssize_t amdgpu_atombios_get_vbios_version(struct device *dev,
|
||||
static DEVICE_ATTR(vbios_version, 0444, amdgpu_atombios_get_vbios_version,
|
||||
NULL);
|
||||
|
||||
static struct attribute *amdgpu_vbios_version_attrs[] = {
|
||||
&dev_attr_vbios_version.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct attribute_group amdgpu_vbios_version_attr_group = {
|
||||
.attrs = amdgpu_vbios_version_attrs
|
||||
};
|
||||
|
||||
/**
|
||||
* amdgpu_atombios_fini - free the driver info and callbacks for atombios
|
||||
*
|
||||
@ -1787,7 +1796,6 @@ void amdgpu_atombios_fini(struct amdgpu_device *adev)
|
||||
adev->mode_info.atom_context = NULL;
|
||||
kfree(adev->mode_info.atom_card_info);
|
||||
adev->mode_info.atom_card_info = NULL;
|
||||
device_remove_file(adev->dev, &dev_attr_vbios_version);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1804,7 +1812,6 @@ int amdgpu_atombios_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct card_info *atom_card_info =
|
||||
kzalloc(sizeof(struct card_info), GFP_KERNEL);
|
||||
int ret;
|
||||
|
||||
if (!atom_card_info)
|
||||
return -ENOMEM;
|
||||
@ -1836,12 +1843,6 @@ int amdgpu_atombios_init(struct amdgpu_device *adev)
|
||||
amdgpu_atombios_allocate_fb_scratch(adev);
|
||||
}
|
||||
|
||||
ret = device_create_file(adev->dev, &dev_attr_vbios_version);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to create device file for VBIOS version\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,8 @@
|
||||
#include <drm/task_barrier.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
|
||||
MODULE_FIRMWARE("amdgpu/vega10_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/vega12_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/raven_gpu_info.bin");
|
||||
@ -282,7 +284,10 @@ void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
|
||||
unsigned long flags;
|
||||
uint32_t hi = ~0;
|
||||
uint64_t last;
|
||||
int idx;
|
||||
|
||||
if (!drm_dev_enter(&adev->ddev, &idx))
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
last = min(pos + size, adev->gmc.visible_vram_size);
|
||||
@ -301,7 +306,7 @@ void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
|
||||
}
|
||||
|
||||
if (count == size)
|
||||
return;
|
||||
goto exit;
|
||||
|
||||
pos += count;
|
||||
buf += count / 4;
|
||||
@ -324,6 +329,11 @@ void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
|
||||
*buf++ = RREG32_NO_KIQ(mmMM_DATA);
|
||||
}
|
||||
spin_unlock_irqrestore(&adev->mmio_idx_lock, flags);
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
exit:
|
||||
#endif
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -333,7 +343,7 @@ void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
|
||||
/* Check if hw access should be skipped because of hotplug or device error */
|
||||
bool amdgpu_device_skip_hw_access(struct amdgpu_device *adev)
|
||||
{
|
||||
if (adev->in_pci_err_recovery)
|
||||
if (adev->no_hw_access)
|
||||
return true;
|
||||
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
@ -2574,34 +2584,26 @@ static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_ip_fini - run fini for hardware IPs
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Main teardown pass for hardware IPs. The list of all the hardware
|
||||
* IPs that make up the asic is walked and the hw_fini and sw_fini callbacks
|
||||
* are run. hw_fini tears down the hardware associated with each IP
|
||||
* and sw_fini tears down any software state associated with each IP.
|
||||
* Returns 0 on success, negative error code on failure.
|
||||
*/
|
||||
static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
|
||||
static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev)
|
||||
{
|
||||
int i, r;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && adev->virt.ras_init_done)
|
||||
amdgpu_virt_release_ras_err_handler_data(adev);
|
||||
for (i = 0; i < adev->num_ip_blocks; i++) {
|
||||
if (!adev->ip_blocks[i].version->funcs->early_fini)
|
||||
continue;
|
||||
|
||||
amdgpu_ras_pre_fini(adev);
|
||||
r = adev->ip_blocks[i].version->funcs->early_fini((void *)adev);
|
||||
if (r) {
|
||||
DRM_DEBUG("early_fini of IP block <%s> failed %d\n",
|
||||
adev->ip_blocks[i].version->funcs->name, r);
|
||||
}
|
||||
}
|
||||
|
||||
if (adev->gmc.xgmi.num_physical_nodes > 1)
|
||||
amdgpu_xgmi_remove_device(adev);
|
||||
amdgpu_amdkfd_suspend(adev, false);
|
||||
|
||||
amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE);
|
||||
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE);
|
||||
|
||||
amdgpu_amdkfd_device_fini(adev);
|
||||
|
||||
/* need to disable SMC first */
|
||||
for (i = 0; i < adev->num_ip_blocks; i++) {
|
||||
if (!adev->ip_blocks[i].status.hw)
|
||||
@ -2632,6 +2634,33 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
|
||||
adev->ip_blocks[i].status.hw = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_ip_fini - run fini for hardware IPs
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Main teardown pass for hardware IPs. The list of all the hardware
|
||||
* IPs that make up the asic is walked and the hw_fini and sw_fini callbacks
|
||||
* are run. hw_fini tears down the hardware associated with each IP
|
||||
* and sw_fini tears down any software state associated with each IP.
|
||||
* Returns 0 on success, negative error code on failure.
|
||||
*/
|
||||
static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
int i, r;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && adev->virt.ras_init_done)
|
||||
amdgpu_virt_release_ras_err_handler_data(adev);
|
||||
|
||||
amdgpu_ras_pre_fini(adev);
|
||||
|
||||
if (adev->gmc.xgmi.num_physical_nodes > 1)
|
||||
amdgpu_xgmi_remove_device(adev);
|
||||
|
||||
amdgpu_amdkfd_device_fini_sw(adev);
|
||||
|
||||
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
|
||||
if (!adev->ip_blocks[i].status.sw)
|
||||
@ -3251,7 +3280,6 @@ static const struct attribute *amdgpu_dev_attributes[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* amdgpu_device_init - initialize the driver
|
||||
*
|
||||
@ -3653,6 +3681,27 @@ failed_unmap:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void amdgpu_device_unmap_mmio(struct amdgpu_device *adev)
|
||||
{
|
||||
/* Clear all CPU mappings pointing to this device */
|
||||
unmap_mapping_range(adev->ddev.anon_inode->i_mapping, 0, 0, 1);
|
||||
|
||||
/* Unmap all mapped bars - Doorbell, registers and VRAM */
|
||||
amdgpu_device_doorbell_fini(adev);
|
||||
|
||||
iounmap(adev->rmmio);
|
||||
adev->rmmio = NULL;
|
||||
if (adev->mman.aper_base_kaddr)
|
||||
iounmap(adev->mman.aper_base_kaddr);
|
||||
adev->mman.aper_base_kaddr = NULL;
|
||||
|
||||
/* Memory manager related */
|
||||
if (!adev->gmc.xgmi.connected_to_cpu) {
|
||||
arch_phys_wc_del(adev->gmc.vram_mtrr);
|
||||
arch_io_free_memtype_wc(adev->gmc.aper_base, adev->gmc.aper_size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_fini - tear down the driver
|
||||
*
|
||||
@ -3661,15 +3710,13 @@ failed_unmap:
|
||||
* Tear down the driver info (all asics).
|
||||
* Called at driver shutdown.
|
||||
*/
|
||||
void amdgpu_device_fini(struct amdgpu_device *adev)
|
||||
void amdgpu_device_fini_hw(struct amdgpu_device *adev)
|
||||
{
|
||||
dev_info(adev->dev, "amdgpu: finishing device.\n");
|
||||
flush_delayed_work(&adev->delayed_init_work);
|
||||
ttm_bo_lock_delayed_workqueue(&adev->mman.bdev);
|
||||
adev->shutdown = true;
|
||||
|
||||
kfree(adev->pci_state);
|
||||
|
||||
/* make sure IB test finished before entering exclusive mode
|
||||
* to avoid preemption on IB test
|
||||
* */
|
||||
@ -3686,11 +3733,29 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
|
||||
else
|
||||
drm_atomic_helper_shutdown(adev_to_drm(adev));
|
||||
}
|
||||
amdgpu_fence_driver_fini(adev);
|
||||
amdgpu_fence_driver_fini_hw(adev);
|
||||
|
||||
if (adev->pm_sysfs_en)
|
||||
amdgpu_pm_sysfs_fini(adev);
|
||||
if (adev->ucode_sysfs_en)
|
||||
amdgpu_ucode_sysfs_fini(adev);
|
||||
sysfs_remove_files(&adev->dev->kobj, amdgpu_dev_attributes);
|
||||
|
||||
amdgpu_fbdev_fini(adev);
|
||||
|
||||
amdgpu_irq_fini_hw(adev);
|
||||
|
||||
amdgpu_device_ip_fini_early(adev);
|
||||
|
||||
amdgpu_gart_dummy_page_fini(adev);
|
||||
|
||||
amdgpu_device_unmap_mmio(adev);
|
||||
}
|
||||
|
||||
void amdgpu_device_fini_sw(struct amdgpu_device *adev)
|
||||
{
|
||||
amdgpu_device_ip_fini(adev);
|
||||
amdgpu_fence_driver_fini_sw(adev);
|
||||
release_firmware(adev->firmware.gpu_info_fw);
|
||||
adev->firmware.gpu_info_fw = NULL;
|
||||
adev->accel_working = false;
|
||||
@ -3712,18 +3777,14 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
|
||||
}
|
||||
if ((adev->pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
|
||||
vga_client_register(adev->pdev, NULL, NULL, NULL);
|
||||
iounmap(adev->rmmio);
|
||||
adev->rmmio = NULL;
|
||||
amdgpu_device_doorbell_fini(adev);
|
||||
|
||||
if (adev->ucode_sysfs_en)
|
||||
amdgpu_ucode_sysfs_fini(adev);
|
||||
|
||||
sysfs_remove_files(&adev->dev->kobj, amdgpu_dev_attributes);
|
||||
if (IS_ENABLED(CONFIG_PERF_EVENTS))
|
||||
amdgpu_pmu_fini(adev);
|
||||
if (adev->mman.discovery_bin)
|
||||
amdgpu_discovery_fini(adev);
|
||||
|
||||
kfree(adev->pci_state);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -5291,9 +5352,9 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev)
|
||||
set_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
|
||||
set_bit(AMDGPU_SKIP_HW_RESET, &reset_context.flags);
|
||||
|
||||
adev->in_pci_err_recovery = true;
|
||||
adev->no_hw_access = true;
|
||||
r = amdgpu_device_pre_asic_reset(adev, &reset_context);
|
||||
adev->in_pci_err_recovery = false;
|
||||
adev->no_hw_access = false;
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
|
@ -1077,12 +1077,9 @@ int amdgpu_display_gem_fb_verify_and_init(
|
||||
/* Verify that the modifier is supported. */
|
||||
if (!drm_any_plane_has_format(dev, mode_cmd->pixel_format,
|
||||
mode_cmd->modifier[0])) {
|
||||
struct drm_format_name_buf format_name;
|
||||
drm_dbg_kms(dev,
|
||||
"unsupported pixel format %s / modifier 0x%llx\n",
|
||||
drm_get_format_name(mode_cmd->pixel_format,
|
||||
&format_name),
|
||||
mode_cmd->modifier[0]);
|
||||
"unsupported pixel format %p4cc / modifier 0x%llx\n",
|
||||
&mode_cmd->pixel_format, mode_cmd->modifier[0]);
|
||||
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
|
@ -42,52 +42,6 @@
|
||||
#include <linux/pci-p2pdma.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
/**
|
||||
* amdgpu_gem_prime_mmap - &drm_driver.gem_prime_mmap implementation
|
||||
* @obj: GEM BO
|
||||
* @vma: Virtual memory area
|
||||
*
|
||||
* Sets up a userspace mapping of the BO's memory in the given
|
||||
* virtual memory area.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int amdgpu_gem_prime_mmap(struct drm_gem_object *obj,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||
unsigned asize = amdgpu_bo_size(bo);
|
||||
int ret;
|
||||
|
||||
if (!vma->vm_file)
|
||||
return -ENODEV;
|
||||
|
||||
if (adev == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
/* Check for valid size. */
|
||||
if (asize < vma->vm_end - vma->vm_start)
|
||||
return -EINVAL;
|
||||
|
||||
if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) ||
|
||||
(bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)) {
|
||||
return -EPERM;
|
||||
}
|
||||
vma->vm_pgoff += amdgpu_bo_mmap_offset(bo) >> PAGE_SHIFT;
|
||||
|
||||
/* prime mmap does not need to check access, so allow here */
|
||||
ret = drm_vma_node_allow(&obj->vma_node, vma->vm_file->private_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ttm_bo_mmap(vma->vm_file, vma, &adev->mman.bdev);
|
||||
drm_vma_node_revoke(&obj->vma_node, vma->vm_file->private_data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
__dma_resv_make_exclusive(struct dma_resv *obj)
|
||||
{
|
||||
|
@ -31,8 +31,6 @@ struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
|
||||
struct dma_buf *dma_buf);
|
||||
bool amdgpu_dmabuf_is_xgmi_accessible(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo *bo);
|
||||
int amdgpu_gem_prime_mmap(struct drm_gem_object *obj,
|
||||
struct vm_area_struct *vma);
|
||||
|
||||
extern const struct dma_buf_ops amdgpu_dmabuf_ops;
|
||||
|
||||
|
@ -1313,14 +1313,16 @@ amdgpu_pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct drm_device *dev = pci_get_drvdata(pdev);
|
||||
|
||||
#ifdef MODULE
|
||||
if (THIS_MODULE->state != MODULE_STATE_GOING)
|
||||
#endif
|
||||
DRM_ERROR("Hotplug removal is not supported\n");
|
||||
drm_dev_unplug(dev);
|
||||
amdgpu_driver_unload_kms(dev);
|
||||
|
||||
/*
|
||||
* Flush any in flight DMA operations from device.
|
||||
* Clear the Bus Master Enable bit and then wait on the PCIe Device
|
||||
* StatusTransactions Pending bit.
|
||||
*/
|
||||
pci_disable_device(pdev);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
pci_wait_for_pending_transaction(pdev);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1555,6 +1557,10 @@ static int amdgpu_pmops_runtime_resume(struct device *dev)
|
||||
if (!adev->runpm)
|
||||
return -EINVAL;
|
||||
|
||||
/* Avoids registers access if device is physically gone */
|
||||
if (!pci_device_is_present(adev->pdev))
|
||||
adev->no_hw_access = true;
|
||||
|
||||
if (amdgpu_device_supports_px(drm_dev)) {
|
||||
drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
|
||||
|
||||
@ -1689,7 +1695,7 @@ static const struct file_operations amdgpu_driver_kms_fops = {
|
||||
.flush = amdgpu_flush,
|
||||
.release = drm_release,
|
||||
.unlocked_ioctl = amdgpu_drm_ioctl,
|
||||
.mmap = amdgpu_mmap,
|
||||
.mmap = drm_gem_mmap,
|
||||
.poll = drm_poll,
|
||||
.read = drm_read,
|
||||
#ifdef CONFIG_COMPAT
|
||||
@ -1751,11 +1757,12 @@ static const struct drm_driver amdgpu_kms_driver = {
|
||||
.dumb_create = amdgpu_mode_dumb_create,
|
||||
.dumb_map_offset = amdgpu_mode_dumb_mmap,
|
||||
.fops = &amdgpu_driver_kms_fops,
|
||||
.release = &amdgpu_driver_release_kms,
|
||||
|
||||
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
|
||||
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
|
||||
.gem_prime_import = amdgpu_gem_prime_import,
|
||||
.gem_prime_mmap = amdgpu_gem_prime_mmap,
|
||||
.gem_prime_mmap = drm_gem_prime_mmap,
|
||||
|
||||
.name = DRIVER_NAME,
|
||||
.desc = DRIVER_DESC,
|
||||
@ -1772,6 +1779,18 @@ static struct pci_error_handlers amdgpu_pci_err_handler = {
|
||||
.resume = amdgpu_pci_resume,
|
||||
};
|
||||
|
||||
extern const struct attribute_group amdgpu_vram_mgr_attr_group;
|
||||
extern const struct attribute_group amdgpu_gtt_mgr_attr_group;
|
||||
extern const struct attribute_group amdgpu_vbios_version_attr_group;
|
||||
|
||||
static const struct attribute_group *amdgpu_sysfs_groups[] = {
|
||||
&amdgpu_vram_mgr_attr_group,
|
||||
&amdgpu_gtt_mgr_attr_group,
|
||||
&amdgpu_vbios_version_attr_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
static struct pci_driver amdgpu_kms_pci_driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.id_table = pciidlist,
|
||||
@ -1780,6 +1799,7 @@ static struct pci_driver amdgpu_kms_pci_driver = {
|
||||
.shutdown = amdgpu_pci_shutdown,
|
||||
.driver.pm = &amdgpu_pm_ops,
|
||||
.err_handler = &amdgpu_pci_err_handler,
|
||||
.dev_groups = amdgpu_sysfs_groups,
|
||||
};
|
||||
|
||||
static int __init amdgpu_init(void)
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_trace.h"
|
||||
|
||||
@ -524,10 +525,9 @@ int amdgpu_fence_driver_init(struct amdgpu_device *adev)
|
||||
*
|
||||
* Tear down the fence driver for all possible rings (all asics).
|
||||
*/
|
||||
void amdgpu_fence_driver_fini(struct amdgpu_device *adev)
|
||||
void amdgpu_fence_driver_fini_hw(struct amdgpu_device *adev)
|
||||
{
|
||||
unsigned i, j;
|
||||
int r;
|
||||
int i, r;
|
||||
|
||||
for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
|
||||
struct amdgpu_ring *ring = adev->rings[i];
|
||||
@ -536,16 +536,33 @@ void amdgpu_fence_driver_fini(struct amdgpu_device *adev)
|
||||
continue;
|
||||
if (!ring->no_scheduler)
|
||||
drm_sched_fini(&ring->sched);
|
||||
r = amdgpu_fence_wait_empty(ring);
|
||||
if (r) {
|
||||
/* no need to trigger GPU reset as we are unloading */
|
||||
/* You can't wait for HW to signal if it's gone */
|
||||
if (!drm_dev_is_unplugged(&adev->ddev))
|
||||
r = amdgpu_fence_wait_empty(ring);
|
||||
else
|
||||
r = -ENODEV;
|
||||
/* no need to trigger GPU reset as we are unloading */
|
||||
if (r)
|
||||
amdgpu_fence_driver_force_completion(ring);
|
||||
}
|
||||
|
||||
if (ring->fence_drv.irq_src)
|
||||
amdgpu_irq_put(adev, ring->fence_drv.irq_src,
|
||||
ring->fence_drv.irq_type);
|
||||
|
||||
del_timer_sync(&ring->fence_drv.fallback_timer);
|
||||
}
|
||||
}
|
||||
|
||||
void amdgpu_fence_driver_fini_sw(struct amdgpu_device *adev)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
|
||||
struct amdgpu_ring *ring = adev->rings[i];
|
||||
|
||||
if (!ring || !ring->fence_drv.initialized)
|
||||
continue;
|
||||
|
||||
for (j = 0; j <= ring->fence_drv.num_fences_mask; ++j)
|
||||
dma_fence_put(ring->fence_drv.fences[j]);
|
||||
kfree(ring->fence_drv.fences);
|
||||
|
@ -92,7 +92,7 @@ static int amdgpu_gart_dummy_page_init(struct amdgpu_device *adev)
|
||||
*
|
||||
* Frees the dummy page used by the driver (all asics).
|
||||
*/
|
||||
static void amdgpu_gart_dummy_page_fini(struct amdgpu_device *adev)
|
||||
void amdgpu_gart_dummy_page_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
if (!adev->dummy_page_addr)
|
||||
return;
|
||||
@ -365,15 +365,3 @@ int amdgpu_gart_init(struct amdgpu_device *adev)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_gart_fini - tear down the driver info for managing the gart
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Tear down the gart driver info and free the dummy page (all asics).
|
||||
*/
|
||||
void amdgpu_gart_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
amdgpu_gart_dummy_page_fini(adev);
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ void amdgpu_gart_table_vram_free(struct amdgpu_device *adev);
|
||||
int amdgpu_gart_table_vram_pin(struct amdgpu_device *adev);
|
||||
void amdgpu_gart_table_vram_unpin(struct amdgpu_device *adev);
|
||||
int amdgpu_gart_init(struct amdgpu_device *adev);
|
||||
void amdgpu_gart_fini(struct amdgpu_device *adev);
|
||||
void amdgpu_gart_dummy_page_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages);
|
||||
int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset,
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <linux/dma-buf.h>
|
||||
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_gem_ttm_helper.h>
|
||||
|
||||
#include "amdgpu.h"
|
||||
@ -41,6 +42,46 @@
|
||||
|
||||
static const struct drm_gem_object_funcs amdgpu_gem_object_funcs;
|
||||
|
||||
static vm_fault_t amdgpu_gem_fault(struct vm_fault *vmf)
|
||||
{
|
||||
struct ttm_buffer_object *bo = vmf->vma->vm_private_data;
|
||||
struct drm_device *ddev = bo->base.dev;
|
||||
vm_fault_t ret;
|
||||
int idx;
|
||||
|
||||
ret = ttm_bo_vm_reserve(bo, vmf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (drm_dev_enter(ddev, &idx)) {
|
||||
ret = amdgpu_bo_fault_reserve_notify(bo);
|
||||
if (ret) {
|
||||
drm_dev_exit(idx);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot,
|
||||
TTM_BO_VM_NUM_PREFAULT, 1);
|
||||
|
||||
drm_dev_exit(idx);
|
||||
} else {
|
||||
ret = ttm_bo_vm_dummy_page(vmf, vmf->vma->vm_page_prot);
|
||||
}
|
||||
if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT))
|
||||
return ret;
|
||||
|
||||
unlock:
|
||||
dma_resv_unlock(bo->base.resv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct vm_operations_struct amdgpu_gem_vm_ops = {
|
||||
.fault = amdgpu_gem_fault,
|
||||
.open = ttm_bo_vm_open,
|
||||
.close = ttm_bo_vm_close,
|
||||
.access = ttm_bo_vm_access
|
||||
};
|
||||
|
||||
static void amdgpu_gem_object_free(struct drm_gem_object *gobj)
|
||||
{
|
||||
struct amdgpu_bo *robj = gem_to_amdgpu_bo(gobj);
|
||||
@ -205,6 +246,18 @@ out_unlock:
|
||||
ttm_eu_backoff_reservation(&ticket, &list);
|
||||
}
|
||||
|
||||
static int amdgpu_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
|
||||
{
|
||||
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
|
||||
|
||||
if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm))
|
||||
return -EPERM;
|
||||
if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)
|
||||
return -EPERM;
|
||||
|
||||
return drm_gem_ttm_mmap(obj, vma);
|
||||
}
|
||||
|
||||
static const struct drm_gem_object_funcs amdgpu_gem_object_funcs = {
|
||||
.free = amdgpu_gem_object_free,
|
||||
.open = amdgpu_gem_object_open,
|
||||
@ -212,6 +265,8 @@ static const struct drm_gem_object_funcs amdgpu_gem_object_funcs = {
|
||||
.export = amdgpu_gem_prime_export,
|
||||
.vmap = drm_gem_ttm_vmap,
|
||||
.vunmap = drm_gem_ttm_vunmap,
|
||||
.mmap = amdgpu_gem_object_mmap,
|
||||
.vm_ops = &amdgpu_gem_vm_ops,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu_xgmi.h"
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
|
||||
/**
|
||||
* amdgpu_gmc_pdb0_alloc - allocate vram for pdb0
|
||||
*
|
||||
@ -151,6 +153,10 @@ int amdgpu_gmc_set_pte_pde(struct amdgpu_device *adev, void *cpu_pt_addr,
|
||||
{
|
||||
void __iomem *ptr = (void *)cpu_pt_addr;
|
||||
uint64_t value;
|
||||
int idx;
|
||||
|
||||
if (!drm_dev_enter(&adev->ddev, &idx))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* The following is for PTE only. GART does not have PDEs.
|
||||
@ -158,6 +164,9 @@ int amdgpu_gmc_set_pte_pde(struct amdgpu_device *adev, void *cpu_pt_addr,
|
||||
value = addr & 0x0000FFFFFFFFF000ULL;
|
||||
value |= flags;
|
||||
writeq(value, ptr + (gpu_page_idx * 8));
|
||||
|
||||
drm_dev_exit(idx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -80,6 +80,16 @@ static DEVICE_ATTR(mem_info_gtt_total, S_IRUGO,
|
||||
static DEVICE_ATTR(mem_info_gtt_used, S_IRUGO,
|
||||
amdgpu_mem_info_gtt_used_show, NULL);
|
||||
|
||||
static struct attribute *amdgpu_gtt_mgr_attributes[] = {
|
||||
&dev_attr_mem_info_gtt_total.attr,
|
||||
&dev_attr_mem_info_gtt_used.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct attribute_group amdgpu_gtt_mgr_attr_group = {
|
||||
.attrs = amdgpu_gtt_mgr_attributes
|
||||
};
|
||||
|
||||
/**
|
||||
* amdgpu_gtt_mgr_has_gart_addr - Check if mem has address space
|
||||
*
|
||||
@ -263,7 +273,6 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size)
|
||||
struct amdgpu_gtt_mgr *mgr = &adev->mman.gtt_mgr;
|
||||
struct ttm_resource_manager *man = &mgr->manager;
|
||||
uint64_t start, size;
|
||||
int ret;
|
||||
|
||||
man->use_tt = true;
|
||||
man->func = &amdgpu_gtt_mgr_func;
|
||||
@ -276,17 +285,6 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size)
|
||||
spin_lock_init(&mgr->lock);
|
||||
atomic64_set(&mgr->available, gtt_size >> PAGE_SHIFT);
|
||||
|
||||
ret = device_create_file(adev->dev, &dev_attr_mem_info_gtt_total);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to create device file mem_info_gtt_total\n");
|
||||
return ret;
|
||||
}
|
||||
ret = device_create_file(adev->dev, &dev_attr_mem_info_gtt_used);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to create device file mem_info_gtt_used\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_TT, &mgr->manager);
|
||||
ttm_resource_manager_set_used(man, true);
|
||||
return 0;
|
||||
@ -316,9 +314,6 @@ void amdgpu_gtt_mgr_fini(struct amdgpu_device *adev)
|
||||
drm_mm_takedown(&mgr->mm);
|
||||
spin_unlock(&mgr->lock);
|
||||
|
||||
device_remove_file(adev->dev, &dev_attr_mem_info_gtt_total);
|
||||
device_remove_file(adev->dev, &dev_attr_mem_info_gtt_used);
|
||||
|
||||
ttm_resource_manager_cleanup(man);
|
||||
ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_TT, NULL);
|
||||
}
|
||||
|
@ -115,9 +115,11 @@ int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
|
||||
*/
|
||||
void amdgpu_ih_ring_fini(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih)
|
||||
{
|
||||
|
||||
if (!ih->ring)
|
||||
return;
|
||||
|
||||
if (ih->use_bus_addr) {
|
||||
if (!ih->ring)
|
||||
return;
|
||||
|
||||
/* add 8 bytes for the rptr/wptr shadows and
|
||||
* add them to the end of the ring allocation.
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_ih.h"
|
||||
#include "atom.h"
|
||||
@ -348,6 +349,25 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void amdgpu_irq_fini_hw(struct amdgpu_device *adev)
|
||||
{
|
||||
if (adev->irq.installed) {
|
||||
drm_irq_uninstall(&adev->ddev);
|
||||
adev->irq.installed = false;
|
||||
if (adev->irq.msi_enabled)
|
||||
pci_free_irq_vectors(adev->pdev);
|
||||
|
||||
if (!amdgpu_device_has_dc_support(adev))
|
||||
flush_work(&adev->hotplug_work);
|
||||
}
|
||||
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih_soft);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih1);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih2);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_irq_fini - shut down interrupt handling
|
||||
*
|
||||
@ -357,19 +377,10 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
|
||||
* functionality, shuts down vblank, hotplug and reset interrupt handling,
|
||||
* turns off interrupts from all sources (all ASICs).
|
||||
*/
|
||||
void amdgpu_irq_fini(struct amdgpu_device *adev)
|
||||
void amdgpu_irq_fini_sw(struct amdgpu_device *adev)
|
||||
{
|
||||
unsigned i, j;
|
||||
|
||||
if (adev->irq.installed) {
|
||||
drm_irq_uninstall(adev_to_drm(adev));
|
||||
adev->irq.installed = false;
|
||||
if (adev->irq.msi_enabled)
|
||||
pci_free_irq_vectors(adev->pdev);
|
||||
if (!amdgpu_device_has_dc_support(adev))
|
||||
flush_work(&adev->hotplug_work);
|
||||
}
|
||||
|
||||
for (i = 0; i < AMDGPU_IRQ_CLIENTID_MAX; ++i) {
|
||||
if (!adev->irq.client[i].sources)
|
||||
continue;
|
||||
|
@ -103,7 +103,8 @@ void amdgpu_irq_disable_all(struct amdgpu_device *adev);
|
||||
irqreturn_t amdgpu_irq_handler(int irq, void *arg);
|
||||
|
||||
int amdgpu_irq_init(struct amdgpu_device *adev);
|
||||
void amdgpu_irq_fini(struct amdgpu_device *adev);
|
||||
void amdgpu_irq_fini_sw(struct amdgpu_device *adev);
|
||||
void amdgpu_irq_fini_hw(struct amdgpu_device *adev);
|
||||
int amdgpu_irq_add_id(struct amdgpu_device *adev,
|
||||
unsigned client_id, unsigned src_id,
|
||||
struct amdgpu_irq_src *source);
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include <linux/wait.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_trace.h"
|
||||
|
||||
@ -34,6 +36,15 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
|
||||
struct amdgpu_job *job = to_amdgpu_job(s_job);
|
||||
struct amdgpu_task_info ti;
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
int idx;
|
||||
|
||||
if (!drm_dev_enter(&adev->ddev, &idx)) {
|
||||
DRM_INFO("%s - device unplugged skipping recovery on scheduler:%s",
|
||||
__func__, s_job->sched->name);
|
||||
|
||||
/* Effectively the job is aborted as the device is gone */
|
||||
return DRM_GPU_SCHED_STAT_ENODEV;
|
||||
}
|
||||
|
||||
memset(&ti, 0, sizeof(struct amdgpu_task_info));
|
||||
|
||||
@ -41,7 +52,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
|
||||
amdgpu_ring_soft_recovery(ring, job->vmid, s_job->s_fence->parent)) {
|
||||
DRM_ERROR("ring %s timeout, but soft recovered\n",
|
||||
s_job->sched->name);
|
||||
return DRM_GPU_SCHED_STAT_NOMINAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
amdgpu_vm_get_task_info(ring->adev, job->pasid, &ti);
|
||||
@ -53,13 +64,15 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
|
||||
|
||||
if (amdgpu_device_should_recover_gpu(ring->adev)) {
|
||||
amdgpu_device_gpu_recover(ring->adev, job);
|
||||
return DRM_GPU_SCHED_STAT_NOMINAL;
|
||||
} else {
|
||||
drm_sched_suspend_timeout(&ring->sched);
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
adev->virt.tdr_debug = true;
|
||||
return DRM_GPU_SCHED_STAT_NOMINAL;
|
||||
}
|
||||
|
||||
exit:
|
||||
drm_dev_exit(idx);
|
||||
return DRM_GPU_SCHED_STAT_NOMINAL;
|
||||
}
|
||||
|
||||
int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs,
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include "amdgpu_uvd.h"
|
||||
#include "amdgpu_vce.h"
|
||||
#include "atom.h"
|
||||
@ -92,7 +93,7 @@ void amdgpu_driver_unload_kms(struct drm_device *dev)
|
||||
}
|
||||
|
||||
amdgpu_acpi_fini(adev);
|
||||
amdgpu_device_fini(adev);
|
||||
amdgpu_device_fini_hw(adev);
|
||||
}
|
||||
|
||||
void amdgpu_register_gpu_instance(struct amdgpu_device *adev)
|
||||
@ -1220,6 +1221,15 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
|
||||
pm_runtime_put_autosuspend(dev->dev);
|
||||
}
|
||||
|
||||
|
||||
void amdgpu_driver_release_kms(struct drm_device *dev)
|
||||
{
|
||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||
|
||||
amdgpu_device_fini_sw(adev);
|
||||
pci_set_drvdata(adev->pdev, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* VBlank related functions.
|
||||
*/
|
||||
|
@ -1072,10 +1072,6 @@ int amdgpu_bo_init(struct amdgpu_device *adev)
|
||||
void amdgpu_bo_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
amdgpu_ttm_fini(adev);
|
||||
if (!adev->gmc.xgmi.connected_to_cpu) {
|
||||
arch_phys_wc_del(adev->gmc.vram_mtrr);
|
||||
arch_io_free_memtype_wc(adev->gmc.aper_base, adev->gmc.aper_size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <drm/drm_drv.h>
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_psp.h"
|
||||
@ -40,6 +41,8 @@
|
||||
#include "amdgpu_securedisplay.h"
|
||||
#include "amdgpu_atomfirmware.h"
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
|
||||
static int psp_sysfs_init(struct amdgpu_device *adev);
|
||||
static void psp_sysfs_fini(struct amdgpu_device *adev);
|
||||
|
||||
@ -231,7 +234,7 @@ int psp_wait_for(struct psp_context *psp, uint32_t reg_index,
|
||||
int i;
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
|
||||
if (psp->adev->in_pci_err_recovery)
|
||||
if (psp->adev->no_hw_access)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
@ -255,12 +258,15 @@ psp_cmd_submit_buf(struct psp_context *psp,
|
||||
struct psp_gfx_cmd_resp *cmd, uint64_t fence_mc_addr)
|
||||
{
|
||||
int ret;
|
||||
int index;
|
||||
int index, idx;
|
||||
int timeout = 20000;
|
||||
bool ras_intr = false;
|
||||
bool skip_unsupport = false;
|
||||
|
||||
if (psp->adev->in_pci_err_recovery)
|
||||
if (psp->adev->no_hw_access)
|
||||
return 0;
|
||||
|
||||
if (!drm_dev_enter(&psp->adev->ddev, &idx))
|
||||
return 0;
|
||||
|
||||
mutex_lock(&psp->mutex);
|
||||
@ -273,8 +279,7 @@ psp_cmd_submit_buf(struct psp_context *psp,
|
||||
ret = psp_ring_cmd_submit(psp, psp->cmd_buf_mc_addr, fence_mc_addr, index);
|
||||
if (ret) {
|
||||
atomic_dec(&psp->fence_value);
|
||||
mutex_unlock(&psp->mutex);
|
||||
return ret;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
amdgpu_asic_invalidate_hdp(psp->adev, NULL);
|
||||
@ -314,8 +319,8 @@ psp_cmd_submit_buf(struct psp_context *psp,
|
||||
psp->cmd_buf_mem->cmd_id,
|
||||
psp->cmd_buf_mem->resp.status);
|
||||
if (!timeout) {
|
||||
mutex_unlock(&psp->mutex);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
@ -323,8 +328,10 @@ psp_cmd_submit_buf(struct psp_context *psp,
|
||||
ucode->tmr_mc_addr_lo = psp->cmd_buf_mem->resp.fw_addr_lo;
|
||||
ucode->tmr_mc_addr_hi = psp->cmd_buf_mem->resp.fw_addr_hi;
|
||||
}
|
||||
mutex_unlock(&psp->mutex);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&psp->mutex);
|
||||
drm_dev_exit(idx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -368,8 +375,7 @@ static int psp_load_toc(struct psp_context *psp,
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
/* Copy toc to psp firmware private buffer */
|
||||
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
|
||||
memcpy(psp->fw_pri_buf, psp->toc_start_addr, psp->toc_bin_size);
|
||||
psp_copy_fw(psp, psp->toc_start_addr, psp->toc_bin_size);
|
||||
|
||||
psp_prep_load_toc_cmd_buf(cmd, psp->fw_pri_mc_addr, psp->toc_bin_size);
|
||||
|
||||
@ -604,8 +610,7 @@ static int psp_asd_load(struct psp_context *psp)
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
|
||||
memcpy(psp->fw_pri_buf, psp->asd_start_addr, psp->asd_ucode_size);
|
||||
psp_copy_fw(psp, psp->asd_start_addr, psp->asd_ucode_size);
|
||||
|
||||
psp_prep_asd_load_cmd_buf(cmd, psp->fw_pri_mc_addr,
|
||||
psp->asd_ucode_size);
|
||||
@ -760,8 +765,7 @@ static int psp_xgmi_load(struct psp_context *psp)
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
|
||||
memcpy(psp->fw_pri_buf, psp->ta_xgmi_start_addr, psp->ta_xgmi_ucode_size);
|
||||
psp_copy_fw(psp, psp->ta_xgmi_start_addr, psp->ta_xgmi_ucode_size);
|
||||
|
||||
psp_prep_ta_load_cmd_buf(cmd,
|
||||
psp->fw_pri_mc_addr,
|
||||
@ -1017,8 +1021,7 @@ static int psp_ras_load(struct psp_context *psp)
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
|
||||
memcpy(psp->fw_pri_buf, psp->ta_ras_start_addr, psp->ta_ras_ucode_size);
|
||||
psp_copy_fw(psp, psp->ta_ras_start_addr, psp->ta_ras_ucode_size);
|
||||
|
||||
ras_cmd = (struct ta_ras_shared_memory *)psp->ras.ras_shared_buf;
|
||||
|
||||
@ -1284,9 +1287,8 @@ static int psp_hdcp_load(struct psp_context *psp)
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
|
||||
memcpy(psp->fw_pri_buf, psp->ta_hdcp_start_addr,
|
||||
psp->ta_hdcp_ucode_size);
|
||||
psp_copy_fw(psp, psp->ta_hdcp_start_addr,
|
||||
psp->ta_hdcp_ucode_size);
|
||||
|
||||
psp_prep_ta_load_cmd_buf(cmd,
|
||||
psp->fw_pri_mc_addr,
|
||||
@ -1436,8 +1438,7 @@ static int psp_dtm_load(struct psp_context *psp)
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
|
||||
memcpy(psp->fw_pri_buf, psp->ta_dtm_start_addr, psp->ta_dtm_ucode_size);
|
||||
psp_copy_fw(psp, psp->ta_dtm_start_addr, psp->ta_dtm_ucode_size);
|
||||
|
||||
psp_prep_ta_load_cmd_buf(cmd,
|
||||
psp->fw_pri_mc_addr,
|
||||
@ -1582,8 +1583,7 @@ static int psp_rap_load(struct psp_context *psp)
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
|
||||
memcpy(psp->fw_pri_buf, psp->ta_rap_start_addr, psp->ta_rap_ucode_size);
|
||||
psp_copy_fw(psp, psp->ta_rap_start_addr, psp->ta_rap_ucode_size);
|
||||
|
||||
psp_prep_ta_load_cmd_buf(cmd,
|
||||
psp->fw_pri_mc_addr,
|
||||
@ -3020,7 +3020,7 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev,
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
void *cpu_addr;
|
||||
dma_addr_t dma_addr;
|
||||
int ret;
|
||||
int ret, idx;
|
||||
char fw_name[100];
|
||||
const struct firmware *usbc_pd_fw;
|
||||
|
||||
@ -3029,6 +3029,9 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev,
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (!drm_dev_enter(ddev, &idx))
|
||||
return -ENODEV;
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s", buf);
|
||||
ret = request_firmware(&usbc_pd_fw, fw_name, adev->dev);
|
||||
if (ret)
|
||||
@ -3060,16 +3063,29 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev,
|
||||
rel_buf:
|
||||
dma_free_coherent(adev->dev, usbc_pd_fw->size, cpu_addr, dma_addr);
|
||||
release_firmware(usbc_pd_fw);
|
||||
|
||||
fail:
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to load USBC PD FW, err = %d", ret);
|
||||
return ret;
|
||||
count = ret;
|
||||
}
|
||||
|
||||
drm_dev_exit(idx);
|
||||
return count;
|
||||
}
|
||||
|
||||
void psp_copy_fw(struct psp_context *psp, uint8_t *start_addr, uint32_t bin_size)
|
||||
{
|
||||
int idx;
|
||||
|
||||
if (!drm_dev_enter(&psp->adev->ddev, &idx))
|
||||
return;
|
||||
|
||||
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
|
||||
memcpy(psp->fw_pri_buf, start_addr, bin_size);
|
||||
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(usbc_pd_fw, S_IRUGO | S_IWUSR,
|
||||
psp_usbc_pd_fw_sysfs_read,
|
||||
psp_usbc_pd_fw_sysfs_write);
|
||||
|
@ -423,4 +423,6 @@ int psp_get_fw_attestation_records_addr(struct psp_context *psp,
|
||||
|
||||
int psp_load_fw_list(struct psp_context *psp,
|
||||
struct amdgpu_firmware_info **ucode_list, int ucode_count);
|
||||
void psp_copy_fw(struct psp_context *psp, uint8_t *start_addr, uint32_t bin_size);
|
||||
|
||||
#endif
|
||||
|
@ -2362,6 +2362,7 @@ int amdgpu_ras_pre_fini(struct amdgpu_device *adev)
|
||||
if (!adev->ras_enabled || !con)
|
||||
return 0;
|
||||
|
||||
|
||||
/* Need disable ras on all IPs here before ip [hw/sw]fini */
|
||||
amdgpu_ras_disable_all_features(adev, 0);
|
||||
amdgpu_ras_recovery_fini(adev);
|
||||
|
@ -107,7 +107,8 @@ struct amdgpu_fence_driver {
|
||||
};
|
||||
|
||||
int amdgpu_fence_driver_init(struct amdgpu_device *adev);
|
||||
void amdgpu_fence_driver_fini(struct amdgpu_device *adev);
|
||||
void amdgpu_fence_driver_fini_hw(struct amdgpu_device *adev);
|
||||
void amdgpu_fence_driver_fini_sw(struct amdgpu_device *adev);
|
||||
void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring);
|
||||
|
||||
int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
|
||||
|
@ -165,25 +165,6 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo,
|
||||
*placement = abo->placement;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_verify_access - Verify access for a mmap call
|
||||
*
|
||||
* @bo: The buffer object to map
|
||||
* @filp: The file pointer from the process performing the mmap
|
||||
*
|
||||
* This is called by ttm_bo_mmap() to verify whether a process
|
||||
* has the right to mmap a BO to their process space.
|
||||
*/
|
||||
static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp)
|
||||
{
|
||||
struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo);
|
||||
|
||||
if (amdgpu_ttm_tt_get_usermm(bo->ttm))
|
||||
return -EPERM;
|
||||
return drm_vma_node_verify_access(&abo->tbo.base.vma_node,
|
||||
filp->private_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_ttm_map_buffer - Map memory into the GART windows
|
||||
* @bo: buffer object to map
|
||||
@ -1475,7 +1456,6 @@ static struct ttm_device_funcs amdgpu_bo_driver = {
|
||||
.eviction_valuable = amdgpu_ttm_bo_eviction_valuable,
|
||||
.evict_flags = &amdgpu_evict_flags,
|
||||
.move = &amdgpu_bo_move,
|
||||
.verify_access = &amdgpu_verify_access,
|
||||
.delete_mem_notify = &amdgpu_bo_delete_mem_notify,
|
||||
.release_notify = &amdgpu_bo_release_notify,
|
||||
.io_mem_reserve = &amdgpu_ttm_io_mem_reserve,
|
||||
@ -1785,10 +1765,6 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev)
|
||||
amdgpu_bo_free_kernel(&adev->mman.discovery_memory, NULL, NULL);
|
||||
amdgpu_ttm_fw_reserve_vram_fini(adev);
|
||||
|
||||
if (adev->mman.aper_base_kaddr)
|
||||
iounmap(adev->mman.aper_base_kaddr);
|
||||
adev->mman.aper_base_kaddr = NULL;
|
||||
|
||||
amdgpu_vram_mgr_fini(adev);
|
||||
amdgpu_gtt_mgr_fini(adev);
|
||||
ttm_range_man_fini(&adev->mman.bdev, AMDGPU_PL_GDS);
|
||||
@ -1847,50 +1823,6 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable)
|
||||
adev->mman.buffer_funcs_enabled = enable;
|
||||
}
|
||||
|
||||
static vm_fault_t amdgpu_ttm_fault(struct vm_fault *vmf)
|
||||
{
|
||||
struct ttm_buffer_object *bo = vmf->vma->vm_private_data;
|
||||
vm_fault_t ret;
|
||||
|
||||
ret = ttm_bo_vm_reserve(bo, vmf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = amdgpu_bo_fault_reserve_notify(bo);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot,
|
||||
TTM_BO_VM_NUM_PREFAULT, 1);
|
||||
if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT))
|
||||
return ret;
|
||||
|
||||
unlock:
|
||||
dma_resv_unlock(bo->base.resv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct vm_operations_struct amdgpu_ttm_vm_ops = {
|
||||
.fault = amdgpu_ttm_fault,
|
||||
.open = ttm_bo_vm_open,
|
||||
.close = ttm_bo_vm_close,
|
||||
.access = ttm_bo_vm_access
|
||||
};
|
||||
|
||||
int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
struct drm_file *file_priv = filp->private_data;
|
||||
struct amdgpu_device *adev = drm_to_adev(file_priv->minor->dev);
|
||||
int r;
|
||||
|
||||
r = ttm_bo_mmap(filp, vma, &adev->mman.bdev);
|
||||
if (unlikely(r != 0))
|
||||
return r;
|
||||
|
||||
vma->vm_ops = &amdgpu_ttm_vm_ops;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset,
|
||||
uint64_t dst_offset, uint32_t byte_count,
|
||||
struct dma_resv *resv,
|
||||
|
@ -142,7 +142,6 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo,
|
||||
struct dma_resv *resv,
|
||||
struct dma_fence **fence);
|
||||
|
||||
int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma);
|
||||
int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo);
|
||||
int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo);
|
||||
uint64_t amdgpu_ttm_domain_start(struct amdgpu_device *adev, uint32_t type);
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <drm/drm.h>
|
||||
#include <drm/drm_drv.h>
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_pm.h"
|
||||
@ -375,7 +376,7 @@ int amdgpu_uvd_suspend(struct amdgpu_device *adev)
|
||||
{
|
||||
unsigned size;
|
||||
void *ptr;
|
||||
int i, j;
|
||||
int i, j, idx;
|
||||
bool in_ras_intr = amdgpu_ras_intr_triggered();
|
||||
|
||||
cancel_delayed_work_sync(&adev->uvd.idle_work);
|
||||
@ -403,11 +404,15 @@ int amdgpu_uvd_suspend(struct amdgpu_device *adev)
|
||||
if (!adev->uvd.inst[j].saved_bo)
|
||||
return -ENOMEM;
|
||||
|
||||
/* re-write 0 since err_event_athub will corrupt VCPU buffer */
|
||||
if (in_ras_intr)
|
||||
memset(adev->uvd.inst[j].saved_bo, 0, size);
|
||||
else
|
||||
memcpy_fromio(adev->uvd.inst[j].saved_bo, ptr, size);
|
||||
if (drm_dev_enter(&adev->ddev, &idx)) {
|
||||
/* re-write 0 since err_event_athub will corrupt VCPU buffer */
|
||||
if (in_ras_intr)
|
||||
memset(adev->uvd.inst[j].saved_bo, 0, size);
|
||||
else
|
||||
memcpy_fromio(adev->uvd.inst[j].saved_bo, ptr, size);
|
||||
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
}
|
||||
|
||||
if (in_ras_intr)
|
||||
@ -420,7 +425,7 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev)
|
||||
{
|
||||
unsigned size;
|
||||
void *ptr;
|
||||
int i;
|
||||
int i, idx;
|
||||
|
||||
for (i = 0; i < adev->uvd.num_uvd_inst; i++) {
|
||||
if (adev->uvd.harvest_config & (1 << i))
|
||||
@ -432,7 +437,10 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev)
|
||||
ptr = adev->uvd.inst[i].cpu_addr;
|
||||
|
||||
if (adev->uvd.inst[i].saved_bo != NULL) {
|
||||
memcpy_toio(ptr, adev->uvd.inst[i].saved_bo, size);
|
||||
if (drm_dev_enter(&adev->ddev, &idx)) {
|
||||
memcpy_toio(ptr, adev->uvd.inst[i].saved_bo, size);
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
kvfree(adev->uvd.inst[i].saved_bo);
|
||||
adev->uvd.inst[i].saved_bo = NULL;
|
||||
} else {
|
||||
@ -442,8 +450,11 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev)
|
||||
hdr = (const struct common_firmware_header *)adev->uvd.fw->data;
|
||||
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
|
||||
offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
|
||||
memcpy_toio(adev->uvd.inst[i].cpu_addr, adev->uvd.fw->data + offset,
|
||||
le32_to_cpu(hdr->ucode_size_bytes));
|
||||
if (drm_dev_enter(&adev->ddev, &idx)) {
|
||||
memcpy_toio(adev->uvd.inst[i].cpu_addr, adev->uvd.fw->data + offset,
|
||||
le32_to_cpu(hdr->ucode_size_bytes));
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
size -= le32_to_cpu(hdr->ucode_size_bytes);
|
||||
ptr += le32_to_cpu(hdr->ucode_size_bytes);
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <drm/drm.h>
|
||||
#include <drm/drm_drv.h>
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_pm.h"
|
||||
@ -293,7 +294,7 @@ int amdgpu_vce_resume(struct amdgpu_device *adev)
|
||||
void *cpu_addr;
|
||||
const struct common_firmware_header *hdr;
|
||||
unsigned offset;
|
||||
int r;
|
||||
int r, idx;
|
||||
|
||||
if (adev->vce.vcpu_bo == NULL)
|
||||
return -EINVAL;
|
||||
@ -313,8 +314,12 @@ int amdgpu_vce_resume(struct amdgpu_device *adev)
|
||||
|
||||
hdr = (const struct common_firmware_header *)adev->vce.fw->data;
|
||||
offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
|
||||
memcpy_toio(cpu_addr, adev->vce.fw->data + offset,
|
||||
adev->vce.fw->size - offset);
|
||||
|
||||
if (drm_dev_enter(&adev->ddev, &idx)) {
|
||||
memcpy_toio(cpu_addr, adev->vce.fw->data + offset,
|
||||
adev->vce.fw->size - offset);
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
|
||||
amdgpu_bo_kunmap(adev->vce.vcpu_bo);
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <drm/drm_drv.h>
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_pm.h"
|
||||
@ -283,7 +284,7 @@ int amdgpu_vcn_suspend(struct amdgpu_device *adev)
|
||||
{
|
||||
unsigned size;
|
||||
void *ptr;
|
||||
int i;
|
||||
int i, idx;
|
||||
|
||||
cancel_delayed_work_sync(&adev->vcn.idle_work);
|
||||
|
||||
@ -300,7 +301,10 @@ int amdgpu_vcn_suspend(struct amdgpu_device *adev)
|
||||
if (!adev->vcn.inst[i].saved_bo)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy_fromio(adev->vcn.inst[i].saved_bo, ptr, size);
|
||||
if (drm_dev_enter(&adev->ddev, &idx)) {
|
||||
memcpy_fromio(adev->vcn.inst[i].saved_bo, ptr, size);
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -309,7 +313,7 @@ int amdgpu_vcn_resume(struct amdgpu_device *adev)
|
||||
{
|
||||
unsigned size;
|
||||
void *ptr;
|
||||
int i;
|
||||
int i, idx;
|
||||
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
|
||||
if (adev->vcn.harvest_config & (1 << i))
|
||||
@ -321,7 +325,10 @@ int amdgpu_vcn_resume(struct amdgpu_device *adev)
|
||||
ptr = adev->vcn.inst[i].cpu_addr;
|
||||
|
||||
if (adev->vcn.inst[i].saved_bo != NULL) {
|
||||
memcpy_toio(ptr, adev->vcn.inst[i].saved_bo, size);
|
||||
if (drm_dev_enter(&adev->ddev, &idx)) {
|
||||
memcpy_toio(ptr, adev->vcn.inst[i].saved_bo, size);
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
kvfree(adev->vcn.inst[i].saved_bo);
|
||||
adev->vcn.inst[i].saved_bo = NULL;
|
||||
} else {
|
||||
@ -331,8 +338,11 @@ int amdgpu_vcn_resume(struct amdgpu_device *adev)
|
||||
hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
|
||||
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
|
||||
offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
|
||||
memcpy_toio(adev->vcn.inst[i].cpu_addr, adev->vcn.fw->data + offset,
|
||||
le32_to_cpu(hdr->ucode_size_bytes));
|
||||
if (drm_dev_enter(&adev->ddev, &idx)) {
|
||||
memcpy_toio(adev->vcn.inst[i].cpu_addr, adev->vcn.fw->data + offset,
|
||||
le32_to_cpu(hdr->ucode_size_bytes));
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
size -= le32_to_cpu(hdr->ucode_size_bytes);
|
||||
ptr += le32_to_cpu(hdr->ucode_size_bytes);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <linux/dma-buf.h>
|
||||
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_trace.h"
|
||||
#include "amdgpu_amdkfd.h"
|
||||
@ -1633,7 +1634,10 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm_update_params params;
|
||||
struct amdgpu_res_cursor cursor;
|
||||
enum amdgpu_sync_mode sync_mode;
|
||||
int r;
|
||||
int r, idx;
|
||||
|
||||
if (!drm_dev_enter(&adev->ddev, &idx))
|
||||
return -ENODEV;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.adev = adev;
|
||||
@ -1728,6 +1732,7 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,
|
||||
|
||||
error_unlock:
|
||||
amdgpu_vm_eviction_unlock(vm);
|
||||
drm_dev_exit(idx);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -172,7 +172,7 @@ static DEVICE_ATTR(mem_info_vis_vram_used, S_IRUGO,
|
||||
static DEVICE_ATTR(mem_info_vram_vendor, S_IRUGO,
|
||||
amdgpu_mem_info_vram_vendor, NULL);
|
||||
|
||||
static const struct attribute *amdgpu_vram_mgr_attributes[] = {
|
||||
static struct attribute *amdgpu_vram_mgr_attributes[] = {
|
||||
&dev_attr_mem_info_vram_total.attr,
|
||||
&dev_attr_mem_info_vis_vram_total.attr,
|
||||
&dev_attr_mem_info_vram_used.attr,
|
||||
@ -181,6 +181,10 @@ static const struct attribute *amdgpu_vram_mgr_attributes[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct attribute_group amdgpu_vram_mgr_attr_group = {
|
||||
.attrs = amdgpu_vram_mgr_attributes
|
||||
};
|
||||
|
||||
/**
|
||||
* amdgpu_vram_mgr_vis_size - Calculate visible node size
|
||||
*
|
||||
@ -684,7 +688,6 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_vram_mgr *mgr = &adev->mman.vram_mgr;
|
||||
struct ttm_resource_manager *man = &mgr->manager;
|
||||
int ret;
|
||||
|
||||
ttm_resource_manager_init(man, adev->gmc.real_vram_size >> PAGE_SHIFT);
|
||||
|
||||
@ -695,11 +698,6 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev)
|
||||
INIT_LIST_HEAD(&mgr->reservations_pending);
|
||||
INIT_LIST_HEAD(&mgr->reserved_pages);
|
||||
|
||||
/* Add the two VRAM-related sysfs files */
|
||||
ret = sysfs_create_files(&adev->dev->kobj, amdgpu_vram_mgr_attributes);
|
||||
if (ret)
|
||||
DRM_ERROR("Failed to register sysfs\n");
|
||||
|
||||
ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_VRAM, &mgr->manager);
|
||||
ttm_resource_manager_set_used(man, true);
|
||||
return 0;
|
||||
@ -737,8 +735,6 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev)
|
||||
drm_mm_takedown(&mgr->mm);
|
||||
spin_unlock(&mgr->lock);
|
||||
|
||||
sysfs_remove_files(&adev->dev->kobj, amdgpu_vram_mgr_attributes);
|
||||
|
||||
ttm_resource_manager_cleanup(man);
|
||||
ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_VRAM, NULL);
|
||||
}
|
||||
|
@ -309,8 +309,7 @@ static int cik_ih_sw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
amdgpu_irq_fini(adev);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih);
|
||||
amdgpu_irq_fini_sw(adev);
|
||||
amdgpu_irq_remove_domain(adev);
|
||||
|
||||
return 0;
|
||||
|
@ -301,8 +301,7 @@ static int cz_ih_sw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
amdgpu_irq_fini(adev);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih);
|
||||
amdgpu_irq_fini_sw(adev);
|
||||
amdgpu_irq_remove_domain(adev);
|
||||
|
||||
return 0;
|
||||
|
@ -7396,7 +7396,7 @@ static int gfx_v10_0_hw_fini(void *handle)
|
||||
amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
|
||||
amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
|
||||
|
||||
if (!adev->in_pci_err_recovery) {
|
||||
if (!adev->no_hw_access) {
|
||||
#ifndef BRING_UP_DEBUG
|
||||
if (amdgpu_async_gfx_ring) {
|
||||
r = gfx_v10_0_kiq_disable_kgq(adev);
|
||||
|
@ -956,7 +956,6 @@ static int gmc_v10_0_sw_init(void *handle)
|
||||
static void gmc_v10_0_gart_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
amdgpu_gart_table_vram_free(adev);
|
||||
amdgpu_gart_fini(adev);
|
||||
}
|
||||
|
||||
static int gmc_v10_0_sw_fini(void *handle)
|
||||
|
@ -898,7 +898,6 @@ static int gmc_v6_0_sw_fini(void *handle)
|
||||
amdgpu_vm_manager_fini(adev);
|
||||
amdgpu_gart_table_vram_free(adev);
|
||||
amdgpu_bo_fini(adev);
|
||||
amdgpu_gart_fini(adev);
|
||||
release_firmware(adev->gmc.fw);
|
||||
adev->gmc.fw = NULL;
|
||||
|
||||
|
@ -1085,7 +1085,6 @@ static int gmc_v7_0_sw_fini(void *handle)
|
||||
kfree(adev->gmc.vm_fault_info);
|
||||
amdgpu_gart_table_vram_free(adev);
|
||||
amdgpu_bo_fini(adev);
|
||||
amdgpu_gart_fini(adev);
|
||||
release_firmware(adev->gmc.fw);
|
||||
adev->gmc.fw = NULL;
|
||||
|
||||
|
@ -1201,7 +1201,6 @@ static int gmc_v8_0_sw_fini(void *handle)
|
||||
kfree(adev->gmc.vm_fault_info);
|
||||
amdgpu_gart_table_vram_free(adev);
|
||||
amdgpu_bo_fini(adev);
|
||||
amdgpu_gart_fini(adev);
|
||||
release_firmware(adev->gmc.fw);
|
||||
adev->gmc.fw = NULL;
|
||||
|
||||
|
@ -1615,7 +1615,6 @@ static int gmc_v9_0_sw_fini(void *handle)
|
||||
amdgpu_gart_table_vram_free(adev);
|
||||
amdgpu_bo_unref(&adev->gmc.pdb0_bo);
|
||||
amdgpu_bo_fini(adev);
|
||||
amdgpu_gart_fini(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -300,8 +300,7 @@ static int iceland_ih_sw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
amdgpu_irq_fini(adev);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih);
|
||||
amdgpu_irq_fini_sw(adev);
|
||||
amdgpu_irq_remove_domain(adev);
|
||||
|
||||
return 0;
|
||||
|
@ -586,11 +586,7 @@ static int navi10_ih_sw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
amdgpu_irq_fini(adev);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih_soft);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih2);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih1);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih);
|
||||
amdgpu_irq_fini_sw(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <drm/drm_drv.h>
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_psp.h"
|
||||
@ -282,10 +283,8 @@ static int psp_v11_0_bootloader_load_kdb(struct psp_context *psp)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
|
||||
|
||||
/* Copy PSP KDB binary to memory */
|
||||
memcpy(psp->fw_pri_buf, psp->kdb_start_addr, psp->kdb_bin_size);
|
||||
psp_copy_fw(psp, psp->kdb_start_addr, psp->kdb_bin_size);
|
||||
|
||||
/* Provide the PSP KDB to bootloader */
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
|
||||
@ -315,10 +314,8 @@ static int psp_v11_0_bootloader_load_spl(struct psp_context *psp)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
|
||||
|
||||
/* Copy PSP SPL binary to memory */
|
||||
memcpy(psp->fw_pri_buf, psp->spl_start_addr, psp->spl_bin_size);
|
||||
psp_copy_fw(psp, psp->spl_start_addr, psp->spl_bin_size);
|
||||
|
||||
/* Provide the PSP SPL to bootloader */
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
|
||||
@ -348,10 +345,8 @@ static int psp_v11_0_bootloader_load_sysdrv(struct psp_context *psp)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
|
||||
|
||||
/* Copy PSP System Driver binary to memory */
|
||||
memcpy(psp->fw_pri_buf, psp->sys_start_addr, psp->sys_bin_size);
|
||||
psp_copy_fw(psp, psp->sys_start_addr, psp->sys_bin_size);
|
||||
|
||||
/* Provide the sys driver to bootloader */
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
|
||||
@ -384,10 +379,8 @@ static int psp_v11_0_bootloader_load_sos(struct psp_context *psp)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
|
||||
|
||||
/* Copy Secure OS binary to PSP memory */
|
||||
memcpy(psp->fw_pri_buf, psp->sos_start_addr, psp->sos_bin_size);
|
||||
psp_copy_fw(psp, psp->sos_start_addr, psp->sos_bin_size);
|
||||
|
||||
/* Provide the PSP secure OS to bootloader */
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
|
||||
@ -621,7 +614,7 @@ static int psp_v11_0_memory_training(struct psp_context *psp, uint32_t ops)
|
||||
uint32_t p2c_header[4];
|
||||
uint32_t sz;
|
||||
void *buf;
|
||||
int ret;
|
||||
int ret, idx;
|
||||
|
||||
if (ctx->init == PSP_MEM_TRAIN_NOT_SUPPORT) {
|
||||
DRM_DEBUG("Memory training is not supported.\n");
|
||||
@ -694,17 +687,24 @@ static int psp_v11_0_memory_training(struct psp_context *psp, uint32_t ops)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy_fromio(buf, adev->mman.aper_base_kaddr, sz);
|
||||
ret = psp_v11_0_memory_training_send_msg(psp, PSP_BL__DRAM_LONG_TRAIN);
|
||||
if (ret) {
|
||||
DRM_ERROR("Send long training msg failed.\n");
|
||||
vfree(buf);
|
||||
return ret;
|
||||
}
|
||||
if (drm_dev_enter(&adev->ddev, &idx)) {
|
||||
memcpy_fromio(buf, adev->mman.aper_base_kaddr, sz);
|
||||
ret = psp_v11_0_memory_training_send_msg(psp, PSP_BL__DRAM_LONG_TRAIN);
|
||||
if (ret) {
|
||||
DRM_ERROR("Send long training msg failed.\n");
|
||||
vfree(buf);
|
||||
drm_dev_exit(idx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy_toio(adev->mman.aper_base_kaddr, buf, sz);
|
||||
adev->hdp.funcs->flush_hdp(adev, NULL);
|
||||
vfree(buf);
|
||||
memcpy_toio(adev->mman.aper_base_kaddr, buf, sz);
|
||||
adev->hdp.funcs->flush_hdp(adev, NULL);
|
||||
vfree(buf);
|
||||
drm_dev_exit(idx);
|
||||
} else {
|
||||
vfree(buf);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
if (ops & PSP_MEM_TRAIN_SAVE) {
|
||||
|
@ -138,10 +138,8 @@ static int psp_v12_0_bootloader_load_sysdrv(struct psp_context *psp)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
|
||||
|
||||
/* Copy PSP System Driver binary to memory */
|
||||
memcpy(psp->fw_pri_buf, psp->sys_start_addr, psp->sys_bin_size);
|
||||
psp_copy_fw(psp, psp->sys_start_addr, psp->sys_bin_size);
|
||||
|
||||
/* Provide the sys driver to bootloader */
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
|
||||
@ -179,10 +177,8 @@ static int psp_v12_0_bootloader_load_sos(struct psp_context *psp)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
|
||||
|
||||
/* Copy Secure OS binary to PSP memory */
|
||||
memcpy(psp->fw_pri_buf, psp->sos_start_addr, psp->sos_bin_size);
|
||||
psp_copy_fw(psp, psp->sos_start_addr, psp->sos_bin_size);
|
||||
|
||||
/* Provide the PSP secure OS to bootloader */
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
|
||||
|
@ -102,10 +102,8 @@ static int psp_v3_1_bootloader_load_sysdrv(struct psp_context *psp)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
|
||||
|
||||
/* Copy PSP System Driver binary to memory */
|
||||
memcpy(psp->fw_pri_buf, psp->sys_start_addr, psp->sys_bin_size);
|
||||
psp_copy_fw(psp, psp->sys_start_addr, psp->sys_bin_size);
|
||||
|
||||
/* Provide the sys driver to bootloader */
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
|
||||
@ -143,10 +141,8 @@ static int psp_v3_1_bootloader_load_sos(struct psp_context *psp)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
|
||||
|
||||
/* Copy Secure OS binary to PSP memory */
|
||||
memcpy(psp->fw_pri_buf, psp->sos_start_addr, psp->sos_bin_size);
|
||||
psp_copy_fw(psp, psp->sos_start_addr, psp->sos_bin_size);
|
||||
|
||||
/* Provide the PSP secure OS to bootloader */
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
|
||||
|
@ -175,8 +175,7 @@ static int si_ih_sw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
amdgpu_irq_fini(adev);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih);
|
||||
amdgpu_irq_fini_sw(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -312,8 +312,7 @@ static int tonga_ih_sw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
amdgpu_irq_fini(adev);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih);
|
||||
amdgpu_irq_fini_sw(adev);
|
||||
amdgpu_irq_remove_domain(adev);
|
||||
|
||||
return 0;
|
||||
|
@ -25,6 +25,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include <drm/drm_drv.h>
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_vce.h"
|
||||
@ -555,16 +556,19 @@ static int vce_v4_0_hw_fini(void *handle)
|
||||
static int vce_v4_0_suspend(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int r;
|
||||
int r, idx;
|
||||
|
||||
if (adev->vce.vcpu_bo == NULL)
|
||||
return 0;
|
||||
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
|
||||
unsigned size = amdgpu_bo_size(adev->vce.vcpu_bo);
|
||||
void *ptr = adev->vce.cpu_addr;
|
||||
if (drm_dev_enter(&adev->ddev, &idx)) {
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
|
||||
unsigned size = amdgpu_bo_size(adev->vce.vcpu_bo);
|
||||
void *ptr = adev->vce.cpu_addr;
|
||||
|
||||
memcpy_fromio(adev->vce.saved_bo, ptr, size);
|
||||
memcpy_fromio(adev->vce.saved_bo, ptr, size);
|
||||
}
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
|
||||
r = vce_v4_0_hw_fini(adev);
|
||||
@ -577,16 +581,20 @@ static int vce_v4_0_suspend(void *handle)
|
||||
static int vce_v4_0_resume(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int r;
|
||||
int r, idx;
|
||||
|
||||
if (adev->vce.vcpu_bo == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
|
||||
unsigned size = amdgpu_bo_size(adev->vce.vcpu_bo);
|
||||
void *ptr = adev->vce.cpu_addr;
|
||||
|
||||
memcpy_toio(ptr, adev->vce.saved_bo, size);
|
||||
if (drm_dev_enter(&adev->ddev, &idx)) {
|
||||
unsigned size = amdgpu_bo_size(adev->vce.vcpu_bo);
|
||||
void *ptr = adev->vce.cpu_addr;
|
||||
|
||||
memcpy_toio(ptr, adev->vce.saved_bo, size);
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
} else {
|
||||
r = amdgpu_vce_resume(adev);
|
||||
if (r)
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include "vcn/vcn_3_0_0_sh_mask.h"
|
||||
#include "ivsrcid/vcn/irqsrcs_vcn_2_0.h"
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
|
||||
#define mmUVD_CONTEXT_ID_INTERNAL_OFFSET 0x27
|
||||
#define mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET 0x0f
|
||||
#define mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET 0x10
|
||||
@ -276,16 +278,20 @@ static int vcn_v3_0_sw_init(void *handle)
|
||||
static int vcn_v3_0_sw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int i, r;
|
||||
int i, r, idx;
|
||||
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
|
||||
volatile struct amdgpu_fw_shared *fw_shared;
|
||||
if (drm_dev_enter(&adev->ddev, &idx)) {
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
|
||||
volatile struct amdgpu_fw_shared *fw_shared;
|
||||
|
||||
if (adev->vcn.harvest_config & (1 << i))
|
||||
continue;
|
||||
fw_shared = adev->vcn.inst[i].fw_shared_cpu_addr;
|
||||
fw_shared->present_flag_0 = 0;
|
||||
fw_shared->sw_ring.is_enabled = false;
|
||||
if (adev->vcn.harvest_config & (1 << i))
|
||||
continue;
|
||||
fw_shared = adev->vcn.inst[i].fw_shared_cpu_addr;
|
||||
fw_shared->present_flag_0 = 0;
|
||||
fw_shared->sw_ring.is_enabled = false;
|
||||
}
|
||||
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
|
@ -514,11 +514,7 @@ static int vega10_ih_sw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
amdgpu_irq_fini(adev);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih_soft);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih2);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih1);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih);
|
||||
amdgpu_irq_fini_sw(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -565,11 +565,7 @@ static int vega20_ih_sw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
amdgpu_irq_fini(adev);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih_soft);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih2);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih1);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih);
|
||||
amdgpu_irq_fini_sw(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -891,7 +891,6 @@ out:
|
||||
void kgd2kfd_device_exit(struct kfd_dev *kfd)
|
||||
{
|
||||
if (kfd->init_complete) {
|
||||
kgd2kfd_suspend(kfd, false);
|
||||
svm_migrate_fini((struct amdgpu_device *)kfd->kgd);
|
||||
device_queue_manager_uninit(kfd->dqm);
|
||||
kfd_interrupt_exit(kfd);
|
||||
|
@ -1291,6 +1291,15 @@ error:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int amdgpu_dm_early_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
amdgpu_dm_audio_fini(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void amdgpu_dm_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
int i;
|
||||
@ -1299,8 +1308,6 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
|
||||
drm_encoder_cleanup(&adev->dm.mst_encoders[i].base);
|
||||
}
|
||||
|
||||
amdgpu_dm_audio_fini(adev);
|
||||
|
||||
amdgpu_dm_destroy_drm_device(&adev->dm);
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
|
||||
@ -2341,6 +2348,7 @@ static const struct amd_ip_funcs amdgpu_dm_funcs = {
|
||||
.late_init = dm_late_init,
|
||||
.sw_init = dm_sw_init,
|
||||
.sw_fini = dm_sw_fini,
|
||||
.early_fini = amdgpu_dm_early_fini,
|
||||
.hw_init = dm_hw_init,
|
||||
.hw_fini = dm_hw_fini,
|
||||
.suspend = dm_suspend,
|
||||
@ -3868,7 +3876,6 @@ fail:
|
||||
|
||||
static void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm)
|
||||
{
|
||||
drm_mode_config_cleanup(dm->ddev);
|
||||
drm_atomic_private_obj_fini(&dm->atomic_obj);
|
||||
return;
|
||||
}
|
||||
|
@ -461,8 +461,8 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
|
||||
&aconnector->dm_dp_aux.aux,
|
||||
16,
|
||||
4,
|
||||
(u8)max_link_enc_cap.lane_count,
|
||||
(u8)max_link_enc_cap.link_rate,
|
||||
max_link_enc_cap.lane_count,
|
||||
drm_dp_bw_code_to_link_rate(max_link_enc_cap.link_rate),
|
||||
aconnector->connector_id);
|
||||
|
||||
drm_connector_attach_dp_subconnector_property(&aconnector->base);
|
||||
|
@ -246,6 +246,7 @@ enum amd_dpm_forced_level;
|
||||
* @late_init: sets up late driver/hw state (post hw_init) - Optional
|
||||
* @sw_init: sets up driver state, does not configure hw
|
||||
* @sw_fini: tears down driver state, does not configure hw
|
||||
* @early_fini: tears down stuff before dev detached from driver
|
||||
* @hw_init: sets up the hw state
|
||||
* @hw_fini: tears down the hw state
|
||||
* @late_fini: final cleanup
|
||||
@ -274,6 +275,7 @@ struct amd_ip_funcs {
|
||||
int (*late_init)(void *handle);
|
||||
int (*sw_init)(void *handle);
|
||||
int (*sw_fini)(void *handle);
|
||||
int (*early_fini)(void *handle);
|
||||
int (*hw_init)(void *handle);
|
||||
int (*hw_fini)(void *handle);
|
||||
void (*late_fini)(void *handle);
|
||||
|
@ -5178,11 +5178,11 @@ typedef struct _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 <EFBFBD> PSI0_VID
|
||||
// 6 <EFBFBD> PSI0_EN
|
||||
// 5 <EFBFBD> PSI1
|
||||
// 4:2 <EFBFBD> load line slope trim.
|
||||
// 1:0 <EFBFBD> offset trim,
|
||||
// 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 ucSVDGpioId; //0~31 indicate GPIO0~31
|
||||
|
@ -126,7 +126,7 @@ int smu_cmn_send_smc_msg_with_param(struct smu_context *smu,
|
||||
struct amdgpu_device *adev = smu->adev;
|
||||
int ret = 0, index = 0;
|
||||
|
||||
if (smu->adev->in_pci_err_recovery)
|
||||
if (smu->adev->no_hw_access)
|
||||
return 0;
|
||||
|
||||
index = smu_cmn_to_asic_specific_index(smu,
|
||||
|
@ -50,6 +50,19 @@ config DRM_CHRONTEL_CH7033
|
||||
|
||||
If in doubt, say "N".
|
||||
|
||||
config DRM_CROS_EC_ANX7688
|
||||
tristate "ChromeOS EC ANX7688 bridge"
|
||||
depends on OF
|
||||
depends on I2C_CROS_EC_TUNNEL || COMPILE_TEST
|
||||
select DRM_KMS_HELPER
|
||||
select REGMAP_I2C
|
||||
help
|
||||
ChromeOS EC ANX7688 is an ultra-low power
|
||||
4K Ultra-HD (4096x2160p60) mobile HD transmitter
|
||||
designed for ChromeOS devices. It converts HDMI
|
||||
2.0 to DisplayPort 1.3 Ultra-HD. It is connected
|
||||
to the ChromeOS Embedded Controller.
|
||||
|
||||
config DRM_DISPLAY_CONNECTOR
|
||||
tristate "Display connector support"
|
||||
depends on OF
|
||||
|
@ -2,6 +2,7 @@
|
||||
obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o
|
||||
obj-$(CONFIG_DRM_CHIPONE_ICN6211) += chipone-icn6211.o
|
||||
obj-$(CONFIG_DRM_CHRONTEL_CH7033) += chrontel-ch7033.o
|
||||
obj-$(CONFIG_DRM_CROS_EC_ANX7688) += cros-ec-anx7688.o
|
||||
obj-$(CONFIG_DRM_DISPLAY_CONNECTOR) += display-connector.o
|
||||
obj-$(CONFIG_DRM_LONTIUM_LT8912B) += lontium-lt8912b.o
|
||||
obj-$(CONFIG_DRM_LONTIUM_LT9611) += lontium-lt9611.o
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
@ -1005,33 +1006,6 @@ static void anx7625_power_on_init(struct anx7625_data *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
static void anx7625_chip_control(struct anx7625_data *ctx, int state)
|
||||
{
|
||||
struct device *dev = &ctx->client->dev;
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(dev, "before set, power_state(%d).\n",
|
||||
atomic_read(&ctx->power_status));
|
||||
|
||||
if (!ctx->pdata.low_power_mode)
|
||||
return;
|
||||
|
||||
if (state) {
|
||||
atomic_inc(&ctx->power_status);
|
||||
if (atomic_read(&ctx->power_status) == 1)
|
||||
anx7625_power_on_init(ctx);
|
||||
} else {
|
||||
if (atomic_read(&ctx->power_status)) {
|
||||
atomic_dec(&ctx->power_status);
|
||||
|
||||
if (atomic_read(&ctx->power_status) == 0)
|
||||
anx7625_power_standby(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(dev, "after set, power_state(%d).\n",
|
||||
atomic_read(&ctx->power_status));
|
||||
}
|
||||
|
||||
static void anx7625_init_gpio(struct anx7625_data *platform)
|
||||
{
|
||||
struct device *dev = &platform->client->dev;
|
||||
@ -1061,9 +1035,6 @@ static void anx7625_stop_dp_work(struct anx7625_data *ctx)
|
||||
ctx->hpd_status = 0;
|
||||
ctx->hpd_high_cnt = 0;
|
||||
ctx->display_timing_valid = 0;
|
||||
|
||||
if (ctx->pdata.low_power_mode == 0)
|
||||
anx7625_disable_pd_protocol(ctx);
|
||||
}
|
||||
|
||||
static void anx7625_start_dp_work(struct anx7625_data *ctx)
|
||||
@ -1105,49 +1076,26 @@ static void anx7625_hpd_polling(struct anx7625_data *ctx)
|
||||
int ret, val;
|
||||
struct device *dev = &ctx->client->dev;
|
||||
|
||||
if (atomic_read(&ctx->power_status) != 1) {
|
||||
DRM_DEV_DEBUG_DRIVER(dev, "No need to poling HPD status.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = readx_poll_timeout(anx7625_read_hpd_status_p0,
|
||||
ctx, val,
|
||||
((val & HPD_STATUS) || (val < 0)),
|
||||
5000,
|
||||
5000 * 100);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dev, "HPD polling timeout!\n");
|
||||
} else {
|
||||
DRM_DEV_DEBUG_DRIVER(dev, "HPD raise up.\n");
|
||||
anx7625_reg_write(ctx, ctx->i2c.tcpc_client,
|
||||
INTR_ALERT_1, 0xFF);
|
||||
anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
|
||||
INTERFACE_CHANGE_INT, 0);
|
||||
DRM_DEV_ERROR(dev, "no hpd.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(dev, "system status: 0x%x. HPD raise up.\n", val);
|
||||
anx7625_reg_write(ctx, ctx->i2c.tcpc_client,
|
||||
INTR_ALERT_1, 0xFF);
|
||||
anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
|
||||
INTERFACE_CHANGE_INT, 0);
|
||||
|
||||
anx7625_start_dp_work(ctx);
|
||||
}
|
||||
|
||||
static void anx7625_disconnect_check(struct anx7625_data *ctx)
|
||||
{
|
||||
if (atomic_read(&ctx->power_status) == 0)
|
||||
anx7625_stop_dp_work(ctx);
|
||||
}
|
||||
|
||||
static void anx7625_low_power_mode_check(struct anx7625_data *ctx,
|
||||
int state)
|
||||
{
|
||||
struct device *dev = &ctx->client->dev;
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(dev, "low power mode check, state(%d).\n", state);
|
||||
|
||||
if (ctx->pdata.low_power_mode) {
|
||||
anx7625_chip_control(ctx, state);
|
||||
if (state)
|
||||
anx7625_hpd_polling(ctx);
|
||||
else
|
||||
anx7625_disconnect_check(ctx);
|
||||
}
|
||||
if (!ctx->pdata.panel_bridge && ctx->bridge_attached)
|
||||
drm_helper_hpd_irq_event(ctx->bridge.dev);
|
||||
}
|
||||
|
||||
static void anx7625_remove_edid(struct anx7625_data *ctx)
|
||||
@ -1180,9 +1128,6 @@ static int anx7625_hpd_change_detect(struct anx7625_data *ctx)
|
||||
int intr_vector, status;
|
||||
struct device *dev = &ctx->client->dev;
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(dev, "power_status=%d\n",
|
||||
(u32)atomic_read(&ctx->power_status));
|
||||
|
||||
status = anx7625_reg_write(ctx, ctx->i2c.tcpc_client,
|
||||
INTR_ALERT_1, 0xFF);
|
||||
if (status < 0) {
|
||||
@ -1228,22 +1173,25 @@ static void anx7625_work_func(struct work_struct *work)
|
||||
struct anx7625_data, work);
|
||||
|
||||
mutex_lock(&ctx->lock);
|
||||
|
||||
if (pm_runtime_suspended(&ctx->client->dev))
|
||||
goto unlock;
|
||||
|
||||
event = anx7625_hpd_change_detect(ctx);
|
||||
mutex_unlock(&ctx->lock);
|
||||
if (event < 0)
|
||||
return;
|
||||
goto unlock;
|
||||
|
||||
if (ctx->bridge_attached)
|
||||
drm_helper_hpd_irq_event(ctx->bridge.dev);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&ctx->lock);
|
||||
}
|
||||
|
||||
static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data)
|
||||
{
|
||||
struct anx7625_data *ctx = (struct anx7625_data *)data;
|
||||
|
||||
if (atomic_read(&ctx->power_status) != 1)
|
||||
return IRQ_NONE;
|
||||
|
||||
queue_work(ctx->workqueue, &ctx->work);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
@ -1305,9 +1253,9 @@ static struct edid *anx7625_get_edid(struct anx7625_data *ctx)
|
||||
return (struct edid *)edid;
|
||||
}
|
||||
|
||||
anx7625_low_power_mode_check(ctx, 1);
|
||||
pm_runtime_get_sync(dev);
|
||||
edid_num = sp_tx_edid_read(ctx, p_edid->edid_raw_data);
|
||||
anx7625_low_power_mode_check(ctx, 0);
|
||||
pm_runtime_put_sync(dev);
|
||||
|
||||
if (edid_num < 1) {
|
||||
DRM_DEV_ERROR(dev, "Fail to read EDID: %d\n", edid_num);
|
||||
@ -1611,10 +1559,7 @@ static void anx7625_bridge_enable(struct drm_bridge *bridge)
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(dev, "drm enable\n");
|
||||
|
||||
anx7625_low_power_mode_check(ctx, 1);
|
||||
|
||||
if (WARN_ON(!atomic_read(&ctx->power_status)))
|
||||
return;
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
anx7625_dp_start(ctx);
|
||||
}
|
||||
@ -1624,14 +1569,11 @@ static void anx7625_bridge_disable(struct drm_bridge *bridge)
|
||||
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
|
||||
struct device *dev = &ctx->client->dev;
|
||||
|
||||
if (WARN_ON(!atomic_read(&ctx->power_status)))
|
||||
return;
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(dev, "drm disable\n");
|
||||
|
||||
anx7625_dp_stop(ctx);
|
||||
|
||||
anx7625_low_power_mode_check(ctx, 0);
|
||||
pm_runtime_put_sync(dev);
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
@ -1735,6 +1677,71 @@ static void anx7625_unregister_i2c_dummy_clients(struct anx7625_data *ctx)
|
||||
i2c_unregister_device(ctx->i2c.tcpc_client);
|
||||
}
|
||||
|
||||
static int __maybe_unused anx7625_runtime_pm_suspend(struct device *dev)
|
||||
{
|
||||
struct anx7625_data *ctx = dev_get_drvdata(dev);
|
||||
|
||||
mutex_lock(&ctx->lock);
|
||||
|
||||
anx7625_stop_dp_work(ctx);
|
||||
anx7625_power_standby(ctx);
|
||||
|
||||
mutex_unlock(&ctx->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused anx7625_runtime_pm_resume(struct device *dev)
|
||||
{
|
||||
struct anx7625_data *ctx = dev_get_drvdata(dev);
|
||||
|
||||
mutex_lock(&ctx->lock);
|
||||
|
||||
anx7625_power_on_init(ctx);
|
||||
anx7625_hpd_polling(ctx);
|
||||
|
||||
mutex_unlock(&ctx->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused anx7625_resume(struct device *dev)
|
||||
{
|
||||
struct anx7625_data *ctx = dev_get_drvdata(dev);
|
||||
|
||||
if (!ctx->pdata.intp_irq)
|
||||
return 0;
|
||||
|
||||
if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
|
||||
enable_irq(ctx->pdata.intp_irq);
|
||||
anx7625_runtime_pm_resume(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused anx7625_suspend(struct device *dev)
|
||||
{
|
||||
struct anx7625_data *ctx = dev_get_drvdata(dev);
|
||||
|
||||
if (!ctx->pdata.intp_irq)
|
||||
return 0;
|
||||
|
||||
if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
|
||||
anx7625_runtime_pm_suspend(dev);
|
||||
disable_irq(ctx->pdata.intp_irq);
|
||||
flush_workqueue(ctx->workqueue);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops anx7625_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(anx7625_suspend, anx7625_resume)
|
||||
SET_RUNTIME_PM_OPS(anx7625_runtime_pm_suspend,
|
||||
anx7625_runtime_pm_resume, NULL)
|
||||
};
|
||||
|
||||
static int anx7625_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
@ -1778,8 +1785,6 @@ static int anx7625_i2c_probe(struct i2c_client *client,
|
||||
}
|
||||
anx7625_init_gpio(platform);
|
||||
|
||||
atomic_set(&platform->power_status, 0);
|
||||
|
||||
mutex_init(&platform->lock);
|
||||
|
||||
platform->pdata.intp_irq = client->irq;
|
||||
@ -1809,9 +1814,11 @@ static int anx7625_i2c_probe(struct i2c_client *client,
|
||||
goto free_wq;
|
||||
}
|
||||
|
||||
if (platform->pdata.low_power_mode == 0) {
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
if (!platform->pdata.low_power_mode) {
|
||||
anx7625_disable_pd_protocol(platform);
|
||||
atomic_set(&platform->power_status, 1);
|
||||
pm_runtime_get_sync(dev);
|
||||
}
|
||||
|
||||
/* Add work function */
|
||||
@ -1847,6 +1854,9 @@ static int anx7625_i2c_remove(struct i2c_client *client)
|
||||
if (platform->pdata.intp_irq)
|
||||
destroy_workqueue(platform->workqueue);
|
||||
|
||||
if (!platform->pdata.low_power_mode)
|
||||
pm_runtime_put_sync_suspend(&client->dev);
|
||||
|
||||
anx7625_unregister_i2c_dummy_clients(platform);
|
||||
|
||||
kfree(platform);
|
||||
@ -1869,6 +1879,7 @@ static struct i2c_driver anx7625_driver = {
|
||||
.driver = {
|
||||
.name = "anx7625",
|
||||
.of_match_table = anx_match_table,
|
||||
.pm = &anx7625_pm_ops,
|
||||
},
|
||||
.probe = anx7625_i2c_probe,
|
||||
.remove = anx7625_i2c_remove,
|
||||
|
@ -369,7 +369,6 @@ struct anx7625_i2c_client {
|
||||
|
||||
struct anx7625_data {
|
||||
struct anx7625_platform_data pdata;
|
||||
atomic_t power_status;
|
||||
int hpd_status;
|
||||
int hpd_high_cnt;
|
||||
/* Lock for work queue */
|
||||
|
@ -2140,7 +2140,7 @@ cdns_mhdp_bridge_atomic_reset(struct drm_bridge *bridge)
|
||||
if (!cdns_mhdp_state)
|
||||
return NULL;
|
||||
|
||||
__drm_atomic_helper_bridge_reset(bridge, &cdns_mhdp_state->base);
|
||||
__drm_atomic_helper_bridge_reset(bridge, &cdns_mhdp_state->base);
|
||||
|
||||
return &cdns_mhdp_state->base;
|
||||
}
|
||||
@ -2478,9 +2478,9 @@ static int cdns_mhdp_probe(struct platform_device *pdev)
|
||||
clk_prepare_enable(clk);
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
ret = pm_runtime_get_sync(dev);
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "pm_runtime_get_sync failed\n");
|
||||
dev_err(dev, "pm_runtime_resume_and_get failed\n");
|
||||
pm_runtime_disable(dev);
|
||||
goto clk_disable;
|
||||
}
|
||||
|
@ -1028,7 +1028,7 @@ static ssize_t cdns_dsi_transfer(struct mipi_dsi_host *host,
|
||||
struct mipi_dsi_packet packet;
|
||||
int ret, i, tx_len, rx_len;
|
||||
|
||||
ret = pm_runtime_get_sync(host->dev);
|
||||
ret = pm_runtime_resume_and_get(host->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
191
drivers/gpu/drm/bridge/cros-ec-anx7688.c
Normal file
191
drivers/gpu/drm/bridge/cros-ec-anx7688.c
Normal file
@ -0,0 +1,191 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* CrOS EC ANX7688 HDMI->DP bridge driver
|
||||
*
|
||||
* Copyright 2020 Google LLC
|
||||
*/
|
||||
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/* Register addresses */
|
||||
#define ANX7688_VENDOR_ID_REG 0x00
|
||||
#define ANX7688_DEVICE_ID_REG 0x02
|
||||
|
||||
#define ANX7688_FW_VERSION_REG 0x80
|
||||
|
||||
#define ANX7688_DP_BANDWIDTH_REG 0x85
|
||||
#define ANX7688_DP_LANE_COUNT_REG 0x86
|
||||
|
||||
#define ANX7688_VENDOR_ID 0x1f29
|
||||
#define ANX7688_DEVICE_ID 0x7688
|
||||
|
||||
/* First supported firmware version (0.85) */
|
||||
#define ANX7688_MINIMUM_FW_VERSION 0x0085
|
||||
|
||||
static const struct regmap_config cros_ec_anx7688_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
};
|
||||
|
||||
struct cros_ec_anx7688 {
|
||||
struct i2c_client *client;
|
||||
struct regmap *regmap;
|
||||
struct drm_bridge bridge;
|
||||
bool filter;
|
||||
};
|
||||
|
||||
static inline struct cros_ec_anx7688 *
|
||||
bridge_to_cros_ec_anx7688(struct drm_bridge *bridge)
|
||||
{
|
||||
return container_of(bridge, struct cros_ec_anx7688, bridge);
|
||||
}
|
||||
|
||||
static bool cros_ec_anx7688_bridge_mode_fixup(struct drm_bridge *bridge,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct cros_ec_anx7688 *anx = bridge_to_cros_ec_anx7688(bridge);
|
||||
int totalbw, requiredbw;
|
||||
u8 dpbw, lanecount;
|
||||
u8 regs[2];
|
||||
int ret;
|
||||
|
||||
if (!anx->filter)
|
||||
return true;
|
||||
|
||||
/* Read both regs 0x85 (bandwidth) and 0x86 (lane count). */
|
||||
ret = regmap_bulk_read(anx->regmap, ANX7688_DP_BANDWIDTH_REG, regs, 2);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("Failed to read bandwidth/lane count\n");
|
||||
return false;
|
||||
}
|
||||
dpbw = regs[0];
|
||||
lanecount = regs[1];
|
||||
|
||||
/* Maximum 0x19 bandwidth (6.75 Gbps Turbo mode), 2 lanes */
|
||||
if (dpbw > 0x19 || lanecount > 2) {
|
||||
DRM_ERROR("Invalid bandwidth/lane count (%02x/%d)\n", dpbw,
|
||||
lanecount);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Compute available bandwidth (kHz) */
|
||||
totalbw = dpbw * lanecount * 270000 * 8 / 10;
|
||||
|
||||
/* Required bandwidth (8 bpc, kHz) */
|
||||
requiredbw = mode->clock * 8 * 3;
|
||||
|
||||
DRM_DEBUG_KMS("DP bandwidth: %d kHz (%02x/%d); mode requires %d Khz\n",
|
||||
totalbw, dpbw, lanecount, requiredbw);
|
||||
|
||||
if (totalbw == 0) {
|
||||
DRM_ERROR("Bandwidth/lane count are 0, not rejecting modes\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
return totalbw >= requiredbw;
|
||||
}
|
||||
|
||||
static const struct drm_bridge_funcs cros_ec_anx7688_bridge_funcs = {
|
||||
.mode_fixup = cros_ec_anx7688_bridge_mode_fixup,
|
||||
};
|
||||
|
||||
static int cros_ec_anx7688_bridge_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct cros_ec_anx7688 *anx7688;
|
||||
u16 vendor, device, fw_version;
|
||||
u8 buffer[4];
|
||||
int ret;
|
||||
|
||||
anx7688 = devm_kzalloc(dev, sizeof(*anx7688), GFP_KERNEL);
|
||||
if (!anx7688)
|
||||
return -ENOMEM;
|
||||
|
||||
anx7688->client = client;
|
||||
i2c_set_clientdata(client, anx7688);
|
||||
|
||||
anx7688->regmap = devm_regmap_init_i2c(client, &cros_ec_anx7688_regmap_config);
|
||||
if (IS_ERR(anx7688->regmap)) {
|
||||
ret = PTR_ERR(anx7688->regmap);
|
||||
dev_err(dev, "regmap i2c init failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Read both vendor and device id (4 bytes). */
|
||||
ret = regmap_bulk_read(anx7688->regmap, ANX7688_VENDOR_ID_REG,
|
||||
buffer, 4);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read chip vendor/device id\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
vendor = (u16)buffer[1] << 8 | buffer[0];
|
||||
device = (u16)buffer[3] << 8 | buffer[2];
|
||||
if (vendor != ANX7688_VENDOR_ID || device != ANX7688_DEVICE_ID) {
|
||||
dev_err(dev, "Invalid vendor/device id %04x/%04x\n",
|
||||
vendor, device);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = regmap_bulk_read(anx7688->regmap, ANX7688_FW_VERSION_REG,
|
||||
buffer, 2);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read firmware version\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
fw_version = (u16)buffer[0] << 8 | buffer[1];
|
||||
dev_info(dev, "ANX7688 firmware version 0x%04x\n", fw_version);
|
||||
|
||||
anx7688->bridge.of_node = dev->of_node;
|
||||
|
||||
/* FW version >= 0.85 supports bandwidth/lane count registers */
|
||||
if (fw_version >= ANX7688_MINIMUM_FW_VERSION)
|
||||
anx7688->filter = true;
|
||||
else
|
||||
/* Warn, but not fail, for backwards compatibility */
|
||||
DRM_WARN("Old ANX7688 FW version (0x%04x), not filtering\n",
|
||||
fw_version);
|
||||
|
||||
anx7688->bridge.funcs = &cros_ec_anx7688_bridge_funcs;
|
||||
drm_bridge_add(&anx7688->bridge);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cros_ec_anx7688_bridge_remove(struct i2c_client *client)
|
||||
{
|
||||
struct cros_ec_anx7688 *anx7688 = i2c_get_clientdata(client);
|
||||
|
||||
drm_bridge_remove(&anx7688->bridge);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id cros_ec_anx7688_bridge_match_table[] = {
|
||||
{ .compatible = "google,cros-ec-anx7688" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cros_ec_anx7688_bridge_match_table);
|
||||
|
||||
static struct i2c_driver cros_ec_anx7688_bridge_driver = {
|
||||
.probe_new = cros_ec_anx7688_bridge_probe,
|
||||
.remove = cros_ec_anx7688_bridge_remove,
|
||||
.driver = {
|
||||
.name = "cros-ec-anx7688-bridge",
|
||||
.of_match_table = cros_ec_anx7688_bridge_match_table,
|
||||
},
|
||||
};
|
||||
|
||||
module_i2c_driver(cros_ec_anx7688_bridge_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ChromeOS EC ANX7688 HDMI->DP bridge driver");
|
||||
MODULE_AUTHOR("Nicolas Boichat <drinkcat@chromium.org>");
|
||||
MODULE_AUTHOR("Enric Balletbo i Serra <enric.balletbo@collabora.com>");
|
||||
MODULE_LICENSE("GPL");
|
@ -898,14 +898,14 @@ static int it66121_probe(struct i2c_client *client,
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
ep = of_graph_get_endpoint_by_regs(dev->of_node, 0, 0);
|
||||
if (!ep)
|
||||
return -EINVAL;
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
ep = of_graph_get_endpoint_by_regs(dev->of_node, 0, 0);
|
||||
if (!ep)
|
||||
return -EINVAL;
|
||||
|
||||
ctx->dev = dev;
|
||||
ctx->client = client;
|
||||
|
||||
@ -943,7 +943,7 @@ static int it66121_probe(struct i2c_client *client,
|
||||
ctx->regmap = devm_regmap_init_i2c(client, &it66121_regmap_config);
|
||||
if (IS_ERR(ctx->regmap)) {
|
||||
ite66121_power_off(ctx);
|
||||
return PTR_ERR(ctx);
|
||||
return PTR_ERR(ctx->regmap);
|
||||
}
|
||||
|
||||
regmap_read(ctx->regmap, IT66121_VENDOR_ID0_REG, &vendor_ids[0]);
|
||||
|
@ -7,8 +7,6 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <drm/drm_probe_helper.h>
|
||||
@ -755,7 +753,6 @@ static struct i2c_driver lt8912_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "lt8912",
|
||||
.of_match_table = lt8912_dt_match,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = lt8912_probe,
|
||||
.remove = lt8912_remove,
|
||||
|
@ -1042,7 +1042,9 @@ exit:
|
||||
pm_runtime_mark_last_busy(pdata->dev);
|
||||
pm_runtime_put_autosuspend(pdata->dev);
|
||||
|
||||
return ret ? ret : len;
|
||||
if (ret)
|
||||
return ret;
|
||||
return len;
|
||||
}
|
||||
|
||||
static int ti_sn_bridge_parse_dsi_host(struct ti_sn65dsi86 *pdata)
|
||||
|
@ -685,6 +685,7 @@ static void drm_cleanup_buf_error(struct drm_device *dev,
|
||||
dmah->size,
|
||||
dmah->vaddr,
|
||||
dmah->busaddr);
|
||||
kfree(dmah);
|
||||
}
|
||||
}
|
||||
kfree(entry->seglist);
|
||||
@ -984,8 +985,16 @@ int drm_legacy_addbufs_pci(struct drm_device *dev,
|
||||
|
||||
while (entry->buf_count < count) {
|
||||
dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL);
|
||||
if (!dmah)
|
||||
if (!dmah) {
|
||||
/* Set count correctly so we free the proper amount. */
|
||||
entry->buf_count = count;
|
||||
entry->seg_count = count;
|
||||
drm_cleanup_buf_error(dev, entry);
|
||||
kfree(temp_pagelist);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
atomic_dec(&dev->buf_alloc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dmah->size = total;
|
||||
dmah->vaddr = dma_alloc_coherent(dev->dev,
|
||||
|
@ -3722,9 +3722,9 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
|
||||
}
|
||||
|
||||
lane_count = min_t(int, mgr->dpcd[2] & DP_MAX_LANE_COUNT_MASK, mgr->max_lane_count);
|
||||
link_rate = min_t(int, mgr->dpcd[1], mgr->max_link_rate);
|
||||
link_rate = min_t(int, drm_dp_bw_code_to_link_rate(mgr->dpcd[1]), mgr->max_link_rate);
|
||||
mgr->pbn_div = drm_dp_get_vc_payload_bw(mgr,
|
||||
drm_dp_bw_code_to_link_rate(link_rate),
|
||||
link_rate,
|
||||
lane_count);
|
||||
if (mgr->pbn_div == 0) {
|
||||
ret = -EINVAL;
|
||||
@ -5454,7 +5454,7 @@ EXPORT_SYMBOL(drm_atomic_get_mst_topology_state);
|
||||
* @max_dpcd_transaction_bytes: hw specific DPCD transaction limit
|
||||
* @max_payloads: maximum number of payloads this GPU can source
|
||||
* @max_lane_count: maximum number of lanes this GPU supports
|
||||
* @max_link_rate: maximum link rate this GPU supports, units as in DPCD
|
||||
* @max_link_rate: maximum link rate per lane this GPU supports in kHz
|
||||
* @conn_base_id: the connector object ID the MST device is connected to.
|
||||
*
|
||||
* Return 0 for success, or negative error code on failure
|
||||
@ -5462,7 +5462,7 @@ EXPORT_SYMBOL(drm_atomic_get_mst_topology_state);
|
||||
int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_device *dev, struct drm_dp_aux *aux,
|
||||
int max_dpcd_transaction_bytes, int max_payloads,
|
||||
u8 max_lane_count, u8 max_link_rate,
|
||||
int max_lane_count, int max_link_rate,
|
||||
int conn_base_id)
|
||||
{
|
||||
struct drm_dp_mst_topology_state *mst_state;
|
||||
|
@ -9,12 +9,14 @@
|
||||
* Copyright (C) 2012 Red Hat
|
||||
*/
|
||||
|
||||
#include <drm/drm_damage_helper.h>
|
||||
#include <drm/drm_fb_cma_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_plane.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
/**
|
||||
@ -97,3 +99,47 @@ dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb,
|
||||
return paddr;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_addr);
|
||||
|
||||
/**
|
||||
* drm_fb_cma_sync_non_coherent - Sync GEM object to non-coherent backing
|
||||
* memory
|
||||
* @drm: DRM device
|
||||
* @old_state: Old plane state
|
||||
* @state: New plane state
|
||||
*
|
||||
* This function can be used by drivers that use damage clips and have
|
||||
* CMA GEM objects backed by non-coherent memory. Calling this function
|
||||
* in a plane's .atomic_update ensures that all the data in the backing
|
||||
* memory have been written to RAM.
|
||||
*/
|
||||
void drm_fb_cma_sync_non_coherent(struct drm_device *drm,
|
||||
struct drm_plane_state *old_state,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
const struct drm_format_info *finfo = state->fb->format;
|
||||
struct drm_atomic_helper_damage_iter iter;
|
||||
const struct drm_gem_cma_object *cma_obj;
|
||||
unsigned int offset, i;
|
||||
struct drm_rect clip;
|
||||
dma_addr_t daddr;
|
||||
size_t nb_bytes;
|
||||
|
||||
for (i = 0; i < finfo->num_planes; i++) {
|
||||
cma_obj = drm_fb_cma_get_gem_obj(state->fb, i);
|
||||
if (!cma_obj->map_noncoherent)
|
||||
continue;
|
||||
|
||||
daddr = drm_fb_cma_get_gem_addr(state->fb, state, i);
|
||||
drm_atomic_helper_damage_iter_init(&iter, old_state, state);
|
||||
|
||||
drm_atomic_for_each_plane_damage(&iter, &clip) {
|
||||
/* Ignore x1/x2 values, invalidate complete lines */
|
||||
offset = clip.y1 * state->fb->pitches[i];
|
||||
|
||||
nb_bytes = (clip.y2 - clip.y1) * state->fb->pitches[i];
|
||||
dma_sync_single_for_device(drm->dev, daddr + offset,
|
||||
nb_bytes, DMA_TO_DEVICE);
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_fb_cma_sync_non_coherent);
|
||||
|
@ -1737,7 +1737,7 @@ void drm_fb_helper_fill_info(struct fb_info *info,
|
||||
sizes->fb_width, sizes->fb_height);
|
||||
|
||||
info->par = fb_helper;
|
||||
snprintf(info->fix.id, sizeof(info->fix.id), "%sdrmfb",
|
||||
snprintf(info->fix.id, sizeof(info->fix.id), "%s",
|
||||
fb_helper->dev->driver->name);
|
||||
|
||||
}
|
||||
|
@ -30,11 +30,6 @@
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
|
||||
static char printable_char(int c)
|
||||
{
|
||||
return isascii(c) && isprint(c) ? c : '?';
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_mode_legacy_fb_format - compute drm fourcc code from legacy description
|
||||
* @bpp: bits per pixels
|
||||
@ -130,26 +125,6 @@ uint32_t drm_driver_legacy_fb_format(struct drm_device *dev,
|
||||
}
|
||||
EXPORT_SYMBOL(drm_driver_legacy_fb_format);
|
||||
|
||||
/**
|
||||
* drm_get_format_name - fill a string with a drm fourcc format's name
|
||||
* @format: format to compute name of
|
||||
* @buf: caller-supplied buffer
|
||||
*/
|
||||
const char *drm_get_format_name(uint32_t format, struct drm_format_name_buf *buf)
|
||||
{
|
||||
snprintf(buf->str, sizeof(buf->str),
|
||||
"%c%c%c%c %s-endian (0x%08x)",
|
||||
printable_char(format & 0xff),
|
||||
printable_char((format >> 8) & 0xff),
|
||||
printable_char((format >> 16) & 0xff),
|
||||
printable_char((format >> 24) & 0x7f),
|
||||
format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little",
|
||||
format);
|
||||
|
||||
return buf->str;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_get_format_name);
|
||||
|
||||
/*
|
||||
* Internal function to query information for a given format. See
|
||||
* drm_format_info() for the public API.
|
||||
|
@ -46,6 +46,7 @@ static const struct drm_gem_object_funcs drm_gem_cma_default_funcs = {
|
||||
* __drm_gem_cma_create - Create a GEM CMA object without allocating memory
|
||||
* @drm: DRM device
|
||||
* @size: size of the object to allocate
|
||||
* @private: true if used for internal purposes
|
||||
*
|
||||
* This function creates and initializes a GEM CMA object of the given size,
|
||||
* but doesn't allocate any memory to back the object.
|
||||
@ -55,11 +56,11 @@ static const struct drm_gem_object_funcs drm_gem_cma_default_funcs = {
|
||||
* error code on failure.
|
||||
*/
|
||||
static struct drm_gem_cma_object *
|
||||
__drm_gem_cma_create(struct drm_device *drm, size_t size)
|
||||
__drm_gem_cma_create(struct drm_device *drm, size_t size, bool private)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj;
|
||||
struct drm_gem_object *gem_obj;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (drm->driver->gem_create_object)
|
||||
gem_obj = drm->driver->gem_create_object(drm, size);
|
||||
@ -73,7 +74,14 @@ __drm_gem_cma_create(struct drm_device *drm, size_t size)
|
||||
|
||||
cma_obj = container_of(gem_obj, struct drm_gem_cma_object, base);
|
||||
|
||||
ret = drm_gem_object_init(drm, gem_obj, size);
|
||||
if (private) {
|
||||
drm_gem_private_object_init(drm, gem_obj, size);
|
||||
|
||||
/* Always use writecombine for dma-buf mappings */
|
||||
cma_obj->map_noncoherent = false;
|
||||
} else {
|
||||
ret = drm_gem_object_init(drm, gem_obj, size);
|
||||
}
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
@ -111,12 +119,19 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
|
||||
|
||||
size = round_up(size, PAGE_SIZE);
|
||||
|
||||
cma_obj = __drm_gem_cma_create(drm, size);
|
||||
cma_obj = __drm_gem_cma_create(drm, size, false);
|
||||
if (IS_ERR(cma_obj))
|
||||
return cma_obj;
|
||||
|
||||
cma_obj->vaddr = dma_alloc_wc(drm->dev, size, &cma_obj->paddr,
|
||||
GFP_KERNEL | __GFP_NOWARN);
|
||||
if (cma_obj->map_noncoherent) {
|
||||
cma_obj->vaddr = dma_alloc_noncoherent(drm->dev, size,
|
||||
&cma_obj->paddr,
|
||||
DMA_TO_DEVICE,
|
||||
GFP_KERNEL | __GFP_NOWARN);
|
||||
} else {
|
||||
cma_obj->vaddr = dma_alloc_wc(drm->dev, size, &cma_obj->paddr,
|
||||
GFP_KERNEL | __GFP_NOWARN);
|
||||
}
|
||||
if (!cma_obj->vaddr) {
|
||||
drm_dbg(drm, "failed to allocate buffer with size %zu\n",
|
||||
size);
|
||||
@ -432,7 +447,7 @@ drm_gem_cma_prime_import_sg_table(struct drm_device *dev,
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* Create a CMA GEM buffer. */
|
||||
cma_obj = __drm_gem_cma_create(dev, attach->dmabuf->size);
|
||||
cma_obj = __drm_gem_cma_create(dev, attach->dmabuf->size, true);
|
||||
if (IS_ERR(cma_obj))
|
||||
return ERR_CAST(cma_obj);
|
||||
|
||||
@ -499,8 +514,16 @@ int drm_gem_cma_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
|
||||
|
||||
cma_obj = to_drm_gem_cma_obj(obj);
|
||||
|
||||
ret = dma_mmap_wc(cma_obj->base.dev->dev, vma, cma_obj->vaddr,
|
||||
cma_obj->paddr, vma->vm_end - vma->vm_start);
|
||||
if (cma_obj->map_noncoherent) {
|
||||
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
|
||||
|
||||
ret = dma_mmap_pages(cma_obj->base.dev->dev,
|
||||
vma, vma->vm_end - vma->vm_start,
|
||||
virt_to_page(cma_obj->vaddr));
|
||||
} else {
|
||||
ret = dma_mmap_wc(cma_obj->base.dev->dev, vma, cma_obj->vaddr,
|
||||
cma_obj->paddr, vma->vm_end - vma->vm_start);
|
||||
}
|
||||
if (ret)
|
||||
drm_gem_vm_close(vma);
|
||||
|
||||
|
@ -149,8 +149,10 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
|
||||
int ret, i;
|
||||
|
||||
info = drm_get_format_info(dev, mode_cmd);
|
||||
if (!info)
|
||||
if (!info) {
|
||||
drm_dbg_kms(dev, "Failed to get FB format info\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < info->num_planes; i++) {
|
||||
unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
|
||||
@ -169,6 +171,9 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
|
||||
+ mode_cmd->offsets[i];
|
||||
|
||||
if (objs[i]->size < min_size) {
|
||||
drm_dbg_kms(dev,
|
||||
"GEM object size (%zu) smaller than minimum size (%u) for plane %d\n",
|
||||
objs[i]->size, min_size, i);
|
||||
drm_gem_object_put(objs[i]);
|
||||
ret = -EINVAL;
|
||||
goto err_gem_object_put;
|
||||
|
@ -54,18 +54,10 @@ void drm_lastclose(struct drm_device *dev);
|
||||
#ifdef CONFIG_PCI
|
||||
|
||||
/* drm_pci.c */
|
||||
int drm_legacy_irq_by_busid(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master);
|
||||
|
||||
#else
|
||||
|
||||
static inline int drm_legacy_irq_by_busid(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int drm_pci_set_busid(struct drm_device *dev,
|
||||
struct drm_master *master)
|
||||
{
|
||||
|
@ -577,7 +577,8 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_legacy_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_legacy_irq_by_busid,
|
||||
DRM_MASTER|DRM_ROOT_ONLY),
|
||||
|
||||
DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_legacy_getmap_ioctl, 0),
|
||||
|
||||
|
@ -14,7 +14,6 @@
|
||||
|
||||
#include "drm_crtc_internal.h"
|
||||
#include "drm_internal.h"
|
||||
#include "drm_legacy.h"
|
||||
|
||||
#define drm_for_each_lessee(lessee, lessor) \
|
||||
list_for_each_entry((lessee), &(lessor)->lessees, lessee_list)
|
||||
|
@ -235,9 +235,17 @@ void drm_master_legacy_init(struct drm_master *master);
|
||||
static inline void drm_master_legacy_init(struct drm_master *master) {}
|
||||
#endif
|
||||
|
||||
/* drm_pci.c */
|
||||
#if IS_ENABLED(CONFIG_DRM_LEGACY) && IS_ENABLED(CONFIG_PCI)
|
||||
int drm_legacy_irq_by_busid(struct drm_device *dev, void *data, struct drm_file *file_priv);
|
||||
void drm_legacy_pci_agp_destroy(struct drm_device *dev);
|
||||
#else
|
||||
static inline int drm_legacy_irq_by_busid(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline void drm_legacy_pci_agp_destroy(struct drm_device *dev) {}
|
||||
#endif
|
||||
|
||||
|
@ -72,7 +72,9 @@ int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p)
|
||||
#ifdef CONFIG_DRM_LEGACY
|
||||
|
||||
static int drm_legacy_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev->dev);
|
||||
|
||||
@ -115,11 +117,9 @@ int drm_legacy_irq_by_busid(struct drm_device *dev, void *data,
|
||||
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return drm_pci_irq_by_busid(dev, p);
|
||||
return drm_legacy_pci_irq_by_busid(dev, p);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_LEGACY
|
||||
|
||||
void drm_legacy_pci_agp_destroy(struct drm_device *dev)
|
||||
{
|
||||
if (dev->agp) {
|
||||
@ -165,9 +165,6 @@ static int drm_legacy_get_pci_dev(struct pci_dev *pdev,
|
||||
dev->hose = pdev->sysdata;
|
||||
#endif
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
pci_set_drvdata(pdev, dev);
|
||||
|
||||
drm_legacy_pci_agp_init(dev);
|
||||
|
||||
ret = drm_dev_register(dev, ent->driver_data);
|
||||
|
@ -3,7 +3,7 @@
|
||||
* DesignWare MIPI DSI Host Controller v1.02 driver
|
||||
*
|
||||
* Copyright (c) 2016 Linaro Limited.
|
||||
* Copyright (c) 2014-2016 Hisilicon Limited.
|
||||
* Copyright (c) 2014-2016 HiSilicon Limited.
|
||||
*
|
||||
* Author:
|
||||
* Xinliang Liu <z.liuxinliang@hisilicon.com>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2016 Linaro Limited.
|
||||
* Copyright (c) 2014-2016 Hisilicon Limited.
|
||||
* Copyright (c) 2014-2016 HiSilicon Limited.
|
||||
*/
|
||||
|
||||
#ifndef __DW_DSI_REG_H__
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2016 Linaro Limited.
|
||||
* Copyright (c) 2014-2016 Hisilicon Limited.
|
||||
* Copyright (c) 2014-2016 HiSilicon Limited.
|
||||
*/
|
||||
|
||||
#ifndef __KIRIN_ADE_REG_H__
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Hisilicon Hi6220 SoC ADE(Advanced Display Engine)'s crtc&plane driver
|
||||
*
|
||||
* Copyright (c) 2016 Linaro Limited.
|
||||
* Copyright (c) 2014-2016 Hisilicon Limited.
|
||||
* Copyright (c) 2014-2016 HiSilicon Limited.
|
||||
*
|
||||
* Author:
|
||||
* Xinliang Liu <z.liuxinliang@hisilicon.com>
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Hisilicon Kirin SoCs drm master driver
|
||||
*
|
||||
* Copyright (c) 2016 Linaro Limited.
|
||||
* Copyright (c) 2014-2016 Hisilicon Limited.
|
||||
* Copyright (c) 2014-2016 HiSilicon Limited.
|
||||
*
|
||||
* Author:
|
||||
* Xinliang Liu <z.liuxinliang@hisilicon.com>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2016 Linaro Limited.
|
||||
* Copyright (c) 2014-2016 Hisilicon Limited.
|
||||
* Copyright (c) 2014-2016 HiSilicon Limited.
|
||||
*/
|
||||
|
||||
#ifndef __KIRIN_DRM_DRV_H__
|
||||
|
@ -963,8 +963,8 @@ intel_dp_mst_encoder_init(struct intel_digital_port *dig_port, int conn_base_id)
|
||||
intel_dp_create_fake_mst_encoders(dig_port);
|
||||
ret = drm_dp_mst_topology_mgr_init(&intel_dp->mst_mgr, &i915->drm,
|
||||
&intel_dp->aux, 16, 3,
|
||||
(u8)dig_port->max_lanes,
|
||||
drm_dp_link_rate_to_bw_code(max_source_rate),
|
||||
dig_port->max_lanes,
|
||||
max_source_rate,
|
||||
conn_base_id);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include <linux/shmem_fs.h>
|
||||
#include <linux/swap.h>
|
||||
|
||||
#include <drm/drm.h> /* for drm_legacy.h! */
|
||||
#include <drm/drm_cache.h>
|
||||
|
||||
#include "gt/intel_gt.h"
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: MIT*/
|
||||
/*
|
||||
* Copyright <EFBFBD> 2003-2018 Intel Corporation
|
||||
* Copyright © 2003-2018 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef _INTEL_GPU_COMMANDS_H_
|
||||
|
@ -51,7 +51,6 @@
|
||||
#include <linux/xarray.h>
|
||||
|
||||
#include <drm/intel-gtt.h>
|
||||
#include <drm/drm_legacy.h> /* for struct drm_dma_handle */
|
||||
#include <drm/drm_gem.h>
|
||||
#include <drm/drm_auth.h>
|
||||
#include <drm/drm_cache.h>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright <EFBFBD> 2008-2018 Intel Corporation
|
||||
* Copyright © 2008-2018 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef _I915_GPU_ERROR_H_
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <linux/component.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
@ -23,6 +24,7 @@
|
||||
#include <drm/drm_color_mgmt.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_damage_helper.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
@ -57,6 +59,7 @@ struct ingenic_dma_hwdescs {
|
||||
struct jz_soc_info {
|
||||
bool needs_dev_clk;
|
||||
bool has_osd;
|
||||
bool map_noncoherent;
|
||||
unsigned int max_width, max_height;
|
||||
const u32 *formats_f0, *formats_f1;
|
||||
unsigned int num_formats_f0, num_formats_f1;
|
||||
@ -342,7 +345,7 @@ static void ingenic_drm_crtc_atomic_flush(struct drm_crtc *crtc,
|
||||
if (priv->update_clk_rate) {
|
||||
mutex_lock(&priv->clk_mutex);
|
||||
clk_set_rate(priv->pix_clk,
|
||||
crtc_state->adjusted_mode.clock * 1000);
|
||||
crtc_state->adjusted_mode.crtc_clock * 1000);
|
||||
priv->update_clk_rate = false;
|
||||
mutex_unlock(&priv->clk_mutex);
|
||||
}
|
||||
@ -410,6 +413,9 @@ static int ingenic_drm_plane_atomic_check(struct drm_plane *plane,
|
||||
old_plane_state->fb->format->format != new_plane_state->fb->format->format))
|
||||
crtc_state->mode_changed = true;
|
||||
|
||||
if (priv->soc_info->map_noncoherent)
|
||||
drm_atomic_helper_check_plane_damage(state, new_plane_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -526,6 +532,13 @@ void ingenic_drm_plane_config(struct device *dev,
|
||||
}
|
||||
}
|
||||
|
||||
bool ingenic_drm_map_noncoherent(const struct device *dev)
|
||||
{
|
||||
const struct ingenic_drm *priv = dev_get_drvdata(dev);
|
||||
|
||||
return priv->soc_info->map_noncoherent;
|
||||
}
|
||||
|
||||
static void ingenic_drm_update_palette(struct ingenic_drm *priv,
|
||||
const struct drm_color_lut *lut)
|
||||
{
|
||||
@ -544,8 +557,8 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct ingenic_drm *priv = drm_device_get_priv(plane->dev);
|
||||
struct drm_plane_state *newstate = drm_atomic_get_new_plane_state(state,
|
||||
plane);
|
||||
struct drm_plane_state *newstate = drm_atomic_get_new_plane_state(state, plane);
|
||||
struct drm_plane_state *oldstate = drm_atomic_get_old_plane_state(state, plane);
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct ingenic_dma_hwdesc *hwdesc;
|
||||
unsigned int width, height, cpp, offset;
|
||||
@ -553,6 +566,9 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane,
|
||||
u32 fourcc;
|
||||
|
||||
if (newstate && newstate->fb) {
|
||||
if (priv->soc_info->map_noncoherent)
|
||||
drm_fb_cma_sync_non_coherent(&priv->drm, oldstate, newstate);
|
||||
|
||||
crtc_state = newstate->crtc->state;
|
||||
|
||||
addr = drm_fb_cma_get_gem_addr(newstate->fb, newstate, 0);
|
||||
@ -742,6 +758,33 @@ static void ingenic_drm_disable_vblank(struct drm_crtc *crtc)
|
||||
regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, JZ_LCD_CTRL_EOF_IRQ, 0);
|
||||
}
|
||||
|
||||
static struct drm_framebuffer *
|
||||
ingenic_drm_gem_fb_create(struct drm_device *drm, struct drm_file *file,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
{
|
||||
struct ingenic_drm *priv = drm_device_get_priv(drm);
|
||||
|
||||
if (priv->soc_info->map_noncoherent)
|
||||
return drm_gem_fb_create_with_dirty(drm, file, mode_cmd);
|
||||
|
||||
return drm_gem_fb_create(drm, file, mode_cmd);
|
||||
}
|
||||
|
||||
static struct drm_gem_object *
|
||||
ingenic_drm_gem_create_object(struct drm_device *drm, size_t size)
|
||||
{
|
||||
struct ingenic_drm *priv = drm_device_get_priv(drm);
|
||||
struct drm_gem_cma_object *obj;
|
||||
|
||||
obj = kzalloc(sizeof(*obj), GFP_KERNEL);
|
||||
if (!obj)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
obj->map_noncoherent = priv->soc_info->map_noncoherent;
|
||||
|
||||
return &obj->base;
|
||||
}
|
||||
|
||||
DEFINE_DRM_GEM_CMA_FOPS(ingenic_drm_fops);
|
||||
|
||||
static const struct drm_driver ingenic_drm_driver_data = {
|
||||
@ -754,6 +797,7 @@ static const struct drm_driver ingenic_drm_driver_data = {
|
||||
.patchlevel = 0,
|
||||
|
||||
.fops = &ingenic_drm_fops,
|
||||
.gem_create_object = ingenic_drm_gem_create_object,
|
||||
DRM_GEM_CMA_DRIVER_OPS,
|
||||
|
||||
.irq_handler = ingenic_drm_irq_handler,
|
||||
@ -804,7 +848,7 @@ static const struct drm_encoder_helper_funcs ingenic_drm_encoder_helper_funcs =
|
||||
};
|
||||
|
||||
static const struct drm_mode_config_funcs ingenic_drm_mode_config_funcs = {
|
||||
.fb_create = drm_gem_fb_create,
|
||||
.fb_create = ingenic_drm_gem_fb_create,
|
||||
.output_poll_changed = drm_fb_helper_output_poll_changed,
|
||||
.atomic_check = drm_atomic_helper_check,
|
||||
.atomic_commit = drm_atomic_helper_commit,
|
||||
@ -961,6 +1005,9 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (soc_info->map_noncoherent)
|
||||
drm_plane_enable_fb_damage_clips(&priv->f1);
|
||||
|
||||
drm_crtc_helper_add(&priv->crtc, &ingenic_drm_crtc_helper_funcs);
|
||||
|
||||
ret = drm_crtc_init_with_planes(drm, &priv->crtc, primary,
|
||||
@ -989,6 +1036,9 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (soc_info->map_noncoherent)
|
||||
drm_plane_enable_fb_damage_clips(&priv->f0);
|
||||
|
||||
if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU) && has_components) {
|
||||
ret = component_bind_all(dev, drm);
|
||||
if (ret) {
|
||||
@ -1245,6 +1295,7 @@ static const u32 jz4770_formats_f0[] = {
|
||||
static const struct jz_soc_info jz4740_soc_info = {
|
||||
.needs_dev_clk = true,
|
||||
.has_osd = false,
|
||||
.map_noncoherent = false,
|
||||
.max_width = 800,
|
||||
.max_height = 600,
|
||||
.formats_f1 = jz4740_formats,
|
||||
@ -1255,6 +1306,7 @@ static const struct jz_soc_info jz4740_soc_info = {
|
||||
static const struct jz_soc_info jz4725b_soc_info = {
|
||||
.needs_dev_clk = false,
|
||||
.has_osd = true,
|
||||
.map_noncoherent = false,
|
||||
.max_width = 800,
|
||||
.max_height = 600,
|
||||
.formats_f1 = jz4725b_formats_f1,
|
||||
@ -1266,6 +1318,7 @@ static const struct jz_soc_info jz4725b_soc_info = {
|
||||
static const struct jz_soc_info jz4770_soc_info = {
|
||||
.needs_dev_clk = false,
|
||||
.has_osd = true,
|
||||
.map_noncoherent = true,
|
||||
.max_width = 1280,
|
||||
.max_height = 720,
|
||||
.formats_f1 = jz4770_formats_f1,
|
||||
|
@ -184,6 +184,7 @@ struct platform_driver;
|
||||
void ingenic_drm_plane_config(struct device *dev,
|
||||
struct drm_plane *plane, u32 fourcc);
|
||||
void ingenic_drm_plane_disable(struct device *dev, struct drm_plane *plane);
|
||||
bool ingenic_drm_map_noncoherent(const struct device *dev);
|
||||
|
||||
extern struct platform_driver *ingenic_ipu_driver_ptr;
|
||||
|
||||
|
@ -20,10 +20,13 @@
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_damage_helper.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_fb_cma_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_gem_atomic_helper.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_plane.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_property.h>
|
||||
@ -285,8 +288,8 @@ static void ingenic_ipu_plane_atomic_update(struct drm_plane *plane,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct ingenic_ipu *ipu = plane_to_ingenic_ipu(plane);
|
||||
struct drm_plane_state *newstate = drm_atomic_get_new_plane_state(state,
|
||||
plane);
|
||||
struct drm_plane_state *newstate = drm_atomic_get_new_plane_state(state, plane);
|
||||
struct drm_plane_state *oldstate = drm_atomic_get_old_plane_state(state, plane);
|
||||
const struct drm_format_info *finfo;
|
||||
u32 ctrl, stride = 0, coef_index = 0, format = 0;
|
||||
bool needs_modeset, upscaling_w, upscaling_h;
|
||||
@ -317,6 +320,9 @@ static void ingenic_ipu_plane_atomic_update(struct drm_plane *plane,
|
||||
JZ_IPU_CTRL_CHIP_EN | JZ_IPU_CTRL_LCDC_SEL);
|
||||
}
|
||||
|
||||
if (ingenic_drm_map_noncoherent(ipu->master))
|
||||
drm_fb_cma_sync_non_coherent(ipu->drm, oldstate, newstate);
|
||||
|
||||
/* New addresses will be committed in vblank handler... */
|
||||
ipu->addr_y = drm_fb_cma_get_gem_addr(newstate->fb, newstate, 0);
|
||||
if (finfo->num_planes > 1)
|
||||
@ -541,7 +547,7 @@ static int ingenic_ipu_plane_atomic_check(struct drm_plane *plane,
|
||||
|
||||
if (!new_plane_state->crtc ||
|
||||
!crtc_state->mode.hdisplay || !crtc_state->mode.vdisplay)
|
||||
return 0;
|
||||
goto out_check_damage;
|
||||
|
||||
/* Plane must be fully visible */
|
||||
if (new_plane_state->crtc_x < 0 || new_plane_state->crtc_y < 0 ||
|
||||
@ -558,7 +564,7 @@ static int ingenic_ipu_plane_atomic_check(struct drm_plane *plane,
|
||||
return -EINVAL;
|
||||
|
||||
if (!osd_changed(new_plane_state, old_plane_state))
|
||||
return 0;
|
||||
goto out_check_damage;
|
||||
|
||||
crtc_state->mode_changed = true;
|
||||
|
||||
@ -592,6 +598,10 @@ static int ingenic_ipu_plane_atomic_check(struct drm_plane *plane,
|
||||
ipu->denom_w = denom_w;
|
||||
ipu->denom_h = denom_h;
|
||||
|
||||
out_check_damage:
|
||||
if (ingenic_drm_map_noncoherent(ipu->master))
|
||||
drm_atomic_helper_check_plane_damage(state, new_plane_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -773,6 +783,9 @@ static int ingenic_ipu_bind(struct device *dev, struct device *master, void *d)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (ingenic_drm_map_noncoherent(master))
|
||||
drm_plane_enable_fb_damage_clips(plane);
|
||||
|
||||
/*
|
||||
* Sharpness settings range is [0,32]
|
||||
* 0 : nearest-neighbor
|
||||
|
@ -1196,10 +1196,8 @@ static int mcde_dsi_probe(struct platform_device *pdev)
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
d->regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(d->regs)) {
|
||||
dev_err(dev, "no DSI regs\n");
|
||||
if (IS_ERR(d->regs))
|
||||
return PTR_ERR(d->regs);
|
||||
}
|
||||
|
||||
dsi_id = readl(d->regs + DSI_ID_REG);
|
||||
dev_info(dev, "HW revision 0x%08x\n", dsi_id);
|
||||
|
@ -1617,8 +1617,9 @@ nv50_mstm_new(struct nouveau_encoder *outp, struct drm_dp_aux *aux, int aux_max,
|
||||
mstm->mgr.cbs = &nv50_mstm;
|
||||
|
||||
ret = drm_dp_mst_topology_mgr_init(&mstm->mgr, dev, aux, aux_max,
|
||||
(u8)max_payloads, outp->dcb->dpconf.link_nr,
|
||||
(u8)outp->dcb->dpconf.link_bw, conn_base_id);
|
||||
max_payloads, outp->dcb->dpconf.link_nr,
|
||||
drm_dp_bw_code_to_link_rate(outp->dcb->dpconf.link_bw),
|
||||
conn_base_id);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user